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 <optional>
15
16#include "llvm/Support/LEB128.h"
17
18#include "lldb/Core/Module.h"
21#include "lldb/Utility/Stream.h"
23
24#include "DWARFCompileUnit.h"
25#include "DWARFDebugAbbrev.h"
26#include "DWARFDebugAranges.h"
27#include "DWARFDebugInfo.h"
28#include "DWARFDebugRanges.h"
29#include "DWARFDeclContext.h"
30#include "DWARFFormValue.h"
31#include "DWARFUnit.h"
32#include "SymbolFileDWARF.h"
33#include "SymbolFileDWARFDwo.h"
34
35using namespace lldb_private;
36using namespace lldb_private::dwarf;
37extern int g_verbose;
38
39// Extract a debug info entry for a given DWARFUnit from the data
40// starting at the offset in offset_ptr
42 const DWARFUnit *cu,
43 lldb::offset_t *offset_ptr) {
44 m_offset = *offset_ptr;
45 m_parent_idx = 0;
46 m_sibling_idx = 0;
47 const uint64_t abbr_idx = data.GetULEB128(offset_ptr);
48 lldbassert(abbr_idx <= UINT16_MAX);
49 m_abbr_idx = abbr_idx;
50
51 // assert (fixed_form_sizes); // For best performance this should be
52 // specified!
53
54 if (m_abbr_idx == 0) {
55 m_tag = llvm::dwarf::DW_TAG_null;
56 m_has_children = false;
57 return true; // NULL debug tag entry
58 }
59
60 lldb::offset_t offset = *offset_ptr;
61 const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
62 if (abbrevDecl == nullptr) {
63 cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
64 "[{0:x16}]: invalid abbreviation code {1}, "
65 "please file a bug and "
66 "attach the file at the start of this error message",
67 (uint64_t)m_offset, (unsigned)abbr_idx);
68 // WE can't parse anymore if the DWARF is borked...
69 *offset_ptr = UINT32_MAX;
70 return false;
71 }
72 m_tag = abbrevDecl->Tag();
73 m_has_children = abbrevDecl->HasChildren();
74 // Skip all data in the .debug_info or .debug_types for the attributes
75 const uint32_t numAttributes = abbrevDecl->NumAttributes();
76 uint32_t i;
77 dw_form_t form;
78 for (i = 0; i < numAttributes; ++i) {
79 form = abbrevDecl->GetFormByIndexUnchecked(i);
80 std::optional<uint8_t> fixed_skip_size =
82 if (fixed_skip_size)
83 offset += *fixed_skip_size;
84 else {
85 bool form_is_indirect = false;
86 do {
87 form_is_indirect = false;
88 uint32_t form_size = 0;
89 switch (form) {
90 // Blocks if inlined data that have a length field and the data bytes
91 // inlined in the .debug_info/.debug_types
92 case DW_FORM_exprloc:
93 case DW_FORM_block:
94 form_size = data.GetULEB128(&offset);
95 break;
96 case DW_FORM_block1:
97 form_size = data.GetU8_unchecked(&offset);
98 break;
99 case DW_FORM_block2:
100 form_size = data.GetU16_unchecked(&offset);
101 break;
102 case DW_FORM_block4:
103 form_size = data.GetU32_unchecked(&offset);
104 break;
105
106 // Inlined NULL terminated C-strings
107 case DW_FORM_string:
108 data.GetCStr(&offset);
109 break;
110
111 // Compile unit address sized values
112 case DW_FORM_addr:
113 form_size = cu->GetAddressByteSize();
114 break;
115 case DW_FORM_ref_addr:
116 if (cu->GetVersion() <= 2)
117 form_size = cu->GetAddressByteSize();
118 else
119 form_size = 4;
120 break;
121
122 // 0 sized form
123 case DW_FORM_flag_present:
124 form_size = 0;
125 break;
126
127 // 1 byte values
128 case DW_FORM_addrx1:
129 case DW_FORM_data1:
130 case DW_FORM_flag:
131 case DW_FORM_ref1:
132 case DW_FORM_strx1:
133 form_size = 1;
134 break;
135
136 // 2 byte values
137 case DW_FORM_addrx2:
138 case DW_FORM_data2:
139 case DW_FORM_ref2:
140 case DW_FORM_strx2:
141 form_size = 2;
142 break;
143
144 // 3 byte values
145 case DW_FORM_addrx3:
146 case DW_FORM_strx3:
147 form_size = 3;
148 break;
149
150 // 4 byte values
151 case DW_FORM_addrx4:
152 case DW_FORM_data4:
153 case DW_FORM_ref4:
154 case DW_FORM_strx4:
155 form_size = 4;
156 break;
157
158 // 8 byte values
159 case DW_FORM_data8:
160 case DW_FORM_ref8:
161 case DW_FORM_ref_sig8:
162 form_size = 8;
163 break;
164
165 // signed or unsigned LEB 128 values
166 case DW_FORM_addrx:
167 case DW_FORM_loclistx:
168 case DW_FORM_rnglistx:
169 case DW_FORM_sdata:
170 case DW_FORM_udata:
171 case DW_FORM_ref_udata:
172 case DW_FORM_GNU_addr_index:
173 case DW_FORM_GNU_str_index:
174 case DW_FORM_strx:
175 data.Skip_LEB128(&offset);
176 break;
177
178 case DW_FORM_indirect:
179 form_is_indirect = true;
180 form = data.GetULEB128(&offset);
181 break;
182
183 case DW_FORM_strp:
184 case DW_FORM_line_strp:
185 case DW_FORM_sec_offset:
186 data.GetU32(&offset);
187 break;
188
189 case DW_FORM_implicit_const:
190 form_size = 0;
191 break;
192
193 default:
194 cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
195 "[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug "
196 "and "
197 "attach the file at the start of this error message",
198 (uint64_t)m_offset, (unsigned)form);
199 *offset_ptr = m_offset;
200 return false;
201 }
202 offset += form_size;
203
204 } while (form_is_indirect);
205 }
206 }
207 *offset_ptr = offset;
208 return true;
209}
210
212 const DWARFDebugInfoEntry &die,
213 const DWARFFormValue &value) {
214 llvm::Expected<DWARFRangeList> expected_ranges =
215 (value.Form() == DW_FORM_rnglistx)
216 ? unit.FindRnglistFromIndex(value.Unsigned())
217 : unit.FindRnglistFromOffset(value.Unsigned());
218 if (expected_ranges)
219 return std::move(*expected_ranges);
220
221 unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
222 "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but "
223 "range extraction failed ({3}), please file a bug "
224 "and attach the file at the start of this error message",
225 die.GetOffset(),
226 llvm::dwarf::FormEncodingString(value.Form()).str().c_str(),
227 value.Unsigned(), toString(expected_ranges.takeError()).c_str());
228 return DWARFRangeList();
229}
230
231// GetDIENamesAndRanges
232//
233// Gets the valid address ranges for a given DIE by looking for a
234// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
236 DWARFUnit *cu, const char *&name, const char *&mangled,
237 DWARFRangeList &ranges, std::optional<int> &decl_file,
238 std::optional<int> &decl_line, std::optional<int> &decl_column,
239 std::optional<int> &call_file, std::optional<int> &call_line,
240 std::optional<int> &call_column, DWARFExpressionList *frame_base) const {
243 std::vector<DWARFDIE> dies;
244 bool set_frame_base_loclist_addr = false;
245
246 const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
247
249 lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule();
250
251 if (abbrevDecl) {
252 const DWARFDataExtractor &data = cu->GetData();
254
255 if (!data.ValidOffset(offset))
256 return false;
257
258 const uint32_t numAttributes = abbrevDecl->NumAttributes();
259 bool do_offset = false;
260
261 for (uint32_t i = 0; i < numAttributes; ++i) {
262 DWARFFormValue form_value(cu);
263 dw_attr_t attr;
264 abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
265
266 if (form_value.ExtractValue(data, &offset)) {
267 switch (attr) {
268 case DW_AT_low_pc:
269 lo_pc = form_value.Address();
270
271 if (do_offset)
272 hi_pc += lo_pc;
273 do_offset = false;
274 break;
275
276 case DW_AT_entry_pc:
277 lo_pc = form_value.Address();
278 break;
279
280 case DW_AT_high_pc:
281 if (form_value.Form() == DW_FORM_addr ||
282 form_value.Form() == DW_FORM_addrx ||
283 form_value.Form() == DW_FORM_GNU_addr_index) {
284 hi_pc = form_value.Address();
285 } else {
286 hi_pc = form_value.Unsigned();
287 if (lo_pc == LLDB_INVALID_ADDRESS)
288 do_offset = hi_pc != LLDB_INVALID_ADDRESS;
289 else
290 hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save
291 // on relocations
292 }
293 break;
294
295 case DW_AT_ranges:
296 ranges = GetRangesOrReportError(*cu, *this, form_value);
297 break;
298
299 case DW_AT_name:
300 if (name == nullptr)
301 name = form_value.AsCString();
302 break;
303
304 case DW_AT_MIPS_linkage_name:
305 case DW_AT_linkage_name:
306 if (mangled == nullptr)
307 mangled = form_value.AsCString();
308 break;
309
310 case DW_AT_abstract_origin:
311 dies.push_back(form_value.Reference());
312 break;
313
314 case DW_AT_specification:
315 dies.push_back(form_value.Reference());
316 break;
317
318 case DW_AT_decl_file:
319 if (!decl_file)
320 decl_file = form_value.Unsigned();
321 break;
322
323 case DW_AT_decl_line:
324 if (!decl_line)
325 decl_line = form_value.Unsigned();
326 break;
327
328 case DW_AT_decl_column:
329 if (!decl_column)
330 decl_column = form_value.Unsigned();
331 break;
332
333 case DW_AT_call_file:
334 if (!call_file)
335 call_file = form_value.Unsigned();
336 break;
337
338 case DW_AT_call_line:
339 if (!call_line)
340 call_line = form_value.Unsigned();
341 break;
342
343 case DW_AT_call_column:
344 if (!call_column)
345 call_column = form_value.Unsigned();
346 break;
347
348 case DW_AT_frame_base:
349 if (frame_base) {
350 if (form_value.BlockData()) {
351 uint32_t block_offset =
352 form_value.BlockData() - data.GetDataStart();
353 uint32_t block_length = form_value.Unsigned();
354 *frame_base =
355 DWARFExpressionList(module,
357 data, block_offset, block_length)),
358 cu);
359 } else {
360 DataExtractor data = cu->GetLocationData();
361 const dw_offset_t offset = form_value.Unsigned();
362 if (data.ValidOffset(offset)) {
363 data = DataExtractor(data, offset, data.GetByteSize() - offset);
364 if (lo_pc != LLDB_INVALID_ADDRESS) {
365 assert(lo_pc >= cu->GetBaseAddress());
366 DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
367 frame_base->SetFuncFileAddress(lo_pc);
368 } else
369 set_frame_base_loclist_addr = true;
370 }
371 }
372 }
373 break;
374
375 default:
376 break;
377 }
378 }
379 }
380 }
381
382 if (ranges.IsEmpty()) {
383 if (lo_pc != LLDB_INVALID_ADDRESS) {
384 if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
385 ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
386 else
387 ranges.Append(DWARFRangeList::Entry(lo_pc, 0));
388 }
389 }
390
391 if (set_frame_base_loclist_addr) {
392 dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
393 assert(lowest_range_pc >= cu->GetBaseAddress());
394 frame_base->SetFuncFileAddress(lowest_range_pc);
395 }
396
397 if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
398 for (const DWARFDIE &die : dies) {
399 if (die) {
400 die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
401 decl_file, decl_line, decl_column,
402 call_file, call_line, call_column);
403 }
404 }
405 }
406 return !ranges.IsEmpty();
407}
408
409// Get all attribute values for a given DIE, including following any
410// specification or abstract origin attributes and including those in the
411// results. Any duplicate attributes will have the first instance take
412// precedence (this can happen for declaration attributes).
414 DWARFAttributes &attributes,
415 Recurse recurse,
416 uint32_t curr_depth) const {
417 const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
418 if (abbrevDecl) {
419 const DWARFDataExtractor &data = cu->GetData();
421
422 const uint32_t num_attributes = abbrevDecl->NumAttributes();
423 for (uint32_t i = 0; i < num_attributes; ++i) {
424 DWARFFormValue form_value(cu);
425 dw_attr_t attr;
426 abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
427 const dw_form_t form = form_value.Form();
428
429 // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
430 // attributes, the depth will be non-zero. We need to omit certain
431 // attributes that don't make sense.
432 switch (attr) {
433 case DW_AT_sibling:
434 case DW_AT_declaration:
435 if (curr_depth > 0) {
436 // This attribute doesn't make sense when combined with the DIE that
437 // references this DIE. We know a DIE is referencing this DIE because
438 // curr_depth is not zero
439 break;
440 }
441 [[fallthrough]];
442 default:
443 attributes.Append(form_value, offset, attr);
444 break;
445 }
446
447 if (recurse == Recurse::yes &&
448 ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) {
449 if (form_value.ExtractValue(data, &offset)) {
450 DWARFDIE spec_die = form_value.Reference();
451 if (spec_die)
452 spec_die.GetDIE()->GetAttributes(spec_die.GetCU(), attributes,
453 recurse, curr_depth + 1);
454 }
455 } else {
456 std::optional<uint8_t> fixed_skip_size =
458 if (fixed_skip_size)
459 offset += *fixed_skip_size;
460 else
461 DWARFFormValue::SkipValue(form, data, &offset, cu);
462 }
463 }
464 } else {
465 attributes.Clear();
466 }
467 return attributes.Size();
468}
469
470// GetAttributeValue
471//
472// Get the value of an attribute and return the .debug_info or .debug_types
473// offset of the attribute if it was properly extracted into form_value,
474// or zero if we fail since an offset of zero is invalid for an attribute (it
475// would be a compile unit header).
477 const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
478 dw_offset_t *end_attr_offset_ptr,
479 bool check_specification_or_abstract_origin) const {
480 if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
481 uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
482
483 if (attr_idx != DW_INVALID_INDEX) {
484 const DWARFDataExtractor &data = cu->GetData();
486
487 uint32_t idx = 0;
488 while (idx < attr_idx)
489 DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++),
490 data, &offset, cu);
491
492 const dw_offset_t attr_offset = offset;
493 form_value.SetUnit(cu);
494 form_value.SetForm(abbrevDecl->GetFormByIndex(idx));
495 if (form_value.ExtractValue(data, &offset)) {
496 if (end_attr_offset_ptr)
497 *end_attr_offset_ptr = offset;
498 return attr_offset;
499 }
500 }
501 }
502
503 if (check_specification_or_abstract_origin) {
504 if (GetAttributeValue(cu, DW_AT_specification, form_value)) {
505 DWARFDIE die = form_value.Reference();
506 if (die) {
507 dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
508 die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
509 if (die_offset)
510 return die_offset;
511 }
512 }
513
514 if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) {
515 DWARFDIE die = form_value.Reference();
516 if (die) {
517 dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
518 die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
519 if (die_offset)
520 return die_offset;
521 }
522 }
523 }
524 return 0;
525}
526
527// GetAttributeValueAsString
528//
529// Get the value of an attribute as a string return it. The resulting pointer
530// to the string data exists within the supplied SymbolFileDWARF and will only
531// be available as long as the SymbolFileDWARF is still around and it's content
532// doesn't change.
534 const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
535 bool check_specification_or_abstract_origin) const {
536 DWARFFormValue form_value;
537 if (GetAttributeValue(cu, attr, form_value, nullptr,
538 check_specification_or_abstract_origin))
539 return form_value.AsCString();
540 return fail_value;
541}
542
543// GetAttributeValueAsUnsigned
544//
545// Get the value of an attribute as unsigned and return it.
547 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
548 bool check_specification_or_abstract_origin) const {
549 DWARFFormValue form_value;
550 if (GetAttributeValue(cu, attr, form_value, nullptr,
551 check_specification_or_abstract_origin))
552 return form_value.Unsigned();
553 return fail_value;
554}
555
556std::optional<uint64_t>
558 const DWARFUnit *cu, const dw_attr_t attr,
559 bool check_specification_or_abstract_origin) const {
560 DWARFFormValue form_value;
561 if (GetAttributeValue(cu, attr, form_value, nullptr,
562 check_specification_or_abstract_origin))
563 return form_value.Unsigned();
564 return std::nullopt;
565}
566
567// GetAttributeValueAsReference
568//
569// Get the value of an attribute as reference and fix up and compile unit
570// relative offsets as needed.
572 const DWARFUnit *cu, const dw_attr_t attr,
573 bool check_specification_or_abstract_origin) const {
574 DWARFFormValue form_value;
575 if (GetAttributeValue(cu, attr, form_value, nullptr,
576 check_specification_or_abstract_origin))
577 return form_value.Reference();
578 return {};
579}
580
582 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
583 bool check_specification_or_abstract_origin) const {
584 DWARFFormValue form_value;
585 if (GetAttributeValue(cu, attr, form_value, nullptr,
586 check_specification_or_abstract_origin))
587 return form_value.Address();
588 return fail_value;
589}
590
591// GetAttributeHighPC
592//
593// Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
594// pc>.
595//
596// Returns the hi_pc or fail_value.
598 const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
599 bool check_specification_or_abstract_origin) const {
600 DWARFFormValue form_value;
601 if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
602 check_specification_or_abstract_origin)) {
603 dw_form_t form = form_value.Form();
604 if (form == DW_FORM_addr || form == DW_FORM_addrx ||
605 form == DW_FORM_GNU_addr_index)
606 return form_value.Address();
607
608 // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
609 return lo_pc + form_value.Unsigned();
610 }
611 return fail_value;
612}
613
614// GetAttributeAddressRange
615//
616// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
617// from-low-pc>.
618//
619// Returns true or sets lo_pc and hi_pc to fail_value.
621 const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
622 uint64_t fail_value, bool check_specification_or_abstract_origin) const {
623 lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
624 check_specification_or_abstract_origin);
625 if (lo_pc != fail_value) {
626 hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
627 check_specification_or_abstract_origin);
628 if (hi_pc != fail_value)
629 return true;
630 }
631 lo_pc = fail_value;
632 hi_pc = fail_value;
633 return false;
634}
635
637 DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
638 bool check_specification_or_abstract_origin) const {
639 ranges.Clear();
640
641 DWARFFormValue form_value;
642 if (GetAttributeValue(cu, DW_AT_ranges, form_value)) {
643 ranges = GetRangesOrReportError(*cu, *this, form_value);
644 } else if (check_hi_lo_pc) {
648 check_specification_or_abstract_origin)) {
649 if (lo_pc < hi_pc)
650 ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
651 }
652 }
653 return ranges.GetSize();
654}
655
656// GetName
657//
658// Get value of the DW_AT_name attribute and return it if one exists, else
659// return NULL.
660const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const {
661 return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
662}
663
664// GetMangledName
665//
666// Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
667// exists, else return the value of the DW_AT_name attribute
668const char *
670 bool substitute_name_allowed) const {
671 const char *name = nullptr;
672
673 name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
674 if (name)
675 return name;
676
677 name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
678 if (name)
679 return name;
680
681 if (!substitute_name_allowed)
682 return nullptr;
683
684 name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
685 return name;
686}
687
688// GetPubname
689//
690// Get value the name for a DIE as it should appear for a .debug_pubnames or
691// .debug_pubtypes section.
692const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const {
693 const char *name = nullptr;
694 if (!cu)
695 return name;
696
697 name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
698 if (name)
699 return name;
700
701 name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
702 if (name)
703 return name;
704
705 name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
706 return name;
707}
708
709/// This function is builds a table very similar to the standard .debug_aranges
710/// table, except that the actual DIE offset for the function is placed in the
711/// table instead of the compile unit offset.
713 DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
714 if (m_tag) {
715 if (m_tag == DW_TAG_subprogram) {
716 DWARFRangeList ranges;
717 GetAttributeAddressRanges(cu, ranges,
718 /*check_hi_lo_pc=*/true);
719 for (const auto &r : ranges) {
720 debug_aranges->AppendRange(GetOffset(), r.GetRangeBase(),
721 r.GetRangeEnd());
722 }
723 }
724
725 const DWARFDebugInfoEntry *child = GetFirstChild();
726 while (child) {
727 child->BuildFunctionAddressRangeTable(cu, debug_aranges);
728 child = child->GetSibling();
729 }
730 }
731}
732
735 DWARFUnit *cu) {
736 DWARFDeclContext dwarf_decl_ctx;
737 for (;;) {
738 const dw_tag_t tag = die->Tag();
739 if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
740 return dwarf_decl_ctx;
741 dwarf_decl_ctx.AppendDeclContext(tag, die->GetName(cu));
742 DWARFDIE parent_decl_ctx_die = die->GetParentDeclContextDIE(cu);
743 if (!parent_decl_ctx_die || parent_decl_ctx_die.GetDIE() == die)
744 return dwarf_decl_ctx;
745 if (parent_decl_ctx_die.Tag() == DW_TAG_compile_unit ||
746 parent_decl_ctx_die.Tag() == DW_TAG_partial_unit)
747 return dwarf_decl_ctx;
748 die = parent_decl_ctx_die.GetDIE();
749 cu = parent_decl_ctx_die.GetCU();
750 }
751}
752
754 return GetDWARFDeclContextStatic(this, cu);
755}
756
759 DWARFAttributes attributes;
760 GetAttributes(cu, attributes, Recurse::yes);
761 return GetParentDeclContextDIE(cu, attributes);
762}
763
766 DWARFUnit *cu, const DWARFAttributes &attributes) const {
767 DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
768
769 while (die) {
770 // If this is the original DIE that we are searching for a declaration for,
771 // then don't look in the cache as we don't want our own decl context to be
772 // our decl context...
773 if (die.GetDIE() != this) {
774 switch (die.Tag()) {
775 case DW_TAG_compile_unit:
776 case DW_TAG_partial_unit:
777 case DW_TAG_namespace:
778 case DW_TAG_structure_type:
779 case DW_TAG_union_type:
780 case DW_TAG_class_type:
781 return die;
782
783 default:
784 break;
785 }
786 }
787
788 DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification);
789 if (spec_die) {
790 DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
791 if (decl_ctx_die)
792 return decl_ctx_die;
793 }
794
795 DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin);
796 if (abs_die) {
797 DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
798 if (decl_ctx_die)
799 return decl_ctx_die;
800 }
801
802 die = die.GetParent();
803 }
804 return DWARFDIE();
805}
806
808 return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
809}
810
813 if (cu) {
814 const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations();
815 if (abbrev_set)
816 return abbrev_set->GetAbbreviationDeclaration(m_abbr_idx);
817 }
818 return nullptr;
819}
820
822 if (Tag() != DW_TAG_variable)
823 return false;
824 const DWARFDebugInfoEntry *parent_die = GetParent();
825 while (parent_die != nullptr) {
826 switch (parent_die->Tag()) {
827 case DW_TAG_subprogram:
828 case DW_TAG_lexical_block:
829 case DW_TAG_inlined_subroutine:
830 return false;
831
832 case DW_TAG_compile_unit:
833 case DW_TAG_partial_unit:
834 return true;
835
836 default:
837 break;
838 }
839 parent_die = parent_die->GetParent();
840 }
841 return false;
842}
843
845 return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
848 m_tag == rhs.m_tag;
849}
850
852 return !(*this == rhs);
853}
static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, const DWARFDebugInfoEntry &die, const DWARFFormValue &value)
int g_verbose
#define lldbassert(x)
Definition: LLDBAssert.h:15
const DWARFAbbreviationDeclaration * GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const
DWARFDIE FormValueAsReference(dw_attr_t attr) const
size_t Size() const
void Append(const DWARFFormValue &form_value, dw_offset_t attr_die_offset, dw_attr_t attr)
dw_tag_t Tag() const
size_t GetAttributes(DWARFAttributes &attributes, Recurse recurse=Recurse::yes) const
DWARFUnit * GetCU() const
Definition: DWARFBaseDIE.h:55
DWARFDIE GetParent() const
Definition: DWARFDIE.cpp:86
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition: DWARFDIE.cpp:118
DWARFDIE GetParentDeclContextDIE() const
Definition: DWARFDIE.cpp:420
void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc)
DWARFDebugInfoEntry objects assume that they are living in one big vector and do pointer arithmetic o...
bool operator==(const DWARFDebugInfoEntry &rhs) const
std::optional< uint64_t > GetAttributeValueAsOptionalUnsigned(const DWARFUnit *cu, const dw_attr_t attr, bool check_specification_or_abstract_origin=false) const
size_t GetAttributeAddressRanges(DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc, bool check_specification_or_abstract_origin=false) const
dw_offset_t GetOffset() const
size_t GetAttributes(DWARFUnit *cu, DWARFAttributes &attrs, Recurse recurse=Recurse::yes) 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.
const char * GetAttributeValueAsString(const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, bool check_specification_or_abstract_origin=false) const
dw_offset_t GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &formValue, dw_offset_t *end_attr_offset_ptr=nullptr, bool check_specification_or_abstract_origin=false) const
bool operator!=(const DWARFDebugInfoEntry &rhs) const
bool Extract(const lldb_private::DWARFDataExtractor &data, const DWARFUnit *cu, lldb::offset_t *offset_ptr)
DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu) const
DWARFDeclContext GetDWARFDeclContext(DWARFUnit *cu) const
bool GetAttributeAddressRange(const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, uint64_t fail_value, bool check_specification_or_abstract_origin=false) const
bool IsGlobalOrStaticScopeVariable() const
bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name, const char *&mangled, DWARFRangeList &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, lldb_private::DWARFExpressionList *frame_base=nullptr) const
const char * GetMangledName(const DWARFUnit *cu, bool substitute_name_allowed=true) const
dw_addr_t GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, bool check_specification_or_abstract_origin=false) 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_specification_or_abstract_origin=false) const
uint64_t GetAttributeValueAsUnsigned(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin=false) const
const char * GetPubname(const DWARFUnit *cu) const
const DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const
uint64_t GetAttributeValueAsAddress(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin=false) const
DWARFDebugInfoEntry * GetFirstChild()
const char * GetName(const DWARFUnit *cu) const
DWARFDebugInfoEntry * GetSibling()
static DWARFDeclContext GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu)
lldb::offset_t GetFirstAttributeOffset() const
DWARFDebugInfoEntry * GetParent()
void AppendDeclContext(dw_tag_t tag, const char *name)
DWARFDIE Reference() const
dw_form_t Form() const
const char * AsCString() const
void SetForm(dw_form_t form)
uint64_t Unsigned() const
const uint8_t * BlockData() const
dw_addr_t Address() const
std::optional< uint8_t > GetFixedSize() const
void SetUnit(const DWARFUnit *unit)
bool ExtractValue(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr)
bool SkipValue(const lldb_private::DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr) const
SymbolFileDWARF & GetSymbolFileDWARF() const
Definition: DWARFUnit.h:200
const lldb_private::DWARFDataExtractor & GetData() const
Get the data that contains the DIE information for this unit.
Definition: DWARFUnit.cpp:1000
uint16_t GetVersion() const
Definition: DWARFUnit.h:155
lldb_private::DWARFDataExtractor GetLocationData() const
Definition: DWARFUnit.cpp:523
uint8_t GetAddressByteSize() const
Definition: DWARFUnit.h:158
llvm::Expected< DWARFRangeList > FindRnglistFromIndex(uint32_t index)
Return a list of address ranges retrieved from an encoded range list whose offset is found via a tabl...
Definition: DWARFUnit.cpp:1075
const DWARFAbbreviationDeclarationSet * GetAbbreviations() const
Definition: DWARFUnit.cpp:437
dw_addr_t GetBaseAddress() const
Definition: DWARFUnit.h:160
llvm::Expected< DWARFRangeList > FindRnglistFromOffset(dw_offset_t offset)
Return a list of address ranges resulting from a (possibly encoded) range list starting at a given of...
Definition: DWARFUnit.cpp:1028
"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.
static bool ParseDWARFLocationList(const DWARFUnit *dwarf_cu, const DataExtractor &data, DWARFExpressionList *loc_list)
An data extractor class.
Definition: DataExtractor.h:48
uint64_t GetULEB128(lldb::offset_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
uint32_t GetU32_unchecked(lldb::offset_t *offset_ptr) const
const char * GetCStr(lldb::offset_t *offset_ptr) const
Extract a C string from *offset_ptr.
uint32_t Skip_LEB128(lldb::offset_t *offset_ptr) const
Skip an LEB128 number at *offset_ptr.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint8_t GetU8_unchecked(lldb::offset_t *offset_ptr) const
const uint8_t * GetDataStart() const
Get the data start pointer.
bool ValidOffset(lldb::offset_t offset) const
Test the validity of offset.
uint16_t GetU16_unchecked(lldb::offset_t *offset_ptr) const
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
Definition: ModuleChild.cpp:24
void Append(const Entry &entry)
Definition: RangeMap.h:179
BaseType GetMinRangeBase(BaseType fail_value) const
Definition: RangeMap.h:261
bool IsEmpty() const
Definition: RangeMap.h:293
size_t GetSize() const
Definition: RangeMap.h:295
ObjectFile * GetObjectFile() override
Definition: SymbolFile.h:477
uint64_t dw_offset_t
Definition: dwarf.h:33
lldb_private::RangeVector< dw_addr_t, dw_addr_t, 2 > DWARFRangeList
Definition: dwarf.h:45
llvm::dwarf::Tag dw_tag_t
Definition: dwarf.h:28
uint64_t dw_addr_t
Definition: dwarf.h:29
#define DW_INVALID_INDEX
Definition: dwarf.h:39
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
#define UINT32_MAX
Definition: lldb-defines.h:19
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
const char * toString(AppleArm64ExceptionClass EC)
uint64_t offset_t
Definition: lldb-types.h:87