xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- DWARFDebugInfoEntry.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 "DWARFDebugInfoEntry.h"
100b57cec5SDimitry Andric 
11fe6060f1SDimitry Andric #include <cassert>
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include <algorithm>
14*0fca6ea1SDimitry Andric #include <limits>
15bdd1243dSDimitry Andric #include <optional>
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "lldb/Core/Module.h"
200b57cec5SDimitry Andric #include "lldb/Expression/DWARFExpression.h"
210b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
23bdd1243dSDimitry Andric #include "lldb/Utility/StreamString.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #include "DWARFCompileUnit.h"
260b57cec5SDimitry Andric #include "DWARFDebugAranges.h"
270b57cec5SDimitry Andric #include "DWARFDebugInfo.h"
280b57cec5SDimitry Andric #include "DWARFDebugRanges.h"
290b57cec5SDimitry Andric #include "DWARFDeclContext.h"
300b57cec5SDimitry Andric #include "DWARFFormValue.h"
310b57cec5SDimitry Andric #include "DWARFUnit.h"
320b57cec5SDimitry Andric #include "SymbolFileDWARF.h"
330b57cec5SDimitry Andric #include "SymbolFileDWARFDwo.h"
340b57cec5SDimitry Andric 
355f757f3fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
365f757f3fSDimitry Andric 
370b57cec5SDimitry Andric using namespace lldb_private;
3881ad6265SDimitry Andric using namespace lldb_private::dwarf;
395f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf;
400b57cec5SDimitry Andric extern int g_verbose;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric // Extract a debug info entry for a given DWARFUnit from the data
430b57cec5SDimitry Andric // starting at the offset in offset_ptr
440b57cec5SDimitry Andric bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
45*0fca6ea1SDimitry Andric                                   const DWARFUnit &unit,
460b57cec5SDimitry Andric                                   lldb::offset_t *offset_ptr) {
470b57cec5SDimitry Andric   m_offset = *offset_ptr;
48*0fca6ea1SDimitry Andric   auto report_error = [&](const char *fmt, const auto &...vals) {
49*0fca6ea1SDimitry Andric     unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
50*0fca6ea1SDimitry Andric         "[{0:x16}]: {1}, please file a bug and "
51*0fca6ea1SDimitry Andric         "attach the file at the start of this error message",
52*0fca6ea1SDimitry Andric         static_cast<uint64_t>(m_offset), llvm::formatv(fmt, vals...));
53*0fca6ea1SDimitry Andric     *offset_ptr = std::numeric_limits<lldb::offset_t>::max();
54*0fca6ea1SDimitry Andric     return false;
55*0fca6ea1SDimitry Andric   };
56*0fca6ea1SDimitry Andric 
570b57cec5SDimitry Andric   m_parent_idx = 0;
580b57cec5SDimitry Andric   m_sibling_idx = 0;
590b57cec5SDimitry Andric   const uint64_t abbr_idx = data.GetULEB128(offset_ptr);
60*0fca6ea1SDimitry Andric   if (abbr_idx > std::numeric_limits<uint16_t>::max())
61*0fca6ea1SDimitry Andric     return report_error("abbreviation code {0} too big", abbr_idx);
620b57cec5SDimitry Andric   m_abbr_idx = abbr_idx;
630b57cec5SDimitry Andric 
64fe6060f1SDimitry Andric   if (m_abbr_idx == 0) {
65fe6060f1SDimitry Andric     m_tag = llvm::dwarf::DW_TAG_null;
66fe6060f1SDimitry Andric     m_has_children = false;
67fe6060f1SDimitry Andric     return true; // NULL debug tag entry
68fe6060f1SDimitry Andric   }
69fe6060f1SDimitry Andric 
70*0fca6ea1SDimitry Andric   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(&unit);
71*0fca6ea1SDimitry Andric   if (abbrevDecl == nullptr)
72*0fca6ea1SDimitry Andric     return report_error("invalid abbreviation code {0}", abbr_idx);
73*0fca6ea1SDimitry Andric 
7406c3fb27SDimitry Andric   m_tag = abbrevDecl->getTag();
7506c3fb27SDimitry Andric   m_has_children = abbrevDecl->hasChildren();
760b57cec5SDimitry Andric   // Skip all data in the .debug_info or .debug_types for the attributes
7706c3fb27SDimitry Andric   for (const auto &attribute : abbrevDecl->attributes()) {
78*0fca6ea1SDimitry Andric     if (DWARFFormValue::SkipValue(attribute.Form, data, offset_ptr, &unit))
795f757f3fSDimitry Andric       continue;
800b57cec5SDimitry Andric 
81*0fca6ea1SDimitry Andric     return report_error("Unsupported DW_FORM_{1:x}", attribute.Form);
820b57cec5SDimitry Andric   }
830b57cec5SDimitry Andric   return true;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
86480093f4SDimitry Andric static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
870b57cec5SDimitry Andric                                              const DWARFDebugInfoEntry &die,
880b57cec5SDimitry Andric                                              const DWARFFormValue &value) {
890b57cec5SDimitry Andric   llvm::Expected<DWARFRangeList> expected_ranges =
900b57cec5SDimitry Andric       (value.Form() == DW_FORM_rnglistx)
910b57cec5SDimitry Andric           ? unit.FindRnglistFromIndex(value.Unsigned())
920b57cec5SDimitry Andric           : unit.FindRnglistFromOffset(value.Unsigned());
930b57cec5SDimitry Andric   if (expected_ranges)
940b57cec5SDimitry Andric     return std::move(*expected_ranges);
95bdd1243dSDimitry Andric 
960b57cec5SDimitry Andric   unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
97bdd1243dSDimitry Andric       "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but "
98bdd1243dSDimitry Andric       "range extraction failed ({3}), please file a bug "
990b57cec5SDimitry Andric       "and attach the file at the start of this error message",
100fe6060f1SDimitry Andric       die.GetOffset(),
101fe6060f1SDimitry Andric       llvm::dwarf::FormEncodingString(value.Form()).str().c_str(),
102fe6060f1SDimitry Andric       value.Unsigned(), toString(expected_ranges.takeError()).c_str());
1030b57cec5SDimitry Andric   return DWARFRangeList();
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
10606c3fb27SDimitry Andric static void ExtractAttrAndFormValue(
10706c3fb27SDimitry Andric     const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec,
10806c3fb27SDimitry Andric     dw_attr_t &attr, DWARFFormValue &form_value) {
10906c3fb27SDimitry Andric   attr = attr_spec.Attr;
11006c3fb27SDimitry Andric   form_value.FormRef() = attr_spec.Form;
11106c3fb27SDimitry Andric   if (attr_spec.isImplicitConst())
11206c3fb27SDimitry Andric     form_value.SetSigned(attr_spec.getImplicitConstValue());
11306c3fb27SDimitry Andric }
11406c3fb27SDimitry Andric 
1150b57cec5SDimitry Andric // GetDIENamesAndRanges
1160b57cec5SDimitry Andric //
1170b57cec5SDimitry Andric // Gets the valid address ranges for a given DIE by looking for a
1180b57cec5SDimitry Andric // DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
1190b57cec5SDimitry Andric bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
120480093f4SDimitry Andric     DWARFUnit *cu, const char *&name, const char *&mangled,
12106c3fb27SDimitry Andric     DWARFRangeList &ranges, std::optional<int> &decl_file,
12206c3fb27SDimitry Andric     std::optional<int> &decl_line, std::optional<int> &decl_column,
12306c3fb27SDimitry Andric     std::optional<int> &call_file, std::optional<int> &call_line,
12406c3fb27SDimitry Andric     std::optional<int> &call_column, DWARFExpressionList *frame_base) const {
1250b57cec5SDimitry Andric   dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
1260b57cec5SDimitry Andric   dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
1270b57cec5SDimitry Andric   std::vector<DWARFDIE> dies;
1280b57cec5SDimitry Andric   bool set_frame_base_loclist_addr = false;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
1310b57cec5SDimitry Andric   lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule();
1320b57cec5SDimitry Andric 
13306c3fb27SDimitry Andric   if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
1340b57cec5SDimitry Andric     const DWARFDataExtractor &data = cu->GetData();
1350b57cec5SDimitry Andric     lldb::offset_t offset = GetFirstAttributeOffset();
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric     if (!data.ValidOffset(offset))
1380b57cec5SDimitry Andric       return false;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     bool do_offset = false;
1410b57cec5SDimitry Andric 
14206c3fb27SDimitry Andric     for (const auto &attribute : abbrevDecl->attributes()) {
1430b57cec5SDimitry Andric       DWARFFormValue form_value(cu);
1440b57cec5SDimitry Andric       dw_attr_t attr;
14506c3fb27SDimitry Andric       ExtractAttrAndFormValue(attribute, attr, form_value);
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric       if (form_value.ExtractValue(data, &offset)) {
1480b57cec5SDimitry Andric         switch (attr) {
1490b57cec5SDimitry Andric         case DW_AT_low_pc:
1500b57cec5SDimitry Andric           lo_pc = form_value.Address();
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric           if (do_offset)
1530b57cec5SDimitry Andric             hi_pc += lo_pc;
1540b57cec5SDimitry Andric           do_offset = false;
1550b57cec5SDimitry Andric           break;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric         case DW_AT_entry_pc:
1580b57cec5SDimitry Andric           lo_pc = form_value.Address();
1590b57cec5SDimitry Andric           break;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric         case DW_AT_high_pc:
1620b57cec5SDimitry Andric           if (form_value.Form() == DW_FORM_addr ||
1630b57cec5SDimitry Andric               form_value.Form() == DW_FORM_addrx ||
1640b57cec5SDimitry Andric               form_value.Form() == DW_FORM_GNU_addr_index) {
1650b57cec5SDimitry Andric             hi_pc = form_value.Address();
1660b57cec5SDimitry Andric           } else {
1670b57cec5SDimitry Andric             hi_pc = form_value.Unsigned();
1680b57cec5SDimitry Andric             if (lo_pc == LLDB_INVALID_ADDRESS)
1690b57cec5SDimitry Andric               do_offset = hi_pc != LLDB_INVALID_ADDRESS;
1700b57cec5SDimitry Andric             else
1710b57cec5SDimitry Andric               hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save
1720b57cec5SDimitry Andric                               // on relocations
1730b57cec5SDimitry Andric           }
1740b57cec5SDimitry Andric           break;
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric         case DW_AT_ranges:
1770b57cec5SDimitry Andric           ranges = GetRangesOrReportError(*cu, *this, form_value);
1780b57cec5SDimitry Andric           break;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric         case DW_AT_name:
1810b57cec5SDimitry Andric           if (name == nullptr)
1820b57cec5SDimitry Andric             name = form_value.AsCString();
1830b57cec5SDimitry Andric           break;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric         case DW_AT_MIPS_linkage_name:
1860b57cec5SDimitry Andric         case DW_AT_linkage_name:
1870b57cec5SDimitry Andric           if (mangled == nullptr)
1880b57cec5SDimitry Andric             mangled = form_value.AsCString();
1890b57cec5SDimitry Andric           break;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric         case DW_AT_abstract_origin:
1920b57cec5SDimitry Andric           dies.push_back(form_value.Reference());
1930b57cec5SDimitry Andric           break;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric         case DW_AT_specification:
1960b57cec5SDimitry Andric           dies.push_back(form_value.Reference());
1970b57cec5SDimitry Andric           break;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric         case DW_AT_decl_file:
20006c3fb27SDimitry Andric           if (!decl_file)
2010b57cec5SDimitry Andric             decl_file = form_value.Unsigned();
2020b57cec5SDimitry Andric           break;
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric         case DW_AT_decl_line:
20506c3fb27SDimitry Andric           if (!decl_line)
2060b57cec5SDimitry Andric             decl_line = form_value.Unsigned();
2070b57cec5SDimitry Andric           break;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric         case DW_AT_decl_column:
21006c3fb27SDimitry Andric           if (!decl_column)
2110b57cec5SDimitry Andric             decl_column = form_value.Unsigned();
2120b57cec5SDimitry Andric           break;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric         case DW_AT_call_file:
21506c3fb27SDimitry Andric           if (!call_file)
2160b57cec5SDimitry Andric             call_file = form_value.Unsigned();
2170b57cec5SDimitry Andric           break;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric         case DW_AT_call_line:
22006c3fb27SDimitry Andric           if (!call_line)
2210b57cec5SDimitry Andric             call_line = form_value.Unsigned();
2220b57cec5SDimitry Andric           break;
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric         case DW_AT_call_column:
22506c3fb27SDimitry Andric           if (!call_column)
2260b57cec5SDimitry Andric             call_column = form_value.Unsigned();
2270b57cec5SDimitry Andric           break;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric         case DW_AT_frame_base:
2300b57cec5SDimitry Andric           if (frame_base) {
2310b57cec5SDimitry Andric             if (form_value.BlockData()) {
2320b57cec5SDimitry Andric               uint32_t block_offset =
2330b57cec5SDimitry Andric                   form_value.BlockData() - data.GetDataStart();
2340b57cec5SDimitry Andric               uint32_t block_length = form_value.Unsigned();
235753f127fSDimitry Andric               *frame_base =
236753f127fSDimitry Andric                   DWARFExpressionList(module,
237753f127fSDimitry Andric                                       DWARFExpression(DataExtractor(
238753f127fSDimitry Andric                                           data, block_offset, block_length)),
239753f127fSDimitry Andric                                       cu);
2400b57cec5SDimitry Andric             } else {
241480093f4SDimitry Andric               DataExtractor data = cu->GetLocationData();
2429dba64beSDimitry Andric               const dw_offset_t offset = form_value.Unsigned();
2439dba64beSDimitry Andric               if (data.ValidOffset(offset)) {
2449dba64beSDimitry Andric                 data = DataExtractor(data, offset, data.GetByteSize() - offset);
2450b57cec5SDimitry Andric                 if (lo_pc != LLDB_INVALID_ADDRESS) {
2460b57cec5SDimitry Andric                   assert(lo_pc >= cu->GetBaseAddress());
247753f127fSDimitry Andric                   DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
248753f127fSDimitry Andric                   frame_base->SetFuncFileAddress(lo_pc);
249753f127fSDimitry Andric                 } else
2500b57cec5SDimitry Andric                   set_frame_base_loclist_addr = true;
2510b57cec5SDimitry Andric               }
2520b57cec5SDimitry Andric             }
2530b57cec5SDimitry Andric           }
2540b57cec5SDimitry Andric           break;
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric         default:
2570b57cec5SDimitry Andric           break;
2580b57cec5SDimitry Andric         }
2590b57cec5SDimitry Andric       }
2600b57cec5SDimitry Andric     }
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   if (ranges.IsEmpty()) {
2640b57cec5SDimitry Andric     if (lo_pc != LLDB_INVALID_ADDRESS) {
2650b57cec5SDimitry Andric       if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
2660b57cec5SDimitry Andric         ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
2670b57cec5SDimitry Andric       else
2680b57cec5SDimitry Andric         ranges.Append(DWARFRangeList::Entry(lo_pc, 0));
2690b57cec5SDimitry Andric     }
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   if (set_frame_base_loclist_addr) {
2730b57cec5SDimitry Andric     dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
2740b57cec5SDimitry Andric     assert(lowest_range_pc >= cu->GetBaseAddress());
275753f127fSDimitry Andric     frame_base->SetFuncFileAddress(lowest_range_pc);
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
2790b57cec5SDimitry Andric     for (const DWARFDIE &die : dies) {
2800b57cec5SDimitry Andric       if (die) {
2810b57cec5SDimitry Andric         die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
2820b57cec5SDimitry Andric                                            decl_file, decl_line, decl_column,
2830b57cec5SDimitry Andric                                            call_file, call_line, call_column);
2840b57cec5SDimitry Andric       }
2850b57cec5SDimitry Andric     }
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric   return !ranges.IsEmpty();
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric // Get all attribute values for a given DIE, including following any
2910b57cec5SDimitry Andric // specification or abstract origin attributes and including those in the
2920b57cec5SDimitry Andric // results. Any duplicate attributes will have the first instance take
2930b57cec5SDimitry Andric // precedence (this can happen for declaration attributes).
29406c3fb27SDimitry Andric void DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu,
2955ffd83dbSDimitry Andric                                         DWARFAttributes &attributes,
2965ffd83dbSDimitry Andric                                         Recurse recurse,
2970b57cec5SDimitry Andric                                         uint32_t curr_depth) const {
2980b57cec5SDimitry Andric   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
29906c3fb27SDimitry Andric   if (!abbrevDecl) {
30006c3fb27SDimitry Andric     attributes.Clear();
30106c3fb27SDimitry Andric     return;
30206c3fb27SDimitry Andric   }
30306c3fb27SDimitry Andric 
3040b57cec5SDimitry Andric   const DWARFDataExtractor &data = cu->GetData();
3050b57cec5SDimitry Andric   lldb::offset_t offset = GetFirstAttributeOffset();
3060b57cec5SDimitry Andric 
30706c3fb27SDimitry Andric   for (const auto &attribute : abbrevDecl->attributes()) {
3080b57cec5SDimitry Andric     DWARFFormValue form_value(cu);
3090b57cec5SDimitry Andric     dw_attr_t attr;
31006c3fb27SDimitry Andric     ExtractAttrAndFormValue(attribute, attr, form_value);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric     // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
3130b57cec5SDimitry Andric     // attributes, the depth will be non-zero. We need to omit certain
3140b57cec5SDimitry Andric     // attributes that don't make sense.
3150b57cec5SDimitry Andric     switch (attr) {
3160b57cec5SDimitry Andric     case DW_AT_sibling:
3170b57cec5SDimitry Andric     case DW_AT_declaration:
3180b57cec5SDimitry Andric       if (curr_depth > 0) {
3190b57cec5SDimitry Andric         // This attribute doesn't make sense when combined with the DIE that
3200b57cec5SDimitry Andric         // references this DIE. We know a DIE is referencing this DIE because
3210b57cec5SDimitry Andric         // curr_depth is not zero
3220b57cec5SDimitry Andric         break;
3230b57cec5SDimitry Andric       }
324bdd1243dSDimitry Andric       [[fallthrough]];
3250b57cec5SDimitry Andric     default:
326fe6060f1SDimitry Andric       attributes.Append(form_value, offset, attr);
3270b57cec5SDimitry Andric       break;
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric 
3305ffd83dbSDimitry Andric     if (recurse == Recurse::yes &&
3315ffd83dbSDimitry Andric         ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) {
3320b57cec5SDimitry Andric       if (form_value.ExtractValue(data, &offset)) {
3330b57cec5SDimitry Andric         DWARFDIE spec_die = form_value.Reference();
3340b57cec5SDimitry Andric         if (spec_die)
3355ffd83dbSDimitry Andric           spec_die.GetDIE()->GetAttributes(spec_die.GetCU(), attributes,
3365ffd83dbSDimitry Andric                                            recurse, curr_depth + 1);
3370b57cec5SDimitry Andric       }
3380b57cec5SDimitry Andric     } else {
33906c3fb27SDimitry Andric       const dw_form_t form = form_value.Form();
340bdd1243dSDimitry Andric       std::optional<uint8_t> fixed_skip_size =
341bdd1243dSDimitry Andric           DWARFFormValue::GetFixedSize(form, cu);
3420b57cec5SDimitry Andric       if (fixed_skip_size)
3430b57cec5SDimitry Andric         offset += *fixed_skip_size;
3440b57cec5SDimitry Andric       else
3450b57cec5SDimitry Andric         DWARFFormValue::SkipValue(form, data, &offset, cu);
3460b57cec5SDimitry Andric     }
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric // GetAttributeValue
3510b57cec5SDimitry Andric //
3520b57cec5SDimitry Andric // Get the value of an attribute and return the .debug_info or .debug_types
3530b57cec5SDimitry Andric // offset of the attribute if it was properly extracted into form_value,
3540b57cec5SDimitry Andric // or zero if we fail since an offset of zero is invalid for an attribute (it
3550b57cec5SDimitry Andric // would be a compile unit header).
3560b57cec5SDimitry Andric dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
3570b57cec5SDimitry Andric     const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
3580b57cec5SDimitry Andric     dw_offset_t *end_attr_offset_ptr,
3590b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
3600b57cec5SDimitry Andric   if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
36106c3fb27SDimitry Andric     std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr);
3620b57cec5SDimitry Andric 
36306c3fb27SDimitry Andric     if (attr_idx) {
3640b57cec5SDimitry Andric       const DWARFDataExtractor &data = cu->GetData();
3650b57cec5SDimitry Andric       lldb::offset_t offset = GetFirstAttributeOffset();
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric       uint32_t idx = 0;
36806c3fb27SDimitry Andric       while (idx < *attr_idx)
36906c3fb27SDimitry Andric         DWARFFormValue::SkipValue(abbrevDecl->getFormByIndex(idx++), data,
37006c3fb27SDimitry Andric                                   &offset, cu);
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric       const dw_offset_t attr_offset = offset;
3730b57cec5SDimitry Andric       form_value.SetUnit(cu);
37406c3fb27SDimitry Andric       form_value.SetForm(abbrevDecl->getFormByIndex(idx));
3750b57cec5SDimitry Andric       if (form_value.ExtractValue(data, &offset)) {
3760b57cec5SDimitry Andric         if (end_attr_offset_ptr)
3770b57cec5SDimitry Andric           *end_attr_offset_ptr = offset;
3780b57cec5SDimitry Andric         return attr_offset;
3790b57cec5SDimitry Andric       }
3800b57cec5SDimitry Andric     }
3810b57cec5SDimitry Andric   }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric   if (check_specification_or_abstract_origin) {
3840b57cec5SDimitry Andric     if (GetAttributeValue(cu, DW_AT_specification, form_value)) {
3850b57cec5SDimitry Andric       DWARFDIE die = form_value.Reference();
3860b57cec5SDimitry Andric       if (die) {
3870b57cec5SDimitry Andric         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
3880b57cec5SDimitry Andric             die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
3890b57cec5SDimitry Andric         if (die_offset)
3900b57cec5SDimitry Andric           return die_offset;
3910b57cec5SDimitry Andric       }
3920b57cec5SDimitry Andric     }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric     if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) {
3950b57cec5SDimitry Andric       DWARFDIE die = form_value.Reference();
3960b57cec5SDimitry Andric       if (die) {
3970b57cec5SDimitry Andric         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
3980b57cec5SDimitry Andric             die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
3990b57cec5SDimitry Andric         if (die_offset)
4000b57cec5SDimitry Andric           return die_offset;
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric     }
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   return 0;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric // GetAttributeValueAsString
4080b57cec5SDimitry Andric //
4090b57cec5SDimitry Andric // Get the value of an attribute as a string return it. The resulting pointer
4100b57cec5SDimitry Andric // to the string data exists within the supplied SymbolFileDWARF and will only
4110b57cec5SDimitry Andric // be available as long as the SymbolFileDWARF is still around and it's content
4120b57cec5SDimitry Andric // doesn't change.
4130b57cec5SDimitry Andric const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
4140b57cec5SDimitry Andric     const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
4150b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
4160b57cec5SDimitry Andric   DWARFFormValue form_value;
4170b57cec5SDimitry Andric   if (GetAttributeValue(cu, attr, form_value, nullptr,
4180b57cec5SDimitry Andric                         check_specification_or_abstract_origin))
4190b57cec5SDimitry Andric     return form_value.AsCString();
4200b57cec5SDimitry Andric   return fail_value;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric // GetAttributeValueAsUnsigned
4240b57cec5SDimitry Andric //
4250b57cec5SDimitry Andric // Get the value of an attribute as unsigned and return it.
4260b57cec5SDimitry Andric uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
4270b57cec5SDimitry Andric     const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
4280b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
4290b57cec5SDimitry Andric   DWARFFormValue form_value;
4300b57cec5SDimitry Andric   if (GetAttributeValue(cu, attr, form_value, nullptr,
4310b57cec5SDimitry Andric                         check_specification_or_abstract_origin))
4320b57cec5SDimitry Andric     return form_value.Unsigned();
4330b57cec5SDimitry Andric   return fail_value;
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric 
436bdd1243dSDimitry Andric std::optional<uint64_t>
437bdd1243dSDimitry Andric DWARFDebugInfoEntry::GetAttributeValueAsOptionalUnsigned(
438bdd1243dSDimitry Andric     const DWARFUnit *cu, const dw_attr_t attr,
439bdd1243dSDimitry Andric     bool check_specification_or_abstract_origin) const {
440bdd1243dSDimitry Andric   DWARFFormValue form_value;
441bdd1243dSDimitry Andric   if (GetAttributeValue(cu, attr, form_value, nullptr,
442bdd1243dSDimitry Andric                         check_specification_or_abstract_origin))
443bdd1243dSDimitry Andric     return form_value.Unsigned();
444bdd1243dSDimitry Andric   return std::nullopt;
445bdd1243dSDimitry Andric }
446bdd1243dSDimitry Andric 
4470b57cec5SDimitry Andric // GetAttributeValueAsReference
4480b57cec5SDimitry Andric //
4490b57cec5SDimitry Andric // Get the value of an attribute as reference and fix up and compile unit
4500b57cec5SDimitry Andric // relative offsets as needed.
4510b57cec5SDimitry Andric DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference(
4520b57cec5SDimitry Andric     const DWARFUnit *cu, const dw_attr_t attr,
4530b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
4540b57cec5SDimitry Andric   DWARFFormValue form_value;
4550b57cec5SDimitry Andric   if (GetAttributeValue(cu, attr, form_value, nullptr,
4560b57cec5SDimitry Andric                         check_specification_or_abstract_origin))
4570b57cec5SDimitry Andric     return form_value.Reference();
4580b57cec5SDimitry Andric   return {};
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
4620b57cec5SDimitry Andric     const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
4630b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
4640b57cec5SDimitry Andric   DWARFFormValue form_value;
4650b57cec5SDimitry Andric   if (GetAttributeValue(cu, attr, form_value, nullptr,
4660b57cec5SDimitry Andric                         check_specification_or_abstract_origin))
4670b57cec5SDimitry Andric     return form_value.Address();
4680b57cec5SDimitry Andric   return fail_value;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric // GetAttributeHighPC
4720b57cec5SDimitry Andric //
4730b57cec5SDimitry Andric // Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
4740b57cec5SDimitry Andric // pc>.
4750b57cec5SDimitry Andric //
4760b57cec5SDimitry Andric // Returns the hi_pc or fail_value.
4770b57cec5SDimitry Andric dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
4780b57cec5SDimitry Andric     const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
4790b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
4800b57cec5SDimitry Andric   DWARFFormValue form_value;
4810b57cec5SDimitry Andric   if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
4820b57cec5SDimitry Andric                         check_specification_or_abstract_origin)) {
4830b57cec5SDimitry Andric     dw_form_t form = form_value.Form();
4840b57cec5SDimitry Andric     if (form == DW_FORM_addr || form == DW_FORM_addrx ||
4850b57cec5SDimitry Andric         form == DW_FORM_GNU_addr_index)
4860b57cec5SDimitry Andric       return form_value.Address();
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric     // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
4890b57cec5SDimitry Andric     return lo_pc + form_value.Unsigned();
4900b57cec5SDimitry Andric   }
4910b57cec5SDimitry Andric   return fail_value;
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric // GetAttributeAddressRange
4950b57cec5SDimitry Andric //
4960b57cec5SDimitry Andric // Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
4970b57cec5SDimitry Andric // from-low-pc>.
4980b57cec5SDimitry Andric //
4990b57cec5SDimitry Andric // Returns true or sets lo_pc and hi_pc to fail_value.
5000b57cec5SDimitry Andric bool DWARFDebugInfoEntry::GetAttributeAddressRange(
5010b57cec5SDimitry Andric     const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
5020b57cec5SDimitry Andric     uint64_t fail_value, bool check_specification_or_abstract_origin) const {
5030b57cec5SDimitry Andric   lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
5040b57cec5SDimitry Andric                                      check_specification_or_abstract_origin);
5050b57cec5SDimitry Andric   if (lo_pc != fail_value) {
5060b57cec5SDimitry Andric     hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
5070b57cec5SDimitry Andric                                check_specification_or_abstract_origin);
5080b57cec5SDimitry Andric     if (hi_pc != fail_value)
5090b57cec5SDimitry Andric       return true;
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric   lo_pc = fail_value;
5120b57cec5SDimitry Andric   hi_pc = fail_value;
5130b57cec5SDimitry Andric   return false;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
51606c3fb27SDimitry Andric DWARFRangeList DWARFDebugInfoEntry::GetAttributeAddressRanges(
51706c3fb27SDimitry Andric     DWARFUnit *cu, bool check_hi_lo_pc,
5180b57cec5SDimitry Andric     bool check_specification_or_abstract_origin) const {
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   DWARFFormValue form_value;
52106c3fb27SDimitry Andric   if (GetAttributeValue(cu, DW_AT_ranges, form_value))
52206c3fb27SDimitry Andric     return GetRangesOrReportError(*cu, *this, form_value);
52306c3fb27SDimitry Andric 
52406c3fb27SDimitry Andric   DWARFRangeList ranges;
52506c3fb27SDimitry Andric   if (check_hi_lo_pc) {
5260b57cec5SDimitry Andric     dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
5270b57cec5SDimitry Andric     dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
5280b57cec5SDimitry Andric     if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS,
5290b57cec5SDimitry Andric                                  check_specification_or_abstract_origin)) {
5300b57cec5SDimitry Andric       if (lo_pc < hi_pc)
5310b57cec5SDimitry Andric         ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
5320b57cec5SDimitry Andric     }
5330b57cec5SDimitry Andric   }
53406c3fb27SDimitry Andric   return ranges;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric // GetName
5380b57cec5SDimitry Andric //
5390b57cec5SDimitry Andric // Get value of the DW_AT_name attribute and return it if one exists, else
5400b57cec5SDimitry Andric // return NULL.
5410b57cec5SDimitry Andric const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const {
5420b57cec5SDimitry Andric   return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric // GetMangledName
5460b57cec5SDimitry Andric //
5470b57cec5SDimitry Andric // Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
5480b57cec5SDimitry Andric // exists, else return the value of the DW_AT_name attribute
5490b57cec5SDimitry Andric const char *
5500b57cec5SDimitry Andric DWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu,
5510b57cec5SDimitry Andric                                     bool substitute_name_allowed) const {
5520b57cec5SDimitry Andric   const char *name = nullptr;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
5550b57cec5SDimitry Andric   if (name)
5560b57cec5SDimitry Andric     return name;
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
5590b57cec5SDimitry Andric   if (name)
5600b57cec5SDimitry Andric     return name;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   if (!substitute_name_allowed)
5630b57cec5SDimitry Andric     return nullptr;
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
5660b57cec5SDimitry Andric   return name;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric // GetPubname
5700b57cec5SDimitry Andric //
5710b57cec5SDimitry Andric // Get value the name for a DIE as it should appear for a .debug_pubnames or
5720b57cec5SDimitry Andric // .debug_pubtypes section.
5730b57cec5SDimitry Andric const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const {
5740b57cec5SDimitry Andric   const char *name = nullptr;
5750b57cec5SDimitry Andric   if (!cu)
5760b57cec5SDimitry Andric     return name;
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
5790b57cec5SDimitry Andric   if (name)
5800b57cec5SDimitry Andric     return name;
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
5830b57cec5SDimitry Andric   if (name)
5840b57cec5SDimitry Andric     return name;
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
5870b57cec5SDimitry Andric   return name;
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric 
5905ffd83dbSDimitry Andric /// This function is builds a table very similar to the standard .debug_aranges
5915ffd83dbSDimitry Andric /// table, except that the actual DIE offset for the function is placed in the
5925ffd83dbSDimitry Andric /// table instead of the compile unit offset.
5930b57cec5SDimitry Andric void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
594e8d8bef9SDimitry Andric     DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
5950b57cec5SDimitry Andric   if (m_tag) {
5960b57cec5SDimitry Andric     if (m_tag == DW_TAG_subprogram) {
59706c3fb27SDimitry Andric       DWARFRangeList ranges =
59806c3fb27SDimitry Andric           GetAttributeAddressRanges(cu, /*check_hi_lo_pc=*/true);
599e8d8bef9SDimitry Andric       for (const auto &r : ranges) {
600e8d8bef9SDimitry Andric         debug_aranges->AppendRange(GetOffset(), r.GetRangeBase(),
601e8d8bef9SDimitry Andric                                    r.GetRangeEnd());
6020b57cec5SDimitry Andric       }
6030b57cec5SDimitry Andric     }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric     const DWARFDebugInfoEntry *child = GetFirstChild();
6060b57cec5SDimitry Andric     while (child) {
6070b57cec5SDimitry Andric       child->BuildFunctionAddressRangeTable(cu, debug_aranges);
6080b57cec5SDimitry Andric       child = child->GetSibling();
6090b57cec5SDimitry Andric     }
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const {
6140b57cec5SDimitry Andric   return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
6175f757f3fSDimitry Andric const llvm::DWARFAbbreviationDeclaration *
6180b57cec5SDimitry Andric DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const {
61906c3fb27SDimitry Andric   if (!cu)
6200b57cec5SDimitry Andric     return nullptr;
62106c3fb27SDimitry Andric 
6225f757f3fSDimitry Andric   const llvm::DWARFAbbreviationDeclarationSet *abbrev_set =
6235f757f3fSDimitry Andric       cu->GetAbbreviations();
62406c3fb27SDimitry Andric   if (!abbrev_set)
62506c3fb27SDimitry Andric     return nullptr;
62606c3fb27SDimitry Andric 
62706c3fb27SDimitry Andric   return abbrev_set->getAbbreviationDeclaration(m_abbr_idx);
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric 
6305ffd83dbSDimitry Andric bool DWARFDebugInfoEntry::IsGlobalOrStaticScopeVariable() const {
6315ffd83dbSDimitry Andric   if (Tag() != DW_TAG_variable)
6325ffd83dbSDimitry Andric     return false;
6335ffd83dbSDimitry Andric   const DWARFDebugInfoEntry *parent_die = GetParent();
6345ffd83dbSDimitry Andric   while (parent_die != nullptr) {
6355ffd83dbSDimitry Andric     switch (parent_die->Tag()) {
6365ffd83dbSDimitry Andric     case DW_TAG_subprogram:
6375ffd83dbSDimitry Andric     case DW_TAG_lexical_block:
6385ffd83dbSDimitry Andric     case DW_TAG_inlined_subroutine:
6395ffd83dbSDimitry Andric       return false;
6405ffd83dbSDimitry Andric 
6415ffd83dbSDimitry Andric     case DW_TAG_compile_unit:
6425ffd83dbSDimitry Andric     case DW_TAG_partial_unit:
6435ffd83dbSDimitry Andric       return true;
6445ffd83dbSDimitry Andric 
6455ffd83dbSDimitry Andric     default:
6465ffd83dbSDimitry Andric       break;
6475ffd83dbSDimitry Andric     }
6485ffd83dbSDimitry Andric     parent_die = parent_die->GetParent();
6495ffd83dbSDimitry Andric   }
6505ffd83dbSDimitry Andric   return false;
6515ffd83dbSDimitry Andric }
6525ffd83dbSDimitry Andric 
6530b57cec5SDimitry Andric bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
6540b57cec5SDimitry Andric   return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
6550b57cec5SDimitry Andric          m_sibling_idx == rhs.m_sibling_idx &&
6560b57cec5SDimitry Andric          m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
6570b57cec5SDimitry Andric          m_tag == rhs.m_tag;
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
6610b57cec5SDimitry Andric   return !(*this == rhs);
6620b57cec5SDimitry Andric }
663