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 m_die_array.shrink_to_fit(); 184 185 ExtractDIEsEndCheck(offset); 186 187 if (m_dwo_symbol_file) { 188 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 189 dwo_cu->ExtractDIEsIfNeeded(); 190 } 191 192 return true; 193 } 194 195 //-------------------------------------------------------------------------- 196 // Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). 197 //-------------------------------------------------------------------------- 198 void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { 199 // Give a little bit of info if we encounter corrupt DWARF (our offset should 200 // always terminate at or before the start of the next compilation unit 201 // header). 202 if (offset > GetNextCompileUnitOffset()) { 203 m_dwarf->GetObjectFile()->GetModule()->ReportWarning( 204 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 205 "0x%8.8" PRIx64 "\n", 206 GetOffset(), offset); 207 } 208 209 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 210 if (log && log->GetVerbose()) { 211 StreamString strm; 212 Dump(&strm); 213 if (m_die_array.empty()) 214 strm.Printf("error: no DIE for compile unit"); 215 else 216 m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); 217 log->PutString(strm.GetString()); 218 } 219 } 220 221 void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 222 uint64_t base_addr = cu_die.GetAttributeValueAsAddress( 223 m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 224 if (base_addr == LLDB_INVALID_ADDRESS) 225 base_addr = cu_die.GetAttributeValueAsAddress( 226 m_dwarf, this, DW_AT_entry_pc, 0); 227 SetBaseAddress(base_addr); 228 229 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 230 m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); 231 if (!dwo_symbol_file) 232 return; 233 234 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 235 if (!dwo_cu) 236 return; // Can't fetch the compile unit from the dwo file. 237 238 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 239 if (!dwo_cu_die.IsValid()) 240 return; // Can't fetch the compile unit DIE from the dwo file. 241 242 uint64_t main_dwo_id = 243 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); 244 uint64_t sub_dwo_id = 245 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 246 if (main_dwo_id != sub_dwo_id) 247 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 248 // a differectn compilation. 249 250 m_dwo_symbol_file = std::move(dwo_symbol_file); 251 252 dw_addr_t addr_base = 253 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0); 254 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 255 m_dwarf, this, DW_AT_GNU_ranges_base, 0); 256 dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset); 257 } 258 259 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 260 if (DIE()) { 261 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 262 263 // Re-check the aranges auto pointer contents in case it was created above 264 if (!func_aranges.IsEmpty()) 265 return GetDIE(func_aranges.FindAddress(address)); 266 } 267 return DWARFDIE(); 268 } 269 270 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 271 DWARFDIECollection &dies, 272 uint32_t depth) const { 273 size_t old_size = dies.Size(); 274 DWARFDebugInfoEntry::const_iterator pos; 275 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 276 for (pos = m_die_array.begin(); pos != end; ++pos) { 277 if (pos->Tag() == tag) 278 dies.Append(DWARFDIE(this, &(*pos))); 279 } 280 281 // Return the number of DIEs added to the collection 282 return dies.Size() - old_size; 283 } 284 285 286 lldb::user_id_t DWARFUnit::GetID() const { 287 dw_offset_t local_id = 288 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 289 if (m_dwarf) 290 return DIERef(local_id, local_id).GetUID(m_dwarf); 291 else 292 return local_id; 293 } 294 295 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 296 return m_offset + GetLengthByteSize() + GetLength(); 297 } 298 299 size_t DWARFUnit::GetDebugInfoSize() const { 300 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 301 } 302 303 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 304 return m_abbrevs; 305 } 306 307 dw_offset_t DWARFUnit::GetAbbrevOffset() const { 308 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 309 } 310 311 void DWARFUnit::SetAddrBase(dw_addr_t addr_base, 312 dw_addr_t ranges_base, 313 dw_offset_t base_obj_offset) { 314 m_addr_base = addr_base; 315 m_ranges_base = ranges_base; 316 m_base_obj_offset = base_obj_offset; 317 } 318 319 void DWARFUnit::ClearDIEs() { 320 m_die_array.clear(); 321 m_die_array.shrink_to_fit(); 322 323 if (m_dwo_symbol_file) 324 m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(); 325 } 326 327 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, 328 DWARFDebugAranges *debug_aranges) { 329 // This function is usually called if there in no .debug_aranges section in 330 // order to produce a compile unit level set of address ranges that is 331 // accurate. 332 333 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 334 335 // First get the compile unit DIE only and check if it has a DW_AT_ranges 336 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 337 338 const dw_offset_t cu_offset = GetOffset(); 339 if (die) { 340 DWARFRangeList ranges; 341 const size_t num_ranges = 342 die->GetAttributeAddressRanges(dwarf, this, ranges, false); 343 if (num_ranges > 0) { 344 // This compile unit has DW_AT_ranges, assume this is correct if it is 345 // present since clang no longer makes .debug_aranges by default and it 346 // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with 347 // recent GCC builds. 348 for (size_t i = 0; i < num_ranges; ++i) { 349 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 350 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 351 range.GetRangeEnd()); 352 } 353 354 return; // We got all of our ranges from the DW_AT_ranges attribute 355 } 356 } 357 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 358 359 // If the DIEs weren't parsed, then we don't want all dies for all compile 360 // units to stay loaded when they weren't needed. So we can end up parsing 361 // the DWARF and then throwing them all away to keep memory usage down. 362 const bool clear_dies = ExtractDIEsIfNeeded(); 363 364 die = DIEPtr(); 365 if (die) 366 die->BuildAddressRangeTable(dwarf, this, debug_aranges); 367 368 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 369 // We got nothing from the functions, maybe we have a line tables only 370 // situation. Check the line tables and build the arange table from this. 371 SymbolContext sc; 372 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 373 if (sc.comp_unit) { 374 SymbolFileDWARFDebugMap *debug_map_sym_file = 375 m_dwarf->GetDebugMapSymfile(); 376 if (debug_map_sym_file == NULL) { 377 LineTable *line_table = sc.comp_unit->GetLineTable(); 378 379 if (line_table) { 380 LineTable::FileAddressRanges file_ranges; 381 const bool append = true; 382 const size_t num_ranges = 383 line_table->GetContiguousFileAddressRanges(file_ranges, append); 384 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 385 const LineTable::FileAddressRanges::Entry &range = 386 file_ranges.GetEntryRef(idx); 387 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 388 range.GetRangeEnd()); 389 } 390 } 391 } else 392 debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); 393 } 394 } 395 396 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 397 // We got nothing from the functions, maybe we have a line tables only 398 // situation. Check the line tables and build the arange table from this. 399 SymbolContext sc; 400 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 401 if (sc.comp_unit) { 402 LineTable *line_table = sc.comp_unit->GetLineTable(); 403 404 if (line_table) { 405 LineTable::FileAddressRanges file_ranges; 406 const bool append = true; 407 const size_t num_ranges = 408 line_table->GetContiguousFileAddressRanges(file_ranges, append); 409 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 410 const LineTable::FileAddressRanges::Entry &range = 411 file_ranges.GetEntryRef(idx); 412 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 413 range.GetRangeEnd()); 414 } 415 } 416 } 417 } 418 419 // Keep memory down by clearing DIEs if this generate function caused them to 420 // be parsed 421 if (clear_dies) 422 ClearDIEs(); 423 } 424 425 lldb::ByteOrder DWARFUnit::GetByteOrder() const { 426 return m_dwarf->GetObjectFile()->GetByteOrder(); 427 } 428 429 TypeSystem *DWARFUnit::GetTypeSystem() { 430 if (m_dwarf) 431 return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); 432 else 433 return nullptr; 434 } 435 436 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 437 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 438 IsDWARF64()); 439 } 440 441 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 442 443 //---------------------------------------------------------------------- 444 // Compare function DWARFDebugAranges::Range structures 445 //---------------------------------------------------------------------- 446 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 447 const dw_offset_t die_offset) { 448 return die.GetOffset() < die_offset; 449 } 450 451 //---------------------------------------------------------------------- 452 // GetDIE() 453 // 454 // Get the DIE (Debug Information Entry) with the specified offset by first 455 // checking if the DIE is contained within this compile unit and grabbing the 456 // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 457 //---------------------------------------------------------------------- 458 DWARFDIE 459 DWARFUnit::GetDIE(dw_offset_t die_offset) { 460 if (die_offset != DW_INVALID_OFFSET) { 461 if (GetDwoSymbolFile()) 462 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 463 464 if (ContainsDIEOffset(die_offset)) { 465 ExtractDIEsIfNeeded(); 466 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 467 DWARFDebugInfoEntry::const_iterator pos = 468 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 469 if (pos != end) { 470 if (die_offset == (*pos).GetOffset()) 471 return DWARFDIE(this, &(*pos)); 472 } 473 } else { 474 // Don't specify the compile unit offset as we don't know it because the 475 // DIE belongs to 476 // a different compile unit in the same symbol file. 477 return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); 478 } 479 } 480 return DWARFDIE(); // Not found 481 } 482 483 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 484 if (cu) 485 return cu->GetAddressByteSize(); 486 return DWARFUnit::GetDefaultAddressSize(); 487 } 488 489 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 490 if (cu) 491 return cu->IsDWARF64(); 492 return false; 493 } 494 495 uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 496 497 void *DWARFUnit::GetUserData() const { return m_user_data; } 498 499 void DWARFUnit::SetUserData(void *d) { 500 m_user_data = d; 501 if (m_dwo_symbol_file) 502 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 503 } 504 505 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 506 if (GetProducer() == eProducerLLVMGCC) 507 return false; 508 return true; 509 } 510 511 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 512 // llvm-gcc makes completely invalid decl file attributes and won't ever be 513 // fixed, so we need to know to ignore these. 514 return GetProducer() == eProducerLLVMGCC; 515 } 516 517 bool DWARFUnit::Supports_unnamed_objc_bitfields() { 518 if (GetProducer() == eProducerClang) { 519 const uint32_t major_version = GetProducerVersionMajor(); 520 if (major_version > 425 || 521 (major_version == 425 && GetProducerVersionUpdate() >= 13)) 522 return true; 523 else 524 return false; 525 } 526 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 527 // info 528 } 529 530 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } 531 532 void DWARFUnit::ParseProducerInfo() { 533 m_producer_version_major = UINT32_MAX; 534 m_producer_version_minor = UINT32_MAX; 535 m_producer_version_update = UINT32_MAX; 536 537 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 538 if (die) { 539 540 const char *producer_cstr = 541 die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); 542 if (producer_cstr) { 543 RegularExpression llvm_gcc_regex( 544 llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " 545 "Inc\\. build [0-9]+\\) \\(LLVM build " 546 "[\\.0-9]+\\)$")); 547 if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { 548 m_producer = eProducerLLVMGCC; 549 } else if (strstr(producer_cstr, "clang")) { 550 static RegularExpression g_clang_version_regex( 551 llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); 552 RegularExpression::Match regex_match(3); 553 if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), 554 ®ex_match)) { 555 std::string str; 556 if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) 557 m_producer_version_major = 558 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 559 if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) 560 m_producer_version_minor = 561 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 562 if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) 563 m_producer_version_update = 564 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 565 } 566 m_producer = eProducerClang; 567 } else if (strstr(producer_cstr, "GNU")) 568 m_producer = eProducerGCC; 569 } 570 } 571 if (m_producer == eProducerInvalid) 572 m_producer = eProcucerOther; 573 } 574 575 DWARFProducer DWARFUnit::GetProducer() { 576 if (m_producer == eProducerInvalid) 577 ParseProducerInfo(); 578 return m_producer; 579 } 580 581 uint32_t DWARFUnit::GetProducerVersionMajor() { 582 if (m_producer_version_major == 0) 583 ParseProducerInfo(); 584 return m_producer_version_major; 585 } 586 587 uint32_t DWARFUnit::GetProducerVersionMinor() { 588 if (m_producer_version_minor == 0) 589 ParseProducerInfo(); 590 return m_producer_version_minor; 591 } 592 593 uint32_t DWARFUnit::GetProducerVersionUpdate() { 594 if (m_producer_version_update == 0) 595 ParseProducerInfo(); 596 return m_producer_version_update; 597 } 598 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 599 // Note: user languages between lo_user and hi_user must be handled 600 // explicitly here. 601 switch (val) { 602 case DW_LANG_Mips_Assembler: 603 return eLanguageTypeMipsAssembler; 604 case DW_LANG_GOOGLE_RenderScript: 605 return eLanguageTypeExtRenderScript; 606 default: 607 return static_cast<LanguageType>(val); 608 } 609 } 610 611 LanguageType DWARFUnit::GetLanguageType() { 612 if (m_language_type != eLanguageTypeUnknown) 613 return m_language_type; 614 615 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 616 if (die) 617 m_language_type = LanguageTypeFromDWARF( 618 die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); 619 return m_language_type; 620 } 621 622 bool DWARFUnit::GetIsOptimized() { 623 if (m_is_optimized == eLazyBoolCalculate) { 624 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 625 if (die) { 626 m_is_optimized = eLazyBoolNo; 627 if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, 628 0) == 1) { 629 m_is_optimized = eLazyBoolYes; 630 } 631 } 632 } 633 return m_is_optimized == eLazyBoolYes; 634 } 635 636 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 637 return m_dwo_symbol_file.get(); 638 } 639 640 dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } 641 642 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 643 if (m_func_aranges_ap.get() == NULL) { 644 m_func_aranges_ap.reset(new DWARFDebugAranges()); 645 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 646 647 if (log) { 648 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 649 log, 650 "DWARFUnit::GetFunctionAranges() for compile unit at " 651 ".debug_info[0x%8.8x]", 652 GetOffset()); 653 } 654 const DWARFDebugInfoEntry *die = DIEPtr(); 655 if (die) 656 die->BuildFunctionAddressRangeTable(m_dwarf, this, 657 m_func_aranges_ap.get()); 658 659 if (m_dwo_symbol_file) { 660 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 661 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 662 if (dwo_die) 663 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 664 m_func_aranges_ap.get()); 665 } 666 667 const bool minimize = false; 668 m_func_aranges_ap->Sort(minimize); 669 } 670 return *m_func_aranges_ap.get(); 671 } 672 673