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