Serenity Operating System
at master 398 lines 15 kB view raw
1/* 2 * Copyright (c) 2020-2021, Itamar S. <itamar8910@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "DwarfInfo.h" 8#include "AddressRanges.h" 9#include "AttributeValue.h" 10#include "CompilationUnit.h" 11 12#include <AK/ByteReader.h> 13#include <AK/LEB128.h> 14#include <AK/MemoryStream.h> 15#include <LibDebug/DebugInfo.h> 16 17namespace Debug::Dwarf { 18 19DwarfInfo::DwarfInfo(ELF::Image const& elf) 20 : m_elf(elf) 21{ 22 m_debug_info_data = section_data(".debug_info"sv); 23 m_abbreviation_data = section_data(".debug_abbrev"sv); 24 m_debug_strings_data = section_data(".debug_str"sv); 25 m_debug_line_data = section_data(".debug_line"sv); 26 m_debug_line_strings_data = section_data(".debug_line_str"sv); 27 m_debug_range_lists_data = section_data(".debug_rnglists"sv); 28 m_debug_str_offsets_data = section_data(".debug_str_offsets"sv); 29 m_debug_addr_data = section_data(".debug_addr"sv); 30 m_debug_ranges_data = section_data(".debug_ranges"sv); 31 32 populate_compilation_units().release_value_but_fixme_should_propagate_errors(); 33} 34 35DwarfInfo::~DwarfInfo() = default; 36 37ReadonlyBytes DwarfInfo::section_data(StringView section_name) const 38{ 39 auto section = m_elf.lookup_section(section_name); 40 if (!section.has_value()) 41 return {}; 42 return section->bytes(); 43} 44 45ErrorOr<void> DwarfInfo::populate_compilation_units() 46{ 47 if (!m_debug_info_data.data()) 48 return {}; 49 50 FixedMemoryStream debug_info_stream { m_debug_info_data }; 51 FixedMemoryStream line_info_stream { m_debug_line_data }; 52 53 while (!debug_info_stream.is_eof()) { 54 auto unit_offset = TRY(debug_info_stream.tell()); 55 56 auto compilation_unit_header = TRY(debug_info_stream.read_value<CompilationUnitHeader>()); 57 VERIFY(compilation_unit_header.common.version <= 5); 58 VERIFY(compilation_unit_header.address_size() == sizeof(FlatPtr)); 59 60 u32 length_after_header = compilation_unit_header.length() - (compilation_unit_header.header_size() - offsetof(CompilationUnitHeader, common.version)); 61 62 auto line_program = make<LineProgram>(*this, line_info_stream); 63 64 // HACK: Clang generates line programs for embedded resource assembly files, but not compile units. 65 // Meaning that for graphical applications, some line info data would be unread, triggering the assertion below. 66 // As a fix, we don't create compilation units for line programs that come from resource files. 67#if defined(AK_COMPILER_CLANG) 68 if (line_program->looks_like_embedded_resource()) { 69 TRY(debug_info_stream.seek(unit_offset)); 70 } else 71#endif 72 { 73 m_compilation_units.append(make<CompilationUnit>(*this, unit_offset, compilation_unit_header, move(line_program))); 74 TRY(debug_info_stream.discard(length_after_header)); 75 } 76 } 77 78 VERIFY(line_info_stream.is_eof()); 79 return {}; 80} 81 82ErrorOr<AttributeValue> DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, 83 SeekableStream& debug_info_stream, CompilationUnit const* unit) const 84{ 85 AttributeValue value; 86 value.m_form = form; 87 value.m_compilation_unit = unit; 88 89 auto assign_raw_bytes_value = [&](size_t length) -> ErrorOr<void> { 90 value.m_data.as_raw_bytes = { debug_info_data().offset_pointer(TRY(debug_info_stream.tell())), length }; 91 TRY(debug_info_stream.discard(length)); 92 return {}; 93 }; 94 95 switch (form) { 96 case AttributeDataForm::StringPointer: { 97 auto offset = TRY(debug_info_stream.read_value<u32>()); 98 value.m_type = AttributeValue::Type::String; 99 100 auto strings_data = debug_strings_data(); 101 value.m_data.as_string = bit_cast<char const*>(strings_data.offset_pointer(offset)); 102 break; 103 } 104 case AttributeDataForm::Data1: { 105 auto data = TRY(debug_info_stream.read_value<u8>()); 106 value.m_type = AttributeValue::Type::UnsignedNumber; 107 value.m_data.as_unsigned = data; 108 break; 109 } 110 case AttributeDataForm::Data2: { 111 auto data = TRY(debug_info_stream.read_value<u16>()); 112 value.m_type = AttributeValue::Type::UnsignedNumber; 113 value.m_data.as_signed = data; 114 break; 115 } 116 case AttributeDataForm::Addr: { 117 auto address = TRY(debug_info_stream.read_value<FlatPtr>()); 118 value.m_type = AttributeValue::Type::Address; 119 value.m_data.as_addr = address; 120 break; 121 } 122 case AttributeDataForm::SData: { 123 i64 data = TRY(debug_info_stream.read_value<LEB128<i64>>()); 124 value.m_type = AttributeValue::Type::SignedNumber; 125 value.m_data.as_signed = data; 126 break; 127 } 128 case AttributeDataForm::UData: { 129 u64 data = TRY(debug_info_stream.read_value<LEB128<u64>>()); 130 value.m_type = AttributeValue::Type::UnsignedNumber; 131 value.m_data.as_unsigned = data; 132 break; 133 } 134 case AttributeDataForm::SecOffset: { 135 auto data = TRY(debug_info_stream.read_value<u32>()); 136 value.m_type = AttributeValue::Type::SecOffset; 137 value.m_data.as_unsigned = data; 138 break; 139 } 140 case AttributeDataForm::Data4: { 141 auto data = TRY(debug_info_stream.read_value<u32>()); 142 value.m_type = AttributeValue::Type::UnsignedNumber; 143 value.m_data.as_unsigned = data; 144 break; 145 } 146 case AttributeDataForm::Data8: { 147 auto data = TRY(debug_info_stream.read_value<u64>()); 148 value.m_type = AttributeValue::Type::UnsignedNumber; 149 value.m_data.as_unsigned = data; 150 break; 151 } 152 case AttributeDataForm::Data16: { 153 value.m_type = AttributeValue::Type::RawBytes; 154 TRY(assign_raw_bytes_value(16)); 155 break; 156 } 157 case AttributeDataForm::Ref4: { 158 auto data = TRY(debug_info_stream.read_value<u32>()); 159 value.m_type = AttributeValue::Type::DieReference; 160 VERIFY(unit); 161 value.m_data.as_unsigned = data + unit->offset(); 162 break; 163 } 164 case AttributeDataForm::FlagPresent: { 165 value.m_type = AttributeValue::Type::Boolean; 166 value.m_data.as_bool = true; 167 break; 168 } 169 case AttributeDataForm::ExprLoc: { 170 size_t length = TRY(debug_info_stream.read_value<LEB128<size_t>>()); 171 value.m_type = AttributeValue::Type::DwarfExpression; 172 TRY(assign_raw_bytes_value(length)); 173 break; 174 } 175 case AttributeDataForm::String: { 176 u32 str_offset = TRY(debug_info_stream.tell()); 177 value.m_type = AttributeValue::Type::String; 178 value.m_data.as_string = bit_cast<char const*>(debug_info_data().offset_pointer(str_offset)); 179 TRY(debug_info_stream.discard(strlen(value.m_data.as_string) + 1)); 180 break; 181 } 182 case AttributeDataForm::Block1: { 183 value.m_type = AttributeValue::Type::RawBytes; 184 auto length = TRY(debug_info_stream.read_value<u8>()); 185 TRY(assign_raw_bytes_value(length)); 186 break; 187 } 188 case AttributeDataForm::Block2: { 189 value.m_type = AttributeValue::Type::RawBytes; 190 auto length = TRY(debug_info_stream.read_value<u16>()); 191 TRY(assign_raw_bytes_value(length)); 192 break; 193 } 194 case AttributeDataForm::Block4: { 195 value.m_type = AttributeValue::Type::RawBytes; 196 auto length = TRY(debug_info_stream.read_value<u32>()); 197 TRY(assign_raw_bytes_value(length)); 198 break; 199 } 200 case AttributeDataForm::Block: { 201 value.m_type = AttributeValue::Type::RawBytes; 202 size_t length = TRY(debug_info_stream.read_value<LEB128<size_t>>()); 203 TRY(assign_raw_bytes_value(length)); 204 break; 205 } 206 case AttributeDataForm::LineStrP: { 207 auto offset = TRY(debug_info_stream.read_value<u32>()); 208 value.m_type = AttributeValue::Type::String; 209 210 auto strings_data = debug_line_strings_data(); 211 value.m_data.as_string = bit_cast<char const*>(strings_data.offset_pointer(offset)); 212 break; 213 } 214 case AttributeDataForm::ImplicitConst: { 215 /* Value is part of the abbreviation record. */ 216 value.m_type = AttributeValue::Type::SignedNumber; 217 value.m_data.as_signed = implicit_const_value; 218 break; 219 } 220 case AttributeDataForm::StrX1: { 221 auto index = TRY(debug_info_stream.read_value<u8>()); 222 value.m_type = AttributeValue::Type::String; 223 value.m_data.as_unsigned = index; 224 break; 225 } 226 case AttributeDataForm::StrX2: { 227 auto index = TRY(debug_info_stream.read_value<u16>()); 228 value.m_type = AttributeValue::Type::String; 229 value.m_data.as_unsigned = index; 230 break; 231 } 232 case AttributeDataForm::StrX4: { 233 auto index = TRY(debug_info_stream.read_value<u32>()); 234 value.m_type = AttributeValue::Type::String; 235 value.m_data.as_unsigned = index; 236 break; 237 } 238 case AttributeDataForm::StrX: { 239 size_t index = TRY(debug_info_stream.read_value<LEB128<size_t>>()); 240 value.m_type = AttributeValue::Type::String; 241 value.m_data.as_unsigned = index; 242 break; 243 } 244 case AttributeDataForm::AddrX1: { 245 auto index = TRY(debug_info_stream.read_value<u8>()); 246 value.m_type = AttributeValue::Type::Address; 247 value.m_data.as_unsigned = index; 248 break; 249 } 250 case AttributeDataForm::AddrX2: { 251 auto index = TRY(debug_info_stream.read_value<u16>()); 252 value.m_type = AttributeValue::Type::Address; 253 value.m_data.as_unsigned = index; 254 break; 255 } 256 case AttributeDataForm::AddrX4: { 257 auto index = TRY(debug_info_stream.read_value<u32>()); 258 value.m_type = AttributeValue::Type::Address; 259 value.m_data.as_unsigned = index; 260 break; 261 } 262 case AttributeDataForm::AddrX: { 263 size_t index = TRY(debug_info_stream.read_value<LEB128<size_t>>()); 264 value.m_type = AttributeValue::Type::Address; 265 value.m_data.as_unsigned = index; 266 break; 267 } 268 case AttributeDataForm::RngListX: { 269 size_t index = TRY(debug_info_stream.read_value<LEB128<size_t>>()); 270 value.m_type = AttributeValue::Type::UnsignedNumber; 271 value.m_data.as_unsigned = index; 272 break; 273 } 274 default: 275 dbgln("Unimplemented AttributeDataForm: {}", to_underlying(form)); 276 VERIFY_NOT_REACHED(); 277 } 278 return value; 279} 280 281ErrorOr<void> DwarfInfo::build_cached_dies() const 282{ 283 auto insert_to_cache = [this](DIE const& die, DIERange const& range) { 284 m_cached_dies_by_range.insert(range.start_address, DIEAndRange { die, range }); 285 m_cached_dies_by_offset.insert(die.offset(), die); 286 }; 287 auto get_ranges_of_die = [this](DIE const& die) -> ErrorOr<Vector<DIERange>> { 288 auto ranges = TRY(die.get_attribute(Attribute::Ranges)); 289 if (ranges.has_value()) { 290 size_t offset; 291 if (ranges->form() == AttributeDataForm::SecOffset) { 292 offset = ranges->as_unsigned(); 293 } else { 294 auto index = ranges->as_unsigned(); 295 auto base = TRY(die.compilation_unit().range_lists_base()); 296 // FIXME: This assumes that the format is DWARf32 297 auto offsets = debug_range_lists_data().slice(base); 298 offset = ByteReader::load32(offsets.offset_pointer(index * sizeof(u32))) + base; 299 } 300 301 Vector<DIERange> entries; 302 if (die.compilation_unit().dwarf_version() == 5) { 303 auto range_lists_stream = TRY(try_make<FixedMemoryStream>(debug_range_lists_data())); 304 TRY(range_lists_stream->seek(offset)); 305 AddressRangesV5 address_ranges(move(range_lists_stream), die.compilation_unit()); 306 TRY(address_ranges.for_each_range([&entries](auto range) { 307 entries.empend(range.start, range.end); 308 })); 309 } else { 310 auto ranges_stream = TRY(try_make<FixedMemoryStream>(debug_ranges_data())); 311 TRY(ranges_stream->seek(offset)); 312 AddressRangesV4 address_ranges(move(ranges_stream), die.compilation_unit()); 313 TRY(address_ranges.for_each_range([&entries](auto range) { 314 entries.empend(range.start, range.end); 315 })); 316 } 317 return entries; 318 } 319 320 auto start = TRY(die.get_attribute(Attribute::LowPc)); 321 auto end = TRY(die.get_attribute(Attribute::HighPc)); 322 323 if (!start.has_value() || !end.has_value()) 324 return Vector<DIERange> {}; 325 326 VERIFY(start->type() == Dwarf::AttributeValue::Type::Address); 327 328 // DW_AT_high_pc attribute can have different meanings depending on the attribute form. 329 // (Dwarf version 5, section 2.17.2). 330 331 uint32_t range_end = 0; 332 if (end->form() == Dwarf::AttributeDataForm::Addr) 333 range_end = TRY(end->as_addr()); 334 else 335 range_end = TRY(start->as_addr()) + end->as_unsigned(); 336 337 return Vector<DIERange> { DIERange { TRY(start.value().as_addr()), range_end } }; 338 }; 339 340 // If we simply use a lambda, type deduction fails because it's used recursively. 341 Function<ErrorOr<void>(DIE const& die)> insert_to_cache_recursively; 342 insert_to_cache_recursively = [&](DIE const& die) -> ErrorOr<void> { 343 if (die.offset() == 0 || die.parent_offset().has_value()) { 344 auto ranges = TRY(get_ranges_of_die(die)); 345 for (auto& range : ranges) { 346 insert_to_cache(die, range); 347 } 348 } 349 TRY(die.for_each_child([&](DIE const& child) -> ErrorOr<void> { 350 if (!child.is_null()) { 351 TRY(insert_to_cache_recursively(child)); 352 } 353 return {}; 354 })); 355 return {}; 356 }; 357 358 TRY(for_each_compilation_unit([&](CompilationUnit const& compilation_unit) -> ErrorOr<void> { 359 TRY(insert_to_cache_recursively(compilation_unit.root_die())); 360 return {}; 361 })); 362 363 m_built_cached_dies = true; 364 return {}; 365} 366 367ErrorOr<Optional<DIE>> DwarfInfo::get_die_at_address(FlatPtr address) const 368{ 369 if (!m_built_cached_dies) 370 TRY(build_cached_dies()); 371 372 auto iter = m_cached_dies_by_range.find_largest_not_above_iterator(address); 373 while (!iter.is_end() && !iter.is_begin() && iter->range.end_address < address) { 374 --iter; 375 } 376 377 if (iter.is_end()) 378 return Optional<DIE> {}; 379 380 if (iter->range.start_address > address || iter->range.end_address < address) { 381 return Optional<DIE> {}; 382 } 383 384 return iter->die; 385} 386 387ErrorOr<Optional<DIE>> DwarfInfo::get_cached_die_at_offset(FlatPtr offset) const 388{ 389 if (!m_built_cached_dies) 390 TRY(build_cached_dies()); 391 392 auto* die = m_cached_dies_by_offset.find(offset); 393 if (!die) 394 return Optional<DIE> {}; 395 return *die; 396} 397 398}