DWARFUnit.cpp revision 344779
1109998Smarkm//===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===// 2109998Smarkm// 3109998Smarkm// The LLVM Compiler Infrastructure 4109998Smarkm// 5109998Smarkm// This file is distributed under the University of Illinois Open Source 6109998Smarkm// License. See LICENSE.TXT for details. 7109998Smarkm// 8109998Smarkm//===----------------------------------------------------------------------===// 9109998Smarkm 10109998Smarkm#include "DWARFUnit.h" 11109998Smarkm 12109998Smarkm#include "lldb/Core/Module.h" 13109998Smarkm#include "lldb/Host/StringConvert.h" 14109998Smarkm#include "lldb/Symbol/CompileUnit.h" 15109998Smarkm#include "lldb/Symbol/LineTable.h" 16109998Smarkm#include "lldb/Symbol/ObjectFile.h" 17109998Smarkm#include "lldb/Utility/LLDBAssert.h" 18109998Smarkm#include "lldb/Utility/StreamString.h" 19109998Smarkm#include "lldb/Utility/Timer.h" 20109998Smarkm 21109998Smarkm#include "DWARFDIECollection.h" 22109998Smarkm#include "DWARFDebugAranges.h" 23109998Smarkm#include "DWARFDebugInfo.h" 24109998Smarkm#include "LogChannelDWARF.h" 25109998Smarkm#include "SymbolFileDWARFDebugMap.h" 26109998Smarkm#include "SymbolFileDWARFDwo.h" 27109998Smarkm 28109998Smarkmusing namespace lldb; 29109998Smarkmusing namespace lldb_private; 30109998Smarkmusing namespace std; 31109998Smarkm 32109998Smarkmextern int g_verbose; 33109998Smarkm 34109998SmarkmDWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) 35109998Smarkm : m_dwarf(dwarf), m_cancel_scopes(false) {} 36109998Smarkm 37109998SmarkmDWARFUnit::~DWARFUnit() {} 38109998Smarkm 39109998Smarkm//---------------------------------------------------------------------- 40109998Smarkm// Parses first DIE of a compile unit. 41109998Smarkm//---------------------------------------------------------------------- 42109998Smarkmvoid DWARFUnit::ExtractUnitDIEIfNeeded() { 43109998Smarkm { 44109998Smarkm llvm::sys::ScopedReader lock(m_first_die_mutex); 45109998Smarkm if (m_first_die) 46109998Smarkm return; // Already parsed 47109998Smarkm } 48109998Smarkm llvm::sys::ScopedWriter lock(m_first_die_mutex); 49109998Smarkm if (m_first_die) 50109998Smarkm return; // Already parsed 51109998Smarkm 52109998Smarkm static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 53109998Smarkm Timer scoped_timer( 54109998Smarkm func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset); 55109998Smarkm 56109998Smarkm // Set the offset to that of the first DIE and calculate the start of the 57109998Smarkm // next compilation unit header. 58109998Smarkm lldb::offset_t offset = GetFirstDIEOffset(); 59109998Smarkm 60109998Smarkm // We are in our compile unit, parse starting at the offset we were told to 61109998Smarkm // parse 62109998Smarkm const DWARFDataExtractor &data = GetData(); 63109998Smarkm DWARFFormValue::FixedFormSizes fixed_form_sizes = 64109998Smarkm DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 65109998Smarkm IsDWARF64()); 66109998Smarkm if (offset < GetNextCompileUnitOffset() && 67109998Smarkm m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) { 68109998Smarkm AddUnitDIE(m_first_die); 69109998Smarkm return; 70109998Smarkm } 71109998Smarkm 72109998Smarkm ExtractDIEsEndCheck(offset); 73109998Smarkm} 74 75//---------------------------------------------------------------------- 76// Parses a compile unit and indexes its DIEs if it hasn't already been done. 77// It will leave this compile unit extracted forever. 78//---------------------------------------------------------------------- 79void DWARFUnit::ExtractDIEsIfNeeded() { 80 m_cancel_scopes = true; 81 82 { 83 llvm::sys::ScopedReader lock(m_die_array_mutex); 84 if (!m_die_array.empty()) 85 return; // Already parsed 86 } 87 llvm::sys::ScopedWriter lock(m_die_array_mutex); 88 if (!m_die_array.empty()) 89 return; // Already parsed 90 91 ExtractDIEsRWLocked(); 92} 93 94//---------------------------------------------------------------------- 95// Parses a compile unit and indexes its DIEs if it hasn't already been done. 96// It will clear this compile unit after returned instance gets out of scope, 97// no other ScopedExtractDIEs instance is running for this compile unit 98// and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs 99// lifetime. 100//---------------------------------------------------------------------- 101DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() { 102 ScopedExtractDIEs scoped(this); 103 104 { 105 llvm::sys::ScopedReader lock(m_die_array_mutex); 106 if (!m_die_array.empty()) 107 return scoped; // Already parsed 108 } 109 llvm::sys::ScopedWriter lock(m_die_array_mutex); 110 if (!m_die_array.empty()) 111 return scoped; // Already parsed 112 113 // Otherwise m_die_array would be already populated. 114 lldbassert(!m_cancel_scopes); 115 116 ExtractDIEsRWLocked(); 117 scoped.m_clear_dies = true; 118 return scoped; 119} 120 121DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit *cu) : m_cu(cu) { 122 lldbassert(m_cu); 123 m_cu->m_die_array_scoped_mutex.lock_shared(); 124} 125 126DWARFUnit::ScopedExtractDIEs::~ScopedExtractDIEs() { 127 if (!m_cu) 128 return; 129 m_cu->m_die_array_scoped_mutex.unlock_shared(); 130 if (!m_clear_dies || m_cu->m_cancel_scopes) 131 return; 132 // Be sure no other ScopedExtractDIEs is running anymore. 133 llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex); 134 llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex); 135 if (m_cu->m_cancel_scopes) 136 return; 137 m_cu->ClearDIEsRWLocked(); 138} 139 140DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs) 141 : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) { 142 rhs.m_cu = nullptr; 143} 144 145DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=( 146 DWARFUnit::ScopedExtractDIEs &&rhs) { 147 m_cu = rhs.m_cu; 148 rhs.m_cu = nullptr; 149 m_clear_dies = rhs.m_clear_dies; 150 return *this; 151} 152 153//---------------------------------------------------------------------- 154// Parses a compile unit and indexes its DIEs, m_die_array_mutex must be 155// held R/W and m_die_array must be empty. 156//---------------------------------------------------------------------- 157void DWARFUnit::ExtractDIEsRWLocked() { 158 llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); 159 160 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 161 Timer scoped_timer( 162 func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset); 163 164 // Set the offset to that of the first DIE and calculate the start of the 165 // next compilation unit header. 166 lldb::offset_t offset = GetFirstDIEOffset(); 167 lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); 168 169 DWARFDebugInfoEntry die; 170 // Keep a flat array of the DIE for binary lookup by DIE offset 171 Log *log( 172 LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); 173 if (log) { 174 m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( 175 log, 176 "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " 177 ".debug_info[0x%8.8x]", 178 GetOffset()); 179 } 180 181 uint32_t depth = 0; 182 // We are in our compile unit, parse starting at the offset we were told to 183 // parse 184 const DWARFDataExtractor &data = GetData(); 185 std::vector<uint32_t> die_index_stack; 186 die_index_stack.reserve(32); 187 die_index_stack.push_back(0); 188 bool prev_die_had_children = false; 189 DWARFFormValue::FixedFormSizes fixed_form_sizes = 190 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 191 IsDWARF64()); 192 while (offset < next_cu_offset && 193 die.FastExtract(data, this, fixed_form_sizes, &offset)) { 194 const bool null_die = die.IsNULL(); 195 if (depth == 0) { 196 assert(m_die_array.empty() && "Compile unit DIE already added"); 197 198 // The average bytes per DIE entry has been seen to be around 14-20 so 199 // lets pre-reserve half of that since we are now stripping the NULL 200 // tags. 201 202 // Only reserve the memory if we are adding children of the main 203 // compile unit DIE. The compile unit DIE is always the first entry, so 204 // if our size is 1, then we are adding the first compile unit child 205 // DIE and should reserve the memory. 206 m_die_array.reserve(GetDebugInfoSize() / 24); 207 m_die_array.push_back(die); 208 209 if (!m_first_die) 210 AddUnitDIE(m_die_array.front()); 211 } else { 212 if (null_die) { 213 if (prev_die_had_children) { 214 // This will only happen if a DIE says is has children but all it 215 // contains is a NULL tag. Since we are removing the NULL DIEs from 216 // the list (saves up to 25% in C++ code), we need a way to let the 217 // DIE know that it actually doesn't have children. 218 if (!m_die_array.empty()) 219 m_die_array.back().SetHasChildren(false); 220 } 221 } else { 222 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 223 224 if (die_index_stack.back()) 225 m_die_array[die_index_stack.back()].SetSiblingIndex( 226 m_die_array.size() - die_index_stack.back()); 227 228 // Only push the DIE if it isn't a NULL DIE 229 m_die_array.push_back(die); 230 } 231 } 232 233 if (null_die) { 234 // NULL DIE. 235 if (!die_index_stack.empty()) 236 die_index_stack.pop_back(); 237 238 if (depth > 0) 239 --depth; 240 prev_die_had_children = false; 241 } else { 242 die_index_stack.back() = m_die_array.size() - 1; 243 // Normal DIE 244 const bool die_has_children = die.HasChildren(); 245 if (die_has_children) { 246 die_index_stack.push_back(0); 247 ++depth; 248 } 249 prev_die_had_children = die_has_children; 250 } 251 252 if (depth == 0) 253 break; // We are done with this compile unit! 254 } 255 256 if (!m_die_array.empty()) { 257 if (m_first_die) { 258 // Only needed for the assertion. 259 m_first_die.SetHasChildren(m_die_array.front().HasChildren()); 260 lldbassert(m_first_die == m_die_array.front()); 261 } 262 m_first_die = m_die_array.front(); 263 } 264 265 m_die_array.shrink_to_fit(); 266 267 ExtractDIEsEndCheck(offset); 268 269 if (m_dwo_symbol_file) { 270 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 271 dwo_cu->ExtractDIEsIfNeeded(); 272 } 273} 274 275//-------------------------------------------------------------------------- 276// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). 277//-------------------------------------------------------------------------- 278void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { 279 // Give a little bit of info if we encounter corrupt DWARF (our offset should 280 // always terminate at or before the start of the next compilation unit 281 // header). 282 if (offset > GetNextCompileUnitOffset()) { 283 m_dwarf->GetObjectFile()->GetModule()->ReportWarning( 284 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 285 "0x%8.8" PRIx64 "\n", 286 GetOffset(), offset); 287 } 288 289 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 290 if (log && log->GetVerbose()) { 291 StreamString strm; 292 Dump(&strm); 293 if (m_die_array.empty()) 294 strm.Printf("error: no DIE for compile unit"); 295 else 296 m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); 297 log->PutString(strm.GetString()); 298 } 299} 300 301// This is used when a split dwarf is enabled. 302// A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute 303// that points to the first string offset of the CU contribution to the 304// .debug_str_offsets. At the same time, the corresponding split debug unit also 305// may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and 306// for that case, we should find the offset (skip the section header). 307static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) { 308 lldb::offset_t baseOffset = 0; 309 310 const DWARFDataExtractor &strOffsets = 311 dwo_cu->GetSymbolFileDWARF()->get_debug_str_offsets_data(); 312 uint64_t length = strOffsets.GetU32(&baseOffset); 313 if (length == 0xffffffff) 314 length = strOffsets.GetU64(&baseOffset); 315 316 // Check version. 317 if (strOffsets.GetU16(&baseOffset) < 5) 318 return; 319 320 // Skip padding. 321 baseOffset += 2; 322 323 dwo_cu->SetStrOffsetsBase(baseOffset); 324} 325 326// m_die_array_mutex must be already held as read/write. 327void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 328 dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned( 329 m_dwarf, this, DW_AT_addr_base, LLDB_INVALID_ADDRESS); 330 if (addr_base != LLDB_INVALID_ADDRESS) 331 SetAddrBase(addr_base); 332 333 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 334 m_dwarf, this, DW_AT_rnglists_base, LLDB_INVALID_ADDRESS); 335 if (ranges_base != LLDB_INVALID_ADDRESS) 336 SetRangesBase(ranges_base); 337 338 SetStrOffsetsBase(cu_die.GetAttributeValueAsUnsigned( 339 m_dwarf, this, DW_AT_str_offsets_base, 0)); 340 341 uint64_t base_addr = cu_die.GetAttributeValueAsAddress( 342 m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 343 if (base_addr == LLDB_INVALID_ADDRESS) 344 base_addr = cu_die.GetAttributeValueAsAddress( 345 m_dwarf, this, DW_AT_entry_pc, 0); 346 SetBaseAddress(base_addr); 347 348 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 349 m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); 350 if (!dwo_symbol_file) 351 return; 352 353 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 354 if (!dwo_cu) 355 return; // Can't fetch the compile unit from the dwo file. 356 357 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 358 if (!dwo_cu_die.IsValid()) 359 return; // Can't fetch the compile unit DIE from the dwo file. 360 361 uint64_t main_dwo_id = 362 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); 363 uint64_t sub_dwo_id = 364 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 365 if (main_dwo_id != sub_dwo_id) 366 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 367 // a differectn compilation. 368 369 m_dwo_symbol_file = std::move(dwo_symbol_file); 370 371 // Here for DWO CU we want to use the address base set in the skeleton unit 372 // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base 373 // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_* 374 // attributes which were applicable to the DWO units. The corresponding 375 // DW_AT_* attributes standardized in DWARF v5 are also applicable to the main 376 // unit in contrast. 377 if (addr_base == LLDB_INVALID_ADDRESS) 378 addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, 379 DW_AT_GNU_addr_base, 0); 380 dwo_cu->SetAddrBase(addr_base); 381 382 if (ranges_base == LLDB_INVALID_ADDRESS) 383 ranges_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, 384 DW_AT_GNU_ranges_base, 0); 385 dwo_cu->SetRangesBase(ranges_base); 386 387 dwo_cu->SetBaseObjOffset(m_offset); 388 389 SetDwoStrOffsetsBase(dwo_cu); 390} 391 392DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 393 if (DIE()) { 394 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 395 396 // Re-check the aranges auto pointer contents in case it was created above 397 if (!func_aranges.IsEmpty()) 398 return GetDIE(func_aranges.FindAddress(address)); 399 } 400 return DWARFDIE(); 401} 402 403size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 404 DWARFDIECollection &dies, 405 uint32_t depth) const { 406 size_t old_size = dies.Size(); 407 { 408 llvm::sys::ScopedReader lock(m_die_array_mutex); 409 DWARFDebugInfoEntry::const_iterator pos; 410 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 411 for (pos = m_die_array.begin(); pos != end; ++pos) { 412 if (pos->Tag() == tag) 413 dies.Append(DWARFDIE(this, &(*pos))); 414 } 415 } 416 417 // Return the number of DIEs added to the collection 418 return dies.Size() - old_size; 419} 420 421 422lldb::user_id_t DWARFUnit::GetID() const { 423 dw_offset_t local_id = 424 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 425 if (m_dwarf) 426 return DIERef(local_id, local_id).GetUID(m_dwarf); 427 else 428 return local_id; 429} 430 431dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 432 return m_offset + GetLengthByteSize() + GetLength(); 433} 434 435size_t DWARFUnit::GetDebugInfoSize() const { 436 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 437} 438 439const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 440 return m_abbrevs; 441} 442 443dw_offset_t DWARFUnit::GetAbbrevOffset() const { 444 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 445} 446 447void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } 448 449void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { 450 m_ranges_base = ranges_base; 451} 452 453void DWARFUnit::SetBaseObjOffset(dw_offset_t base_obj_offset) { 454 m_base_obj_offset = base_obj_offset; 455} 456 457void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { 458 m_str_offsets_base = str_offsets_base; 459} 460 461// It may be called only with m_die_array_mutex held R/W. 462void DWARFUnit::ClearDIEsRWLocked() { 463 m_die_array.clear(); 464 m_die_array.shrink_to_fit(); 465 466 if (m_dwo_symbol_file) 467 m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked(); 468} 469 470void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, 471 DWARFDebugAranges *debug_aranges) { 472 // This function is usually called if there in no .debug_aranges section in 473 // order to produce a compile unit level set of address ranges that is 474 // accurate. 475 476 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 477 478 // First get the compile unit DIE only and check if it has a DW_AT_ranges 479 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 480 481 const dw_offset_t cu_offset = GetOffset(); 482 if (die) { 483 DWARFRangeList ranges; 484 const size_t num_ranges = 485 die->GetAttributeAddressRanges(dwarf, this, ranges, false); 486 if (num_ranges > 0) { 487 // This compile unit has DW_AT_ranges, assume this is correct if it is 488 // present since clang no longer makes .debug_aranges by default and it 489 // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with 490 // recent GCC builds. 491 for (size_t i = 0; i < num_ranges; ++i) { 492 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 493 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 494 range.GetRangeEnd()); 495 } 496 497 return; // We got all of our ranges from the DW_AT_ranges attribute 498 } 499 } 500 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 501 502 // If the DIEs weren't parsed, then we don't want all dies for all compile 503 // units to stay loaded when they weren't needed. So we can end up parsing 504 // the DWARF and then throwing them all away to keep memory usage down. 505 ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); 506 507 die = DIEPtr(); 508 if (die) 509 die->BuildAddressRangeTable(dwarf, this, debug_aranges); 510 511 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 512 // We got nothing from the functions, maybe we have a line tables only 513 // situation. Check the line tables and build the arange table from this. 514 SymbolContext sc; 515 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 516 if (sc.comp_unit) { 517 SymbolFileDWARFDebugMap *debug_map_sym_file = 518 m_dwarf->GetDebugMapSymfile(); 519 if (debug_map_sym_file == NULL) { 520 LineTable *line_table = sc.comp_unit->GetLineTable(); 521 522 if (line_table) { 523 LineTable::FileAddressRanges file_ranges; 524 const bool append = true; 525 const size_t num_ranges = 526 line_table->GetContiguousFileAddressRanges(file_ranges, append); 527 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 528 const LineTable::FileAddressRanges::Entry &range = 529 file_ranges.GetEntryRef(idx); 530 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 531 range.GetRangeEnd()); 532 } 533 } 534 } else 535 debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); 536 } 537 } 538 539 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 540 // We got nothing from the functions, maybe we have a line tables only 541 // situation. Check the line tables and build the arange table from this. 542 SymbolContext sc; 543 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 544 if (sc.comp_unit) { 545 LineTable *line_table = sc.comp_unit->GetLineTable(); 546 547 if (line_table) { 548 LineTable::FileAddressRanges file_ranges; 549 const bool append = true; 550 const size_t num_ranges = 551 line_table->GetContiguousFileAddressRanges(file_ranges, append); 552 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 553 const LineTable::FileAddressRanges::Entry &range = 554 file_ranges.GetEntryRef(idx); 555 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 556 range.GetRangeEnd()); 557 } 558 } 559 } 560 } 561} 562 563lldb::ByteOrder DWARFUnit::GetByteOrder() const { 564 return m_dwarf->GetObjectFile()->GetByteOrder(); 565} 566 567TypeSystem *DWARFUnit::GetTypeSystem() { 568 if (m_dwarf) 569 return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); 570 else 571 return nullptr; 572} 573 574DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 575 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 576 IsDWARF64()); 577} 578 579void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 580 581//---------------------------------------------------------------------- 582// Compare function DWARFDebugAranges::Range structures 583//---------------------------------------------------------------------- 584static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 585 const dw_offset_t die_offset) { 586 return die.GetOffset() < die_offset; 587} 588 589//---------------------------------------------------------------------- 590// GetDIE() 591// 592// Get the DIE (Debug Information Entry) with the specified offset by first 593// checking if the DIE is contained within this compile unit and grabbing the 594// DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 595//---------------------------------------------------------------------- 596DWARFDIE 597DWARFUnit::GetDIE(dw_offset_t die_offset) { 598 if (die_offset != DW_INVALID_OFFSET) { 599 if (GetDwoSymbolFile()) 600 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 601 602 if (ContainsDIEOffset(die_offset)) { 603 ExtractDIEsIfNeeded(); 604 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 605 DWARFDebugInfoEntry::const_iterator pos = 606 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 607 if (pos != end) { 608 if (die_offset == (*pos).GetOffset()) 609 return DWARFDIE(this, &(*pos)); 610 } 611 } else { 612 // Don't specify the compile unit offset as we don't know it because the 613 // DIE belongs to 614 // a different compile unit in the same symbol file. 615 return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); 616 } 617 } 618 return DWARFDIE(); // Not found 619} 620 621uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 622 if (cu) 623 return cu->GetAddressByteSize(); 624 return DWARFUnit::GetDefaultAddressSize(); 625} 626 627bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 628 if (cu) 629 return cu->IsDWARF64(); 630 return false; 631} 632 633uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 634 635void *DWARFUnit::GetUserData() const { return m_user_data; } 636 637void DWARFUnit::SetUserData(void *d) { 638 m_user_data = d; 639 if (m_dwo_symbol_file) 640 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 641} 642 643bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 644 return GetProducer() != eProducerLLVMGCC; 645} 646 647bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 648 // llvm-gcc makes completely invalid decl file attributes and won't ever be 649 // fixed, so we need to know to ignore these. 650 return GetProducer() == eProducerLLVMGCC; 651} 652 653bool DWARFUnit::Supports_unnamed_objc_bitfields() { 654 if (GetProducer() == eProducerClang) { 655 const uint32_t major_version = GetProducerVersionMajor(); 656 return major_version > 425 || 657 (major_version == 425 && GetProducerVersionUpdate() >= 13); 658 } 659 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 660 // info 661} 662 663SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } 664 665void DWARFUnit::ParseProducerInfo() { 666 m_producer_version_major = UINT32_MAX; 667 m_producer_version_minor = UINT32_MAX; 668 m_producer_version_update = UINT32_MAX; 669 670 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 671 if (die) { 672 673 const char *producer_cstr = 674 die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); 675 if (producer_cstr) { 676 RegularExpression llvm_gcc_regex( 677 llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " 678 "Inc\\. build [0-9]+\\) \\(LLVM build " 679 "[\\.0-9]+\\)$")); 680 if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { 681 m_producer = eProducerLLVMGCC; 682 } else if (strstr(producer_cstr, "clang")) { 683 static RegularExpression g_clang_version_regex( 684 llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); 685 RegularExpression::Match regex_match(3); 686 if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), 687 ®ex_match)) { 688 std::string str; 689 if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) 690 m_producer_version_major = 691 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 692 if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) 693 m_producer_version_minor = 694 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 695 if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) 696 m_producer_version_update = 697 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 698 } 699 m_producer = eProducerClang; 700 } else if (strstr(producer_cstr, "GNU")) 701 m_producer = eProducerGCC; 702 } 703 } 704 if (m_producer == eProducerInvalid) 705 m_producer = eProcucerOther; 706} 707 708DWARFProducer DWARFUnit::GetProducer() { 709 if (m_producer == eProducerInvalid) 710 ParseProducerInfo(); 711 return m_producer; 712} 713 714uint32_t DWARFUnit::GetProducerVersionMajor() { 715 if (m_producer_version_major == 0) 716 ParseProducerInfo(); 717 return m_producer_version_major; 718} 719 720uint32_t DWARFUnit::GetProducerVersionMinor() { 721 if (m_producer_version_minor == 0) 722 ParseProducerInfo(); 723 return m_producer_version_minor; 724} 725 726uint32_t DWARFUnit::GetProducerVersionUpdate() { 727 if (m_producer_version_update == 0) 728 ParseProducerInfo(); 729 return m_producer_version_update; 730} 731LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 732 // Note: user languages between lo_user and hi_user must be handled 733 // explicitly here. 734 switch (val) { 735 case DW_LANG_Mips_Assembler: 736 return eLanguageTypeMipsAssembler; 737 case DW_LANG_GOOGLE_RenderScript: 738 return eLanguageTypeExtRenderScript; 739 default: 740 return static_cast<LanguageType>(val); 741 } 742} 743 744LanguageType DWARFUnit::GetLanguageType() { 745 if (m_language_type != eLanguageTypeUnknown) 746 return m_language_type; 747 748 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 749 if (die) 750 m_language_type = LanguageTypeFromDWARF( 751 die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); 752 return m_language_type; 753} 754 755bool DWARFUnit::GetIsOptimized() { 756 if (m_is_optimized == eLazyBoolCalculate) { 757 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 758 if (die) { 759 m_is_optimized = eLazyBoolNo; 760 if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, 761 0) == 1) { 762 m_is_optimized = eLazyBoolYes; 763 } 764 } 765 } 766 return m_is_optimized == eLazyBoolYes; 767} 768 769SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 770 return m_dwo_symbol_file.get(); 771} 772 773dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } 774 775const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 776 if (m_func_aranges_ap.get() == NULL) { 777 m_func_aranges_ap.reset(new DWARFDebugAranges()); 778 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 779 780 if (log) { 781 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 782 log, 783 "DWARFUnit::GetFunctionAranges() for compile unit at " 784 ".debug_info[0x%8.8x]", 785 GetOffset()); 786 } 787 const DWARFDebugInfoEntry *die = DIEPtr(); 788 if (die) 789 die->BuildFunctionAddressRangeTable(m_dwarf, this, 790 m_func_aranges_ap.get()); 791 792 if (m_dwo_symbol_file) { 793 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 794 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 795 if (dwo_die) 796 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 797 m_func_aranges_ap.get()); 798 } 799 800 const bool minimize = false; 801 m_func_aranges_ap->Sort(minimize); 802 } 803 return *m_func_aranges_ap.get(); 804} 805 806