1 //===-- DWARFDebugInfoEntry.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "DWARFDebugInfoEntry.h"
10 
11 #include <cassert>
12 
13 #include <algorithm>
14 #include <optional>
15 
16 #include "llvm/Support/LEB128.h"
17 
18 #include "lldb/Core/Module.h"
19 #include "lldb/Expression/DWARFExpression.h"
20 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Utility/Stream.h"
22 #include "lldb/Utility/StreamString.h"
23 
24 #include "DWARFCompileUnit.h"
25 #include "DWARFDebugAranges.h"
26 #include "DWARFDebugInfo.h"
27 #include "DWARFDebugRanges.h"
28 #include "DWARFDeclContext.h"
29 #include "DWARFFormValue.h"
30 #include "DWARFUnit.h"
31 #include "SymbolFileDWARF.h"
32 #include "SymbolFileDWARFDwo.h"
33 
34 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
35 
36 using namespace lldb_private;
37 using namespace lldb_private::dwarf;
38 using namespace lldb_private::plugin::dwarf;
39 extern int g_verbose;
40 
41 // Extract a debug info entry for a given DWARFUnit from the data
42 // starting at the offset in offset_ptr
Extract(const DWARFDataExtractor & data,const DWARFUnit * cu,lldb::offset_t * offset_ptr)43 bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
44                                   const DWARFUnit *cu,
45                                   lldb::offset_t *offset_ptr) {
46   m_offset = *offset_ptr;
47   m_parent_idx = 0;
48   m_sibling_idx = 0;
49   const uint64_t abbr_idx = data.GetULEB128(offset_ptr);
50   lldbassert(abbr_idx <= UINT16_MAX);
51   m_abbr_idx = abbr_idx;
52 
53   if (m_abbr_idx == 0) {
54     m_tag = llvm::dwarf::DW_TAG_null;
55     m_has_children = false;
56     return true; // NULL debug tag entry
57   }
58 
59   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
60   if (abbrevDecl == nullptr) {
61     cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
62         "[{0:x16}]: invalid abbreviation code {1}, "
63         "please file a bug and "
64         "attach the file at the start of this error message",
65         (uint64_t)m_offset, (unsigned)abbr_idx);
66     // WE can't parse anymore if the DWARF is borked...
67     *offset_ptr = UINT32_MAX;
68     return false;
69   }
70   m_tag = abbrevDecl->getTag();
71   m_has_children = abbrevDecl->hasChildren();
72   // Skip all data in the .debug_info or .debug_types for the attributes
73   for (const auto &attribute : abbrevDecl->attributes()) {
74     if (DWARFFormValue::SkipValue(attribute.Form, data, offset_ptr, cu))
75       continue;
76 
77     cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
78         "[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug "
79         "and "
80         "attach the file at the start of this error message",
81         (uint64_t)m_offset, (unsigned)attribute.Form);
82     *offset_ptr = m_offset;
83     return false;
84   }
85   return true;
86 }
87 
GetRangesOrReportError(DWARFUnit & unit,const DWARFDebugInfoEntry & die,const DWARFFormValue & value)88 static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
89                                              const DWARFDebugInfoEntry &die,
90                                              const DWARFFormValue &value) {
91   llvm::Expected<DWARFRangeList> expected_ranges =
92       (value.Form() == DW_FORM_rnglistx)
93           ? unit.FindRnglistFromIndex(value.Unsigned())
94           : unit.FindRnglistFromOffset(value.Unsigned());
95   if (expected_ranges)
96     return std::move(*expected_ranges);
97 
98   unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
99       "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but "
100       "range extraction failed ({3}), please file a bug "
101       "and attach the file at the start of this error message",
102       die.GetOffset(),
103       llvm::dwarf::FormEncodingString(value.Form()).str().c_str(),
104       value.Unsigned(), toString(expected_ranges.takeError()).c_str());
105   return DWARFRangeList();
106 }
107 
ExtractAttrAndFormValue(const llvm::DWARFAbbreviationDeclaration::AttributeSpec & attr_spec,dw_attr_t & attr,DWARFFormValue & form_value)108 static void ExtractAttrAndFormValue(
109     const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec,
110     dw_attr_t &attr, DWARFFormValue &form_value) {
111   attr = attr_spec.Attr;
112   form_value.FormRef() = attr_spec.Form;
113   if (attr_spec.isImplicitConst())
114     form_value.SetSigned(attr_spec.getImplicitConstValue());
115 }
116 
117 // GetDIENamesAndRanges
118 //
119 // Gets the valid address ranges for a given DIE by looking for a
120 // DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
GetDIENamesAndRanges(DWARFUnit * cu,const char * & name,const char * & mangled,DWARFRangeList & ranges,std::optional<int> & decl_file,std::optional<int> & decl_line,std::optional<int> & decl_column,std::optional<int> & call_file,std::optional<int> & call_line,std::optional<int> & call_column,DWARFExpressionList * frame_base) const121 bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
122     DWARFUnit *cu, const char *&name, const char *&mangled,
123     DWARFRangeList &ranges, std::optional<int> &decl_file,
124     std::optional<int> &decl_line, std::optional<int> &decl_column,
125     std::optional<int> &call_file, std::optional<int> &call_line,
126     std::optional<int> &call_column, DWARFExpressionList *frame_base) const {
127   dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
128   dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
129   std::vector<DWARFDIE> dies;
130   bool set_frame_base_loclist_addr = false;
131 
132   SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
133   lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule();
134 
135   if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
136     const DWARFDataExtractor &data = cu->GetData();
137     lldb::offset_t offset = GetFirstAttributeOffset();
138 
139     if (!data.ValidOffset(offset))
140       return false;
141 
142     bool do_offset = false;
143 
144     for (const auto &attribute : abbrevDecl->attributes()) {
145       DWARFFormValue form_value(cu);
146       dw_attr_t attr;
147       ExtractAttrAndFormValue(attribute, attr, form_value);
148 
149       if (form_value.ExtractValue(data, &offset)) {
150         switch (attr) {
151         case DW_AT_low_pc:
152           lo_pc = form_value.Address();
153 
154           if (do_offset)
155             hi_pc += lo_pc;
156           do_offset = false;
157           break;
158 
159         case DW_AT_entry_pc:
160           lo_pc = form_value.Address();
161           break;
162 
163         case DW_AT_high_pc:
164           if (form_value.Form() == DW_FORM_addr ||
165               form_value.Form() == DW_FORM_addrx ||
166               form_value.Form() == DW_FORM_GNU_addr_index) {
167             hi_pc = form_value.Address();
168           } else {
169             hi_pc = form_value.Unsigned();
170             if (lo_pc == LLDB_INVALID_ADDRESS)
171               do_offset = hi_pc != LLDB_INVALID_ADDRESS;
172             else
173               hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save
174                               // on relocations
175           }
176           break;
177 
178         case DW_AT_ranges:
179           ranges = GetRangesOrReportError(*cu, *this, form_value);
180           break;
181 
182         case DW_AT_name:
183           if (name == nullptr)
184             name = form_value.AsCString();
185           break;
186 
187         case DW_AT_MIPS_linkage_name:
188         case DW_AT_linkage_name:
189           if (mangled == nullptr)
190             mangled = form_value.AsCString();
191           break;
192 
193         case DW_AT_abstract_origin:
194           dies.push_back(form_value.Reference());
195           break;
196 
197         case DW_AT_specification:
198           dies.push_back(form_value.Reference());
199           break;
200 
201         case DW_AT_decl_file:
202           if (!decl_file)
203             decl_file = form_value.Unsigned();
204           break;
205 
206         case DW_AT_decl_line:
207           if (!decl_line)
208             decl_line = form_value.Unsigned();
209           break;
210 
211         case DW_AT_decl_column:
212           if (!decl_column)
213             decl_column = form_value.Unsigned();
214           break;
215 
216         case DW_AT_call_file:
217           if (!call_file)
218             call_file = form_value.Unsigned();
219           break;
220 
221         case DW_AT_call_line:
222           if (!call_line)
223             call_line = form_value.Unsigned();
224           break;
225 
226         case DW_AT_call_column:
227           if (!call_column)
228             call_column = form_value.Unsigned();
229           break;
230 
231         case DW_AT_frame_base:
232           if (frame_base) {
233             if (form_value.BlockData()) {
234               uint32_t block_offset =
235                   form_value.BlockData() - data.GetDataStart();
236               uint32_t block_length = form_value.Unsigned();
237               *frame_base =
238                   DWARFExpressionList(module,
239                                       DWARFExpression(DataExtractor(
240                                           data, block_offset, block_length)),
241                                       cu);
242             } else {
243               DataExtractor data = cu->GetLocationData();
244               const dw_offset_t offset = form_value.Unsigned();
245               if (data.ValidOffset(offset)) {
246                 data = DataExtractor(data, offset, data.GetByteSize() - offset);
247                 if (lo_pc != LLDB_INVALID_ADDRESS) {
248                   assert(lo_pc >= cu->GetBaseAddress());
249                   DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
250                   frame_base->SetFuncFileAddress(lo_pc);
251                 } else
252                   set_frame_base_loclist_addr = true;
253               }
254             }
255           }
256           break;
257 
258         default:
259           break;
260         }
261       }
262     }
263   }
264 
265   if (ranges.IsEmpty()) {
266     if (lo_pc != LLDB_INVALID_ADDRESS) {
267       if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
268         ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
269       else
270         ranges.Append(DWARFRangeList::Entry(lo_pc, 0));
271     }
272   }
273 
274   if (set_frame_base_loclist_addr) {
275     dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
276     assert(lowest_range_pc >= cu->GetBaseAddress());
277     frame_base->SetFuncFileAddress(lowest_range_pc);
278   }
279 
280   if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
281     for (const DWARFDIE &die : dies) {
282       if (die) {
283         die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
284                                            decl_file, decl_line, decl_column,
285                                            call_file, call_line, call_column);
286       }
287     }
288   }
289   return !ranges.IsEmpty();
290 }
291 
292 // Get all attribute values for a given DIE, including following any
293 // specification or abstract origin attributes and including those in the
294 // results. Any duplicate attributes will have the first instance take
295 // precedence (this can happen for declaration attributes).
GetAttributes(DWARFUnit * cu,DWARFAttributes & attributes,Recurse recurse,uint32_t curr_depth) const296 void DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu,
297                                         DWARFAttributes &attributes,
298                                         Recurse recurse,
299                                         uint32_t curr_depth) const {
300   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
301   if (!abbrevDecl) {
302     attributes.Clear();
303     return;
304   }
305 
306   const DWARFDataExtractor &data = cu->GetData();
307   lldb::offset_t offset = GetFirstAttributeOffset();
308 
309   for (const auto &attribute : abbrevDecl->attributes()) {
310     DWARFFormValue form_value(cu);
311     dw_attr_t attr;
312     ExtractAttrAndFormValue(attribute, attr, form_value);
313 
314     // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
315     // attributes, the depth will be non-zero. We need to omit certain
316     // attributes that don't make sense.
317     switch (attr) {
318     case DW_AT_sibling:
319     case DW_AT_declaration:
320       if (curr_depth > 0) {
321         // This attribute doesn't make sense when combined with the DIE that
322         // references this DIE. We know a DIE is referencing this DIE because
323         // curr_depth is not zero
324         break;
325       }
326       [[fallthrough]];
327     default:
328       attributes.Append(form_value, offset, attr);
329       break;
330     }
331 
332     if (recurse == Recurse::yes &&
333         ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) {
334       if (form_value.ExtractValue(data, &offset)) {
335         DWARFDIE spec_die = form_value.Reference();
336         if (spec_die)
337           spec_die.GetDIE()->GetAttributes(spec_die.GetCU(), attributes,
338                                            recurse, curr_depth + 1);
339       }
340     } else {
341       const dw_form_t form = form_value.Form();
342       std::optional<uint8_t> fixed_skip_size =
343           DWARFFormValue::GetFixedSize(form, cu);
344       if (fixed_skip_size)
345         offset += *fixed_skip_size;
346       else
347         DWARFFormValue::SkipValue(form, data, &offset, cu);
348     }
349   }
350 }
351 
352 // GetAttributeValue
353 //
354 // Get the value of an attribute and return the .debug_info or .debug_types
355 // offset of the attribute if it was properly extracted into form_value,
356 // or zero if we fail since an offset of zero is invalid for an attribute (it
357 // would be a compile unit header).
GetAttributeValue(const DWARFUnit * cu,const dw_attr_t attr,DWARFFormValue & form_value,dw_offset_t * end_attr_offset_ptr,bool check_specification_or_abstract_origin) const358 dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
359     const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
360     dw_offset_t *end_attr_offset_ptr,
361     bool check_specification_or_abstract_origin) const {
362   if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
363     std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr);
364 
365     if (attr_idx) {
366       const DWARFDataExtractor &data = cu->GetData();
367       lldb::offset_t offset = GetFirstAttributeOffset();
368 
369       uint32_t idx = 0;
370       while (idx < *attr_idx)
371         DWARFFormValue::SkipValue(abbrevDecl->getFormByIndex(idx++), data,
372                                   &offset, cu);
373 
374       const dw_offset_t attr_offset = offset;
375       form_value.SetUnit(cu);
376       form_value.SetForm(abbrevDecl->getFormByIndex(idx));
377       if (form_value.ExtractValue(data, &offset)) {
378         if (end_attr_offset_ptr)
379           *end_attr_offset_ptr = offset;
380         return attr_offset;
381       }
382     }
383   }
384 
385   if (check_specification_or_abstract_origin) {
386     if (GetAttributeValue(cu, DW_AT_specification, form_value)) {
387       DWARFDIE die = form_value.Reference();
388       if (die) {
389         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
390             die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
391         if (die_offset)
392           return die_offset;
393       }
394     }
395 
396     if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) {
397       DWARFDIE die = form_value.Reference();
398       if (die) {
399         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
400             die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
401         if (die_offset)
402           return die_offset;
403       }
404     }
405   }
406   return 0;
407 }
408 
409 // GetAttributeValueAsString
410 //
411 // Get the value of an attribute as a string return it. The resulting pointer
412 // to the string data exists within the supplied SymbolFileDWARF and will only
413 // be available as long as the SymbolFileDWARF is still around and it's content
414 // doesn't change.
GetAttributeValueAsString(const DWARFUnit * cu,const dw_attr_t attr,const char * fail_value,bool check_specification_or_abstract_origin) const415 const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
416     const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
417     bool check_specification_or_abstract_origin) const {
418   DWARFFormValue form_value;
419   if (GetAttributeValue(cu, attr, form_value, nullptr,
420                         check_specification_or_abstract_origin))
421     return form_value.AsCString();
422   return fail_value;
423 }
424 
425 // GetAttributeValueAsUnsigned
426 //
427 // Get the value of an attribute as unsigned and return it.
GetAttributeValueAsUnsigned(const DWARFUnit * cu,const dw_attr_t attr,uint64_t fail_value,bool check_specification_or_abstract_origin) const428 uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
429     const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
430     bool check_specification_or_abstract_origin) const {
431   DWARFFormValue form_value;
432   if (GetAttributeValue(cu, attr, form_value, nullptr,
433                         check_specification_or_abstract_origin))
434     return form_value.Unsigned();
435   return fail_value;
436 }
437 
438 std::optional<uint64_t>
GetAttributeValueAsOptionalUnsigned(const DWARFUnit * cu,const dw_attr_t attr,bool check_specification_or_abstract_origin) const439 DWARFDebugInfoEntry::GetAttributeValueAsOptionalUnsigned(
440     const DWARFUnit *cu, const dw_attr_t attr,
441     bool check_specification_or_abstract_origin) const {
442   DWARFFormValue form_value;
443   if (GetAttributeValue(cu, attr, form_value, nullptr,
444                         check_specification_or_abstract_origin))
445     return form_value.Unsigned();
446   return std::nullopt;
447 }
448 
449 // GetAttributeValueAsReference
450 //
451 // Get the value of an attribute as reference and fix up and compile unit
452 // relative offsets as needed.
GetAttributeValueAsReference(const DWARFUnit * cu,const dw_attr_t attr,bool check_specification_or_abstract_origin) const453 DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference(
454     const DWARFUnit *cu, const dw_attr_t attr,
455     bool check_specification_or_abstract_origin) const {
456   DWARFFormValue form_value;
457   if (GetAttributeValue(cu, attr, form_value, nullptr,
458                         check_specification_or_abstract_origin))
459     return form_value.Reference();
460   return {};
461 }
462 
GetAttributeValueAsAddress(const DWARFUnit * cu,const dw_attr_t attr,uint64_t fail_value,bool check_specification_or_abstract_origin) const463 uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
464     const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
465     bool check_specification_or_abstract_origin) const {
466   DWARFFormValue form_value;
467   if (GetAttributeValue(cu, attr, form_value, nullptr,
468                         check_specification_or_abstract_origin))
469     return form_value.Address();
470   return fail_value;
471 }
472 
473 // GetAttributeHighPC
474 //
475 // Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
476 // pc>.
477 //
478 // Returns the hi_pc or fail_value.
GetAttributeHighPC(const DWARFUnit * cu,dw_addr_t lo_pc,uint64_t fail_value,bool check_specification_or_abstract_origin) const479 dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
480     const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
481     bool check_specification_or_abstract_origin) const {
482   DWARFFormValue form_value;
483   if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
484                         check_specification_or_abstract_origin)) {
485     dw_form_t form = form_value.Form();
486     if (form == DW_FORM_addr || form == DW_FORM_addrx ||
487         form == DW_FORM_GNU_addr_index)
488       return form_value.Address();
489 
490     // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
491     return lo_pc + form_value.Unsigned();
492   }
493   return fail_value;
494 }
495 
496 // GetAttributeAddressRange
497 //
498 // Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
499 // from-low-pc>.
500 //
501 // Returns true or sets lo_pc and hi_pc to fail_value.
GetAttributeAddressRange(const DWARFUnit * cu,dw_addr_t & lo_pc,dw_addr_t & hi_pc,uint64_t fail_value,bool check_specification_or_abstract_origin) const502 bool DWARFDebugInfoEntry::GetAttributeAddressRange(
503     const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
504     uint64_t fail_value, bool check_specification_or_abstract_origin) const {
505   lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
506                                      check_specification_or_abstract_origin);
507   if (lo_pc != fail_value) {
508     hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
509                                check_specification_or_abstract_origin);
510     if (hi_pc != fail_value)
511       return true;
512   }
513   lo_pc = fail_value;
514   hi_pc = fail_value;
515   return false;
516 }
517 
GetAttributeAddressRanges(DWARFUnit * cu,bool check_hi_lo_pc,bool check_specification_or_abstract_origin) const518 DWARFRangeList DWARFDebugInfoEntry::GetAttributeAddressRanges(
519     DWARFUnit *cu, bool check_hi_lo_pc,
520     bool check_specification_or_abstract_origin) const {
521 
522   DWARFFormValue form_value;
523   if (GetAttributeValue(cu, DW_AT_ranges, form_value))
524     return GetRangesOrReportError(*cu, *this, form_value);
525 
526   DWARFRangeList ranges;
527   if (check_hi_lo_pc) {
528     dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
529     dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
530     if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS,
531                                  check_specification_or_abstract_origin)) {
532       if (lo_pc < hi_pc)
533         ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
534     }
535   }
536   return ranges;
537 }
538 
539 // GetName
540 //
541 // Get value of the DW_AT_name attribute and return it if one exists, else
542 // return NULL.
GetName(const DWARFUnit * cu) const543 const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const {
544   return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
545 }
546 
547 // GetMangledName
548 //
549 // Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
550 // exists, else return the value of the DW_AT_name attribute
551 const char *
GetMangledName(const DWARFUnit * cu,bool substitute_name_allowed) const552 DWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu,
553                                     bool substitute_name_allowed) const {
554   const char *name = nullptr;
555 
556   name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
557   if (name)
558     return name;
559 
560   name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
561   if (name)
562     return name;
563 
564   if (!substitute_name_allowed)
565     return nullptr;
566 
567   name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
568   return name;
569 }
570 
571 // GetPubname
572 //
573 // Get value the name for a DIE as it should appear for a .debug_pubnames or
574 // .debug_pubtypes section.
GetPubname(const DWARFUnit * cu) const575 const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const {
576   const char *name = nullptr;
577   if (!cu)
578     return name;
579 
580   name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
581   if (name)
582     return name;
583 
584   name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
585   if (name)
586     return name;
587 
588   name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
589   return name;
590 }
591 
592 /// This function is builds a table very similar to the standard .debug_aranges
593 /// table, except that the actual DIE offset for the function is placed in the
594 /// table instead of the compile unit offset.
BuildFunctionAddressRangeTable(DWARFUnit * cu,DWARFDebugAranges * debug_aranges) const595 void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
596     DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
597   if (m_tag) {
598     if (m_tag == DW_TAG_subprogram) {
599       DWARFRangeList ranges =
600           GetAttributeAddressRanges(cu, /*check_hi_lo_pc=*/true);
601       for (const auto &r : ranges) {
602         debug_aranges->AppendRange(GetOffset(), r.GetRangeBase(),
603                                    r.GetRangeEnd());
604       }
605     }
606 
607     const DWARFDebugInfoEntry *child = GetFirstChild();
608     while (child) {
609       child->BuildFunctionAddressRangeTable(cu, debug_aranges);
610       child = child->GetSibling();
611     }
612   }
613 }
614 
615 DWARFDeclContext
GetDWARFDeclContextStatic(const DWARFDebugInfoEntry * die,DWARFUnit * cu)616 DWARFDebugInfoEntry::GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die,
617                                                DWARFUnit *cu) {
618   DWARFDeclContext dwarf_decl_ctx;
619   for (;;) {
620     const dw_tag_t tag = die->Tag();
621     if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
622       return dwarf_decl_ctx;
623     dwarf_decl_ctx.AppendDeclContext(tag, die->GetName(cu));
624     DWARFDIE parent_decl_ctx_die = die->GetParentDeclContextDIE(cu);
625     if (!parent_decl_ctx_die || parent_decl_ctx_die.GetDIE() == die)
626       return dwarf_decl_ctx;
627     if (parent_decl_ctx_die.Tag() == DW_TAG_compile_unit ||
628         parent_decl_ctx_die.Tag() == DW_TAG_partial_unit)
629       return dwarf_decl_ctx;
630     die = parent_decl_ctx_die.GetDIE();
631     cu = parent_decl_ctx_die.GetCU();
632   }
633 }
634 
GetDWARFDeclContext(DWARFUnit * cu) const635 DWARFDeclContext DWARFDebugInfoEntry::GetDWARFDeclContext(DWARFUnit *cu) const {
636   return GetDWARFDeclContextStatic(this, cu);
637 }
638 
639 DWARFDIE
GetParentDeclContextDIE(DWARFUnit * cu) const640 DWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const {
641   DWARFAttributes attributes = GetAttributes(cu, Recurse::yes);
642   return GetParentDeclContextDIE(cu, attributes);
643 }
644 
645 DWARFDIE
GetParentDeclContextDIE(DWARFUnit * cu,const DWARFAttributes & attributes) const646 DWARFDebugInfoEntry::GetParentDeclContextDIE(
647     DWARFUnit *cu, const DWARFAttributes &attributes) const {
648   DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
649 
650   while (die) {
651     // If this is the original DIE that we are searching for a declaration for,
652     // then don't look in the cache as we don't want our own decl context to be
653     // our decl context...
654     if (die.GetDIE() != this) {
655       switch (die.Tag()) {
656       case DW_TAG_compile_unit:
657       case DW_TAG_partial_unit:
658       case DW_TAG_namespace:
659       case DW_TAG_structure_type:
660       case DW_TAG_union_type:
661       case DW_TAG_class_type:
662         return die;
663 
664       default:
665         break;
666       }
667     }
668 
669     DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification);
670     if (spec_die) {
671       DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
672       if (decl_ctx_die)
673         return decl_ctx_die;
674     }
675 
676     DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin);
677     if (abs_die) {
678       DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
679       if (decl_ctx_die)
680         return decl_ctx_die;
681     }
682 
683     die = die.GetParent();
684   }
685   return DWARFDIE();
686 }
687 
GetFirstAttributeOffset() const688 lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const {
689   return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
690 }
691 
692 const llvm::DWARFAbbreviationDeclaration *
GetAbbreviationDeclarationPtr(const DWARFUnit * cu) const693 DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const {
694   if (!cu)
695     return nullptr;
696 
697   const llvm::DWARFAbbreviationDeclarationSet *abbrev_set =
698       cu->GetAbbreviations();
699   if (!abbrev_set)
700     return nullptr;
701 
702   return abbrev_set->getAbbreviationDeclaration(m_abbr_idx);
703 }
704 
IsGlobalOrStaticScopeVariable() const705 bool DWARFDebugInfoEntry::IsGlobalOrStaticScopeVariable() const {
706   if (Tag() != DW_TAG_variable)
707     return false;
708   const DWARFDebugInfoEntry *parent_die = GetParent();
709   while (parent_die != nullptr) {
710     switch (parent_die->Tag()) {
711     case DW_TAG_subprogram:
712     case DW_TAG_lexical_block:
713     case DW_TAG_inlined_subroutine:
714       return false;
715 
716     case DW_TAG_compile_unit:
717     case DW_TAG_partial_unit:
718       return true;
719 
720     default:
721       break;
722     }
723     parent_die = parent_die->GetParent();
724   }
725   return false;
726 }
727 
operator ==(const DWARFDebugInfoEntry & rhs) const728 bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
729   return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
730          m_sibling_idx == rhs.m_sibling_idx &&
731          m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
732          m_tag == rhs.m_tag;
733 }
734 
operator !=(const DWARFDebugInfoEntry & rhs) const735 bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
736   return !(*this == rhs);
737 }
738