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