15ffd83dbSDimitry Andric //===-- DWARFUnit.cpp -----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "DWARFUnit.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Module.h" 120b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 130b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h" 140b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 150b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 165f757f3fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 1781ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 180b57cec5SDimitry Andric #include "llvm/Object/Error.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "DWARFCompileUnit.h" 210b57cec5SDimitry Andric #include "DWARFDebugAranges.h" 220b57cec5SDimitry Andric #include "DWARFDebugInfo.h" 230b57cec5SDimitry Andric #include "DWARFTypeUnit.h" 240b57cec5SDimitry Andric #include "LogChannelDWARF.h" 250b57cec5SDimitry Andric #include "SymbolFileDWARFDwo.h" 26bdd1243dSDimitry Andric #include <optional> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace lldb; 290b57cec5SDimitry Andric using namespace lldb_private; 3081ad6265SDimitry Andric using namespace lldb_private::dwarf; 315f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric extern int g_verbose; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, 36*0fca6ea1SDimitry Andric const llvm::DWARFUnitHeader &header, 375f757f3fSDimitry Andric const llvm::DWARFAbbreviationDeclarationSet &abbrevs, 38480093f4SDimitry Andric DIERef::Section section, bool is_dwo) 390b57cec5SDimitry Andric : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs), 40e8d8bef9SDimitry Andric m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo), 41*0fca6ea1SDimitry Andric m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.getDWOId()) {} 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric DWARFUnit::~DWARFUnit() = default; 440b57cec5SDimitry Andric 45349cc55cSDimitry Andric // Parses first DIE of a compile unit, excluding DWO. 46349cc55cSDimitry Andric void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() { 470b57cec5SDimitry Andric { 480b57cec5SDimitry Andric llvm::sys::ScopedReader lock(m_first_die_mutex); 490b57cec5SDimitry Andric if (m_first_die) 500b57cec5SDimitry Andric return; // Already parsed 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric llvm::sys::ScopedWriter lock(m_first_die_mutex); 530b57cec5SDimitry Andric if (m_first_die) 540b57cec5SDimitry Andric return; // Already parsed 550b57cec5SDimitry Andric 56349cc55cSDimitry Andric ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef()); 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // Set the offset to that of the first DIE and calculate the start of the 590b57cec5SDimitry Andric // next compilation unit header. 600b57cec5SDimitry Andric lldb::offset_t offset = GetFirstDIEOffset(); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // We are in our compile unit, parse starting at the offset we were told to 630b57cec5SDimitry Andric // parse 640b57cec5SDimitry Andric const DWARFDataExtractor &data = GetData(); 650b57cec5SDimitry Andric if (offset < GetNextUnitOffset() && 66*0fca6ea1SDimitry Andric m_first_die.Extract(data, *this, &offset)) { 670b57cec5SDimitry Andric AddUnitDIE(m_first_die); 680b57cec5SDimitry Andric return; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 72349cc55cSDimitry Andric // Parses first DIE of a compile unit including DWO. 73349cc55cSDimitry Andric void DWARFUnit::ExtractUnitDIEIfNeeded() { 74349cc55cSDimitry Andric ExtractUnitDIENoDwoIfNeeded(); 75349cc55cSDimitry Andric 76349cc55cSDimitry Andric if (m_has_parsed_non_skeleton_unit) 77349cc55cSDimitry Andric return; 78349cc55cSDimitry Andric 79349cc55cSDimitry Andric m_has_parsed_non_skeleton_unit = true; 80bdd1243dSDimitry Andric m_dwo_error.Clear(); 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric if (!m_dwo_id) 83bdd1243dSDimitry Andric return; // No DWO file. 84349cc55cSDimitry Andric 85349cc55cSDimitry Andric std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 86349cc55cSDimitry Andric m_dwarf.GetDwoSymbolFileForCompileUnit(*this, m_first_die); 87349cc55cSDimitry Andric if (!dwo_symbol_file) 88349cc55cSDimitry Andric return; 89349cc55cSDimitry Andric 90bdd1243dSDimitry Andric DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(*m_dwo_id); 91349cc55cSDimitry Andric 92bdd1243dSDimitry Andric if (!dwo_cu) { 93bdd1243dSDimitry Andric SetDwoError(Status::createWithFormat( 94bdd1243dSDimitry Andric "unable to load .dwo file from \"{0}\" due to ID ({1:x16}) mismatch " 95bdd1243dSDimitry Andric "for skeleton DIE at {2:x8}", 96bdd1243dSDimitry Andric dwo_symbol_file->GetObjectFile()->GetFileSpec().GetPath().c_str(), 97bdd1243dSDimitry Andric *m_dwo_id, m_first_die.GetOffset())); 98349cc55cSDimitry Andric return; // Can't fetch the compile unit from the dwo file. 99bdd1243dSDimitry Andric } 100*0fca6ea1SDimitry Andric // If the skeleton compile unit gets its unit DIE parsed first, then this 101*0fca6ea1SDimitry Andric // will fill in the DWO file's back pointer to this skeleton compile unit. 102*0fca6ea1SDimitry Andric // If the DWO files get parsed on their own first the skeleton back link 103*0fca6ea1SDimitry Andric // can be done manually in DWARFUnit::GetSkeletonCompileUnit() which will 104*0fca6ea1SDimitry Andric // do a reverse lookup and cache the result. 105*0fca6ea1SDimitry Andric dwo_cu->SetSkeletonUnit(this); 106349cc55cSDimitry Andric 107349cc55cSDimitry Andric DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 108bdd1243dSDimitry Andric if (!dwo_cu_die.IsValid()) { 109bdd1243dSDimitry Andric // Can't fetch the compile unit DIE from the dwo file. 110bdd1243dSDimitry Andric SetDwoError(Status::createWithFormat( 111bdd1243dSDimitry Andric "unable to extract compile unit DIE from .dwo file for skeleton " 112bdd1243dSDimitry Andric "DIE at {0:x16}", 113bdd1243dSDimitry Andric m_first_die.GetOffset())); 114bdd1243dSDimitry Andric return; 115bdd1243dSDimitry Andric } 116349cc55cSDimitry Andric 117349cc55cSDimitry Andric // Here for DWO CU we want to use the address base set in the skeleton unit 118349cc55cSDimitry Andric // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base 119349cc55cSDimitry Andric // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_* 120349cc55cSDimitry Andric // attributes which were applicable to the DWO units. The corresponding 121349cc55cSDimitry Andric // DW_AT_* attributes standardized in DWARF v5 are also applicable to the 122349cc55cSDimitry Andric // main unit in contrast. 123349cc55cSDimitry Andric if (m_addr_base) 124349cc55cSDimitry Andric dwo_cu->SetAddrBase(*m_addr_base); 125349cc55cSDimitry Andric else if (m_gnu_addr_base) 126349cc55cSDimitry Andric dwo_cu->SetAddrBase(*m_gnu_addr_base); 127349cc55cSDimitry Andric 128349cc55cSDimitry Andric if (GetVersion() <= 4 && m_gnu_ranges_base) 129349cc55cSDimitry Andric dwo_cu->SetRangesBase(*m_gnu_ranges_base); 130349cc55cSDimitry Andric else if (dwo_symbol_file->GetDWARFContext() 131349cc55cSDimitry Andric .getOrLoadRngListsData() 132349cc55cSDimitry Andric .GetByteSize() > 0) 133349cc55cSDimitry Andric dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); 134349cc55cSDimitry Andric 135349cc55cSDimitry Andric if (GetVersion() >= 5 && 136349cc55cSDimitry Andric dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() > 137349cc55cSDimitry Andric 0) 138349cc55cSDimitry Andric dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); 139349cc55cSDimitry Andric 140349cc55cSDimitry Andric dwo_cu->SetBaseAddress(GetBaseAddress()); 141349cc55cSDimitry Andric 142349cc55cSDimitry Andric m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu); 143349cc55cSDimitry Andric } 144349cc55cSDimitry Andric 1450b57cec5SDimitry Andric // Parses a compile unit and indexes its DIEs if it hasn't already been done. 1460b57cec5SDimitry Andric // It will leave this compile unit extracted forever. 1470b57cec5SDimitry Andric void DWARFUnit::ExtractDIEsIfNeeded() { 1480b57cec5SDimitry Andric m_cancel_scopes = true; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric { 1510b57cec5SDimitry Andric llvm::sys::ScopedReader lock(m_die_array_mutex); 1520b57cec5SDimitry Andric if (!m_die_array.empty()) 1530b57cec5SDimitry Andric return; // Already parsed 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric llvm::sys::ScopedWriter lock(m_die_array_mutex); 1560b57cec5SDimitry Andric if (!m_die_array.empty()) 1570b57cec5SDimitry Andric return; // Already parsed 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric ExtractDIEsRWLocked(); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // Parses a compile unit and indexes its DIEs if it hasn't already been done. 1630b57cec5SDimitry Andric // It will clear this compile unit after returned instance gets out of scope, 1640b57cec5SDimitry Andric // no other ScopedExtractDIEs instance is running for this compile unit 1650b57cec5SDimitry Andric // and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs 1660b57cec5SDimitry Andric // lifetime. 1670b57cec5SDimitry Andric DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() { 1680b57cec5SDimitry Andric ScopedExtractDIEs scoped(*this); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric { 1710b57cec5SDimitry Andric llvm::sys::ScopedReader lock(m_die_array_mutex); 1720b57cec5SDimitry Andric if (!m_die_array.empty()) 1730b57cec5SDimitry Andric return scoped; // Already parsed 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric llvm::sys::ScopedWriter lock(m_die_array_mutex); 1760b57cec5SDimitry Andric if (!m_die_array.empty()) 1770b57cec5SDimitry Andric return scoped; // Already parsed 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // Otherwise m_die_array would be already populated. 1800b57cec5SDimitry Andric lldbassert(!m_cancel_scopes); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric ExtractDIEsRWLocked(); 1830b57cec5SDimitry Andric scoped.m_clear_dies = true; 1840b57cec5SDimitry Andric return scoped; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit &cu) : m_cu(&cu) { 1880b57cec5SDimitry Andric m_cu->m_die_array_scoped_mutex.lock_shared(); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric DWARFUnit::ScopedExtractDIEs::~ScopedExtractDIEs() { 1920b57cec5SDimitry Andric if (!m_cu) 1930b57cec5SDimitry Andric return; 1940b57cec5SDimitry Andric m_cu->m_die_array_scoped_mutex.unlock_shared(); 1950b57cec5SDimitry Andric if (!m_clear_dies || m_cu->m_cancel_scopes) 1960b57cec5SDimitry Andric return; 1970b57cec5SDimitry Andric // Be sure no other ScopedExtractDIEs is running anymore. 1980b57cec5SDimitry Andric llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex); 1990b57cec5SDimitry Andric llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex); 2000b57cec5SDimitry Andric if (m_cu->m_cancel_scopes) 2010b57cec5SDimitry Andric return; 2020b57cec5SDimitry Andric m_cu->ClearDIEsRWLocked(); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs) 2060b57cec5SDimitry Andric : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) { 2070b57cec5SDimitry Andric rhs.m_cu = nullptr; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2105f757f3fSDimitry Andric DWARFUnit::ScopedExtractDIEs & 2115f757f3fSDimitry Andric DWARFUnit::ScopedExtractDIEs::operator=(DWARFUnit::ScopedExtractDIEs &&rhs) { 2120b57cec5SDimitry Andric m_cu = rhs.m_cu; 2130b57cec5SDimitry Andric rhs.m_cu = nullptr; 2140b57cec5SDimitry Andric m_clear_dies = rhs.m_clear_dies; 2150b57cec5SDimitry Andric return *this; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric // Parses a compile unit and indexes its DIEs, m_die_array_mutex must be 2190b57cec5SDimitry Andric // held R/W and m_die_array must be empty. 2200b57cec5SDimitry Andric void DWARFUnit::ExtractDIEsRWLocked() { 2210b57cec5SDimitry Andric llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); 2220b57cec5SDimitry Andric 223349cc55cSDimitry Andric ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef()); 224bdd1243dSDimitry Andric LLDB_SCOPED_TIMERF( 225bdd1243dSDimitry Andric "%s", 226bdd1243dSDimitry Andric llvm::formatv("{0:x16}: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset()) 227bdd1243dSDimitry Andric .str() 228bdd1243dSDimitry Andric .c_str()); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // Set the offset to that of the first DIE and calculate the start of the 2310b57cec5SDimitry Andric // next compilation unit header. 2320b57cec5SDimitry Andric lldb::offset_t offset = GetFirstDIEOffset(); 2330b57cec5SDimitry Andric lldb::offset_t next_cu_offset = GetNextUnitOffset(); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric DWARFDebugInfoEntry die; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric uint32_t depth = 0; 2380b57cec5SDimitry Andric // We are in our compile unit, parse starting at the offset we were told to 2390b57cec5SDimitry Andric // parse 2400b57cec5SDimitry Andric const DWARFDataExtractor &data = GetData(); 2410b57cec5SDimitry Andric std::vector<uint32_t> die_index_stack; 2420b57cec5SDimitry Andric die_index_stack.reserve(32); 2430b57cec5SDimitry Andric die_index_stack.push_back(0); 2440b57cec5SDimitry Andric bool prev_die_had_children = false; 245*0fca6ea1SDimitry Andric while (offset < next_cu_offset && die.Extract(data, *this, &offset)) { 2460b57cec5SDimitry Andric const bool null_die = die.IsNULL(); 2470b57cec5SDimitry Andric if (depth == 0) { 2480b57cec5SDimitry Andric assert(m_die_array.empty() && "Compile unit DIE already added"); 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric // The average bytes per DIE entry has been seen to be around 14-20 so 2510b57cec5SDimitry Andric // lets pre-reserve half of that since we are now stripping the NULL 2520b57cec5SDimitry Andric // tags. 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric // Only reserve the memory if we are adding children of the main 2550b57cec5SDimitry Andric // compile unit DIE. The compile unit DIE is always the first entry, so 2560b57cec5SDimitry Andric // if our size is 1, then we are adding the first compile unit child 2570b57cec5SDimitry Andric // DIE and should reserve the memory. 2580b57cec5SDimitry Andric m_die_array.reserve(GetDebugInfoSize() / 24); 2590b57cec5SDimitry Andric m_die_array.push_back(die); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric if (!m_first_die) 2620b57cec5SDimitry Andric AddUnitDIE(m_die_array.front()); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // With -fsplit-dwarf-inlining, clang will emit non-empty skeleton compile 2650b57cec5SDimitry Andric // units. We are not able to access these DIE *and* the dwo file 2660b57cec5SDimitry Andric // simultaneously. We also don't need to do that as the dwo file will 2670b57cec5SDimitry Andric // contain a superset of information. So, we don't even attempt to parse 2680b57cec5SDimitry Andric // any remaining DIEs. 2695ffd83dbSDimitry Andric if (m_dwo) { 2700b57cec5SDimitry Andric m_die_array.front().SetHasChildren(false); 2710b57cec5SDimitry Andric break; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric } else { 2750b57cec5SDimitry Andric if (null_die) { 2760b57cec5SDimitry Andric if (prev_die_had_children) { 2770b57cec5SDimitry Andric // This will only happen if a DIE says is has children but all it 2780b57cec5SDimitry Andric // contains is a NULL tag. Since we are removing the NULL DIEs from 2790b57cec5SDimitry Andric // the list (saves up to 25% in C++ code), we need a way to let the 2800b57cec5SDimitry Andric // DIE know that it actually doesn't have children. 2810b57cec5SDimitry Andric if (!m_die_array.empty()) 2820b57cec5SDimitry Andric m_die_array.back().SetHasChildren(false); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric } else { 2850b57cec5SDimitry Andric die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric if (die_index_stack.back()) 2880b57cec5SDimitry Andric m_die_array[die_index_stack.back()].SetSiblingIndex( 2890b57cec5SDimitry Andric m_die_array.size() - die_index_stack.back()); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // Only push the DIE if it isn't a NULL DIE 2920b57cec5SDimitry Andric m_die_array.push_back(die); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric if (null_die) { 2970b57cec5SDimitry Andric // NULL DIE. 2980b57cec5SDimitry Andric if (!die_index_stack.empty()) 2990b57cec5SDimitry Andric die_index_stack.pop_back(); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric if (depth > 0) 3020b57cec5SDimitry Andric --depth; 3030b57cec5SDimitry Andric prev_die_had_children = false; 3040b57cec5SDimitry Andric } else { 3050b57cec5SDimitry Andric die_index_stack.back() = m_die_array.size() - 1; 3060b57cec5SDimitry Andric // Normal DIE 3070b57cec5SDimitry Andric const bool die_has_children = die.HasChildren(); 3080b57cec5SDimitry Andric if (die_has_children) { 3090b57cec5SDimitry Andric die_index_stack.push_back(0); 3100b57cec5SDimitry Andric ++depth; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric prev_die_had_children = die_has_children; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (depth == 0) 3160b57cec5SDimitry Andric break; // We are done with this compile unit! 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric if (!m_die_array.empty()) { 3205f757f3fSDimitry Andric // The last die cannot have children (if it did, it wouldn't be the last 3215f757f3fSDimitry Andric // one). This only makes a difference for malformed dwarf that does not have 3225f757f3fSDimitry Andric // a terminating null die. 323fe6060f1SDimitry Andric m_die_array.back().SetHasChildren(false); 324fe6060f1SDimitry Andric 3250b57cec5SDimitry Andric if (m_first_die) { 3260b57cec5SDimitry Andric // Only needed for the assertion. 3270b57cec5SDimitry Andric m_first_die.SetHasChildren(m_die_array.front().HasChildren()); 3280b57cec5SDimitry Andric lldbassert(m_first_die == m_die_array.front()); 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric m_first_die = m_die_array.front(); 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric m_die_array.shrink_to_fit(); 3340b57cec5SDimitry Andric 3355ffd83dbSDimitry Andric if (m_dwo) 3365ffd83dbSDimitry Andric m_dwo->ExtractDIEsIfNeeded(); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric // This is used when a split dwarf is enabled. 3400b57cec5SDimitry Andric // A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute 3410b57cec5SDimitry Andric // that points to the first string offset of the CU contribution to the 3420b57cec5SDimitry Andric // .debug_str_offsets. At the same time, the corresponding split debug unit also 3430b57cec5SDimitry Andric // may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and 3440b57cec5SDimitry Andric // for that case, we should find the offset (skip the section header). 3455ffd83dbSDimitry Andric void DWARFUnit::SetDwoStrOffsetsBase() { 3460b57cec5SDimitry Andric lldb::offset_t baseOffset = 0; 3470b57cec5SDimitry Andric 348*0fca6ea1SDimitry Andric if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) { 3495ffd83dbSDimitry Andric if (const auto *contribution = 3505ffd83dbSDimitry Andric entry->getContribution(llvm::DW_SECT_STR_OFFSETS)) 35106c3fb27SDimitry Andric baseOffset = contribution->getOffset(); 3525ffd83dbSDimitry Andric else 3535ffd83dbSDimitry Andric return; 3545ffd83dbSDimitry Andric } 3555ffd83dbSDimitry Andric 3565ffd83dbSDimitry Andric if (GetVersion() >= 5) { 3570b57cec5SDimitry Andric const DWARFDataExtractor &strOffsets = 3585ffd83dbSDimitry Andric GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); 3590b57cec5SDimitry Andric uint64_t length = strOffsets.GetU32(&baseOffset); 3600b57cec5SDimitry Andric if (length == 0xffffffff) 3610b57cec5SDimitry Andric length = strOffsets.GetU64(&baseOffset); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric // Check version. 3640b57cec5SDimitry Andric if (strOffsets.GetU16(&baseOffset) < 5) 3650b57cec5SDimitry Andric return; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric // Skip padding. 3680b57cec5SDimitry Andric baseOffset += 2; 3695ffd83dbSDimitry Andric } 3700b57cec5SDimitry Andric 3715ffd83dbSDimitry Andric SetStrOffsetsBase(baseOffset); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 374bdd1243dSDimitry Andric std::optional<uint64_t> DWARFUnit::GetDWOId() { 375349cc55cSDimitry Andric ExtractUnitDIENoDwoIfNeeded(); 376e8d8bef9SDimitry Andric return m_dwo_id; 377e8d8bef9SDimitry Andric } 378e8d8bef9SDimitry Andric 3790b57cec5SDimitry Andric // m_die_array_mutex must be already held as read/write. 3800b57cec5SDimitry Andric void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 38106c3fb27SDimitry Andric DWARFAttributes attributes = cu_die.GetAttributes(this); 382480093f4SDimitry Andric 383480093f4SDimitry Andric // Extract DW_AT_addr_base first, as other attributes may need it. 38406c3fb27SDimitry Andric for (size_t i = 0; i < attributes.Size(); ++i) { 385480093f4SDimitry Andric if (attributes.AttributeAtIndex(i) != DW_AT_addr_base) 386480093f4SDimitry Andric continue; 387480093f4SDimitry Andric DWARFFormValue form_value; 388480093f4SDimitry Andric if (attributes.ExtractFormValueAtIndex(i, form_value)) { 389349cc55cSDimitry Andric SetAddrBase(form_value.Unsigned()); 390480093f4SDimitry Andric break; 391480093f4SDimitry Andric } 392480093f4SDimitry Andric } 393480093f4SDimitry Andric 39406c3fb27SDimitry Andric for (size_t i = 0; i < attributes.Size(); ++i) { 3950b57cec5SDimitry Andric dw_attr_t attr = attributes.AttributeAtIndex(i); 3960b57cec5SDimitry Andric DWARFFormValue form_value; 3970b57cec5SDimitry Andric if (!attributes.ExtractFormValueAtIndex(i, form_value)) 3980b57cec5SDimitry Andric continue; 3990b57cec5SDimitry Andric switch (attr) { 40006c3fb27SDimitry Andric default: 40106c3fb27SDimitry Andric break; 402480093f4SDimitry Andric case DW_AT_loclists_base: 403480093f4SDimitry Andric SetLoclistsBase(form_value.Unsigned()); 4040b57cec5SDimitry Andric break; 4050b57cec5SDimitry Andric case DW_AT_rnglists_base: 406fe6060f1SDimitry Andric SetRangesBase(form_value.Unsigned()); 4070b57cec5SDimitry Andric break; 4080b57cec5SDimitry Andric case DW_AT_str_offsets_base: 4090b57cec5SDimitry Andric SetStrOffsetsBase(form_value.Unsigned()); 4100b57cec5SDimitry Andric break; 4110b57cec5SDimitry Andric case DW_AT_low_pc: 4120b57cec5SDimitry Andric SetBaseAddress(form_value.Address()); 4130b57cec5SDimitry Andric break; 4140b57cec5SDimitry Andric case DW_AT_entry_pc: 4150b57cec5SDimitry Andric // If the value was already set by DW_AT_low_pc, don't update it. 4160b57cec5SDimitry Andric if (m_base_addr == LLDB_INVALID_ADDRESS) 4170b57cec5SDimitry Andric SetBaseAddress(form_value.Address()); 4180b57cec5SDimitry Andric break; 4190b57cec5SDimitry Andric case DW_AT_stmt_list: 4200b57cec5SDimitry Andric m_line_table_offset = form_value.Unsigned(); 4210b57cec5SDimitry Andric break; 4220b57cec5SDimitry Andric case DW_AT_GNU_addr_base: 423349cc55cSDimitry Andric m_gnu_addr_base = form_value.Unsigned(); 4240b57cec5SDimitry Andric break; 4250b57cec5SDimitry Andric case DW_AT_GNU_ranges_base: 426349cc55cSDimitry Andric m_gnu_ranges_base = form_value.Unsigned(); 4270b57cec5SDimitry Andric break; 428e8d8bef9SDimitry Andric case DW_AT_GNU_dwo_id: 429e8d8bef9SDimitry Andric m_dwo_id = form_value.Unsigned(); 430e8d8bef9SDimitry Andric break; 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric 4345ffd83dbSDimitry Andric if (m_is_dwo) { 435349cc55cSDimitry Andric m_has_parsed_non_skeleton_unit = true; 4365ffd83dbSDimitry Andric SetDwoStrOffsetsBase(); 437480093f4SDimitry Andric return; 4385ffd83dbSDimitry Andric } 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric size_t DWARFUnit::GetDebugInfoSize() const { 4420b57cec5SDimitry Andric return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4455f757f3fSDimitry Andric const llvm::DWARFAbbreviationDeclarationSet * 4465f757f3fSDimitry Andric DWARFUnit::GetAbbreviations() const { 4470b57cec5SDimitry Andric return m_abbrevs; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric dw_offset_t DWARFUnit::GetAbbrevOffset() const { 45106c3fb27SDimitry Andric return m_abbrevs ? m_abbrevs->getOffset() : DW_INVALID_OFFSET; 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric dw_offset_t DWARFUnit::GetLineTableOffset() { 455349cc55cSDimitry Andric ExtractUnitDIENoDwoIfNeeded(); 4560b57cec5SDimitry Andric return m_line_table_offset; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } 4600b57cec5SDimitry Andric 461480093f4SDimitry Andric // Parse the rangelist table header, including the optional array of offsets 462480093f4SDimitry Andric // following it (DWARF v5 and later). 463480093f4SDimitry Andric template <typename ListTableType> 464480093f4SDimitry Andric static llvm::Expected<ListTableType> 465480093f4SDimitry Andric ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset, 466480093f4SDimitry Andric DwarfFormat format) { 467480093f4SDimitry Andric // We are expected to be called with Offset 0 or pointing just past the table 468480093f4SDimitry Andric // header. Correct Offset in the latter case so that it points to the start 469480093f4SDimitry Andric // of the header. 470349cc55cSDimitry Andric if (offset == 0) { 471349cc55cSDimitry Andric // This means DW_AT_rnglists_base is missing and therefore DW_FORM_rnglistx 472349cc55cSDimitry Andric // cannot be handled. Returning a default-constructed ListTableType allows 473349cc55cSDimitry Andric // DW_FORM_sec_offset to be supported. 474349cc55cSDimitry Andric return ListTableType(); 475349cc55cSDimitry Andric } 476349cc55cSDimitry Andric 477480093f4SDimitry Andric uint64_t HeaderSize = llvm::DWARFListTableHeader::getHeaderSize(format); 478480093f4SDimitry Andric if (offset < HeaderSize) 47981ad6265SDimitry Andric return llvm::createStringError(std::errc::invalid_argument, 480480093f4SDimitry Andric "did not detect a valid" 481480093f4SDimitry Andric " list table with base = 0x%" PRIx64 "\n", 482480093f4SDimitry Andric offset); 483480093f4SDimitry Andric offset -= HeaderSize; 484480093f4SDimitry Andric ListTableType Table; 485480093f4SDimitry Andric if (llvm::Error E = Table.extractHeaderAndOffsets(data, &offset)) 486480093f4SDimitry Andric return std::move(E); 487480093f4SDimitry Andric return Table; 488480093f4SDimitry Andric } 489480093f4SDimitry Andric 490480093f4SDimitry Andric void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) { 491349cc55cSDimitry Andric uint64_t offset = 0; 492*0fca6ea1SDimitry Andric if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) { 493349cc55cSDimitry Andric const auto *contribution = entry->getContribution(llvm::DW_SECT_LOCLISTS); 494349cc55cSDimitry Andric if (!contribution) { 495349cc55cSDimitry Andric GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 496349cc55cSDimitry Andric "Failed to find location list contribution for CU with DWO Id " 497bdd1243dSDimitry Andric "{0:x16}", 498bdd1243dSDimitry Andric *GetDWOId()); 499349cc55cSDimitry Andric return; 500349cc55cSDimitry Andric } 50106c3fb27SDimitry Andric offset += contribution->getOffset(); 502349cc55cSDimitry Andric } 503480093f4SDimitry Andric m_loclists_base = loclists_base; 504480093f4SDimitry Andric 505480093f4SDimitry Andric uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32); 506480093f4SDimitry Andric if (loclists_base < header_size) 507480093f4SDimitry Andric return; 508480093f4SDimitry Andric 509480093f4SDimitry Andric m_loclist_table_header.emplace(".debug_loclists", "locations"); 510349cc55cSDimitry Andric offset += loclists_base - header_size; 511480093f4SDimitry Andric if (llvm::Error E = m_loclist_table_header->extract( 51206c3fb27SDimitry Andric m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVMDWARF(), 513480093f4SDimitry Andric &offset)) { 514480093f4SDimitry Andric GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 515bdd1243dSDimitry Andric "Failed to extract location list table at offset {0:x16} (location " 516bdd1243dSDimitry Andric "list base: {1:x16}): {2}", 517349cc55cSDimitry Andric offset, loclists_base, toString(std::move(E)).c_str()); 518480093f4SDimitry Andric } 519480093f4SDimitry Andric } 520480093f4SDimitry Andric 521480093f4SDimitry Andric std::unique_ptr<llvm::DWARFLocationTable> 522480093f4SDimitry Andric DWARFUnit::GetLocationTable(const DataExtractor &data) const { 523480093f4SDimitry Andric llvm::DWARFDataExtractor llvm_data( 5245ffd83dbSDimitry Andric data.GetData(), data.GetByteOrder() == lldb::eByteOrderLittle, 5255ffd83dbSDimitry Andric data.GetAddressByteSize()); 526480093f4SDimitry Andric 527480093f4SDimitry Andric if (m_is_dwo || GetVersion() >= 5) 528480093f4SDimitry Andric return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion()); 529480093f4SDimitry Andric return std::make_unique<llvm::DWARFDebugLoc>(llvm_data); 530480093f4SDimitry Andric } 531480093f4SDimitry Andric 5325ffd83dbSDimitry Andric DWARFDataExtractor DWARFUnit::GetLocationData() const { 533480093f4SDimitry Andric DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext(); 5345ffd83dbSDimitry Andric const DWARFDataExtractor &data = 5355ffd83dbSDimitry Andric GetVersion() >= 5 ? Ctx.getOrLoadLocListsData() : Ctx.getOrLoadLocData(); 536*0fca6ea1SDimitry Andric if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) { 537349cc55cSDimitry Andric if (const auto *contribution = entry->getContribution( 538349cc55cSDimitry Andric GetVersion() >= 5 ? llvm::DW_SECT_LOCLISTS : llvm::DW_SECT_EXT_LOC)) 53906c3fb27SDimitry Andric return DWARFDataExtractor(data, contribution->getOffset(), 540bdd1243dSDimitry Andric contribution->getLength32()); 5415ffd83dbSDimitry Andric return DWARFDataExtractor(); 5425ffd83dbSDimitry Andric } 5435ffd83dbSDimitry Andric return data; 544480093f4SDimitry Andric } 545480093f4SDimitry Andric 546349cc55cSDimitry Andric DWARFDataExtractor DWARFUnit::GetRnglistData() const { 547349cc55cSDimitry Andric DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext(); 548349cc55cSDimitry Andric const DWARFDataExtractor &data = Ctx.getOrLoadRngListsData(); 549*0fca6ea1SDimitry Andric if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) { 550349cc55cSDimitry Andric if (const auto *contribution = 551349cc55cSDimitry Andric entry->getContribution(llvm::DW_SECT_RNGLISTS)) 55206c3fb27SDimitry Andric return DWARFDataExtractor(data, contribution->getOffset(), 553bdd1243dSDimitry Andric contribution->getLength32()); 554349cc55cSDimitry Andric GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 555bdd1243dSDimitry Andric "Failed to find range list contribution for CU with signature {0:x16}", 556349cc55cSDimitry Andric entry->getSignature()); 557349cc55cSDimitry Andric 558349cc55cSDimitry Andric return DWARFDataExtractor(); 559349cc55cSDimitry Andric } 560349cc55cSDimitry Andric return data; 561349cc55cSDimitry Andric } 562349cc55cSDimitry Andric 5630b57cec5SDimitry Andric void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { 564fe6060f1SDimitry Andric lldbassert(!m_rnglist_table_done); 565fe6060f1SDimitry Andric 5660b57cec5SDimitry Andric m_ranges_base = ranges_base; 567fe6060f1SDimitry Andric } 568480093f4SDimitry Andric 569bdd1243dSDimitry Andric const std::optional<llvm::DWARFDebugRnglistTable> & 570fe6060f1SDimitry Andric DWARFUnit::GetRnglistTable() { 571fe6060f1SDimitry Andric if (GetVersion() >= 5 && !m_rnglist_table_done) { 572fe6060f1SDimitry Andric m_rnglist_table_done = true; 573fe6060f1SDimitry Andric if (auto table_or_error = 574fe6060f1SDimitry Andric ParseListTableHeader<llvm::DWARFDebugRnglistTable>( 57506c3fb27SDimitry Andric GetRnglistData().GetAsLLVMDWARF(), m_ranges_base, DWARF32)) 576480093f4SDimitry Andric m_rnglist_table = std::move(table_or_error.get()); 577480093f4SDimitry Andric else 578480093f4SDimitry Andric GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 579bdd1243dSDimitry Andric "Failed to extract range list table at offset {0:x16}: {1}", 580fe6060f1SDimitry Andric m_ranges_base, toString(table_or_error.takeError()).c_str()); 581fe6060f1SDimitry Andric } 582fe6060f1SDimitry Andric return m_rnglist_table; 583fe6060f1SDimitry Andric } 584fe6060f1SDimitry Andric 585fe6060f1SDimitry Andric // This function is called only for DW_FORM_rnglistx. 586fe6060f1SDimitry Andric llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) { 587fe6060f1SDimitry Andric if (!GetRnglistTable()) 58881ad6265SDimitry Andric return llvm::createStringError(std::errc::invalid_argument, 589fe6060f1SDimitry Andric "missing or invalid range list table"); 590fe6060f1SDimitry Andric if (!m_ranges_base) 591bdd1243dSDimitry Andric return llvm::createStringError( 592bdd1243dSDimitry Andric std::errc::invalid_argument, 593bdd1243dSDimitry Andric llvm::formatv("DW_FORM_rnglistx cannot be used without " 594bdd1243dSDimitry Andric "DW_AT_rnglists_base for CU at {0:x16}", 595bdd1243dSDimitry Andric GetOffset()) 596bdd1243dSDimitry Andric .str() 597bdd1243dSDimitry Andric .c_str()); 598bdd1243dSDimitry Andric if (std::optional<uint64_t> off = GetRnglistTable()->getOffsetEntry( 599349cc55cSDimitry Andric GetRnglistData().GetAsLLVM(), Index)) 600fe6060f1SDimitry Andric return *off + m_ranges_base; 601fe6060f1SDimitry Andric return llvm::createStringError( 60281ad6265SDimitry Andric std::errc::invalid_argument, 603fe6060f1SDimitry Andric "invalid range list table index %u; OffsetEntryCount is %u, " 604fe6060f1SDimitry Andric "DW_AT_rnglists_base is %" PRIu64, 605fe6060f1SDimitry Andric Index, GetRnglistTable()->getOffsetEntryCount(), m_ranges_base); 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { 6090b57cec5SDimitry Andric m_str_offsets_base = str_offsets_base; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 612753f127fSDimitry Andric dw_addr_t DWARFUnit::ReadAddressFromDebugAddrSection(uint32_t index) const { 613753f127fSDimitry Andric uint32_t index_size = GetAddressByteSize(); 614753f127fSDimitry Andric dw_offset_t addr_base = GetAddrBase(); 615bdd1243dSDimitry Andric dw_addr_t offset = addr_base + static_cast<dw_addr_t>(index) * index_size; 616753f127fSDimitry Andric const DWARFDataExtractor &data = 617753f127fSDimitry Andric m_dwarf.GetDWARFContext().getOrLoadAddrData(); 618753f127fSDimitry Andric if (data.ValidOffsetForDataOfSize(offset, index_size)) 619753f127fSDimitry Andric return data.GetMaxU64_unchecked(&offset, index_size); 620753f127fSDimitry Andric return LLDB_INVALID_ADDRESS; 621753f127fSDimitry Andric } 622753f127fSDimitry Andric 6230b57cec5SDimitry Andric // It may be called only with m_die_array_mutex held R/W. 6240b57cec5SDimitry Andric void DWARFUnit::ClearDIEsRWLocked() { 6250b57cec5SDimitry Andric m_die_array.clear(); 6260b57cec5SDimitry Andric m_die_array.shrink_to_fit(); 6270b57cec5SDimitry Andric 628bdd1243dSDimitry Andric if (m_dwo && !m_dwo->m_cancel_scopes) 6295ffd83dbSDimitry Andric m_dwo->ClearDIEsRWLocked(); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric lldb::ByteOrder DWARFUnit::GetByteOrder() const { 6330b57cec5SDimitry Andric return m_dwarf.GetObjectFile()->GetByteOrder(); 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric // Compare function DWARFDebugAranges::Range structures 6390b57cec5SDimitry Andric static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 6400b57cec5SDimitry Andric const dw_offset_t die_offset) { 6410b57cec5SDimitry Andric return die.GetOffset() < die_offset; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric // GetDIE() 6450b57cec5SDimitry Andric // 6460b57cec5SDimitry Andric // Get the DIE (Debug Information Entry) with the specified offset by first 6470b57cec5SDimitry Andric // checking if the DIE is contained within this compile unit and grabbing the 6480b57cec5SDimitry Andric // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 6490b57cec5SDimitry Andric DWARFDIE 6500b57cec5SDimitry Andric DWARFUnit::GetDIE(dw_offset_t die_offset) { 651e8d8bef9SDimitry Andric if (die_offset == DW_INVALID_OFFSET) 652e8d8bef9SDimitry Andric return DWARFDIE(); // Not found 653e8d8bef9SDimitry Andric 654e8d8bef9SDimitry Andric if (!ContainsDIEOffset(die_offset)) { 655e8d8bef9SDimitry Andric GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 656bdd1243dSDimitry Andric "GetDIE for DIE {0:x16} is outside of its CU {0:x16}", die_offset, 657bdd1243dSDimitry Andric GetOffset()); 658e8d8bef9SDimitry Andric return DWARFDIE(); // Not found 659e8d8bef9SDimitry Andric } 660e8d8bef9SDimitry Andric 6610b57cec5SDimitry Andric ExtractDIEsIfNeeded(); 6620b57cec5SDimitry Andric DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 6630b57cec5SDimitry Andric DWARFDebugInfoEntry::const_iterator pos = 6640b57cec5SDimitry Andric lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 665e8d8bef9SDimitry Andric 666e8d8bef9SDimitry Andric if (pos != end && die_offset == (*pos).GetOffset()) 6670b57cec5SDimitry Andric return DWARFDIE(this, &(*pos)); 6680b57cec5SDimitry Andric return DWARFDIE(); // Not found 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6717a6dacacSDimitry Andric llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) { 6727a6dacacSDimitry Andric DWARFDebugInfoEntry die; 673*0fca6ea1SDimitry Andric if (!die.Extract(GetData(), *this, &die_offset)) 6747a6dacacSDimitry Andric return llvm::StringRef(); 6757a6dacacSDimitry Andric 6767a6dacacSDimitry Andric // Does die contain a DW_AT_Name? 6777a6dacacSDimitry Andric if (const char *name = 6787a6dacacSDimitry Andric die.GetAttributeValueAsString(this, DW_AT_name, nullptr)) 6797a6dacacSDimitry Andric return name; 6807a6dacacSDimitry Andric 6817a6dacacSDimitry Andric // Does its DW_AT_specification or DW_AT_abstract_origin contain an AT_Name? 6827a6dacacSDimitry Andric for (auto attr : {DW_AT_specification, DW_AT_abstract_origin}) { 6837a6dacacSDimitry Andric DWARFFormValue form_value; 6847a6dacacSDimitry Andric if (!die.GetAttributeValue(this, attr, form_value)) 6857a6dacacSDimitry Andric continue; 6867a6dacacSDimitry Andric auto [unit, offset] = form_value.ReferencedUnitAndOffset(); 6877a6dacacSDimitry Andric if (unit) 6887a6dacacSDimitry Andric if (auto name = unit->PeekDIEName(offset); !name.empty()) 6897a6dacacSDimitry Andric return name; 6907a6dacacSDimitry Andric } 6917a6dacacSDimitry Andric 6927a6dacacSDimitry Andric return llvm::StringRef(); 6937a6dacacSDimitry Andric } 6947a6dacacSDimitry Andric 6950b57cec5SDimitry Andric DWARFUnit &DWARFUnit::GetNonSkeletonUnit() { 6965ffd83dbSDimitry Andric ExtractUnitDIEIfNeeded(); 6975ffd83dbSDimitry Andric if (m_dwo) 6985ffd83dbSDimitry Andric return *m_dwo; 6990b57cec5SDimitry Andric return *this; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 7030b57cec5SDimitry Andric if (cu) 7040b57cec5SDimitry Andric return cu->GetAddressByteSize(); 7050b57cec5SDimitry Andric return DWARFUnit::GetDefaultAddressSize(); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 7090b57cec5SDimitry Andric 710*0fca6ea1SDimitry Andric DWARFCompileUnit *DWARFUnit::GetSkeletonUnit() { 711*0fca6ea1SDimitry Andric if (m_skeleton_unit == nullptr && IsDWOUnit()) { 712*0fca6ea1SDimitry Andric SymbolFileDWARFDwo *dwo = 713*0fca6ea1SDimitry Andric llvm::dyn_cast_or_null<SymbolFileDWARFDwo>(&GetSymbolFileDWARF()); 714*0fca6ea1SDimitry Andric // Do a reverse lookup if the skeleton compile unit wasn't set. 715*0fca6ea1SDimitry Andric if (dwo) 716*0fca6ea1SDimitry Andric m_skeleton_unit = dwo->GetBaseSymbolFile().GetSkeletonUnit(this); 717*0fca6ea1SDimitry Andric } 718*0fca6ea1SDimitry Andric return llvm::dyn_cast_or_null<DWARFCompileUnit>(m_skeleton_unit); 719*0fca6ea1SDimitry Andric } 7200b57cec5SDimitry Andric 721*0fca6ea1SDimitry Andric void DWARFUnit::SetSkeletonUnit(DWARFUnit *skeleton_unit) { 722*0fca6ea1SDimitry Andric // If someone is re-setting the skeleton compile unit backlink, make sure 723*0fca6ea1SDimitry Andric // it is setting it to a valid value when it wasn't valid, or if the 724*0fca6ea1SDimitry Andric // value in m_skeleton_unit was valid, it should be the same value. 725*0fca6ea1SDimitry Andric assert(skeleton_unit); 726*0fca6ea1SDimitry Andric assert(m_skeleton_unit == nullptr || m_skeleton_unit == skeleton_unit); 727*0fca6ea1SDimitry Andric m_skeleton_unit = skeleton_unit; 728*0fca6ea1SDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 7310b57cec5SDimitry Andric return GetProducer() != eProducerLLVMGCC; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 7350b57cec5SDimitry Andric // llvm-gcc makes completely invalid decl file attributes and won't ever be 7360b57cec5SDimitry Andric // fixed, so we need to know to ignore these. 7370b57cec5SDimitry Andric return GetProducer() == eProducerLLVMGCC; 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric bool DWARFUnit::Supports_unnamed_objc_bitfields() { 741349cc55cSDimitry Andric if (GetProducer() == eProducerClang) 742349cc55cSDimitry Andric return GetProducerVersion() >= llvm::VersionTuple(425, 0, 13); 743349cc55cSDimitry Andric // Assume all other compilers didn't have incorrect ObjC bitfield info. 744349cc55cSDimitry Andric return true; 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric void DWARFUnit::ParseProducerInfo() { 748349cc55cSDimitry Andric m_producer = eProducerOther; 7490b57cec5SDimitry Andric const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 750349cc55cSDimitry Andric if (!die) 751349cc55cSDimitry Andric return; 7520b57cec5SDimitry Andric 753349cc55cSDimitry Andric llvm::StringRef producer( 754349cc55cSDimitry Andric die->GetAttributeValueAsString(this, DW_AT_producer, nullptr)); 755349cc55cSDimitry Andric if (producer.empty()) 756349cc55cSDimitry Andric return; 757349cc55cSDimitry Andric 758349cc55cSDimitry Andric static const RegularExpression g_swiftlang_version_regex( 759349cc55cSDimitry Andric llvm::StringRef(R"(swiftlang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))")); 760349cc55cSDimitry Andric static const RegularExpression g_clang_version_regex( 761349cc55cSDimitry Andric llvm::StringRef(R"(clang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))")); 762349cc55cSDimitry Andric static const RegularExpression g_llvm_gcc_regex( 763349cc55cSDimitry Andric llvm::StringRef(R"(4\.[012]\.[01] )" 764349cc55cSDimitry Andric R"(\(Based on Apple Inc\. build [0-9]+\) )" 765349cc55cSDimitry Andric R"(\(LLVM build [\.0-9]+\)$)")); 766349cc55cSDimitry Andric 767349cc55cSDimitry Andric llvm::SmallVector<llvm::StringRef, 3> matches; 768349cc55cSDimitry Andric if (g_swiftlang_version_regex.Execute(producer, &matches)) { 769349cc55cSDimitry Andric m_producer_version.tryParse(matches[1]); 770349cc55cSDimitry Andric m_producer = eProducerSwift; 771349cc55cSDimitry Andric } else if (producer.contains("clang")) { 772349cc55cSDimitry Andric if (g_clang_version_regex.Execute(producer, &matches)) 773349cc55cSDimitry Andric m_producer_version.tryParse(matches[1]); 7740b57cec5SDimitry Andric m_producer = eProducerClang; 775349cc55cSDimitry Andric } else if (producer.contains("GNU")) { 7760b57cec5SDimitry Andric m_producer = eProducerGCC; 777349cc55cSDimitry Andric } else if (g_llvm_gcc_regex.Execute(producer)) { 778349cc55cSDimitry Andric m_producer = eProducerLLVMGCC; 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric DWARFProducer DWARFUnit::GetProducer() { 7830b57cec5SDimitry Andric if (m_producer == eProducerInvalid) 7840b57cec5SDimitry Andric ParseProducerInfo(); 7850b57cec5SDimitry Andric return m_producer; 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 788349cc55cSDimitry Andric llvm::VersionTuple DWARFUnit::GetProducerVersion() { 789349cc55cSDimitry Andric if (m_producer_version.empty()) 7900b57cec5SDimitry Andric ParseProducerInfo(); 791349cc55cSDimitry Andric return m_producer_version; 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 7945ffd83dbSDimitry Andric uint64_t DWARFUnit::GetDWARFLanguageType() { 7955ffd83dbSDimitry Andric if (m_language_type) 7965ffd83dbSDimitry Andric return *m_language_type; 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 7995ffd83dbSDimitry Andric if (!die) 8005ffd83dbSDimitry Andric m_language_type = 0; 8015ffd83dbSDimitry Andric else 8025ffd83dbSDimitry Andric m_language_type = die->GetAttributeValueAsUnsigned(this, DW_AT_language, 0); 8035ffd83dbSDimitry Andric return *m_language_type; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric bool DWARFUnit::GetIsOptimized() { 8070b57cec5SDimitry Andric if (m_is_optimized == eLazyBoolCalculate) { 8080b57cec5SDimitry Andric const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 8090b57cec5SDimitry Andric if (die) { 8100b57cec5SDimitry Andric m_is_optimized = eLazyBoolNo; 8110b57cec5SDimitry Andric if (die->GetAttributeValueAsUnsigned(this, DW_AT_APPLE_optimized, 0) == 8120b57cec5SDimitry Andric 1) { 8130b57cec5SDimitry Andric m_is_optimized = eLazyBoolYes; 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric return m_is_optimized == eLazyBoolYes; 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric FileSpec::Style DWARFUnit::GetPathStyle() { 8210b57cec5SDimitry Andric if (!m_comp_dir) 8220b57cec5SDimitry Andric ComputeCompDirAndGuessPathStyle(); 8230b57cec5SDimitry Andric return m_comp_dir->GetPathStyle(); 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric const FileSpec &DWARFUnit::GetCompilationDirectory() { 8270b57cec5SDimitry Andric if (!m_comp_dir) 8280b57cec5SDimitry Andric ComputeCompDirAndGuessPathStyle(); 8290b57cec5SDimitry Andric return *m_comp_dir; 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric const FileSpec &DWARFUnit::GetAbsolutePath() { 8330b57cec5SDimitry Andric if (!m_file_spec) 8340b57cec5SDimitry Andric ComputeAbsolutePath(); 8350b57cec5SDimitry Andric return *m_file_spec; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric FileSpec DWARFUnit::GetFile(size_t file_idx) { 8390b57cec5SDimitry Andric return m_dwarf.GetFile(*this, file_idx); 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric // DWARF2/3 suggests the form hostname:pathname for compilation directory. 8430b57cec5SDimitry Andric // Remove the host part if present. 8440b57cec5SDimitry Andric static llvm::StringRef 8450b57cec5SDimitry Andric removeHostnameFromPathname(llvm::StringRef path_from_dwarf) { 846480093f4SDimitry Andric if (!path_from_dwarf.contains(':')) 847480093f4SDimitry Andric return path_from_dwarf; 8480b57cec5SDimitry Andric llvm::StringRef host, path; 8490b57cec5SDimitry Andric std::tie(host, path) = path_from_dwarf.split(':'); 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric if (host.contains('/')) 8520b57cec5SDimitry Andric return path_from_dwarf; 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric // check whether we have a windows path, and so the first character is a 8550b57cec5SDimitry Andric // drive-letter not a hostname. 85681ad6265SDimitry Andric if (host.size() == 1 && llvm::isAlpha(host[0]) && 8575f757f3fSDimitry Andric (path.starts_with("\\") || path.starts_with("/"))) 8580b57cec5SDimitry Andric return path_from_dwarf; 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric return path; 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric void DWARFUnit::ComputeCompDirAndGuessPathStyle() { 8640b57cec5SDimitry Andric m_comp_dir = FileSpec(); 8650b57cec5SDimitry Andric const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 8660b57cec5SDimitry Andric if (!die) 8670b57cec5SDimitry Andric return; 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric llvm::StringRef comp_dir = removeHostnameFromPathname( 8700b57cec5SDimitry Andric die->GetAttributeValueAsString(this, DW_AT_comp_dir, nullptr)); 8710b57cec5SDimitry Andric if (!comp_dir.empty()) { 8720b57cec5SDimitry Andric FileSpec::Style comp_dir_style = 87381ad6265SDimitry Andric FileSpec::GuessPathStyle(comp_dir).value_or(FileSpec::Style::native); 8745ffd83dbSDimitry Andric m_comp_dir = FileSpec(comp_dir, comp_dir_style); 8750b57cec5SDimitry Andric } else { 8760b57cec5SDimitry Andric // Try to detect the style based on the DW_AT_name attribute, but just store 8770b57cec5SDimitry Andric // the detected style in the m_comp_dir field. 8780b57cec5SDimitry Andric const char *name = 8790b57cec5SDimitry Andric die->GetAttributeValueAsString(this, DW_AT_name, nullptr); 8800b57cec5SDimitry Andric m_comp_dir = FileSpec( 88181ad6265SDimitry Andric "", FileSpec::GuessPathStyle(name).value_or(FileSpec::Style::native)); 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andric void DWARFUnit::ComputeAbsolutePath() { 8860b57cec5SDimitry Andric m_file_spec = FileSpec(); 8870b57cec5SDimitry Andric const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 8880b57cec5SDimitry Andric if (!die) 8890b57cec5SDimitry Andric return; 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric m_file_spec = 8920b57cec5SDimitry Andric FileSpec(die->GetAttributeValueAsString(this, DW_AT_name, nullptr), 8930b57cec5SDimitry Andric GetPathStyle()); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric if (m_file_spec->IsRelative()) 8960b57cec5SDimitry Andric m_file_spec->MakeAbsolute(GetCompilationDirectory()); 8970b57cec5SDimitry Andric } 8980b57cec5SDimitry Andric 899*0fca6ea1SDimitry Andric SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile(bool load_all_debug_info) { 900*0fca6ea1SDimitry Andric if (load_all_debug_info) 901480093f4SDimitry Andric ExtractUnitDIEIfNeeded(); 9025ffd83dbSDimitry Andric if (m_dwo) 9035ffd83dbSDimitry Andric return &llvm::cast<SymbolFileDWARFDwo>(m_dwo->GetSymbolFileDWARF()); 9045ffd83dbSDimitry Andric return nullptr; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 9080b57cec5SDimitry Andric if (m_func_aranges_up == nullptr) { 9095ffd83dbSDimitry Andric m_func_aranges_up = std::make_unique<DWARFDebugAranges>(); 9100b57cec5SDimitry Andric const DWARFDebugInfoEntry *die = DIEPtr(); 9110b57cec5SDimitry Andric if (die) 9120b57cec5SDimitry Andric die->BuildFunctionAddressRangeTable(this, m_func_aranges_up.get()); 9130b57cec5SDimitry Andric 9145ffd83dbSDimitry Andric if (m_dwo) { 9155ffd83dbSDimitry Andric const DWARFDebugInfoEntry *dwo_die = m_dwo->DIEPtr(); 9160b57cec5SDimitry Andric if (dwo_die) 9175ffd83dbSDimitry Andric dwo_die->BuildFunctionAddressRangeTable(m_dwo.get(), 9180b57cec5SDimitry Andric m_func_aranges_up.get()); 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric const bool minimize = false; 9220b57cec5SDimitry Andric m_func_aranges_up->Sort(minimize); 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric return *m_func_aranges_up; 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric llvm::Expected<DWARFUnitSP> 9280b57cec5SDimitry Andric DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, 9290b57cec5SDimitry Andric const DWARFDataExtractor &debug_info, 930fe6060f1SDimitry Andric DIERef::Section section, lldb::offset_t *offset_ptr) { 9310b57cec5SDimitry Andric assert(debug_info.ValidOffset(*offset_ptr)); 9320b57cec5SDimitry Andric 9335f757f3fSDimitry Andric DWARFContext &context = dwarf.GetDWARFContext(); 934*0fca6ea1SDimitry Andric 935*0fca6ea1SDimitry Andric // FIXME: Either properly map between DIERef::Section and 936*0fca6ea1SDimitry Andric // llvm::DWARFSectionKind or switch to llvm's definition entirely. 937*0fca6ea1SDimitry Andric llvm::DWARFSectionKind section_kind_llvm = 938*0fca6ea1SDimitry Andric section == DIERef::Section::DebugInfo 939*0fca6ea1SDimitry Andric ? llvm::DWARFSectionKind::DW_SECT_INFO 940*0fca6ea1SDimitry Andric : llvm::DWARFSectionKind::DW_SECT_EXT_TYPES; 941*0fca6ea1SDimitry Andric 942*0fca6ea1SDimitry Andric llvm::DWARFDataExtractor debug_info_llvm = debug_info.GetAsLLVMDWARF(); 943*0fca6ea1SDimitry Andric llvm::DWARFUnitHeader header; 944*0fca6ea1SDimitry Andric if (llvm::Error extract_err = header.extract( 945*0fca6ea1SDimitry Andric context.GetAsLLVM(), debug_info_llvm, offset_ptr, section_kind_llvm)) 946*0fca6ea1SDimitry Andric return std::move(extract_err); 9470b57cec5SDimitry Andric 9485f757f3fSDimitry Andric if (context.isDwo()) { 9495f757f3fSDimitry Andric const llvm::DWARFUnitIndex::Entry *entry = nullptr; 950*0fca6ea1SDimitry Andric const llvm::DWARFUnitIndex &index = header.isTypeUnit() 9515f757f3fSDimitry Andric ? context.GetAsLLVM().getTUIndex() 9525f757f3fSDimitry Andric : context.GetAsLLVM().getCUIndex(); 9535f757f3fSDimitry Andric if (index) { 954*0fca6ea1SDimitry Andric if (header.isTypeUnit()) 955*0fca6ea1SDimitry Andric entry = index.getFromHash(header.getTypeHash()); 956*0fca6ea1SDimitry Andric else if (auto dwo_id = header.getDWOId()) 9575f757f3fSDimitry Andric entry = index.getFromHash(*dwo_id); 9585f757f3fSDimitry Andric } 9595f757f3fSDimitry Andric if (!entry) 960*0fca6ea1SDimitry Andric entry = index.getFromOffset(header.getOffset()); 9615f757f3fSDimitry Andric if (entry) 962*0fca6ea1SDimitry Andric if (llvm::Error err = header.applyIndexEntry(entry)) 9635f757f3fSDimitry Andric return std::move(err); 9645f757f3fSDimitry Andric } 9655f757f3fSDimitry Andric 9665f757f3fSDimitry Andric const llvm::DWARFDebugAbbrev *abbr = dwarf.DebugAbbrev(); 9670b57cec5SDimitry Andric if (!abbr) 9680b57cec5SDimitry Andric return llvm::make_error<llvm::object::GenericBinaryError>( 9690b57cec5SDimitry Andric "No debug_abbrev data"); 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric bool abbr_offset_OK = 9720b57cec5SDimitry Andric dwarf.GetDWARFContext().getOrLoadAbbrevData().ValidOffset( 973*0fca6ea1SDimitry Andric header.getAbbrOffset()); 9740b57cec5SDimitry Andric if (!abbr_offset_OK) 9750b57cec5SDimitry Andric return llvm::make_error<llvm::object::GenericBinaryError>( 9760b57cec5SDimitry Andric "Abbreviation offset for unit is not valid"); 9770b57cec5SDimitry Andric 9785f757f3fSDimitry Andric llvm::Expected<const llvm::DWARFAbbreviationDeclarationSet *> abbrevs_or_err = 979*0fca6ea1SDimitry Andric abbr->getAbbreviationDeclarationSet(header.getAbbrOffset()); 9805f757f3fSDimitry Andric if (!abbrevs_or_err) 9815f757f3fSDimitry Andric return abbrevs_or_err.takeError(); 9825f757f3fSDimitry Andric 9835f757f3fSDimitry Andric const llvm::DWARFAbbreviationDeclarationSet *abbrevs = *abbrevs_or_err; 9840b57cec5SDimitry Andric if (!abbrevs) 9850b57cec5SDimitry Andric return llvm::make_error<llvm::object::GenericBinaryError>( 9860b57cec5SDimitry Andric "No abbrev exists at the specified offset."); 9870b57cec5SDimitry Andric 988480093f4SDimitry Andric bool is_dwo = dwarf.GetDWARFContext().isDwo(); 989*0fca6ea1SDimitry Andric if (header.isTypeUnit()) 990*0fca6ea1SDimitry Andric return DWARFUnitSP( 991*0fca6ea1SDimitry Andric new DWARFTypeUnit(dwarf, uid, header, *abbrevs, section, is_dwo)); 992*0fca6ea1SDimitry Andric return DWARFUnitSP( 993*0fca6ea1SDimitry Andric new DWARFCompileUnit(dwarf, uid, header, *abbrevs, section, is_dwo)); 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const { 9970b57cec5SDimitry Andric return m_section == DIERef::Section::DebugTypes 9980b57cec5SDimitry Andric ? m_dwarf.GetDWARFContext().getOrLoadDebugTypesData() 9990b57cec5SDimitry Andric : m_dwarf.GetDWARFContext().getOrLoadDebugInfoData(); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric uint32_t DWARFUnit::GetHeaderByteSize() const { 1003*0fca6ea1SDimitry Andric switch (m_header.getUnitType()) { 10040b57cec5SDimitry Andric case llvm::dwarf::DW_UT_compile: 10050b57cec5SDimitry Andric case llvm::dwarf::DW_UT_partial: 10060b57cec5SDimitry Andric return GetVersion() < 5 ? 11 : 12; 10070b57cec5SDimitry Andric case llvm::dwarf::DW_UT_skeleton: 10080b57cec5SDimitry Andric case llvm::dwarf::DW_UT_split_compile: 10090b57cec5SDimitry Andric return 20; 10100b57cec5SDimitry Andric case llvm::dwarf::DW_UT_type: 10110b57cec5SDimitry Andric case llvm::dwarf::DW_UT_split_type: 10120b57cec5SDimitry Andric return GetVersion() < 5 ? 23 : 24; 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric llvm_unreachable("invalid UnitType."); 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric 1017bdd1243dSDimitry Andric std::optional<uint64_t> 10185ffd83dbSDimitry Andric DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { 10195ffd83dbSDimitry Andric offset_t offset = GetStrOffsetsBase() + index * 4; 10205ffd83dbSDimitry Andric return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); 10215ffd83dbSDimitry Andric } 10225ffd83dbSDimitry Andric 10230b57cec5SDimitry Andric llvm::Expected<DWARFRangeList> 1024480093f4SDimitry Andric DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { 10250b57cec5SDimitry Andric if (GetVersion() <= 4) { 1026480093f4SDimitry Andric const DWARFDebugRanges *debug_ranges = m_dwarf.GetDebugRanges(); 10270b57cec5SDimitry Andric if (!debug_ranges) 1028480093f4SDimitry Andric return llvm::make_error<llvm::object::GenericBinaryError>( 1029480093f4SDimitry Andric "No debug_ranges section"); 103006c3fb27SDimitry Andric return debug_ranges->FindRanges(this, offset); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 1033fe6060f1SDimitry Andric if (!GetRnglistTable()) 103481ad6265SDimitry Andric return llvm::createStringError(std::errc::invalid_argument, 1035480093f4SDimitry Andric "missing or invalid range list table"); 1036480093f4SDimitry Andric 103706c3fb27SDimitry Andric llvm::DWARFDataExtractor data = GetRnglistData().GetAsLLVMDWARF(); 1038349cc55cSDimitry Andric 1039349cc55cSDimitry Andric // As DW_AT_rnglists_base may be missing we need to call setAddressSize. 1040*0fca6ea1SDimitry Andric data.setAddressSize(m_header.getAddressByteSize()); 1041349cc55cSDimitry Andric auto range_list_or_error = GetRnglistTable()->findList(data, offset); 1042480093f4SDimitry Andric if (!range_list_or_error) 1043480093f4SDimitry Andric return range_list_or_error.takeError(); 1044480093f4SDimitry Andric 1045480093f4SDimitry Andric llvm::Expected<llvm::DWARFAddressRangesVector> llvm_ranges = 1046480093f4SDimitry Andric range_list_or_error->getAbsoluteRanges( 1047480093f4SDimitry Andric llvm::object::SectionedAddress{GetBaseAddress()}, 1048e8d8bef9SDimitry Andric GetAddressByteSize(), [&](uint32_t index) { 1049480093f4SDimitry Andric uint32_t index_size = GetAddressByteSize(); 1050480093f4SDimitry Andric dw_offset_t addr_base = GetAddrBase(); 1051bdd1243dSDimitry Andric lldb::offset_t offset = 1052bdd1243dSDimitry Andric addr_base + static_cast<lldb::offset_t>(index) * index_size; 1053480093f4SDimitry Andric return llvm::object::SectionedAddress{ 1054480093f4SDimitry Andric m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64( 1055480093f4SDimitry Andric &offset, index_size)}; 1056480093f4SDimitry Andric }); 1057480093f4SDimitry Andric if (!llvm_ranges) 1058480093f4SDimitry Andric return llvm_ranges.takeError(); 1059480093f4SDimitry Andric 1060480093f4SDimitry Andric DWARFRangeList ranges; 1061480093f4SDimitry Andric for (const llvm::DWARFAddressRange &llvm_range : *llvm_ranges) { 1062480093f4SDimitry Andric ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC, 1063480093f4SDimitry Andric llvm_range.HighPC - llvm_range.LowPC)); 1064480093f4SDimitry Andric } 1065*0fca6ea1SDimitry Andric ranges.Sort(); 1066480093f4SDimitry Andric return ranges; 1067480093f4SDimitry Andric } 1068480093f4SDimitry Andric 10695f757f3fSDimitry Andric llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) { 1070fe6060f1SDimitry Andric llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index); 1071fe6060f1SDimitry Andric if (!maybe_offset) 1072fe6060f1SDimitry Andric return maybe_offset.takeError(); 1073fe6060f1SDimitry Andric return FindRnglistFromOffset(*maybe_offset); 10740b57cec5SDimitry Andric } 1075bdd1243dSDimitry Andric 1076bdd1243dSDimitry Andric bool DWARFUnit::HasAny(llvm::ArrayRef<dw_tag_t> tags) { 1077bdd1243dSDimitry Andric ExtractUnitDIEIfNeeded(); 1078bdd1243dSDimitry Andric if (m_dwo) 1079bdd1243dSDimitry Andric return m_dwo->HasAny(tags); 1080bdd1243dSDimitry Andric 1081bdd1243dSDimitry Andric for (const auto &die : m_die_array) { 1082bdd1243dSDimitry Andric for (const auto tag : tags) { 1083bdd1243dSDimitry Andric if (tag == die.Tag()) 1084bdd1243dSDimitry Andric return true; 1085bdd1243dSDimitry Andric } 1086bdd1243dSDimitry Andric } 1087bdd1243dSDimitry Andric return false; 1088bdd1243dSDimitry Andric } 1089