LLDB mainline
DWARFDebugInfoEntry.cpp
Go to the documentation of this file.
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
10
11#include <cassert>
12
13#include <algorithm>
14#include <limits>
15#include <optional>
16
17#include "LogChannelDWARF.h"
18#include "lldb/Core/Module.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/FormatAdapters.h"
25#include "llvm/Support/LEB128.h"
26
27#include "DWARFCompileUnit.h"
28#include "DWARFDebugAranges.h"
29#include "DWARFDebugInfo.h"
30#include "DWARFDeclContext.h"
31#include "DWARFFormValue.h"
32#include "DWARFUnit.h"
33#include "SymbolFileDWARF.h"
34#include "SymbolFileDWARFDwo.h"
35
36using namespace lldb_private;
37using namespace lldb_private::plugin::dwarf;
38using namespace llvm::dwarf;
39extern 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
44 const DWARFUnit &unit,
45 lldb::offset_t *offset_ptr) {
46 m_offset = *offset_ptr;
47 auto report_error = [&](const char *fmt, const auto &...vals) {
48 unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportInternalError(
49 "[{0:x16}]: {1}", static_cast<uint64_t>(m_offset),
50 llvm::formatv(fmt, vals...));
51 *offset_ptr = std::numeric_limits<lldb::offset_t>::max();
52 return false;
53 };
54
55 m_parent_idx = 0;
56 m_sibling_idx = 0;
57 const uint64_t abbr_idx = data.GetULEB128(offset_ptr);
58 if (abbr_idx > std::numeric_limits<uint16_t>::max())
59 return report_error("abbreviation code {0} too big", abbr_idx);
60 m_abbr_idx = abbr_idx;
61
62 if (m_abbr_idx == 0) {
63 m_tag = llvm::dwarf::DW_TAG_null;
64 m_has_children = false;
65 return true; // NULL debug tag entry
66 }
67
68 const auto *abbrevDecl = GetAbbreviationDeclarationPtr(&unit);
69 if (abbrevDecl == nullptr)
70 return report_error("invalid abbreviation code {0}", abbr_idx);
71
72 m_tag = abbrevDecl->getTag();
73 m_has_children = abbrevDecl->hasChildren();
74 // Skip all data in the .debug_info or .debug_types for the attributes
75 for (const auto &attribute : abbrevDecl->attributes()) {
76 if (DWARFFormValue::SkipValue(attribute.Form, data, offset_ptr, &unit))
77 continue;
78
79 return report_error("Unsupported DW_FORM_{1:x}", attribute.Form);
80 }
81 return true;
82}
83
84static llvm::Expected<llvm::DWARFAddressRangesVector>
85GetRanges(DWARFUnit &unit, const DWARFFormValue &value) {
86 return (value.Form() == DW_FORM_rnglistx)
87 ? unit.FindRnglistFromIndex(value.Unsigned())
88 : unit.FindRnglistFromOffset(value.Unsigned());
89}
90
92 const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec,
93 dw_attr_t &attr, DWARFFormValue &form_value) {
94 attr = attr_spec.Attr;
95 form_value.FormRef() = attr_spec.Form;
96 if (attr_spec.isImplicitConst())
97 form_value.SetSigned(attr_spec.getImplicitConstValue());
98}
99
100/// Helper for the public \ref DWARFDebugInfoEntry::GetDIENamesAndRanges API.
101/// Fills in the output parameters that aren't set yet from \c die and appends
102/// the DIEs it elaborates on to \c elaborating_dies.
104 const DWARFDIE &die, const char *&name, const char *&mangled,
105 llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file,
106 std::optional<int> &decl_line, std::optional<int> &decl_column,
107 std::optional<int> &call_file, std::optional<int> &call_line,
108 std::optional<int> &call_column, DWARFExpressionList *frame_base,
109 llvm::SmallVectorImpl<DWARFDIE> &elaborating_dies) {
110 DWARFUnit *cu = die.GetCU();
113 std::vector<DWARFDIE> dies;
114 bool set_frame_base_loclist_addr = false;
115
117 lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule();
118
119 if (const auto *abbrevDecl =
120 die.GetDIE()->GetAbbreviationDeclarationPtr(cu)) {
121 const DWARFDataExtractor &data = cu->GetData();
122 lldb::offset_t offset = die.GetDIE()->GetFirstAttributeOffset();
123
124 if (!data.ValidOffset(offset))
125 return;
126
127 bool do_offset = false;
128
129 for (const auto &attribute : abbrevDecl->attributes()) {
130 DWARFFormValue form_value(cu);
131 dw_attr_t attr;
132 ExtractAttrAndFormValue(attribute, attr, form_value);
133
134 if (form_value.ExtractValue(data, &offset)) {
135 switch (attr) {
136 case DW_AT_low_pc:
137 lo_pc = form_value.Address();
138
139 if (do_offset)
140 hi_pc += lo_pc;
141 do_offset = false;
142 break;
143
144 case DW_AT_entry_pc:
145 lo_pc = form_value.Address();
146 break;
147
148 case DW_AT_high_pc:
149 if (form_value.Form() == DW_FORM_addr ||
150 form_value.Form() == DW_FORM_addrx ||
151 form_value.Form() == DW_FORM_GNU_addr_index) {
152 hi_pc = form_value.Address();
153 } else {
154 hi_pc = form_value.Unsigned();
155 if (lo_pc == LLDB_INVALID_ADDRESS)
156 do_offset = hi_pc != LLDB_INVALID_ADDRESS;
157 else
158 hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save
159 // on relocations
160 }
161 break;
162
163 case DW_AT_ranges:
164 if (llvm::Expected<llvm::DWARFAddressRangesVector> r =
165 GetRanges(*cu, form_value)) {
166 ranges = std::move(*r);
167 } else {
168 module->ReportInternalError(
169 "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but "
170 "range extraction failed ({3})",
171 die.GetOffset(),
172 llvm::dwarf::FormEncodingString(form_value.Form()),
173 form_value.Unsigned(), fmt_consume(r.takeError()));
174 }
175 break;
176
177 case DW_AT_name:
178 if (name == nullptr)
179 name = form_value.AsCString();
180 break;
181
182 case DW_AT_MIPS_linkage_name:
183 case DW_AT_linkage_name:
184 if (mangled == nullptr)
185 mangled = form_value.AsCString();
186 break;
187
188 case DW_AT_abstract_origin:
189 dies.push_back(form_value.Reference());
190 break;
191
192 case DW_AT_specification:
193 dies.push_back(form_value.Reference());
194 break;
195
196 case DW_AT_decl_file:
197 if (!decl_file)
198 decl_file = form_value.Unsigned();
199 break;
200
201 case DW_AT_decl_line:
202 if (!decl_line)
203 decl_line = form_value.Unsigned();
204 break;
205
206 case DW_AT_decl_column:
207 if (!decl_column)
208 decl_column = form_value.Unsigned();
209 break;
210
211 case DW_AT_call_file:
212 if (!call_file)
213 call_file = form_value.Unsigned();
214 break;
215
216 case DW_AT_call_line:
217 if (!call_line)
218 call_line = form_value.Unsigned();
219 break;
220
221 case DW_AT_call_column:
222 if (!call_column)
223 call_column = form_value.Unsigned();
224 break;
225
226 case DW_AT_frame_base:
227 if (frame_base) {
228 if (form_value.BlockData()) {
229 uint64_t block_offset =
230 form_value.BlockData() - data.GetDataStart();
231 uint64_t block_length = form_value.Unsigned();
232 *frame_base =
233 DWARFExpressionList(module,
235 data, block_offset, block_length)),
236 cu);
237 } else {
238 DataExtractor data = cu->GetLocationData();
239 const dw_offset_t offset = form_value.Unsigned();
240 if (data.ValidOffset(offset)) {
241 data = DataExtractor(data, offset, data.GetByteSize() - offset);
242 if (lo_pc != LLDB_INVALID_ADDRESS) {
243 assert(lo_pc >= cu->GetBaseAddress());
244 cu->ParseDWARFLocationList(data, *frame_base);
245 frame_base->SetFuncFileAddress(lo_pc);
246 } else
247 set_frame_base_loclist_addr = true;
248 }
249 }
250 }
251 break;
252
253 default:
254 break;
255 }
256 }
257 }
258 }
259
260 if (ranges.empty() && lo_pc != LLDB_INVALID_ADDRESS) {
261 lldb::addr_t range_hi_pc =
262 (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) ? hi_pc : lo_pc;
263 ranges.emplace_back(lo_pc, range_hi_pc);
264 }
265
266 if (set_frame_base_loclist_addr && !ranges.empty()) {
267 dw_addr_t file_addr = ranges.begin()->LowPC;
268 assert(file_addr >= cu->GetBaseAddress());
269 frame_base->SetFuncFileAddress(file_addr);
270 }
271
272 if (ranges.empty() || name == nullptr || mangled == nullptr) {
273 for (const DWARFDIE &die : dies) {
274 if (die)
275 elaborating_dies.push_back(die);
276 }
277 }
278}
279
280// GetDIENamesAndRanges
281//
282// Gets the valid address ranges for a given DIE by looking for a
283// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
285 DWARFUnit *cu, const char *&name, const char *&mangled,
286 llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file,
287 std::optional<int> &decl_line, std::optional<int> &decl_column,
288 std::optional<int> &call_file, std::optional<int> &call_line,
289 std::optional<int> &call_column, DWARFExpressionList *frame_base) const {
290 llvm::SmallVector<DWARFDIE, 3> worklist;
291 worklist.emplace_back(cu, this);
292
293 // Keep track of the DIEs already seen to catch cycles.
294 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> seen;
295 seen.insert(this);
296
297 // The frame base is only taken from the DIE itself, not from the DIEs it
298 // elaborates on.
299 DWARFExpressionList *die_frame_base = frame_base;
300
301 while (!worklist.empty()) {
302 DWARFDIE current = worklist.pop_back_val();
303
304 llvm::SmallVector<DWARFDIE, 3> elaborating_dies;
305 ::GetDIENamesAndRanges(current, name, mangled, ranges, decl_file, decl_line,
306 decl_column, call_file, call_line, call_column,
307 die_frame_base, elaborating_dies);
308 die_frame_base = nullptr;
309
310 // Push in reverse so that the worklist handles them in the order.
311 for (const DWARFDIE &die : llvm::reverse(elaborating_dies)) {
312 if (seen.insert(die.GetDIE()).second)
313 worklist.push_back(die);
314 }
315 }
316
317 return !ranges.empty();
318}
319
320/// Helper for the public \ref DWARFDebugInfoEntry::GetAttributes API.
321/// Adds all attributes of the DIE at the top of the \c worklist to the
322/// \c attributes list. Specifcations and abstract origins are added
323/// to the \c worklist if the referenced DIE has not been seen before.
324static bool
326 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> &seen,
327 DWARFAttributes &attributes) {
328 assert(!worklist.empty() && "Need at least one DIE to visit.");
329 assert(seen.size() >= 1 &&
330 "Need to have seen at least the currently visited entry.");
331
332 DWARFDIE current = worklist.pop_back_val();
333
334 const auto *cu = current.GetCU();
335 assert(cu);
336
337 const auto *entry = current.GetDIE();
338 assert(entry);
339
340 const auto *abbrevDecl =
341 entry->GetAbbreviationDeclarationPtr(current.GetCU());
342 if (!abbrevDecl)
343 return false;
344
345 const DWARFDataExtractor &data = cu->GetData();
346 lldb::offset_t offset = current.GetDIE()->GetFirstAttributeOffset();
347
348 const bool is_first_die = seen.size() == 1;
349
350 for (const auto &attribute : abbrevDecl->attributes()) {
351 DWARFFormValue form_value(cu);
352 dw_attr_t attr;
353 ExtractAttrAndFormValue(attribute, attr, form_value);
354
355 // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
356 // attributes, the depth will be non-zero. We need to omit certain
357 // attributes that don't make sense.
358 switch (attr) {
359 case DW_AT_sibling:
360 case DW_AT_declaration:
361 if (!is_first_die) {
362 // This attribute doesn't make sense when combined with the DIE that
363 // references this DIE. We know a DIE is referencing this DIE because
364 // we've visited more than one DIE already.
365 break;
366 }
367 [[fallthrough]];
368 default:
369 attributes.Append(form_value, offset, attr);
370 break;
371 }
372
373 if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
374 if (form_value.ExtractValue(data, &offset)) {
375 if (DWARFDIE spec_die = form_value.Reference()) {
376 if (seen.insert(spec_die.GetDIE()).second)
377 worklist.push_back(spec_die);
378 }
379 }
380 } else {
381 const dw_form_t form = form_value.Form();
382 std::optional<uint8_t> fixed_skip_size =
384 if (fixed_skip_size)
385 offset += *fixed_skip_size;
386 else
387 DWARFFormValue::SkipValue(form, data, &offset, cu);
388 }
389 }
390
391 return true;
392}
393
395 Recurse recurse) const {
396 // FIXME: use ElaboratingDIEIterator to follow specifications/abstract origins
397 // instead of maintaining our own worklist/seen list.
398
399 DWARFAttributes attributes;
400
401 llvm::SmallVector<DWARFDIE, 3> worklist;
402 worklist.emplace_back(cu, this);
403
404 // Keep track if DIEs already seen to prevent infinite recursion.
405 // Value of '3' was picked for the same reason that
406 // DWARFDie::findRecursively does.
407 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> seen;
408 seen.insert(this);
409
410 do {
411 if (!::GetAttributes(worklist, seen, attributes)) {
412 attributes.Clear();
413 break;
414 }
415 } while (!worklist.empty() && recurse == Recurse::yes);
416
417 return attributes;
418}
419
420// GetAttributeValue
421//
422// Get the value of an attribute and return the .debug_info or .debug_types
423// offset of the attribute if it was properly extracted into form_value,
424// or zero if we fail since an offset of zero is invalid for an attribute (it
425// would be a compile unit header).
427 const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
428 dw_offset_t *end_attr_offset_ptr, bool check_elaborating_dies) const {
429 if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
430 std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr);
431
432 if (attr_idx) {
433 const DWARFDataExtractor &data = cu->GetData();
435
436 uint32_t idx = 0;
437 while (idx < *attr_idx)
438 DWARFFormValue::SkipValue(abbrevDecl->getFormByIndex(idx++), data,
439 &offset, cu);
440
441 const dw_offset_t attr_offset = offset;
442 form_value.SetUnit(cu);
443 form_value.SetForm(abbrevDecl->getFormByIndex(idx));
444 if (abbrevDecl->getAttrIsImplicitConstByIndex(idx))
445 form_value.SetValue(abbrevDecl->getAttrImplicitConstValueByIndex(idx));
446
447 if (form_value.ExtractValue(data, &offset)) {
448 if (end_attr_offset_ptr)
449 *end_attr_offset_ptr = offset;
450 return attr_offset;
451 }
452 }
453 }
454
455 if (check_elaborating_dies) {
456 for (dw_attr_t elaborating_attr :
457 {DW_AT_specification, DW_AT_abstract_origin, DW_AT_signature}) {
458 if (!GetAttributeValue(cu, elaborating_attr, form_value))
459 continue;
460 DWARFDIE die = form_value.Reference();
461 if (!die)
462 continue;
463 dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
464 die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
465 if (die_offset)
466 return die_offset;
467 }
468 }
469 return 0;
470}
471
472// GetAttributeValueAsString
473//
474// Get the value of an attribute as a string return it. The resulting pointer
475// to the string data exists within the supplied SymbolFileDWARF and will only
476// be available as long as the SymbolFileDWARF is still around and it's content
477// doesn't change.
479 const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
480 bool check_elaborating_dies) const {
481 DWARFFormValue form_value;
482 if (GetAttributeValue(cu, attr, form_value, nullptr, check_elaborating_dies))
483 return form_value.AsCString();
484 return fail_value;
485}
486
487// GetAttributeValueAsUnsigned
488//
489// Get the value of an attribute as unsigned and return it.
491 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
492 bool check_elaborating_dies) const {
493 DWARFFormValue form_value;
494 if (GetAttributeValue(cu, attr, form_value, nullptr, check_elaborating_dies))
495 return form_value.Unsigned();
496 return fail_value;
497}
498
499std::optional<uint64_t>
501 const DWARFUnit *cu, const dw_attr_t attr,
502 bool check_elaborating_dies) const {
503 DWARFFormValue form_value;
504 if (GetAttributeValue(cu, attr, form_value, nullptr, check_elaborating_dies))
505 return form_value.Unsigned();
506 return std::nullopt;
507}
508
509// GetAttributeValueAsReference
510//
511// Get the value of an attribute as reference and fix up and compile unit
512// relative offsets as needed.
514 const DWARFUnit *cu, const dw_attr_t attr,
515 bool check_elaborating_dies) const {
516 DWARFFormValue form_value;
517 if (GetAttributeValue(cu, attr, form_value, nullptr, check_elaborating_dies))
518 return form_value.Reference();
519 return {};
520}
521
523 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
524 bool check_elaborating_dies) const {
525 DWARFFormValue form_value;
526 if (GetAttributeValue(cu, attr, form_value, nullptr, check_elaborating_dies))
527 return form_value.Address();
528 return fail_value;
529}
530
531// GetAttributeHighPC
532//
533// Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
534// pc>.
535//
536// Returns the hi_pc or fail_value.
539 uint64_t fail_value,
540 bool check_elaborating_dies) const {
541 DWARFFormValue form_value;
542 if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
543 check_elaborating_dies)) {
544 dw_form_t form = form_value.Form();
545 if (form == DW_FORM_addr || form == DW_FORM_addrx ||
546 form == DW_FORM_GNU_addr_index)
547 return form_value.Address();
548
549 // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
550 return lo_pc + form_value.Unsigned();
551 }
552 return fail_value;
553}
554
555// GetAttributeAddressRange
556//
557// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
558// from-low-pc>.
559//
560// Returns true or sets lo_pc and hi_pc to fail_value.
562 const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
563 uint64_t fail_value, bool check_elaborating_dies) const {
564 lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
565 check_elaborating_dies);
566 if (lo_pc != fail_value) {
567 hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value, check_elaborating_dies);
568 if (hi_pc != fail_value)
569 return true;
570 }
571 lo_pc = fail_value;
572 hi_pc = fail_value;
573 return false;
574}
575
576llvm::Expected<llvm::DWARFAddressRangesVector>
578 DWARFUnit *cu, bool check_hi_lo_pc, bool check_elaborating_dies) const {
579
580 DWARFFormValue form_value;
581 if (GetAttributeValue(cu, DW_AT_ranges, form_value))
582 return GetRanges(*cu, form_value);
583
584 if (check_hi_lo_pc) {
588 check_elaborating_dies) &&
589 lo_pc < hi_pc)
590 return llvm::DWARFAddressRangesVector{{lo_pc, hi_pc}};
591 }
592 return llvm::createStringError("DIE has no address range information");
593}
594
595// GetName
596//
597// Get value of the DW_AT_name attribute and return it if one exists, else
598// return NULL.
599const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const {
600 return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
601}
602
603// GetMangledName
604//
605// Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
606// exists, else return the value of the DW_AT_name attribute
607const char *
609 bool substitute_name_allowed) const {
610 const char *name = nullptr;
611
612 name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
613 if (name)
614 return name;
615
616 name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
617 if (name)
618 return name;
619
620 if (!substitute_name_allowed)
621 return nullptr;
622
623 name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
624 return name;
625}
626
627// GetPubname
628//
629// Get value the name for a DIE as it should appear for a .debug_pubnames or
630// .debug_pubtypes section.
631const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const {
632 const char *name = nullptr;
633 if (!cu)
634 return name;
635
636 name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
637 if (name)
638 return name;
639
640 name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
641 if (name)
642 return name;
643
644 name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
645 return name;
646}
647
648/// This function is builds a table very similar to the standard .debug_aranges
649/// table, except that the actual DIE offset for the function is placed in the
650/// table instead of the compile unit offset.
652 DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
654 if (m_tag) {
655 // Subprogram forward declarations don't have
656 // DW_AT_ranges/DW_AT_low_pc/DW_AT_high_pc attributes, so don't even try
657 // getting address range information for them.
658 if (m_tag == DW_TAG_subprogram &&
659 !GetAttributeValueAsOptionalUnsigned(cu, DW_AT_declaration)) {
660 if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
661 GetAttributeAddressRanges(cu, /*check_hi_lo_pc=*/true)) {
662 for (const auto &r : *ranges)
663 debug_aranges->AppendRange(GetOffset(), r.LowPC, r.HighPC);
664 } else {
665 LLDB_LOG_ERRORV(log, ranges.takeError(), "DIE({1:x}): {0}",
666 GetOffset());
667 }
668 }
669
670 const DWARFDebugInfoEntry *child = GetFirstChild();
671 while (child) {
672 child->BuildFunctionAddressRangeTable(cu, debug_aranges);
673 child = child->GetSibling();
674 }
675 }
676}
677
679 return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
680}
681
682const llvm::DWARFAbbreviationDeclaration *
684 if (!cu)
685 return nullptr;
686
687 const llvm::DWARFAbbreviationDeclarationSet *abbrev_set =
688 cu->GetAbbreviations();
689 if (!abbrev_set)
690 return nullptr;
691
692 return abbrev_set->getAbbreviationDeclaration(m_abbr_idx);
693}
694
696 if (Tag() != DW_TAG_variable && Tag() != DW_TAG_member)
697 return false;
698 const DWARFDebugInfoEntry *parent_die = GetParent();
699 while (parent_die != nullptr) {
700 switch (parent_die->Tag()) {
701 case DW_TAG_subprogram:
702 case DW_TAG_lexical_block:
703 case DW_TAG_inlined_subroutine:
704 return false;
705
706 case DW_TAG_compile_unit:
707 case DW_TAG_partial_unit:
708 return true;
709
710 default:
711 break;
712 }
713 parent_die = parent_die->GetParent();
714 }
715 return false;
716}
717
719 return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
722 m_tag == rhs.m_tag;
723}
724
726 return !(*this == rhs);
727}
static void ExtractAttrAndFormValue(const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec, dw_attr_t &attr, DWARFFormValue &form_value)
static bool GetAttributes(llvm::SmallVectorImpl< DWARFDIE > &worklist, llvm::SmallPtrSet< DWARFDebugInfoEntry const *, 3 > &seen, DWARFAttributes &attributes)
Helper for the public DWARFDebugInfoEntry::GetAttributes API.
static llvm::Expected< llvm::DWARFAddressRangesVector > GetRanges(DWARFUnit &unit, const DWARFFormValue &value)
static void GetDIENamesAndRanges(const DWARFDIE &die, const char *&name, const char *&mangled, llvm::DWARFAddressRangesVector &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, llvm::SmallVectorImpl< DWARFDIE > &elaborating_dies)
Helper for the public DWARFDebugInfoEntry::GetDIENamesAndRanges API.
int g_verbose
#define LLDB_LOG_ERRORV(log, error,...)
Definition Log.h:421
"lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file address range to a single ...
void SetFuncFileAddress(lldb::addr_t func_file_addr)
"lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location expression and interprets it.
An data extractor class.
uint64_t GetULEB128(lldb::offset_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
virtual const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
virtual uint64_t GetByteSize() const
Get the number of bytes contained in this object.
const uint8_t * GetDataStart() const
Get the data start pointer.
bool ValidOffset(lldb::offset_t offset) const
Test the validity of offset.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
ObjectFile * GetObjectFile() override
Definition SymbolFile.h:601
void Append(const DWARFFormValue &form_value, dw_offset_t attr_die_offset, dw_attr_t attr)
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition DWARFDIE.cpp:126
void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc)
bool operator==(const DWARFDebugInfoEntry &rhs) const
dw_tag_t m_tag
A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table.
bool GetAttributeAddressRange(const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, uint64_t fail_value, bool check_elaborating_dies=false) const
dw_addr_t GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, bool check_elaborating_dies=false) const
bool operator!=(const DWARFDebugInfoEntry &rhs) const
llvm::Expected< llvm::DWARFAddressRangesVector > GetAttributeAddressRanges(DWARFUnit *cu, bool check_hi_lo_pc, bool check_elaborating_dies=false) const
DWARFAttributes GetAttributes(const DWARFUnit *cu, Recurse recurse=Recurse::yes) const
Get all attribute values for a given DIE, optionally following any specifications and abstract origin...
const char * GetMangledName(const DWARFUnit *cu, bool substitute_name_allowed=true) const
std::optional< uint64_t > GetAttributeValueAsOptionalUnsigned(const DWARFUnit *cu, const dw_attr_t attr, bool check_elaborating_dies=false) const
const llvm::DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const
void BuildFunctionAddressRangeTable(DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const
This function is builds a table very similar to the standard .debug_aranges table,...
DWARFDIE GetAttributeValueAsReference(const DWARFUnit *cu, const dw_attr_t attr, bool check_elaborating_dies=false) const
const char * GetAttributeValueAsString(const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, bool check_elaborating_dies=false) const
bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name, const char *&mangled, llvm::DWARFAddressRangesVector &rangeList, 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=nullptr) const
uint64_t GetAttributeValueAsAddress(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_elaborating_dies=false) const
uint64_t GetAttributeValueAsUnsigned(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_elaborating_dies=false) const
const char * GetPubname(const DWARFUnit *cu) const
bool Extract(const DWARFDataExtractor &data, const DWARFUnit &cu, lldb::offset_t *offset_ptr)
dw_offset_t GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &formValue, dw_offset_t *end_attr_offset_ptr=nullptr, bool check_elaborating_dies=false) const
const char * GetName(const DWARFUnit *cu) const
bool ExtractValue(const DWARFDataExtractor &data, lldb::offset_t *offset_ptr)
std::optional< uint8_t > GetFixedSize() const
bool SkipValue(const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr) const
llvm::Expected< llvm::DWARFAddressRangesVector > FindRnglistFromOffset(dw_offset_t offset)
Return a list of address ranges resulting from a (possibly encoded) range list starting at a given of...
SymbolFileDWARF & GetSymbolFileDWARF() const
Definition DWARFUnit.h:201
dw_addr_t GetBaseAddress() const override
Definition DWARFUnit.h:131
const DWARFDataExtractor & GetData() const
Get the data that contains the DIE information for this unit.
DWARFDataExtractor GetLocationData() const
bool ParseDWARFLocationList(const DataExtractor &data, DWARFExpressionList &loc_list) const
llvm::Expected< llvm::DWARFAddressRangesVector > FindRnglistFromIndex(uint32_t index)
Return a list of address ranges retrieved from an encoded range list whose offset is found via a tabl...
const llvm::DWARFAbbreviationDeclarationSet * GetAbbreviations() const
uint64_t dw_offset_t
Definition dwarf.h:24
llvm::dwarf::Attribute dw_attr_t
Definition dwarf.h:17
uint64_t dw_addr_t
Definition dwarf.h:20
llvm::dwarf::Form dw_form_t
Definition dwarf.h:18
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
uint64_t offset_t
Definition lldb-types.h:86
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP