1 //===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "DWARFUnit.h" 11 12 #include "lldb/Core/Module.h" 13 #include "lldb/Host/StringConvert.h" 14 #include "lldb/Symbol/CompileUnit.h" 15 #include "lldb/Symbol/LineTable.h" 16 #include "lldb/Symbol/ObjectFile.h" 17 #include "lldb/Utility/LLDBAssert.h" 18 #include "lldb/Utility/StreamString.h" 19 #include "lldb/Utility/Timer.h" 20 21 #include "DWARFDIECollection.h" 22 #include "DWARFDebugAranges.h" 23 #include "DWARFDebugInfo.h" 24 #include "LogChannelDWARF.h" 25 #include "SymbolFileDWARFDebugMap.h" 26 #include "SymbolFileDWARFDwo.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 using namespace std; 31 32 extern int g_verbose; 33 34 DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) : m_dwarf(dwarf) {} 35 36 DWARFUnit::~DWARFUnit() {} 37 38 //---------------------------------------------------------------------- 39 // Parses first DIE of a compile unit. 40 //---------------------------------------------------------------------- 41 void DWARFUnit::ExtractUnitDIEIfNeeded() { 42 if (m_first_die) 43 return; // Already parsed 44 45 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 46 Timer scoped_timer( 47 func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset); 48 49 // Set the offset to that of the first DIE and calculate the start of the 50 // next compilation unit header. 51 lldb::offset_t offset = GetFirstDIEOffset(); 52 53 // We are in our compile unit, parse starting at the offset we were told to 54 // parse 55 const DWARFDataExtractor &data = GetData(); 56 DWARFFormValue::FixedFormSizes fixed_form_sizes = 57 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 58 IsDWARF64()); 59 if (offset < GetNextCompileUnitOffset() && 60 m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) { 61 AddUnitDIE(m_first_die); 62 return; 63 } 64 65 ExtractDIEsEndCheck(offset); 66 } 67 68 //---------------------------------------------------------------------- 69 // Parses a compile unit and indexes its DIEs if it hasn't already been done. 70 //---------------------------------------------------------------------- 71 bool DWARFUnit::ExtractDIEsIfNeeded() { 72 if (!m_die_array.empty()) 73 return 0; // Already parsed 74 75 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 76 Timer scoped_timer( 77 func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset); 78 79 // Set the offset to that of the first DIE and calculate the start of the 80 // next compilation unit header. 81 lldb::offset_t offset = GetFirstDIEOffset(); 82 lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); 83 84 DWARFDebugInfoEntry die; 85 // Keep a flat array of the DIE for binary lookup by DIE offset 86 Log *log( 87 LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); 88 if (log) { 89 m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( 90 log, 91 "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " 92 ".debug_info[0x%8.8x]", 93 GetOffset()); 94 } 95 96 uint32_t depth = 0; 97 // We are in our compile unit, parse starting at the offset we were told to 98 // parse 99 const DWARFDataExtractor &data = GetData(); 100 std::vector<uint32_t> die_index_stack; 101 die_index_stack.reserve(32); 102 die_index_stack.push_back(0); 103 bool prev_die_had_children = false; 104 DWARFFormValue::FixedFormSizes fixed_form_sizes = 105 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 106 IsDWARF64()); 107 while (offset < next_cu_offset && 108 die.FastExtract(data, this, fixed_form_sizes, &offset)) { 109 // if (log) 110 // log->Printf("0x%8.8x: %*.*s%s%s", 111 // die.GetOffset(), 112 // depth * 2, depth * 2, "", 113 // DW_TAG_value_to_name (die.Tag()), 114 // die.HasChildren() ? " *" : ""); 115 116 const bool null_die = die.IsNULL(); 117 if (depth == 0) { 118 assert(m_die_array.empty() && "Compile unit DIE already added"); 119 120 // The average bytes per DIE entry has been seen to be around 14-20 so 121 // lets pre-reserve half of that since we are now stripping the NULL 122 // tags. 123 124 // Only reserve the memory if we are adding children of the main 125 // compile unit DIE. The compile unit DIE is always the first entry, so 126 // if our size is 1, then we are adding the first compile unit child 127 // DIE and should reserve the memory. 128 m_die_array.reserve(GetDebugInfoSize() / 24); 129 m_die_array.push_back(die); 130 131 if (!m_first_die) 132 AddUnitDIE(m_die_array.front()); 133 } else { 134 if (null_die) { 135 if (prev_die_had_children) { 136 // This will only happen if a DIE says is has children but all it 137 // contains is a NULL tag. Since we are removing the NULL DIEs from 138 // the list (saves up to 25% in C++ code), we need a way to let the 139 // DIE know that it actually doesn't have children. 140 if (!m_die_array.empty()) 141 m_die_array.back().SetEmptyChildren(true); 142 } 143 } else { 144 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 145 146 if (die_index_stack.back()) 147 m_die_array[die_index_stack.back()].SetSiblingIndex( 148 m_die_array.size() - die_index_stack.back()); 149 150 // Only push the DIE if it isn't a NULL DIE 151 m_die_array.push_back(die); 152 } 153 } 154 155 if (null_die) { 156 // NULL DIE. 157 if (!die_index_stack.empty()) 158 die_index_stack.pop_back(); 159 160 if (depth > 0) 161 --depth; 162 if (depth == 0) 163 break; // We are done with this compile unit! 164 165 prev_die_had_children = false; 166 } else { 167 die_index_stack.back() = m_die_array.size() - 1; 168 // Normal DIE 169 const bool die_has_children = die.HasChildren(); 170 if (die_has_children) { 171 die_index_stack.push_back(0); 172 ++depth; 173 } 174 prev_die_had_children = die_has_children; 175 } 176 } 177 178 if (!m_die_array.empty()) { 179 lldbassert(!m_first_die || m_first_die == m_die_array.front()); 180 m_first_die = m_die_array.front(); 181 } 182 183 // Since std::vector objects will double their size, we really need to make a 184 // new array with the perfect size so we don't end up wasting space. So here 185 // we copy and swap to make sure we don't have any extra memory taken up. 186 187 if (m_die_array.size() < m_die_array.capacity()) { 188 DWARFDebugInfoEntry::collection exact_size_die_array(m_die_array.begin(), 189 m_die_array.end()); 190 exact_size_die_array.swap(m_die_array); 191 } 192 193 ExtractDIEsEndCheck(offset); 194 195 if (m_dwo_symbol_file) { 196 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 197 dwo_cu->ExtractDIEsIfNeeded(); 198 } 199 200 return true; 201 } 202 203 //-------------------------------------------------------------------------- 204 // Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). 205 //-------------------------------------------------------------------------- 206 void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { 207 // Give a little bit of info if we encounter corrupt DWARF (our offset should 208 // always terminate at or before the start of the next compilation unit 209 // header). 210 if (offset > GetNextCompileUnitOffset()) { 211 m_dwarf->GetObjectFile()->GetModule()->ReportWarning( 212 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 213 "0x%8.8" PRIx64 "\n", 214 GetOffset(), offset); 215 } 216 217 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 218 if (log && log->GetVerbose()) { 219 StreamString strm; 220 Dump(&strm); 221 if (m_die_array.empty()) 222 strm.Printf("error: no DIE for compile unit"); 223 else 224 m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); 225 log->PutString(strm.GetString()); 226 } 227 } 228 229 void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 230 uint64_t base_addr = cu_die.GetAttributeValueAsAddress( 231 m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 232 if (base_addr == LLDB_INVALID_ADDRESS) 233 base_addr = cu_die.GetAttributeValueAsAddress( 234 m_dwarf, this, DW_AT_entry_pc, 0); 235 SetBaseAddress(base_addr); 236 237 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 238 m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); 239 if (!dwo_symbol_file) 240 return; 241 242 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 243 if (!dwo_cu) 244 return; // Can't fetch the compile unit from the dwo file. 245 246 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 247 if (!dwo_cu_die.IsValid()) 248 return; // Can't fetch the compile unit DIE from the dwo file. 249 250 uint64_t main_dwo_id = 251 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); 252 uint64_t sub_dwo_id = 253 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 254 if (main_dwo_id != sub_dwo_id) 255 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 256 // a differectn compilation. 257 258 m_dwo_symbol_file = std::move(dwo_symbol_file); 259 260 dw_addr_t addr_base = 261 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0); 262 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 263 m_dwarf, this, DW_AT_GNU_ranges_base, 0); 264 dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset); 265 } 266 267 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 268 if (DIE()) { 269 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 270 271 // Re-check the aranges auto pointer contents in case it was created above 272 if (!func_aranges.IsEmpty()) 273 return GetDIE(func_aranges.FindAddress(address)); 274 } 275 return DWARFDIE(); 276 } 277 278 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 279 DWARFDIECollection &dies, 280 uint32_t depth) const { 281 size_t old_size = dies.Size(); 282 DWARFDebugInfoEntry::const_iterator pos; 283 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 284 for (pos = m_die_array.begin(); pos != end; ++pos) { 285 if (pos->Tag() == tag) 286 dies.Append(DWARFDIE(this, &(*pos))); 287 } 288 289 // Return the number of DIEs added to the collection 290 return dies.Size() - old_size; 291 } 292 293 294 lldb::user_id_t DWARFUnit::GetID() const { 295 dw_offset_t local_id = 296 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 297 if (m_dwarf) 298 return DIERef(local_id, local_id).GetUID(m_dwarf); 299 else 300 return local_id; 301 } 302 303 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 304 return m_offset + GetLengthByteSize() + GetLength(); 305 } 306 307 size_t DWARFUnit::GetDebugInfoSize() const { 308 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 309 } 310 311 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 312 return m_abbrevs; 313 } 314 315 dw_offset_t DWARFUnit::GetAbbrevOffset() const { 316 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 317 } 318 319 void DWARFUnit::SetAddrBase(dw_addr_t addr_base, 320 dw_addr_t ranges_base, 321 dw_offset_t base_obj_offset) { 322 m_addr_base = addr_base; 323 m_ranges_base = ranges_base; 324 m_base_obj_offset = base_obj_offset; 325 } 326 327 void DWARFUnit::ClearDIEs() { 328 m_die_array.clear(); 329 m_die_array.shrink_to_fit(); 330 331 if (m_dwo_symbol_file) 332 m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(); 333 } 334 335 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, 336 DWARFDebugAranges *debug_aranges) { 337 // This function is usually called if there in no .debug_aranges section in 338 // order to produce a compile unit level set of address ranges that is 339 // accurate. 340 341 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 342 343 // First get the compile unit DIE only and check if it has a DW_AT_ranges 344 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 345 346 const dw_offset_t cu_offset = GetOffset(); 347 if (die) { 348 DWARFRangeList ranges; 349 const size_t num_ranges = 350 die->GetAttributeAddressRanges(dwarf, this, ranges, false); 351 if (num_ranges > 0) { 352 // This compile unit has DW_AT_ranges, assume this is correct if it is 353 // present since clang no longer makes .debug_aranges by default and it 354 // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with 355 // recent GCC builds. 356 for (size_t i = 0; i < num_ranges; ++i) { 357 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 358 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 359 range.GetRangeEnd()); 360 } 361 362 return; // We got all of our ranges from the DW_AT_ranges attribute 363 } 364 } 365 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 366 367 // If the DIEs weren't parsed, then we don't want all dies for all compile 368 // units to stay loaded when they weren't needed. So we can end up parsing 369 // the DWARF and then throwing them all away to keep memory usage down. 370 const bool clear_dies = ExtractDIEsIfNeeded(); 371 372 die = DIEPtr(); 373 if (die) 374 die->BuildAddressRangeTable(dwarf, this, debug_aranges); 375 376 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 377 // We got nothing from the functions, maybe we have a line tables only 378 // situation. Check the line tables and build the arange table from this. 379 SymbolContext sc; 380 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 381 if (sc.comp_unit) { 382 SymbolFileDWARFDebugMap *debug_map_sym_file = 383 m_dwarf->GetDebugMapSymfile(); 384 if (debug_map_sym_file == NULL) { 385 LineTable *line_table = sc.comp_unit->GetLineTable(); 386 387 if (line_table) { 388 LineTable::FileAddressRanges file_ranges; 389 const bool append = true; 390 const size_t num_ranges = 391 line_table->GetContiguousFileAddressRanges(file_ranges, append); 392 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 393 const LineTable::FileAddressRanges::Entry &range = 394 file_ranges.GetEntryRef(idx); 395 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 396 range.GetRangeEnd()); 397 } 398 } 399 } else 400 debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); 401 } 402 } 403 404 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 405 // We got nothing from the functions, maybe we have a line tables only 406 // situation. Check the line tables and build the arange table from this. 407 SymbolContext sc; 408 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 409 if (sc.comp_unit) { 410 LineTable *line_table = sc.comp_unit->GetLineTable(); 411 412 if (line_table) { 413 LineTable::FileAddressRanges file_ranges; 414 const bool append = true; 415 const size_t num_ranges = 416 line_table->GetContiguousFileAddressRanges(file_ranges, append); 417 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 418 const LineTable::FileAddressRanges::Entry &range = 419 file_ranges.GetEntryRef(idx); 420 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 421 range.GetRangeEnd()); 422 } 423 } 424 } 425 } 426 427 // Keep memory down by clearing DIEs if this generate function caused them to 428 // be parsed 429 if (clear_dies) 430 ClearDIEs(); 431 } 432 433 lldb::ByteOrder DWARFUnit::GetByteOrder() const { 434 return m_dwarf->GetObjectFile()->GetByteOrder(); 435 } 436 437 TypeSystem *DWARFUnit::GetTypeSystem() { 438 if (m_dwarf) 439 return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); 440 else 441 return nullptr; 442 } 443 444 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 445 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 446 IsDWARF64()); 447 } 448 449 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 450 451 //---------------------------------------------------------------------- 452 // Compare function DWARFDebugAranges::Range structures 453 //---------------------------------------------------------------------- 454 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 455 const dw_offset_t die_offset) { 456 return die.GetOffset() < die_offset; 457 } 458 459 //---------------------------------------------------------------------- 460 // GetDIE() 461 // 462 // Get the DIE (Debug Information Entry) with the specified offset by first 463 // checking if the DIE is contained within this compile unit and grabbing the 464 // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 465 //---------------------------------------------------------------------- 466 DWARFDIE 467 DWARFUnit::GetDIE(dw_offset_t die_offset) { 468 if (die_offset != DW_INVALID_OFFSET) { 469 if (GetDwoSymbolFile()) 470 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 471 472 if (ContainsDIEOffset(die_offset)) { 473 ExtractDIEsIfNeeded(); 474 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 475 DWARFDebugInfoEntry::const_iterator pos = 476 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 477 if (pos != end) { 478 if (die_offset == (*pos).GetOffset()) 479 return DWARFDIE(this, &(*pos)); 480 } 481 } else { 482 // Don't specify the compile unit offset as we don't know it because the 483 // DIE belongs to 484 // a different compile unit in the same symbol file. 485 return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); 486 } 487 } 488 return DWARFDIE(); // Not found 489 } 490 491 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 492 if (cu) 493 return cu->GetAddressByteSize(); 494 return DWARFUnit::GetDefaultAddressSize(); 495 } 496 497 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 498 if (cu) 499 return cu->IsDWARF64(); 500 return false; 501 } 502 503 uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 504 505 void *DWARFUnit::GetUserData() const { return m_user_data; } 506 507 void DWARFUnit::SetUserData(void *d) { 508 m_user_data = d; 509 if (m_dwo_symbol_file) 510 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 511 } 512 513 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 514 if (GetProducer() == eProducerLLVMGCC) 515 return false; 516 return true; 517 } 518 519 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 520 // llvm-gcc makes completely invalid decl file attributes and won't ever be 521 // fixed, so we need to know to ignore these. 522 return GetProducer() == eProducerLLVMGCC; 523 } 524 525 bool DWARFUnit::Supports_unnamed_objc_bitfields() { 526 if (GetProducer() == eProducerClang) { 527 const uint32_t major_version = GetProducerVersionMajor(); 528 if (major_version > 425 || 529 (major_version == 425 && GetProducerVersionUpdate() >= 13)) 530 return true; 531 else 532 return false; 533 } 534 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 535 // info 536 } 537 538 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } 539 540 void DWARFUnit::ParseProducerInfo() { 541 m_producer_version_major = UINT32_MAX; 542 m_producer_version_minor = UINT32_MAX; 543 m_producer_version_update = UINT32_MAX; 544 545 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 546 if (die) { 547 548 const char *producer_cstr = 549 die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); 550 if (producer_cstr) { 551 RegularExpression llvm_gcc_regex( 552 llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " 553 "Inc\\. build [0-9]+\\) \\(LLVM build " 554 "[\\.0-9]+\\)$")); 555 if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { 556 m_producer = eProducerLLVMGCC; 557 } else if (strstr(producer_cstr, "clang")) { 558 static RegularExpression g_clang_version_regex( 559 llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); 560 RegularExpression::Match regex_match(3); 561 if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), 562 ®ex_match)) { 563 std::string str; 564 if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) 565 m_producer_version_major = 566 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 567 if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) 568 m_producer_version_minor = 569 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 570 if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) 571 m_producer_version_update = 572 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 573 } 574 m_producer = eProducerClang; 575 } else if (strstr(producer_cstr, "GNU")) 576 m_producer = eProducerGCC; 577 } 578 } 579 if (m_producer == eProducerInvalid) 580 m_producer = eProcucerOther; 581 } 582 583 DWARFProducer DWARFUnit::GetProducer() { 584 if (m_producer == eProducerInvalid) 585 ParseProducerInfo(); 586 return m_producer; 587 } 588 589 uint32_t DWARFUnit::GetProducerVersionMajor() { 590 if (m_producer_version_major == 0) 591 ParseProducerInfo(); 592 return m_producer_version_major; 593 } 594 595 uint32_t DWARFUnit::GetProducerVersionMinor() { 596 if (m_producer_version_minor == 0) 597 ParseProducerInfo(); 598 return m_producer_version_minor; 599 } 600 601 uint32_t DWARFUnit::GetProducerVersionUpdate() { 602 if (m_producer_version_update == 0) 603 ParseProducerInfo(); 604 return m_producer_version_update; 605 } 606 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 607 // Note: user languages between lo_user and hi_user must be handled 608 // explicitly here. 609 switch (val) { 610 case DW_LANG_Mips_Assembler: 611 return eLanguageTypeMipsAssembler; 612 case DW_LANG_GOOGLE_RenderScript: 613 return eLanguageTypeExtRenderScript; 614 default: 615 return static_cast<LanguageType>(val); 616 } 617 } 618 619 LanguageType DWARFUnit::GetLanguageType() { 620 if (m_language_type != eLanguageTypeUnknown) 621 return m_language_type; 622 623 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 624 if (die) 625 m_language_type = LanguageTypeFromDWARF( 626 die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); 627 return m_language_type; 628 } 629 630 bool DWARFUnit::GetIsOptimized() { 631 if (m_is_optimized == eLazyBoolCalculate) { 632 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 633 if (die) { 634 m_is_optimized = eLazyBoolNo; 635 if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, 636 0) == 1) { 637 m_is_optimized = eLazyBoolYes; 638 } 639 } 640 } 641 return m_is_optimized == eLazyBoolYes; 642 } 643 644 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 645 return m_dwo_symbol_file.get(); 646 } 647 648 dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } 649 650 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 651 if (m_func_aranges_ap.get() == NULL) { 652 m_func_aranges_ap.reset(new DWARFDebugAranges()); 653 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 654 655 if (log) { 656 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 657 log, 658 "DWARFUnit::GetFunctionAranges() for compile unit at " 659 ".debug_info[0x%8.8x]", 660 GetOffset()); 661 } 662 const DWARFDebugInfoEntry *die = DIEPtr(); 663 if (die) 664 die->BuildFunctionAddressRangeTable(m_dwarf, this, 665 m_func_aranges_ap.get()); 666 667 if (m_dwo_symbol_file) { 668 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 669 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 670 if (dwo_die) 671 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 672 m_func_aranges_ap.get()); 673 } 674 675 const bool minimize = false; 676 m_func_aranges_ap->Sort(minimize); 677 } 678 return *m_func_aranges_ap.get(); 679 } 680 681