1 //===-- DWARFCompileUnit.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 "DWARFCompileUnit.h" 11 12 #include "lldb/Core/DumpDataExtractor.h" 13 #include "lldb/Core/Mangled.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Host/StringConvert.h" 16 #include "lldb/Symbol/CompileUnit.h" 17 #include "lldb/Symbol/LineTable.h" 18 #include "lldb/Symbol/ObjectFile.h" 19 #include "lldb/Utility/Stream.h" 20 #include "lldb/Utility/StreamString.h" 21 #include "lldb/Utility/Timer.h" 22 23 #include "DWARFDIECollection.h" 24 #include "DWARFDebugAbbrev.h" 25 #include "DWARFDebugAranges.h" 26 #include "DWARFDebugInfo.h" 27 #include "DWARFFormValue.h" 28 #include "LogChannelDWARF.h" 29 #include "NameToDIE.h" 30 #include "SymbolFileDWARF.h" 31 #include "SymbolFileDWARFDebugMap.h" 32 #include "SymbolFileDWARFDwo.h" 33 34 using namespace lldb; 35 using namespace lldb_private; 36 using namespace std; 37 38 extern int g_verbose; 39 40 DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data) 41 : m_dwarf2Data(dwarf2Data) {} 42 43 DWARFUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data, 44 lldb::offset_t *offset_ptr) { 45 // std::make_shared would require the ctor to be public. 46 std::shared_ptr<DWARFCompileUnit> cu_sp(new DWARFCompileUnit(dwarf2Data)); 47 // Out of memory? 48 if (cu_sp.get() == NULL) 49 return nullptr; 50 51 const DWARFDataExtractor &debug_info = dwarf2Data->get_debug_info_data(); 52 53 cu_sp->m_offset = *offset_ptr; 54 55 if (debug_info.ValidOffset(*offset_ptr)) { 56 dw_offset_t abbr_offset; 57 const DWARFDebugAbbrev *abbr = dwarf2Data->DebugAbbrev(); 58 cu_sp->m_length = debug_info.GetDWARFInitialLength(offset_ptr); 59 cu_sp->m_is_dwarf64 = debug_info.IsDWARF64(); 60 cu_sp->m_version = debug_info.GetU16(offset_ptr); 61 abbr_offset = debug_info.GetDWARFOffset(offset_ptr); 62 cu_sp->m_addr_size = debug_info.GetU8(offset_ptr); 63 64 bool length_OK = 65 debug_info.ValidOffset(cu_sp->GetNextCompileUnitOffset() - 1); 66 bool version_OK = SymbolFileDWARF::SupportedVersion(cu_sp->m_version); 67 bool abbr_offset_OK = 68 dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); 69 bool addr_size_OK = (cu_sp->m_addr_size == 4) || (cu_sp->m_addr_size == 8); 70 71 if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && 72 abbr != NULL) { 73 cu_sp->m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); 74 return cu_sp; 75 } 76 77 // reset the offset to where we tried to parse from if anything went wrong 78 *offset_ptr = cu_sp->m_offset; 79 } 80 81 return nullptr; 82 } 83 84 void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) { 85 if (m_die_array.size() > 1) { 86 // std::vectors never get any smaller when resized to a smaller size, 87 // or when clear() or erase() are called, the size will report that it 88 // is smaller, but the memory allocated remains intact (call capacity() 89 // to see this). So we need to create a temporary vector and swap the 90 // contents which will cause just the internal pointers to be swapped 91 // so that when "tmp_array" goes out of scope, it will destroy the 92 // contents. 93 94 // Save at least the compile unit DIE 95 DWARFDebugInfoEntry::collection tmp_array; 96 m_die_array.swap(tmp_array); 97 if (keep_compile_unit_die) 98 m_die_array.push_back(tmp_array.front()); 99 } 100 101 if (m_dwo_symbol_file) 102 m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die); 103 } 104 105 //---------------------------------------------------------------------- 106 // ParseCompileUnitDIEsIfNeeded 107 // 108 // Parses a compile unit and indexes its DIEs if it hasn't already been 109 // done. 110 //---------------------------------------------------------------------- 111 size_t DWARFCompileUnit::ExtractDIEsIfNeeded(bool cu_die_only) { 112 const size_t initial_die_array_size = m_die_array.size(); 113 if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) 114 return 0; // Already parsed 115 116 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 117 Timer scoped_timer( 118 func_cat, 119 "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )", 120 m_offset, cu_die_only); 121 122 // Set the offset to that of the first DIE and calculate the start of the 123 // next compilation unit header. 124 lldb::offset_t offset = GetFirstDIEOffset(); 125 lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); 126 127 DWARFDebugInfoEntry die; 128 // Keep a flat array of the DIE for binary lookup by DIE offset 129 if (!cu_die_only) { 130 Log *log( 131 LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); 132 if (log) { 133 m_dwarf2Data->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( 134 log, "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at " 135 ".debug_info[0x%8.8x]", 136 GetOffset()); 137 } 138 } 139 140 uint32_t depth = 0; 141 // We are in our compile unit, parse starting at the offset 142 // we were told to parse 143 const DWARFDataExtractor &debug_info_data = 144 m_dwarf2Data->get_debug_info_data(); 145 std::vector<uint32_t> die_index_stack; 146 die_index_stack.reserve(32); 147 die_index_stack.push_back(0); 148 bool prev_die_had_children = false; 149 DWARFFormValue::FixedFormSizes fixed_form_sizes = 150 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 151 m_is_dwarf64); 152 while (offset < next_cu_offset && 153 die.FastExtract(debug_info_data, this, fixed_form_sizes, &offset)) { 154 // if (log) 155 // log->Printf("0x%8.8x: %*.*s%s%s", 156 // die.GetOffset(), 157 // depth * 2, depth * 2, "", 158 // DW_TAG_value_to_name (die.Tag()), 159 // die.HasChildren() ? " *" : ""); 160 161 const bool null_die = die.IsNULL(); 162 if (depth == 0) { 163 if (initial_die_array_size == 0) 164 AddCompileUnitDIE(die); 165 uint64_t base_addr = die.GetAttributeValueAsAddress( 166 m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 167 if (base_addr == LLDB_INVALID_ADDRESS) 168 base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, 169 DW_AT_entry_pc, 0); 170 SetBaseAddress(base_addr); 171 if (cu_die_only) 172 return 1; 173 } else { 174 if (null_die) { 175 if (prev_die_had_children) { 176 // This will only happen if a DIE says is has children 177 // but all it contains is a NULL tag. Since we are removing 178 // the NULL DIEs from the list (saves up to 25% in C++ code), 179 // we need a way to let the DIE know that it actually doesn't 180 // have children. 181 if (!m_die_array.empty()) 182 m_die_array.back().SetEmptyChildren(true); 183 } 184 } else { 185 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 186 187 if (die_index_stack.back()) 188 m_die_array[die_index_stack.back()].SetSiblingIndex( 189 m_die_array.size() - die_index_stack.back()); 190 191 // Only push the DIE if it isn't a NULL DIE 192 m_die_array.push_back(die); 193 } 194 } 195 196 if (null_die) { 197 // NULL DIE. 198 if (!die_index_stack.empty()) 199 die_index_stack.pop_back(); 200 201 if (depth > 0) 202 --depth; 203 if (depth == 0) 204 break; // We are done with this compile unit! 205 206 prev_die_had_children = false; 207 } else { 208 die_index_stack.back() = m_die_array.size() - 1; 209 // Normal DIE 210 const bool die_has_children = die.HasChildren(); 211 if (die_has_children) { 212 die_index_stack.push_back(0); 213 ++depth; 214 } 215 prev_die_had_children = die_has_children; 216 } 217 } 218 219 // Give a little bit of info if we encounter corrupt DWARF (our offset 220 // should always terminate at or before the start of the next compilation 221 // unit header). 222 if (offset > next_cu_offset) { 223 m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning( 224 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 225 "0x%8.8" PRIx64 "\n", 226 GetOffset(), offset); 227 } 228 229 // Since std::vector objects will double their size, we really need to 230 // make a new array with the perfect size so we don't end up wasting 231 // space. So here we copy and swap to make sure we don't have any extra 232 // memory taken up. 233 234 if (m_die_array.size() < m_die_array.capacity()) { 235 DWARFDebugInfoEntry::collection exact_size_die_array(m_die_array.begin(), 236 m_die_array.end()); 237 exact_size_die_array.swap(m_die_array); 238 } 239 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 240 if (log && log->GetVerbose()) { 241 StreamString strm; 242 Dump(&strm); 243 if (m_die_array.empty()) 244 strm.Printf("error: no DIE for compile unit"); 245 else 246 m_die_array[0].Dump(m_dwarf2Data, this, strm, UINT32_MAX); 247 log->PutString(strm.GetString()); 248 } 249 250 if (!m_dwo_symbol_file) 251 return m_die_array.size(); 252 253 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 254 size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only); 255 return m_die_array.size() + dwo_die_count - 256 1; // We have 2 CU die, but we want to count it only as one 257 } 258 259 void DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry &die) { 260 assert(m_die_array.empty() && "Compile unit DIE already added"); 261 AddDIE(die); 262 263 const DWARFDebugInfoEntry &cu_die = m_die_array.front(); 264 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 265 m_dwarf2Data->GetDwoSymbolFileForCompileUnit(*this, cu_die); 266 if (!dwo_symbol_file) 267 return; 268 269 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 270 if (!dwo_cu) 271 return; // Can't fetch the compile unit from the dwo file. 272 273 DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly(); 274 if (!dwo_cu_die.IsValid()) 275 return; // Can't fetch the compile unit DIE from the dwo file. 276 277 uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned( 278 m_dwarf2Data, this, DW_AT_GNU_dwo_id, 0); 279 uint64_t sub_dwo_id = 280 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 281 if (main_dwo_id != sub_dwo_id) 282 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 283 // a differectn compilation. 284 285 m_dwo_symbol_file = std::move(dwo_symbol_file); 286 287 dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned( 288 m_dwarf2Data, this, DW_AT_GNU_addr_base, 0); 289 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 290 m_dwarf2Data, this, DW_AT_GNU_ranges_base, 0); 291 dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset); 292 } 293 294 dw_offset_t DWARFCompileUnit::GetAbbrevOffset() const { 295 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 296 } 297 298 bool DWARFCompileUnit::Verify(Stream *s) const { 299 const DWARFDataExtractor &debug_info = m_dwarf2Data->get_debug_info_data(); 300 bool valid_offset = debug_info.ValidOffset(m_offset); 301 bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1); 302 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 303 bool abbr_offset_OK = 304 m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset()); 305 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 306 if (valid_offset && length_OK && version_OK && addr_size_OK && 307 abbr_offset_OK) { 308 return true; 309 } else { 310 s->Printf(" 0x%8.8x: ", m_offset); 311 DumpDataExtractor(m_dwarf2Data->get_debug_info_data(), s, m_offset, 312 lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 313 0); 314 s->EOL(); 315 if (valid_offset) { 316 if (!length_OK) 317 s->Printf(" The length (0x%8.8x) for this compile unit is too " 318 "large for the .debug_info provided.\n", 319 m_length); 320 if (!version_OK) 321 s->Printf(" The 16 bit compile unit header version is not " 322 "supported.\n"); 323 if (!abbr_offset_OK) 324 s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) " 325 "is not valid.\n", 326 GetAbbrevOffset()); 327 if (!addr_size_OK) 328 s->Printf(" The address size is unsupported: 0x%2.2x\n", 329 m_addr_size); 330 } else 331 s->Printf(" The start offset of the compile unit header in the " 332 ".debug_info is invalid.\n"); 333 } 334 return false; 335 } 336 337 void DWARFCompileUnit::Dump(Stream *s) const { 338 s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, " 339 "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " 340 "{0x%8.8x})\n", 341 m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, 342 GetNextCompileUnitOffset()); 343 } 344 345 lldb::user_id_t DWARFCompileUnit::GetID() const { 346 dw_offset_t local_id = 347 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 348 if (m_dwarf2Data) 349 return DIERef(local_id, local_id).GetUID(m_dwarf2Data); 350 else 351 return local_id; 352 } 353 354 void DWARFCompileUnit::BuildAddressRangeTable( 355 SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges) { 356 // This function is usually called if there in no .debug_aranges section 357 // in order to produce a compile unit level set of address ranges that 358 // is accurate. 359 360 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 361 362 // First get the compile unit DIE only and check if it has a DW_AT_ranges 363 const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); 364 365 const dw_offset_t cu_offset = GetOffset(); 366 if (die) { 367 DWARFRangeList ranges; 368 const size_t num_ranges = 369 die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false); 370 if (num_ranges > 0) { 371 // This compile unit has DW_AT_ranges, assume this is correct if it 372 // is present since clang no longer makes .debug_aranges by default 373 // and it emits DW_AT_ranges for DW_TAG_compile_units. GCC also does 374 // this with recent GCC builds. 375 for (size_t i = 0; i < num_ranges; ++i) { 376 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 377 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 378 range.GetRangeEnd()); 379 } 380 381 return; // We got all of our ranges from the DW_AT_ranges attribute 382 } 383 } 384 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 385 386 // If the DIEs weren't parsed, then we don't want all dies for all compile 387 // units 388 // to stay loaded when they weren't needed. So we can end up parsing the DWARF 389 // and then throwing them all away to keep memory usage down. 390 const bool clear_dies = ExtractDIEsIfNeeded(false) > 1; 391 392 die = DIEPtr(); 393 if (die) 394 die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); 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 = dwarf2Data->GetCompUnitForDWARFCompUnit(this); 401 if (sc.comp_unit) { 402 SymbolFileDWARFDebugMap *debug_map_sym_file = 403 m_dwarf2Data->GetDebugMapSymfile(); 404 if (debug_map_sym_file == NULL) { 405 LineTable *line_table = sc.comp_unit->GetLineTable(); 406 407 if (line_table) { 408 LineTable::FileAddressRanges file_ranges; 409 const bool append = true; 410 const size_t num_ranges = 411 line_table->GetContiguousFileAddressRanges(file_ranges, append); 412 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 413 const LineTable::FileAddressRanges::Entry &range = 414 file_ranges.GetEntryRef(idx); 415 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 416 range.GetRangeEnd()); 417 } 418 } 419 } else 420 debug_map_sym_file->AddOSOARanges(dwarf2Data, debug_aranges); 421 } 422 } 423 424 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 425 // We got nothing from the functions, maybe we have a line tables only 426 // situation. Check the line tables and build the arange table from this. 427 SymbolContext sc; 428 sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this); 429 if (sc.comp_unit) { 430 LineTable *line_table = sc.comp_unit->GetLineTable(); 431 432 if (line_table) { 433 LineTable::FileAddressRanges file_ranges; 434 const bool append = true; 435 const size_t num_ranges = 436 line_table->GetContiguousFileAddressRanges(file_ranges, append); 437 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 438 const LineTable::FileAddressRanges::Entry &range = 439 file_ranges.GetEntryRef(idx); 440 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 441 range.GetRangeEnd()); 442 } 443 } 444 } 445 } 446 447 // Keep memory down by clearing DIEs if this generate function 448 // caused them to be parsed 449 if (clear_dies) 450 ClearDIEs(true); 451 } 452 453 const DWARFDebugAranges &DWARFCompileUnit::GetFunctionAranges() { 454 if (m_func_aranges_ap.get() == NULL) { 455 m_func_aranges_ap.reset(new DWARFDebugAranges()); 456 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 457 458 if (log) { 459 m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage( 460 log, "DWARFCompileUnit::GetFunctionAranges() for compile unit at " 461 ".debug_info[0x%8.8x]", 462 GetOffset()); 463 } 464 const DWARFDebugInfoEntry *die = DIEPtr(); 465 if (die) 466 die->BuildFunctionAddressRangeTable(m_dwarf2Data, this, 467 m_func_aranges_ap.get()); 468 469 if (m_dwo_symbol_file) { 470 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 471 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 472 if (dwo_die) 473 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 474 m_func_aranges_ap.get()); 475 } 476 477 const bool minimize = false; 478 m_func_aranges_ap->Sort(minimize); 479 } 480 return *m_func_aranges_ap.get(); 481 } 482 483 DWARFDIE 484 DWARFCompileUnit::LookupAddress(const dw_addr_t address) { 485 if (DIE()) { 486 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 487 488 // Re-check the aranges auto pointer contents in case it was created above 489 if (!func_aranges.IsEmpty()) 490 return GetDIE(func_aranges.FindAddress(address)); 491 } 492 return DWARFDIE(); 493 } 494 495 size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag, 496 DWARFDIECollection &dies, 497 uint32_t depth) const { 498 size_t old_size = dies.Size(); 499 DWARFDebugInfoEntry::const_iterator pos; 500 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 501 for (pos = m_die_array.begin(); pos != end; ++pos) { 502 if (pos->Tag() == tag) 503 dies.Append(DWARFDIE(this, &(*pos))); 504 } 505 506 // Return the number of DIEs added to the collection 507 return dies.Size() - old_size; 508 } 509 510 // void 511 // DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx) 512 //{ 513 // m_global_die_indexes.push_back (die_idx); 514 //} 515 // 516 // 517 // void 518 // DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die) 519 //{ 520 // // Indexes to all file level global and static variables 521 // m_global_die_indexes; 522 // 523 // if (m_die_array.empty()) 524 // return; 525 // 526 // const DWARFDebugInfoEntry* first_die = &m_die_array[0]; 527 // const DWARFDebugInfoEntry* end = first_die + m_die_array.size(); 528 // if (first_die <= die && die < end) 529 // m_global_die_indexes.push_back (die - first_die); 530 //} 531 532 void DWARFCompileUnit::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 = GetCompileUnitDIEPtrOnly(); 538 if (die) { 539 540 const char *producer_cstr = die->GetAttributeValueAsString( 541 m_dwarf2Data, 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 DWARFCompileUnit::GetProducer() { 576 if (m_producer == eProducerInvalid) 577 ParseProducerInfo(); 578 return m_producer; 579 } 580 581 uint32_t DWARFCompileUnit::GetProducerVersionMajor() { 582 if (m_producer_version_major == 0) 583 ParseProducerInfo(); 584 return m_producer_version_major; 585 } 586 587 uint32_t DWARFCompileUnit::GetProducerVersionMinor() { 588 if (m_producer_version_minor == 0) 589 ParseProducerInfo(); 590 return m_producer_version_minor; 591 } 592 593 uint32_t DWARFCompileUnit::GetProducerVersionUpdate() { 594 if (m_producer_version_update == 0) 595 ParseProducerInfo(); 596 return m_producer_version_update; 597 } 598 599 LanguageType DWARFCompileUnit::GetLanguageType() { 600 if (m_language_type != eLanguageTypeUnknown) 601 return m_language_type; 602 603 const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); 604 if (die) 605 m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned( 606 m_dwarf2Data, this, DW_AT_language, 0)); 607 return m_language_type; 608 } 609 610 bool DWARFCompileUnit::GetIsOptimized() { 611 if (m_is_optimized == eLazyBoolCalculate) { 612 const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); 613 if (die) { 614 m_is_optimized = eLazyBoolNo; 615 if (die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, 616 DW_AT_APPLE_optimized, 0) == 1) { 617 m_is_optimized = eLazyBoolYes; 618 } 619 } 620 } 621 if (m_is_optimized == eLazyBoolYes) { 622 return true; 623 } else { 624 return false; 625 } 626 } 627 628 TypeSystem *DWARFCompileUnit::GetTypeSystem() { 629 if (m_dwarf2Data) 630 return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType()); 631 else 632 return nullptr; 633 } 634 635 void DWARFCompileUnit::SetUserData(void *d) { 636 m_user_data = d; 637 if (m_dwo_symbol_file) 638 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 639 } 640 641 void DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base, 642 dw_addr_t ranges_base, 643 dw_offset_t base_obj_offset) { 644 m_addr_base = addr_base; 645 m_ranges_base = ranges_base; 646 m_base_obj_offset = base_obj_offset; 647 } 648