xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (revision 061da546b983eb767bad15e67af1174fb0bcf31c)
1*061da546Spatrick //===-- DWARFDebugInfoEntry.cpp ---------------------------------*- C++ -*-===//
2*061da546Spatrick //
3*061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*061da546Spatrick //
7*061da546Spatrick //===----------------------------------------------------------------------===//
8*061da546Spatrick 
9*061da546Spatrick #include "DWARFDebugInfoEntry.h"
10*061da546Spatrick 
11*061da546Spatrick #include <assert.h>
12*061da546Spatrick 
13*061da546Spatrick #include <algorithm>
14*061da546Spatrick 
15*061da546Spatrick #include "llvm/Support/LEB128.h"
16*061da546Spatrick 
17*061da546Spatrick #include "lldb/Core/Module.h"
18*061da546Spatrick #include "lldb/Expression/DWARFExpression.h"
19*061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
20*061da546Spatrick #include "lldb/Utility/Stream.h"
21*061da546Spatrick 
22*061da546Spatrick #include "DWARFCompileUnit.h"
23*061da546Spatrick #include "DWARFDebugAbbrev.h"
24*061da546Spatrick #include "DWARFDebugAranges.h"
25*061da546Spatrick #include "DWARFDebugInfo.h"
26*061da546Spatrick #include "DWARFDebugRanges.h"
27*061da546Spatrick #include "DWARFDeclContext.h"
28*061da546Spatrick #include "DWARFFormValue.h"
29*061da546Spatrick #include "DWARFUnit.h"
30*061da546Spatrick #include "SymbolFileDWARF.h"
31*061da546Spatrick #include "SymbolFileDWARFDwo.h"
32*061da546Spatrick 
33*061da546Spatrick using namespace lldb_private;
34*061da546Spatrick using namespace std;
35*061da546Spatrick extern int g_verbose;
36*061da546Spatrick 
37*061da546Spatrick // Extract a debug info entry for a given DWARFUnit from the data
38*061da546Spatrick // starting at the offset in offset_ptr
39*061da546Spatrick bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
40*061da546Spatrick                                   const DWARFUnit *cu,
41*061da546Spatrick                                   lldb::offset_t *offset_ptr) {
42*061da546Spatrick   m_offset = *offset_ptr;
43*061da546Spatrick   m_parent_idx = 0;
44*061da546Spatrick   m_sibling_idx = 0;
45*061da546Spatrick   const uint64_t abbr_idx = data.GetULEB128(offset_ptr);
46*061da546Spatrick   lldbassert(abbr_idx <= UINT16_MAX);
47*061da546Spatrick   m_abbr_idx = abbr_idx;
48*061da546Spatrick 
49*061da546Spatrick   // assert (fixed_form_sizes);  // For best performance this should be
50*061da546Spatrick   // specified!
51*061da546Spatrick 
52*061da546Spatrick   if (m_abbr_idx) {
53*061da546Spatrick     lldb::offset_t offset = *offset_ptr;
54*061da546Spatrick     const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
55*061da546Spatrick     if (abbrevDecl == nullptr) {
56*061da546Spatrick       cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
57*061da546Spatrick           "{0x%8.8x}: invalid abbreviation code %u, please file a bug and "
58*061da546Spatrick           "attach the file at the start of this error message",
59*061da546Spatrick           m_offset, (unsigned)abbr_idx);
60*061da546Spatrick       // WE can't parse anymore if the DWARF is borked...
61*061da546Spatrick       *offset_ptr = UINT32_MAX;
62*061da546Spatrick       return false;
63*061da546Spatrick     }
64*061da546Spatrick     m_tag = abbrevDecl->Tag();
65*061da546Spatrick     m_has_children = abbrevDecl->HasChildren();
66*061da546Spatrick     // Skip all data in the .debug_info or .debug_types for the attributes
67*061da546Spatrick     const uint32_t numAttributes = abbrevDecl->NumAttributes();
68*061da546Spatrick     uint32_t i;
69*061da546Spatrick     dw_form_t form;
70*061da546Spatrick     for (i = 0; i < numAttributes; ++i) {
71*061da546Spatrick       form = abbrevDecl->GetFormByIndexUnchecked(i);
72*061da546Spatrick       llvm::Optional<uint8_t> fixed_skip_size =
73*061da546Spatrick           DWARFFormValue::GetFixedSize(form, cu);
74*061da546Spatrick       if (fixed_skip_size)
75*061da546Spatrick         offset += *fixed_skip_size;
76*061da546Spatrick       else {
77*061da546Spatrick         bool form_is_indirect = false;
78*061da546Spatrick         do {
79*061da546Spatrick           form_is_indirect = false;
80*061da546Spatrick           uint32_t form_size = 0;
81*061da546Spatrick           switch (form) {
82*061da546Spatrick           // Blocks if inlined data that have a length field and the data bytes
83*061da546Spatrick           // inlined in the .debug_info/.debug_types
84*061da546Spatrick           case DW_FORM_exprloc:
85*061da546Spatrick           case DW_FORM_block:
86*061da546Spatrick             form_size = data.GetULEB128(&offset);
87*061da546Spatrick             break;
88*061da546Spatrick           case DW_FORM_block1:
89*061da546Spatrick             form_size = data.GetU8_unchecked(&offset);
90*061da546Spatrick             break;
91*061da546Spatrick           case DW_FORM_block2:
92*061da546Spatrick             form_size = data.GetU16_unchecked(&offset);
93*061da546Spatrick             break;
94*061da546Spatrick           case DW_FORM_block4:
95*061da546Spatrick             form_size = data.GetU32_unchecked(&offset);
96*061da546Spatrick             break;
97*061da546Spatrick 
98*061da546Spatrick           // Inlined NULL terminated C-strings
99*061da546Spatrick           case DW_FORM_string:
100*061da546Spatrick             data.GetCStr(&offset);
101*061da546Spatrick             break;
102*061da546Spatrick 
103*061da546Spatrick           // Compile unit address sized values
104*061da546Spatrick           case DW_FORM_addr:
105*061da546Spatrick             form_size = cu->GetAddressByteSize();
106*061da546Spatrick             break;
107*061da546Spatrick           case DW_FORM_ref_addr:
108*061da546Spatrick             if (cu->GetVersion() <= 2)
109*061da546Spatrick               form_size = cu->GetAddressByteSize();
110*061da546Spatrick             else
111*061da546Spatrick               form_size = 4;
112*061da546Spatrick             break;
113*061da546Spatrick 
114*061da546Spatrick           // 0 sized form
115*061da546Spatrick           case DW_FORM_flag_present:
116*061da546Spatrick             form_size = 0;
117*061da546Spatrick             break;
118*061da546Spatrick 
119*061da546Spatrick           // 1 byte values
120*061da546Spatrick           case DW_FORM_addrx1:
121*061da546Spatrick           case DW_FORM_data1:
122*061da546Spatrick           case DW_FORM_flag:
123*061da546Spatrick           case DW_FORM_ref1:
124*061da546Spatrick           case DW_FORM_strx1:
125*061da546Spatrick             form_size = 1;
126*061da546Spatrick             break;
127*061da546Spatrick 
128*061da546Spatrick           // 2 byte values
129*061da546Spatrick           case DW_FORM_addrx2:
130*061da546Spatrick           case DW_FORM_data2:
131*061da546Spatrick           case DW_FORM_ref2:
132*061da546Spatrick           case DW_FORM_strx2:
133*061da546Spatrick             form_size = 2;
134*061da546Spatrick             break;
135*061da546Spatrick 
136*061da546Spatrick           // 3 byte values
137*061da546Spatrick           case DW_FORM_addrx3:
138*061da546Spatrick           case DW_FORM_strx3:
139*061da546Spatrick             form_size = 3;
140*061da546Spatrick             break;
141*061da546Spatrick 
142*061da546Spatrick           // 4 byte values
143*061da546Spatrick           case DW_FORM_addrx4:
144*061da546Spatrick           case DW_FORM_data4:
145*061da546Spatrick           case DW_FORM_ref4:
146*061da546Spatrick           case DW_FORM_strx4:
147*061da546Spatrick             form_size = 4;
148*061da546Spatrick             break;
149*061da546Spatrick 
150*061da546Spatrick           // 8 byte values
151*061da546Spatrick           case DW_FORM_data8:
152*061da546Spatrick           case DW_FORM_ref8:
153*061da546Spatrick           case DW_FORM_ref_sig8:
154*061da546Spatrick             form_size = 8;
155*061da546Spatrick             break;
156*061da546Spatrick 
157*061da546Spatrick           // signed or unsigned LEB 128 values
158*061da546Spatrick           case DW_FORM_addrx:
159*061da546Spatrick           case DW_FORM_loclistx:
160*061da546Spatrick           case DW_FORM_rnglistx:
161*061da546Spatrick           case DW_FORM_sdata:
162*061da546Spatrick           case DW_FORM_udata:
163*061da546Spatrick           case DW_FORM_ref_udata:
164*061da546Spatrick           case DW_FORM_GNU_addr_index:
165*061da546Spatrick           case DW_FORM_GNU_str_index:
166*061da546Spatrick           case DW_FORM_strx:
167*061da546Spatrick             data.Skip_LEB128(&offset);
168*061da546Spatrick             break;
169*061da546Spatrick 
170*061da546Spatrick           case DW_FORM_indirect:
171*061da546Spatrick             form_is_indirect = true;
172*061da546Spatrick             form = data.GetULEB128(&offset);
173*061da546Spatrick             break;
174*061da546Spatrick 
175*061da546Spatrick           case DW_FORM_strp:
176*061da546Spatrick           case DW_FORM_sec_offset:
177*061da546Spatrick             data.GetU32(&offset);
178*061da546Spatrick             break;
179*061da546Spatrick 
180*061da546Spatrick           case DW_FORM_implicit_const:
181*061da546Spatrick             form_size = 0;
182*061da546Spatrick             break;
183*061da546Spatrick 
184*061da546Spatrick           default:
185*061da546Spatrick             *offset_ptr = m_offset;
186*061da546Spatrick             return false;
187*061da546Spatrick           }
188*061da546Spatrick           offset += form_size;
189*061da546Spatrick 
190*061da546Spatrick         } while (form_is_indirect);
191*061da546Spatrick       }
192*061da546Spatrick     }
193*061da546Spatrick     *offset_ptr = offset;
194*061da546Spatrick     return true;
195*061da546Spatrick   } else {
196*061da546Spatrick     m_tag = llvm::dwarf::DW_TAG_null;
197*061da546Spatrick     m_has_children = false;
198*061da546Spatrick     return true; // NULL debug tag entry
199*061da546Spatrick   }
200*061da546Spatrick 
201*061da546Spatrick   return false;
202*061da546Spatrick }
203*061da546Spatrick 
204*061da546Spatrick static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
205*061da546Spatrick                                              const DWARFDebugInfoEntry &die,
206*061da546Spatrick                                              const DWARFFormValue &value) {
207*061da546Spatrick   llvm::Expected<DWARFRangeList> expected_ranges =
208*061da546Spatrick       (value.Form() == DW_FORM_rnglistx)
209*061da546Spatrick           ? unit.FindRnglistFromIndex(value.Unsigned())
210*061da546Spatrick           : unit.FindRnglistFromOffset(value.Unsigned());
211*061da546Spatrick   if (expected_ranges)
212*061da546Spatrick     return std::move(*expected_ranges);
213*061da546Spatrick   unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
214*061da546Spatrick       "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but "
215*061da546Spatrick       "range extraction failed (%s), please file a bug "
216*061da546Spatrick       "and attach the file at the start of this error message",
217*061da546Spatrick       die.GetOffset(), value.Unsigned(),
218*061da546Spatrick       toString(expected_ranges.takeError()).c_str());
219*061da546Spatrick   return DWARFRangeList();
220*061da546Spatrick }
221*061da546Spatrick 
222*061da546Spatrick // GetDIENamesAndRanges
223*061da546Spatrick //
224*061da546Spatrick // Gets the valid address ranges for a given DIE by looking for a
225*061da546Spatrick // DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
226*061da546Spatrick bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
227*061da546Spatrick     DWARFUnit *cu, const char *&name, const char *&mangled,
228*061da546Spatrick     DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
229*061da546Spatrick     int &call_file, int &call_line, int &call_column,
230*061da546Spatrick     DWARFExpression *frame_base) const {
231*061da546Spatrick   dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
232*061da546Spatrick   dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
233*061da546Spatrick   std::vector<DWARFDIE> dies;
234*061da546Spatrick   bool set_frame_base_loclist_addr = false;
235*061da546Spatrick 
236*061da546Spatrick   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
237*061da546Spatrick 
238*061da546Spatrick   SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
239*061da546Spatrick   lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule();
240*061da546Spatrick 
241*061da546Spatrick   if (abbrevDecl) {
242*061da546Spatrick     const DWARFDataExtractor &data = cu->GetData();
243*061da546Spatrick     lldb::offset_t offset = GetFirstAttributeOffset();
244*061da546Spatrick 
245*061da546Spatrick     if (!data.ValidOffset(offset))
246*061da546Spatrick       return false;
247*061da546Spatrick 
248*061da546Spatrick     const uint32_t numAttributes = abbrevDecl->NumAttributes();
249*061da546Spatrick     bool do_offset = false;
250*061da546Spatrick 
251*061da546Spatrick     for (uint32_t i = 0; i < numAttributes; ++i) {
252*061da546Spatrick       DWARFFormValue form_value(cu);
253*061da546Spatrick       dw_attr_t attr;
254*061da546Spatrick       abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
255*061da546Spatrick 
256*061da546Spatrick       if (form_value.ExtractValue(data, &offset)) {
257*061da546Spatrick         switch (attr) {
258*061da546Spatrick         case DW_AT_low_pc:
259*061da546Spatrick           lo_pc = form_value.Address();
260*061da546Spatrick 
261*061da546Spatrick           if (do_offset)
262*061da546Spatrick             hi_pc += lo_pc;
263*061da546Spatrick           do_offset = false;
264*061da546Spatrick           break;
265*061da546Spatrick 
266*061da546Spatrick         case DW_AT_entry_pc:
267*061da546Spatrick           lo_pc = form_value.Address();
268*061da546Spatrick           break;
269*061da546Spatrick 
270*061da546Spatrick         case DW_AT_high_pc:
271*061da546Spatrick           if (form_value.Form() == DW_FORM_addr ||
272*061da546Spatrick               form_value.Form() == DW_FORM_addrx ||
273*061da546Spatrick               form_value.Form() == DW_FORM_GNU_addr_index) {
274*061da546Spatrick             hi_pc = form_value.Address();
275*061da546Spatrick           } else {
276*061da546Spatrick             hi_pc = form_value.Unsigned();
277*061da546Spatrick             if (lo_pc == LLDB_INVALID_ADDRESS)
278*061da546Spatrick               do_offset = hi_pc != LLDB_INVALID_ADDRESS;
279*061da546Spatrick             else
280*061da546Spatrick               hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save
281*061da546Spatrick                               // on relocations
282*061da546Spatrick           }
283*061da546Spatrick           break;
284*061da546Spatrick 
285*061da546Spatrick         case DW_AT_ranges:
286*061da546Spatrick           ranges = GetRangesOrReportError(*cu, *this, form_value);
287*061da546Spatrick           break;
288*061da546Spatrick 
289*061da546Spatrick         case DW_AT_name:
290*061da546Spatrick           if (name == nullptr)
291*061da546Spatrick             name = form_value.AsCString();
292*061da546Spatrick           break;
293*061da546Spatrick 
294*061da546Spatrick         case DW_AT_MIPS_linkage_name:
295*061da546Spatrick         case DW_AT_linkage_name:
296*061da546Spatrick           if (mangled == nullptr)
297*061da546Spatrick             mangled = form_value.AsCString();
298*061da546Spatrick           break;
299*061da546Spatrick 
300*061da546Spatrick         case DW_AT_abstract_origin:
301*061da546Spatrick           dies.push_back(form_value.Reference());
302*061da546Spatrick           break;
303*061da546Spatrick 
304*061da546Spatrick         case DW_AT_specification:
305*061da546Spatrick           dies.push_back(form_value.Reference());
306*061da546Spatrick           break;
307*061da546Spatrick 
308*061da546Spatrick         case DW_AT_decl_file:
309*061da546Spatrick           if (decl_file == 0)
310*061da546Spatrick             decl_file = form_value.Unsigned();
311*061da546Spatrick           break;
312*061da546Spatrick 
313*061da546Spatrick         case DW_AT_decl_line:
314*061da546Spatrick           if (decl_line == 0)
315*061da546Spatrick             decl_line = form_value.Unsigned();
316*061da546Spatrick           break;
317*061da546Spatrick 
318*061da546Spatrick         case DW_AT_decl_column:
319*061da546Spatrick           if (decl_column == 0)
320*061da546Spatrick             decl_column = form_value.Unsigned();
321*061da546Spatrick           break;
322*061da546Spatrick 
323*061da546Spatrick         case DW_AT_call_file:
324*061da546Spatrick           if (call_file == 0)
325*061da546Spatrick             call_file = form_value.Unsigned();
326*061da546Spatrick           break;
327*061da546Spatrick 
328*061da546Spatrick         case DW_AT_call_line:
329*061da546Spatrick           if (call_line == 0)
330*061da546Spatrick             call_line = form_value.Unsigned();
331*061da546Spatrick           break;
332*061da546Spatrick 
333*061da546Spatrick         case DW_AT_call_column:
334*061da546Spatrick           if (call_column == 0)
335*061da546Spatrick             call_column = form_value.Unsigned();
336*061da546Spatrick           break;
337*061da546Spatrick 
338*061da546Spatrick         case DW_AT_frame_base:
339*061da546Spatrick           if (frame_base) {
340*061da546Spatrick             if (form_value.BlockData()) {
341*061da546Spatrick               uint32_t block_offset =
342*061da546Spatrick                   form_value.BlockData() - data.GetDataStart();
343*061da546Spatrick               uint32_t block_length = form_value.Unsigned();
344*061da546Spatrick               *frame_base = DWARFExpression(
345*061da546Spatrick                   module, DataExtractor(data, block_offset, block_length), cu);
346*061da546Spatrick             } else {
347*061da546Spatrick               DataExtractor data = cu->GetLocationData();
348*061da546Spatrick               const dw_offset_t offset = form_value.Unsigned();
349*061da546Spatrick               if (data.ValidOffset(offset)) {
350*061da546Spatrick                 data = DataExtractor(data, offset, data.GetByteSize() - offset);
351*061da546Spatrick                 *frame_base = DWARFExpression(module, data, cu);
352*061da546Spatrick                 if (lo_pc != LLDB_INVALID_ADDRESS) {
353*061da546Spatrick                   assert(lo_pc >= cu->GetBaseAddress());
354*061da546Spatrick                   frame_base->SetLocationListAddresses(cu->GetBaseAddress(),
355*061da546Spatrick                                                        lo_pc);
356*061da546Spatrick                 } else {
357*061da546Spatrick                   set_frame_base_loclist_addr = true;
358*061da546Spatrick                 }
359*061da546Spatrick               }
360*061da546Spatrick             }
361*061da546Spatrick           }
362*061da546Spatrick           break;
363*061da546Spatrick 
364*061da546Spatrick         default:
365*061da546Spatrick           break;
366*061da546Spatrick         }
367*061da546Spatrick       }
368*061da546Spatrick     }
369*061da546Spatrick   }
370*061da546Spatrick 
371*061da546Spatrick   if (ranges.IsEmpty()) {
372*061da546Spatrick     if (lo_pc != LLDB_INVALID_ADDRESS) {
373*061da546Spatrick       if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
374*061da546Spatrick         ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
375*061da546Spatrick       else
376*061da546Spatrick         ranges.Append(DWARFRangeList::Entry(lo_pc, 0));
377*061da546Spatrick     }
378*061da546Spatrick   }
379*061da546Spatrick 
380*061da546Spatrick   if (set_frame_base_loclist_addr) {
381*061da546Spatrick     dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
382*061da546Spatrick     assert(lowest_range_pc >= cu->GetBaseAddress());
383*061da546Spatrick     frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc);
384*061da546Spatrick   }
385*061da546Spatrick 
386*061da546Spatrick   if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
387*061da546Spatrick     for (const DWARFDIE &die : dies) {
388*061da546Spatrick       if (die) {
389*061da546Spatrick         die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
390*061da546Spatrick                                            decl_file, decl_line, decl_column,
391*061da546Spatrick                                            call_file, call_line, call_column);
392*061da546Spatrick       }
393*061da546Spatrick     }
394*061da546Spatrick   }
395*061da546Spatrick   return !ranges.IsEmpty();
396*061da546Spatrick }
397*061da546Spatrick 
398*061da546Spatrick // Dump
399*061da546Spatrick //
400*061da546Spatrick // Dumps a debug information entry and all of it's attributes to the specified
401*061da546Spatrick // stream.
402*061da546Spatrick void DWARFDebugInfoEntry::Dump(const DWARFUnit *cu, Stream &s,
403*061da546Spatrick                                uint32_t recurse_depth) const {
404*061da546Spatrick   const DWARFDataExtractor &data = cu->GetData();
405*061da546Spatrick   lldb::offset_t offset = m_offset;
406*061da546Spatrick 
407*061da546Spatrick   if (data.ValidOffset(offset)) {
408*061da546Spatrick     dw_uleb128_t abbrCode = data.GetULEB128(&offset);
409*061da546Spatrick 
410*061da546Spatrick     s.Printf("\n0x%8.8x: ", m_offset);
411*061da546Spatrick     s.Indent();
412*061da546Spatrick     if (abbrCode != m_abbr_idx) {
413*061da546Spatrick       s.Printf("error: DWARF has been modified\n");
414*061da546Spatrick     } else if (abbrCode) {
415*061da546Spatrick       const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
416*061da546Spatrick       if (abbrevDecl) {
417*061da546Spatrick         s.PutCString(DW_TAG_value_to_name(abbrevDecl->Tag()));
418*061da546Spatrick         s.Printf(" [%u] %c\n", abbrCode, abbrevDecl->HasChildren() ? '*' : ' ');
419*061da546Spatrick 
420*061da546Spatrick         // Dump all data in the .debug_info/.debug_types for the attributes
421*061da546Spatrick         const uint32_t numAttributes = abbrevDecl->NumAttributes();
422*061da546Spatrick         for (uint32_t i = 0; i < numAttributes; ++i) {
423*061da546Spatrick           DWARFFormValue form_value(cu);
424*061da546Spatrick           dw_attr_t attr;
425*061da546Spatrick           abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
426*061da546Spatrick 
427*061da546Spatrick           DumpAttribute(cu, data, &offset, s, attr, form_value);
428*061da546Spatrick         }
429*061da546Spatrick 
430*061da546Spatrick         const DWARFDebugInfoEntry *child = GetFirstChild();
431*061da546Spatrick         if (recurse_depth > 0 && child) {
432*061da546Spatrick           s.IndentMore();
433*061da546Spatrick 
434*061da546Spatrick           while (child) {
435*061da546Spatrick             child->Dump(cu, s, recurse_depth - 1);
436*061da546Spatrick             child = child->GetSibling();
437*061da546Spatrick           }
438*061da546Spatrick           s.IndentLess();
439*061da546Spatrick         }
440*061da546Spatrick       } else
441*061da546Spatrick         s.Printf("Abbreviation code note found in 'debug_abbrev' class for "
442*061da546Spatrick                  "code: %u\n",
443*061da546Spatrick                  abbrCode);
444*061da546Spatrick     } else {
445*061da546Spatrick       s.Printf("NULL\n");
446*061da546Spatrick     }
447*061da546Spatrick   }
448*061da546Spatrick }
449*061da546Spatrick 
450*061da546Spatrick // DumpAttribute
451*061da546Spatrick //
452*061da546Spatrick // Dumps a debug information entry attribute along with it's form. Any special
453*061da546Spatrick // display of attributes is done (disassemble location lists, show enumeration
454*061da546Spatrick // values for attributes, etc).
455*061da546Spatrick void DWARFDebugInfoEntry::DumpAttribute(
456*061da546Spatrick     const DWARFUnit *cu, const DWARFDataExtractor &data,
457*061da546Spatrick     lldb::offset_t *offset_ptr, Stream &s, dw_attr_t attr,
458*061da546Spatrick     DWARFFormValue &form_value) {
459*061da546Spatrick   bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
460*061da546Spatrick 
461*061da546Spatrick   s.Printf("            ");
462*061da546Spatrick   s.Indent(DW_AT_value_to_name(attr));
463*061da546Spatrick 
464*061da546Spatrick   if (show_form) {
465*061da546Spatrick     s.Printf("[%s", DW_FORM_value_to_name(form_value.Form()));
466*061da546Spatrick   }
467*061da546Spatrick 
468*061da546Spatrick   if (!form_value.ExtractValue(data, offset_ptr))
469*061da546Spatrick     return;
470*061da546Spatrick 
471*061da546Spatrick   if (show_form) {
472*061da546Spatrick     if (form_value.Form() == DW_FORM_indirect) {
473*061da546Spatrick       s.Printf(" [%s]", DW_FORM_value_to_name(form_value.Form()));
474*061da546Spatrick     }
475*061da546Spatrick 
476*061da546Spatrick     s.PutCString("] ");
477*061da546Spatrick   }
478*061da546Spatrick 
479*061da546Spatrick   s.PutCString("( ");
480*061da546Spatrick 
481*061da546Spatrick   // Check to see if we have any special attribute formatters
482*061da546Spatrick   switch (attr) {
483*061da546Spatrick   case DW_AT_stmt_list:
484*061da546Spatrick     s.Printf("0x%8.8" PRIx64, form_value.Unsigned());
485*061da546Spatrick     break;
486*061da546Spatrick 
487*061da546Spatrick   case DW_AT_language:
488*061da546Spatrick     s.PutCString(DW_LANG_value_to_name(form_value.Unsigned()));
489*061da546Spatrick     break;
490*061da546Spatrick 
491*061da546Spatrick   case DW_AT_encoding:
492*061da546Spatrick     s.PutCString(DW_ATE_value_to_name(form_value.Unsigned()));
493*061da546Spatrick     break;
494*061da546Spatrick 
495*061da546Spatrick   case DW_AT_frame_base:
496*061da546Spatrick   case DW_AT_location:
497*061da546Spatrick   case DW_AT_data_member_location: {
498*061da546Spatrick     const uint8_t *blockData = form_value.BlockData();
499*061da546Spatrick     if (blockData) {
500*061da546Spatrick       // Location description is inlined in data in the form value
501*061da546Spatrick       DWARFDataExtractor locationData(data,
502*061da546Spatrick                                       (*offset_ptr) - form_value.Unsigned(),
503*061da546Spatrick                                       form_value.Unsigned());
504*061da546Spatrick       DWARFExpression::PrintDWARFExpression(
505*061da546Spatrick           s, locationData, DWARFUnit::GetAddressByteSize(cu), 4, false);
506*061da546Spatrick     } else {
507*061da546Spatrick       // We have a location list offset as the value that is the offset into
508*061da546Spatrick       // the .debug_loc section that describes the value over it's lifetime
509*061da546Spatrick       uint64_t debug_loc_offset = form_value.Unsigned();
510*061da546Spatrick       DWARFExpression::PrintDWARFLocationList(s, cu, cu->GetLocationData(),
511*061da546Spatrick                                               debug_loc_offset);
512*061da546Spatrick     }
513*061da546Spatrick   } break;
514*061da546Spatrick 
515*061da546Spatrick   case DW_AT_abstract_origin:
516*061da546Spatrick   case DW_AT_specification: {
517*061da546Spatrick     DWARFDIE abstract_die = form_value.Reference();
518*061da546Spatrick     form_value.Dump(s);
519*061da546Spatrick     //  *ostrm_ptr << HEX32 << abstract_die.GetOffset() << " ( ";
520*061da546Spatrick     abstract_die.GetName(s);
521*061da546Spatrick   } break;
522*061da546Spatrick 
523*061da546Spatrick   case DW_AT_type: {
524*061da546Spatrick     DWARFDIE type_die = form_value.Reference();
525*061da546Spatrick     s.PutCString(" ( ");
526*061da546Spatrick     type_die.AppendTypeName(s);
527*061da546Spatrick     s.PutCString(" )");
528*061da546Spatrick   } break;
529*061da546Spatrick 
530*061da546Spatrick   default:
531*061da546Spatrick     break;
532*061da546Spatrick   }
533*061da546Spatrick 
534*061da546Spatrick   s.PutCString(" )\n");
535*061da546Spatrick }
536*061da546Spatrick 
537*061da546Spatrick // Get all attribute values for a given DIE, including following any
538*061da546Spatrick // specification or abstract origin attributes and including those in the
539*061da546Spatrick // results. Any duplicate attributes will have the first instance take
540*061da546Spatrick // precedence (this can happen for declaration attributes).
541*061da546Spatrick size_t DWARFDebugInfoEntry::GetAttributes(
542*061da546Spatrick     const DWARFUnit *cu, DWARFAttributes &attributes,
543*061da546Spatrick     uint32_t curr_depth) const {
544*061da546Spatrick   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
545*061da546Spatrick   if (abbrevDecl) {
546*061da546Spatrick     const DWARFDataExtractor &data = cu->GetData();
547*061da546Spatrick     lldb::offset_t offset = GetFirstAttributeOffset();
548*061da546Spatrick 
549*061da546Spatrick     const uint32_t num_attributes = abbrevDecl->NumAttributes();
550*061da546Spatrick     for (uint32_t i = 0; i < num_attributes; ++i) {
551*061da546Spatrick       DWARFFormValue form_value(cu);
552*061da546Spatrick       dw_attr_t attr;
553*061da546Spatrick       abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
554*061da546Spatrick       const dw_form_t form = form_value.Form();
555*061da546Spatrick 
556*061da546Spatrick       // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
557*061da546Spatrick       // attributes, the depth will be non-zero. We need to omit certain
558*061da546Spatrick       // attributes that don't make sense.
559*061da546Spatrick       switch (attr) {
560*061da546Spatrick       case DW_AT_sibling:
561*061da546Spatrick       case DW_AT_declaration:
562*061da546Spatrick         if (curr_depth > 0) {
563*061da546Spatrick           // This attribute doesn't make sense when combined with the DIE that
564*061da546Spatrick           // references this DIE. We know a DIE is referencing this DIE because
565*061da546Spatrick           // curr_depth is not zero
566*061da546Spatrick           break;
567*061da546Spatrick         }
568*061da546Spatrick         LLVM_FALLTHROUGH;
569*061da546Spatrick       default:
570*061da546Spatrick         attributes.Append(cu, offset, attr, form);
571*061da546Spatrick         break;
572*061da546Spatrick       }
573*061da546Spatrick 
574*061da546Spatrick       if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) {
575*061da546Spatrick         if (form_value.ExtractValue(data, &offset)) {
576*061da546Spatrick           DWARFDIE spec_die = form_value.Reference();
577*061da546Spatrick           if (spec_die)
578*061da546Spatrick             spec_die.GetAttributes(attributes, curr_depth + 1);
579*061da546Spatrick         }
580*061da546Spatrick       } else {
581*061da546Spatrick         llvm::Optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu);
582*061da546Spatrick         if (fixed_skip_size)
583*061da546Spatrick           offset += *fixed_skip_size;
584*061da546Spatrick         else
585*061da546Spatrick           DWARFFormValue::SkipValue(form, data, &offset, cu);
586*061da546Spatrick       }
587*061da546Spatrick     }
588*061da546Spatrick   } else {
589*061da546Spatrick     attributes.Clear();
590*061da546Spatrick   }
591*061da546Spatrick   return attributes.Size();
592*061da546Spatrick }
593*061da546Spatrick 
594*061da546Spatrick // GetAttributeValue
595*061da546Spatrick //
596*061da546Spatrick // Get the value of an attribute and return the .debug_info or .debug_types
597*061da546Spatrick // offset of the attribute if it was properly extracted into form_value,
598*061da546Spatrick // or zero if we fail since an offset of zero is invalid for an attribute (it
599*061da546Spatrick // would be a compile unit header).
600*061da546Spatrick dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
601*061da546Spatrick     const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
602*061da546Spatrick     dw_offset_t *end_attr_offset_ptr,
603*061da546Spatrick     bool check_specification_or_abstract_origin) const {
604*061da546Spatrick   if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
605*061da546Spatrick     uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
606*061da546Spatrick 
607*061da546Spatrick     if (attr_idx != DW_INVALID_INDEX) {
608*061da546Spatrick       const DWARFDataExtractor &data = cu->GetData();
609*061da546Spatrick       lldb::offset_t offset = GetFirstAttributeOffset();
610*061da546Spatrick 
611*061da546Spatrick       uint32_t idx = 0;
612*061da546Spatrick       while (idx < attr_idx)
613*061da546Spatrick         DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++),
614*061da546Spatrick                                   data, &offset, cu);
615*061da546Spatrick 
616*061da546Spatrick       const dw_offset_t attr_offset = offset;
617*061da546Spatrick       form_value.SetUnit(cu);
618*061da546Spatrick       form_value.SetForm(abbrevDecl->GetFormByIndex(idx));
619*061da546Spatrick       if (form_value.ExtractValue(data, &offset)) {
620*061da546Spatrick         if (end_attr_offset_ptr)
621*061da546Spatrick           *end_attr_offset_ptr = offset;
622*061da546Spatrick         return attr_offset;
623*061da546Spatrick       }
624*061da546Spatrick     }
625*061da546Spatrick   }
626*061da546Spatrick 
627*061da546Spatrick   if (check_specification_or_abstract_origin) {
628*061da546Spatrick     if (GetAttributeValue(cu, DW_AT_specification, form_value)) {
629*061da546Spatrick       DWARFDIE die = form_value.Reference();
630*061da546Spatrick       if (die) {
631*061da546Spatrick         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
632*061da546Spatrick             die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
633*061da546Spatrick         if (die_offset)
634*061da546Spatrick           return die_offset;
635*061da546Spatrick       }
636*061da546Spatrick     }
637*061da546Spatrick 
638*061da546Spatrick     if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) {
639*061da546Spatrick       DWARFDIE die = form_value.Reference();
640*061da546Spatrick       if (die) {
641*061da546Spatrick         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
642*061da546Spatrick             die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
643*061da546Spatrick         if (die_offset)
644*061da546Spatrick           return die_offset;
645*061da546Spatrick       }
646*061da546Spatrick     }
647*061da546Spatrick   }
648*061da546Spatrick   return 0;
649*061da546Spatrick }
650*061da546Spatrick 
651*061da546Spatrick // GetAttributeValueAsString
652*061da546Spatrick //
653*061da546Spatrick // Get the value of an attribute as a string return it. The resulting pointer
654*061da546Spatrick // to the string data exists within the supplied SymbolFileDWARF and will only
655*061da546Spatrick // be available as long as the SymbolFileDWARF is still around and it's content
656*061da546Spatrick // doesn't change.
657*061da546Spatrick const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
658*061da546Spatrick     const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
659*061da546Spatrick     bool check_specification_or_abstract_origin) const {
660*061da546Spatrick   DWARFFormValue form_value;
661*061da546Spatrick   if (GetAttributeValue(cu, attr, form_value, nullptr,
662*061da546Spatrick                         check_specification_or_abstract_origin))
663*061da546Spatrick     return form_value.AsCString();
664*061da546Spatrick   return fail_value;
665*061da546Spatrick }
666*061da546Spatrick 
667*061da546Spatrick // GetAttributeValueAsUnsigned
668*061da546Spatrick //
669*061da546Spatrick // Get the value of an attribute as unsigned and return it.
670*061da546Spatrick uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
671*061da546Spatrick     const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
672*061da546Spatrick     bool check_specification_or_abstract_origin) const {
673*061da546Spatrick   DWARFFormValue form_value;
674*061da546Spatrick   if (GetAttributeValue(cu, attr, form_value, nullptr,
675*061da546Spatrick                         check_specification_or_abstract_origin))
676*061da546Spatrick     return form_value.Unsigned();
677*061da546Spatrick   return fail_value;
678*061da546Spatrick }
679*061da546Spatrick 
680*061da546Spatrick // GetAttributeValueAsReference
681*061da546Spatrick //
682*061da546Spatrick // Get the value of an attribute as reference and fix up and compile unit
683*061da546Spatrick // relative offsets as needed.
684*061da546Spatrick DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference(
685*061da546Spatrick     const DWARFUnit *cu, const dw_attr_t attr,
686*061da546Spatrick     bool check_specification_or_abstract_origin) const {
687*061da546Spatrick   DWARFFormValue form_value;
688*061da546Spatrick   if (GetAttributeValue(cu, attr, form_value, nullptr,
689*061da546Spatrick                         check_specification_or_abstract_origin))
690*061da546Spatrick     return form_value.Reference();
691*061da546Spatrick   return {};
692*061da546Spatrick }
693*061da546Spatrick 
694*061da546Spatrick uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
695*061da546Spatrick     const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
696*061da546Spatrick     bool check_specification_or_abstract_origin) const {
697*061da546Spatrick   DWARFFormValue form_value;
698*061da546Spatrick   if (GetAttributeValue(cu, attr, form_value, nullptr,
699*061da546Spatrick                         check_specification_or_abstract_origin))
700*061da546Spatrick     return form_value.Address();
701*061da546Spatrick   return fail_value;
702*061da546Spatrick }
703*061da546Spatrick 
704*061da546Spatrick // GetAttributeHighPC
705*061da546Spatrick //
706*061da546Spatrick // Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
707*061da546Spatrick // pc>.
708*061da546Spatrick //
709*061da546Spatrick // Returns the hi_pc or fail_value.
710*061da546Spatrick dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
711*061da546Spatrick     const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
712*061da546Spatrick     bool check_specification_or_abstract_origin) const {
713*061da546Spatrick   DWARFFormValue form_value;
714*061da546Spatrick   if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
715*061da546Spatrick                         check_specification_or_abstract_origin)) {
716*061da546Spatrick     dw_form_t form = form_value.Form();
717*061da546Spatrick     if (form == DW_FORM_addr || form == DW_FORM_addrx ||
718*061da546Spatrick         form == DW_FORM_GNU_addr_index)
719*061da546Spatrick       return form_value.Address();
720*061da546Spatrick 
721*061da546Spatrick     // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
722*061da546Spatrick     return lo_pc + form_value.Unsigned();
723*061da546Spatrick   }
724*061da546Spatrick   return fail_value;
725*061da546Spatrick }
726*061da546Spatrick 
727*061da546Spatrick // GetAttributeAddressRange
728*061da546Spatrick //
729*061da546Spatrick // Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
730*061da546Spatrick // from-low-pc>.
731*061da546Spatrick //
732*061da546Spatrick // Returns true or sets lo_pc and hi_pc to fail_value.
733*061da546Spatrick bool DWARFDebugInfoEntry::GetAttributeAddressRange(
734*061da546Spatrick     const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
735*061da546Spatrick     uint64_t fail_value, bool check_specification_or_abstract_origin) const {
736*061da546Spatrick   lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
737*061da546Spatrick                                      check_specification_or_abstract_origin);
738*061da546Spatrick   if (lo_pc != fail_value) {
739*061da546Spatrick     hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
740*061da546Spatrick                                check_specification_or_abstract_origin);
741*061da546Spatrick     if (hi_pc != fail_value)
742*061da546Spatrick       return true;
743*061da546Spatrick   }
744*061da546Spatrick   lo_pc = fail_value;
745*061da546Spatrick   hi_pc = fail_value;
746*061da546Spatrick   return false;
747*061da546Spatrick }
748*061da546Spatrick 
749*061da546Spatrick size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
750*061da546Spatrick     DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
751*061da546Spatrick     bool check_specification_or_abstract_origin) const {
752*061da546Spatrick   ranges.Clear();
753*061da546Spatrick 
754*061da546Spatrick   DWARFFormValue form_value;
755*061da546Spatrick   if (GetAttributeValue(cu, DW_AT_ranges, form_value)) {
756*061da546Spatrick     ranges = GetRangesOrReportError(*cu, *this, form_value);
757*061da546Spatrick   } else if (check_hi_lo_pc) {
758*061da546Spatrick     dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
759*061da546Spatrick     dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
760*061da546Spatrick     if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS,
761*061da546Spatrick                                  check_specification_or_abstract_origin)) {
762*061da546Spatrick       if (lo_pc < hi_pc)
763*061da546Spatrick         ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
764*061da546Spatrick     }
765*061da546Spatrick   }
766*061da546Spatrick   return ranges.GetSize();
767*061da546Spatrick }
768*061da546Spatrick 
769*061da546Spatrick // GetName
770*061da546Spatrick //
771*061da546Spatrick // Get value of the DW_AT_name attribute and return it if one exists, else
772*061da546Spatrick // return NULL.
773*061da546Spatrick const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const {
774*061da546Spatrick   return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
775*061da546Spatrick }
776*061da546Spatrick 
777*061da546Spatrick // GetMangledName
778*061da546Spatrick //
779*061da546Spatrick // Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
780*061da546Spatrick // exists, else return the value of the DW_AT_name attribute
781*061da546Spatrick const char *
782*061da546Spatrick DWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu,
783*061da546Spatrick                                     bool substitute_name_allowed) const {
784*061da546Spatrick   const char *name = nullptr;
785*061da546Spatrick 
786*061da546Spatrick   name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
787*061da546Spatrick   if (name)
788*061da546Spatrick     return name;
789*061da546Spatrick 
790*061da546Spatrick   name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
791*061da546Spatrick   if (name)
792*061da546Spatrick     return name;
793*061da546Spatrick 
794*061da546Spatrick   if (!substitute_name_allowed)
795*061da546Spatrick     return nullptr;
796*061da546Spatrick 
797*061da546Spatrick   name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
798*061da546Spatrick   return name;
799*061da546Spatrick }
800*061da546Spatrick 
801*061da546Spatrick // GetPubname
802*061da546Spatrick //
803*061da546Spatrick // Get value the name for a DIE as it should appear for a .debug_pubnames or
804*061da546Spatrick // .debug_pubtypes section.
805*061da546Spatrick const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const {
806*061da546Spatrick   const char *name = nullptr;
807*061da546Spatrick   if (!cu)
808*061da546Spatrick     return name;
809*061da546Spatrick 
810*061da546Spatrick   name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
811*061da546Spatrick   if (name)
812*061da546Spatrick     return name;
813*061da546Spatrick 
814*061da546Spatrick   name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
815*061da546Spatrick   if (name)
816*061da546Spatrick     return name;
817*061da546Spatrick 
818*061da546Spatrick   name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
819*061da546Spatrick   return name;
820*061da546Spatrick }
821*061da546Spatrick 
822*061da546Spatrick // BuildAddressRangeTable
823*061da546Spatrick void DWARFDebugInfoEntry::BuildAddressRangeTable(
824*061da546Spatrick     const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
825*061da546Spatrick   if (m_tag) {
826*061da546Spatrick     if (m_tag == DW_TAG_subprogram) {
827*061da546Spatrick       dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
828*061da546Spatrick       dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
829*061da546Spatrick       if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) {
830*061da546Spatrick         /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x -
831*061da546Spatrick         /// 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc);
832*061da546Spatrick         debug_aranges->AppendRange(cu->GetOffset(), lo_pc, hi_pc);
833*061da546Spatrick       }
834*061da546Spatrick     }
835*061da546Spatrick 
836*061da546Spatrick     const DWARFDebugInfoEntry *child = GetFirstChild();
837*061da546Spatrick     while (child) {
838*061da546Spatrick       child->BuildAddressRangeTable(cu, debug_aranges);
839*061da546Spatrick       child = child->GetSibling();
840*061da546Spatrick     }
841*061da546Spatrick   }
842*061da546Spatrick }
843*061da546Spatrick 
844*061da546Spatrick // BuildFunctionAddressRangeTable
845*061da546Spatrick //
846*061da546Spatrick // This function is very similar to the BuildAddressRangeTable function except
847*061da546Spatrick // that the actual DIE offset for the function is placed in the table instead
848*061da546Spatrick // of the compile unit offset (which is the way the standard .debug_aranges
849*061da546Spatrick // section does it).
850*061da546Spatrick void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
851*061da546Spatrick     const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
852*061da546Spatrick   if (m_tag) {
853*061da546Spatrick     if (m_tag == DW_TAG_subprogram) {
854*061da546Spatrick       dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
855*061da546Spatrick       dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
856*061da546Spatrick       if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) {
857*061da546Spatrick         //  printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16" PRIx64 " -
858*061da546Spatrick         //  0x%16.16" PRIx64 ")\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY
859*061da546Spatrick         debug_aranges->AppendRange(GetOffset(), lo_pc, hi_pc);
860*061da546Spatrick       }
861*061da546Spatrick     }
862*061da546Spatrick 
863*061da546Spatrick     const DWARFDebugInfoEntry *child = GetFirstChild();
864*061da546Spatrick     while (child) {
865*061da546Spatrick       child->BuildFunctionAddressRangeTable(cu, debug_aranges);
866*061da546Spatrick       child = child->GetSibling();
867*061da546Spatrick     }
868*061da546Spatrick   }
869*061da546Spatrick }
870*061da546Spatrick 
871*061da546Spatrick void DWARFDebugInfoEntry::GetDWARFDeclContext(
872*061da546Spatrick     DWARFUnit *cu, DWARFDeclContext &dwarf_decl_ctx) const {
873*061da546Spatrick   const dw_tag_t tag = Tag();
874*061da546Spatrick   if (tag != DW_TAG_compile_unit && tag != DW_TAG_partial_unit) {
875*061da546Spatrick     dwarf_decl_ctx.AppendDeclContext(tag, GetName(cu));
876*061da546Spatrick     DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu);
877*061da546Spatrick     if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) {
878*061da546Spatrick       if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit &&
879*061da546Spatrick           parent_decl_ctx_die.Tag() != DW_TAG_partial_unit)
880*061da546Spatrick         parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext(
881*061da546Spatrick             parent_decl_ctx_die.GetCU(), dwarf_decl_ctx);
882*061da546Spatrick     }
883*061da546Spatrick   }
884*061da546Spatrick }
885*061da546Spatrick 
886*061da546Spatrick DWARFDIE
887*061da546Spatrick DWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const {
888*061da546Spatrick   DWARFAttributes attributes;
889*061da546Spatrick   GetAttributes(cu, attributes);
890*061da546Spatrick   return GetParentDeclContextDIE(cu, attributes);
891*061da546Spatrick }
892*061da546Spatrick 
893*061da546Spatrick DWARFDIE
894*061da546Spatrick DWARFDebugInfoEntry::GetParentDeclContextDIE(
895*061da546Spatrick     DWARFUnit *cu, const DWARFAttributes &attributes) const {
896*061da546Spatrick   DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
897*061da546Spatrick 
898*061da546Spatrick   while (die) {
899*061da546Spatrick     // If this is the original DIE that we are searching for a declaration for,
900*061da546Spatrick     // then don't look in the cache as we don't want our own decl context to be
901*061da546Spatrick     // our decl context...
902*061da546Spatrick     if (die.GetDIE() != this) {
903*061da546Spatrick       switch (die.Tag()) {
904*061da546Spatrick       case DW_TAG_compile_unit:
905*061da546Spatrick       case DW_TAG_partial_unit:
906*061da546Spatrick       case DW_TAG_namespace:
907*061da546Spatrick       case DW_TAG_structure_type:
908*061da546Spatrick       case DW_TAG_union_type:
909*061da546Spatrick       case DW_TAG_class_type:
910*061da546Spatrick         return die;
911*061da546Spatrick 
912*061da546Spatrick       default:
913*061da546Spatrick         break;
914*061da546Spatrick       }
915*061da546Spatrick     }
916*061da546Spatrick 
917*061da546Spatrick     DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification);
918*061da546Spatrick     if (spec_die) {
919*061da546Spatrick       DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
920*061da546Spatrick       if (decl_ctx_die)
921*061da546Spatrick         return decl_ctx_die;
922*061da546Spatrick     }
923*061da546Spatrick 
924*061da546Spatrick     DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin);
925*061da546Spatrick     if (abs_die) {
926*061da546Spatrick       DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
927*061da546Spatrick       if (decl_ctx_die)
928*061da546Spatrick         return decl_ctx_die;
929*061da546Spatrick     }
930*061da546Spatrick 
931*061da546Spatrick     die = die.GetParent();
932*061da546Spatrick   }
933*061da546Spatrick   return DWARFDIE();
934*061da546Spatrick }
935*061da546Spatrick 
936*061da546Spatrick const char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
937*061da546Spatrick                                                   std::string &storage) const {
938*061da546Spatrick   DWARFAttributes attributes;
939*061da546Spatrick   GetAttributes(cu, attributes);
940*061da546Spatrick   return GetQualifiedName(cu, attributes, storage);
941*061da546Spatrick }
942*061da546Spatrick 
943*061da546Spatrick const char *
944*061da546Spatrick DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
945*061da546Spatrick                                       const DWARFAttributes &attributes,
946*061da546Spatrick                                       std::string &storage) const {
947*061da546Spatrick 
948*061da546Spatrick   const char *name = GetName(cu);
949*061da546Spatrick 
950*061da546Spatrick   if (name) {
951*061da546Spatrick     DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu);
952*061da546Spatrick     storage.clear();
953*061da546Spatrick     // TODO: change this to get the correct decl context parent....
954*061da546Spatrick     while (parent_decl_ctx_die) {
955*061da546Spatrick       const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();
956*061da546Spatrick       switch (parent_tag) {
957*061da546Spatrick       case DW_TAG_namespace: {
958*061da546Spatrick         const char *namespace_name = parent_decl_ctx_die.GetName();
959*061da546Spatrick         if (namespace_name) {
960*061da546Spatrick           storage.insert(0, "::");
961*061da546Spatrick           storage.insert(0, namespace_name);
962*061da546Spatrick         } else {
963*061da546Spatrick           storage.insert(0, "(anonymous namespace)::");
964*061da546Spatrick         }
965*061da546Spatrick         parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
966*061da546Spatrick       } break;
967*061da546Spatrick 
968*061da546Spatrick       case DW_TAG_class_type:
969*061da546Spatrick       case DW_TAG_structure_type:
970*061da546Spatrick       case DW_TAG_union_type: {
971*061da546Spatrick         const char *class_union_struct_name = parent_decl_ctx_die.GetName();
972*061da546Spatrick 
973*061da546Spatrick         if (class_union_struct_name) {
974*061da546Spatrick           storage.insert(0, "::");
975*061da546Spatrick           storage.insert(0, class_union_struct_name);
976*061da546Spatrick         }
977*061da546Spatrick         parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
978*061da546Spatrick       } break;
979*061da546Spatrick 
980*061da546Spatrick       default:
981*061da546Spatrick         parent_decl_ctx_die.Clear();
982*061da546Spatrick         break;
983*061da546Spatrick       }
984*061da546Spatrick     }
985*061da546Spatrick 
986*061da546Spatrick     if (storage.empty())
987*061da546Spatrick       storage.append("::");
988*061da546Spatrick 
989*061da546Spatrick     storage.append(name);
990*061da546Spatrick   }
991*061da546Spatrick   if (storage.empty())
992*061da546Spatrick     return nullptr;
993*061da546Spatrick   return storage.c_str();
994*061da546Spatrick }
995*061da546Spatrick 
996*061da546Spatrick bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu,
997*061da546Spatrick                                         DWARFDebugInfoEntry **function_die,
998*061da546Spatrick                                         DWARFDebugInfoEntry **block_die) {
999*061da546Spatrick   bool found_address = false;
1000*061da546Spatrick   if (m_tag) {
1001*061da546Spatrick     bool check_children = false;
1002*061da546Spatrick     bool match_addr_range = false;
1003*061da546Spatrick     //  printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset,
1004*061da546Spatrick     //  DW_TAG_value_to_name(tag), address);
1005*061da546Spatrick     switch (m_tag) {
1006*061da546Spatrick     case DW_TAG_array_type:
1007*061da546Spatrick       break;
1008*061da546Spatrick     case DW_TAG_class_type:
1009*061da546Spatrick       check_children = true;
1010*061da546Spatrick       break;
1011*061da546Spatrick     case DW_TAG_entry_point:
1012*061da546Spatrick     case DW_TAG_enumeration_type:
1013*061da546Spatrick     case DW_TAG_formal_parameter:
1014*061da546Spatrick     case DW_TAG_imported_declaration:
1015*061da546Spatrick     case DW_TAG_label:
1016*061da546Spatrick       break;
1017*061da546Spatrick     case DW_TAG_lexical_block:
1018*061da546Spatrick       check_children = true;
1019*061da546Spatrick       match_addr_range = true;
1020*061da546Spatrick       break;
1021*061da546Spatrick     case DW_TAG_member:
1022*061da546Spatrick     case DW_TAG_pointer_type:
1023*061da546Spatrick     case DW_TAG_reference_type:
1024*061da546Spatrick       break;
1025*061da546Spatrick     case DW_TAG_compile_unit:
1026*061da546Spatrick       match_addr_range = true;
1027*061da546Spatrick       break;
1028*061da546Spatrick     case DW_TAG_string_type:
1029*061da546Spatrick       break;
1030*061da546Spatrick     case DW_TAG_structure_type:
1031*061da546Spatrick       check_children = true;
1032*061da546Spatrick       break;
1033*061da546Spatrick     case DW_TAG_subroutine_type:
1034*061da546Spatrick     case DW_TAG_typedef:
1035*061da546Spatrick     case DW_TAG_union_type:
1036*061da546Spatrick     case DW_TAG_unspecified_parameters:
1037*061da546Spatrick     case DW_TAG_variant:
1038*061da546Spatrick       break;
1039*061da546Spatrick     case DW_TAG_common_block:
1040*061da546Spatrick       check_children = true;
1041*061da546Spatrick       break;
1042*061da546Spatrick     case DW_TAG_common_inclusion:
1043*061da546Spatrick     case DW_TAG_inheritance:
1044*061da546Spatrick       break;
1045*061da546Spatrick     case DW_TAG_inlined_subroutine:
1046*061da546Spatrick       check_children = true;
1047*061da546Spatrick       match_addr_range = true;
1048*061da546Spatrick       break;
1049*061da546Spatrick     case DW_TAG_module:
1050*061da546Spatrick       match_addr_range = true;
1051*061da546Spatrick       break;
1052*061da546Spatrick     case DW_TAG_ptr_to_member_type:
1053*061da546Spatrick     case DW_TAG_set_type:
1054*061da546Spatrick     case DW_TAG_subrange_type:
1055*061da546Spatrick     case DW_TAG_with_stmt:
1056*061da546Spatrick     case DW_TAG_access_declaration:
1057*061da546Spatrick     case DW_TAG_base_type:
1058*061da546Spatrick       break;
1059*061da546Spatrick     case DW_TAG_catch_block:
1060*061da546Spatrick       match_addr_range = true;
1061*061da546Spatrick       break;
1062*061da546Spatrick     case DW_TAG_const_type:
1063*061da546Spatrick     case DW_TAG_constant:
1064*061da546Spatrick     case DW_TAG_enumerator:
1065*061da546Spatrick     case DW_TAG_file_type:
1066*061da546Spatrick     case DW_TAG_friend:
1067*061da546Spatrick     case DW_TAG_namelist:
1068*061da546Spatrick     case DW_TAG_namelist_item:
1069*061da546Spatrick     case DW_TAG_packed_type:
1070*061da546Spatrick       break;
1071*061da546Spatrick     case DW_TAG_subprogram:
1072*061da546Spatrick       match_addr_range = true;
1073*061da546Spatrick       break;
1074*061da546Spatrick     case DW_TAG_template_type_parameter:
1075*061da546Spatrick     case DW_TAG_template_value_parameter:
1076*061da546Spatrick     case DW_TAG_GNU_template_parameter_pack:
1077*061da546Spatrick     case DW_TAG_thrown_type:
1078*061da546Spatrick       break;
1079*061da546Spatrick     case DW_TAG_try_block:
1080*061da546Spatrick       match_addr_range = true;
1081*061da546Spatrick       break;
1082*061da546Spatrick     case DW_TAG_variant_part:
1083*061da546Spatrick     case DW_TAG_variable:
1084*061da546Spatrick     case DW_TAG_volatile_type:
1085*061da546Spatrick     case DW_TAG_dwarf_procedure:
1086*061da546Spatrick     case DW_TAG_restrict_type:
1087*061da546Spatrick     case DW_TAG_interface_type:
1088*061da546Spatrick       break;
1089*061da546Spatrick     case DW_TAG_namespace:
1090*061da546Spatrick       check_children = true;
1091*061da546Spatrick       break;
1092*061da546Spatrick     case DW_TAG_imported_module:
1093*061da546Spatrick     case DW_TAG_unspecified_type:
1094*061da546Spatrick       break;
1095*061da546Spatrick     case DW_TAG_partial_unit:
1096*061da546Spatrick       match_addr_range = true;
1097*061da546Spatrick       break;
1098*061da546Spatrick     case DW_TAG_imported_unit:
1099*061da546Spatrick     case DW_TAG_shared_type:
1100*061da546Spatrick     default:
1101*061da546Spatrick       break;
1102*061da546Spatrick     }
1103*061da546Spatrick 
1104*061da546Spatrick     if (match_addr_range) {
1105*061da546Spatrick       dw_addr_t lo_pc =
1106*061da546Spatrick           GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
1107*061da546Spatrick       if (lo_pc != LLDB_INVALID_ADDRESS) {
1108*061da546Spatrick         dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS);
1109*061da546Spatrick         if (hi_pc != LLDB_INVALID_ADDRESS) {
1110*061da546Spatrick           //  printf("\n0x%8.8x: %30s: address = 0x%8.8x  [0x%8.8x - 0x%8.8x) ",
1111*061da546Spatrick           //  m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc);
1112*061da546Spatrick           if ((lo_pc <= address) && (address < hi_pc)) {
1113*061da546Spatrick             found_address = true;
1114*061da546Spatrick             //  puts("***MATCH***");
1115*061da546Spatrick             switch (m_tag) {
1116*061da546Spatrick             case DW_TAG_compile_unit: // File
1117*061da546Spatrick             case DW_TAG_partial_unit: // File
1118*061da546Spatrick               check_children =
1119*061da546Spatrick                   ((function_die != nullptr) || (block_die != nullptr));
1120*061da546Spatrick               break;
1121*061da546Spatrick 
1122*061da546Spatrick             case DW_TAG_subprogram: // Function
1123*061da546Spatrick               if (function_die)
1124*061da546Spatrick                 *function_die = this;
1125*061da546Spatrick               check_children = (block_die != nullptr);
1126*061da546Spatrick               break;
1127*061da546Spatrick 
1128*061da546Spatrick             case DW_TAG_inlined_subroutine: // Inlined Function
1129*061da546Spatrick             case DW_TAG_lexical_block:      // Block { } in code
1130*061da546Spatrick               if (block_die) {
1131*061da546Spatrick                 *block_die = this;
1132*061da546Spatrick                 check_children = true;
1133*061da546Spatrick               }
1134*061da546Spatrick               break;
1135*061da546Spatrick 
1136*061da546Spatrick             default:
1137*061da546Spatrick               check_children = true;
1138*061da546Spatrick               break;
1139*061da546Spatrick             }
1140*061da546Spatrick           }
1141*061da546Spatrick         } else {
1142*061da546Spatrick           // Compile units may not have a valid high/low pc when there
1143*061da546Spatrick           // are address gaps in subroutines so we must always search
1144*061da546Spatrick           // if there is no valid high and low PC.
1145*061da546Spatrick           check_children =
1146*061da546Spatrick               (m_tag == DW_TAG_compile_unit || m_tag == DW_TAG_partial_unit) &&
1147*061da546Spatrick               ((function_die != nullptr) || (block_die != nullptr));
1148*061da546Spatrick         }
1149*061da546Spatrick       } else {
1150*061da546Spatrick         DWARFRangeList ranges;
1151*061da546Spatrick         if (GetAttributeAddressRanges(cu, ranges, /*check_hi_lo_pc*/ false) &&
1152*061da546Spatrick             ranges.FindEntryThatContains(address)) {
1153*061da546Spatrick           found_address = true;
1154*061da546Spatrick           //  puts("***MATCH***");
1155*061da546Spatrick           switch (m_tag) {
1156*061da546Spatrick           case DW_TAG_compile_unit: // File
1157*061da546Spatrick           case DW_TAG_partial_unit: // File
1158*061da546Spatrick               check_children =
1159*061da546Spatrick                   ((function_die != nullptr) || (block_die != nullptr));
1160*061da546Spatrick               break;
1161*061da546Spatrick 
1162*061da546Spatrick           case DW_TAG_subprogram: // Function
1163*061da546Spatrick             if (function_die)
1164*061da546Spatrick               *function_die = this;
1165*061da546Spatrick             check_children = (block_die != nullptr);
1166*061da546Spatrick             break;
1167*061da546Spatrick 
1168*061da546Spatrick           case DW_TAG_inlined_subroutine: // Inlined Function
1169*061da546Spatrick           case DW_TAG_lexical_block:      // Block { } in code
1170*061da546Spatrick             if (block_die) {
1171*061da546Spatrick               *block_die = this;
1172*061da546Spatrick               check_children = true;
1173*061da546Spatrick             }
1174*061da546Spatrick             break;
1175*061da546Spatrick 
1176*061da546Spatrick           default:
1177*061da546Spatrick             check_children = true;
1178*061da546Spatrick             break;
1179*061da546Spatrick           }
1180*061da546Spatrick         } else {
1181*061da546Spatrick           check_children = false;
1182*061da546Spatrick         }
1183*061da546Spatrick       }
1184*061da546Spatrick     }
1185*061da546Spatrick 
1186*061da546Spatrick     if (check_children) {
1187*061da546Spatrick       //  printf("checking children\n");
1188*061da546Spatrick       DWARFDebugInfoEntry *child = GetFirstChild();
1189*061da546Spatrick       while (child) {
1190*061da546Spatrick         if (child->LookupAddress(address, cu, function_die, block_die))
1191*061da546Spatrick           return true;
1192*061da546Spatrick         child = child->GetSibling();
1193*061da546Spatrick       }
1194*061da546Spatrick     }
1195*061da546Spatrick   }
1196*061da546Spatrick   return found_address;
1197*061da546Spatrick }
1198*061da546Spatrick 
1199*061da546Spatrick lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const {
1200*061da546Spatrick   return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
1201*061da546Spatrick }
1202*061da546Spatrick 
1203*061da546Spatrick const DWARFAbbreviationDeclaration *
1204*061da546Spatrick DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const {
1205*061da546Spatrick   if (cu) {
1206*061da546Spatrick     const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations();
1207*061da546Spatrick     if (abbrev_set)
1208*061da546Spatrick       return abbrev_set->GetAbbreviationDeclaration(m_abbr_idx);
1209*061da546Spatrick   }
1210*061da546Spatrick   return nullptr;
1211*061da546Spatrick }
1212*061da546Spatrick 
1213*061da546Spatrick bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
1214*061da546Spatrick   return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
1215*061da546Spatrick          m_sibling_idx == rhs.m_sibling_idx &&
1216*061da546Spatrick          m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
1217*061da546Spatrick          m_tag == rhs.m_tag;
1218*061da546Spatrick }
1219*061da546Spatrick 
1220*061da546Spatrick bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
1221*061da546Spatrick   return !(*this == rhs);
1222*061da546Spatrick }
1223