xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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