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