Coverage Report

Created: 2023-11-11 10:31

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