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 lldb_private::dwarf;
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,DWARFExpressionList * 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 DWARFExpressionList *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 =
349 DWARFExpressionList(module,
350 DWARFExpression(DataExtractor(
351 data, block_offset, block_length)),
352 cu);
353 } else {
354 DataExtractor data = cu->GetLocationData();
355 const dw_offset_t offset = form_value.Unsigned();
356 if (data.ValidOffset(offset)) {
357 data = DataExtractor(data, offset, data.GetByteSize() - offset);
358 if (lo_pc != LLDB_INVALID_ADDRESS) {
359 assert(lo_pc >= cu->GetBaseAddress());
360 DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
361 frame_base->SetFuncFileAddress(lo_pc);
362 } else
363 set_frame_base_loclist_addr = true;
364 }
365 }
366 }
367 break;
368
369 default:
370 break;
371 }
372 }
373 }
374 }
375
376 if (ranges.IsEmpty()) {
377 if (lo_pc != LLDB_INVALID_ADDRESS) {
378 if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
379 ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
380 else
381 ranges.Append(DWARFRangeList::Entry(lo_pc, 0));
382 }
383 }
384
385 if (set_frame_base_loclist_addr) {
386 dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
387 assert(lowest_range_pc >= cu->GetBaseAddress());
388 frame_base->SetFuncFileAddress(lowest_range_pc);
389 }
390
391 if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
392 for (const DWARFDIE &die : dies) {
393 if (die) {
394 die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
395 decl_file, decl_line, decl_column,
396 call_file, call_line, call_column);
397 }
398 }
399 }
400 return !ranges.IsEmpty();
401 }
402
403 // Get all attribute values for a given DIE, including following any
404 // specification or abstract origin attributes and including those in the
405 // results. Any duplicate attributes will have the first instance take
406 // precedence (this can happen for declaration attributes).
GetAttributes(DWARFUnit * cu,DWARFAttributes & attributes,Recurse recurse,uint32_t curr_depth) const407 size_t DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu,
408 DWARFAttributes &attributes,
409 Recurse recurse,
410 uint32_t curr_depth) const {
411 const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
412 if (abbrevDecl) {
413 const DWARFDataExtractor &data = cu->GetData();
414 lldb::offset_t offset = GetFirstAttributeOffset();
415
416 const uint32_t num_attributes = abbrevDecl->NumAttributes();
417 for (uint32_t i = 0; i < num_attributes; ++i) {
418 DWARFFormValue form_value(cu);
419 dw_attr_t attr;
420 abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
421 const dw_form_t form = form_value.Form();
422
423 // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
424 // attributes, the depth will be non-zero. We need to omit certain
425 // attributes that don't make sense.
426 switch (attr) {
427 case DW_AT_sibling:
428 case DW_AT_declaration:
429 if (curr_depth > 0) {
430 // This attribute doesn't make sense when combined with the DIE that
431 // references this DIE. We know a DIE is referencing this DIE because
432 // curr_depth is not zero
433 break;
434 }
435 LLVM_FALLTHROUGH;
436 default:
437 attributes.Append(form_value, offset, attr);
438 break;
439 }
440
441 if (recurse == Recurse::yes &&
442 ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) {
443 if (form_value.ExtractValue(data, &offset)) {
444 DWARFDIE spec_die = form_value.Reference();
445 if (spec_die)
446 spec_die.GetDIE()->GetAttributes(spec_die.GetCU(), attributes,
447 recurse, curr_depth + 1);
448 }
449 } else {
450 llvm::Optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu);
451 if (fixed_skip_size)
452 offset += *fixed_skip_size;
453 else
454 DWARFFormValue::SkipValue(form, data, &offset, cu);
455 }
456 }
457 } else {
458 attributes.Clear();
459 }
460 return attributes.Size();
461 }
462
463 // GetAttributeValue
464 //
465 // Get the value of an attribute and return the .debug_info or .debug_types
466 // offset of the attribute if it was properly extracted into form_value,
467 // or zero if we fail since an offset of zero is invalid for an attribute (it
468 // 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) const469 dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
470 const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
471 dw_offset_t *end_attr_offset_ptr,
472 bool check_specification_or_abstract_origin) const {
473 if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
474 uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
475
476 if (attr_idx != DW_INVALID_INDEX) {
477 const DWARFDataExtractor &data = cu->GetData();
478 lldb::offset_t offset = GetFirstAttributeOffset();
479
480 uint32_t idx = 0;
481 while (idx < attr_idx)
482 DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++),
483 data, &offset, cu);
484
485 const dw_offset_t attr_offset = offset;
486 form_value.SetUnit(cu);
487 form_value.SetForm(abbrevDecl->GetFormByIndex(idx));
488 if (form_value.ExtractValue(data, &offset)) {
489 if (end_attr_offset_ptr)
490 *end_attr_offset_ptr = offset;
491 return attr_offset;
492 }
493 }
494 }
495
496 if (check_specification_or_abstract_origin) {
497 if (GetAttributeValue(cu, DW_AT_specification, form_value)) {
498 DWARFDIE die = form_value.Reference();
499 if (die) {
500 dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
501 die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
502 if (die_offset)
503 return die_offset;
504 }
505 }
506
507 if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) {
508 DWARFDIE die = form_value.Reference();
509 if (die) {
510 dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
511 die.GetCU(), attr, form_value, end_attr_offset_ptr, false);
512 if (die_offset)
513 return die_offset;
514 }
515 }
516 }
517 return 0;
518 }
519
520 // GetAttributeValueAsString
521 //
522 // Get the value of an attribute as a string return it. The resulting pointer
523 // to the string data exists within the supplied SymbolFileDWARF and will only
524 // be available as long as the SymbolFileDWARF is still around and it's content
525 // doesn't change.
GetAttributeValueAsString(const DWARFUnit * cu,const dw_attr_t attr,const char * fail_value,bool check_specification_or_abstract_origin) const526 const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
527 const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
528 bool check_specification_or_abstract_origin) const {
529 DWARFFormValue form_value;
530 if (GetAttributeValue(cu, attr, form_value, nullptr,
531 check_specification_or_abstract_origin))
532 return form_value.AsCString();
533 return fail_value;
534 }
535
536 // GetAttributeValueAsUnsigned
537 //
538 // 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) const539 uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
540 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
541 bool check_specification_or_abstract_origin) const {
542 DWARFFormValue form_value;
543 if (GetAttributeValue(cu, attr, form_value, nullptr,
544 check_specification_or_abstract_origin))
545 return form_value.Unsigned();
546 return fail_value;
547 }
548
549 // GetAttributeValueAsReference
550 //
551 // Get the value of an attribute as reference and fix up and compile unit
552 // relative offsets as needed.
GetAttributeValueAsReference(const DWARFUnit * cu,const dw_attr_t attr,bool check_specification_or_abstract_origin) const553 DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference(
554 const DWARFUnit *cu, const dw_attr_t attr,
555 bool check_specification_or_abstract_origin) const {
556 DWARFFormValue form_value;
557 if (GetAttributeValue(cu, attr, form_value, nullptr,
558 check_specification_or_abstract_origin))
559 return form_value.Reference();
560 return {};
561 }
562
GetAttributeValueAsAddress(const DWARFUnit * cu,const dw_attr_t attr,uint64_t fail_value,bool check_specification_or_abstract_origin) const563 uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
564 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
565 bool check_specification_or_abstract_origin) const {
566 DWARFFormValue form_value;
567 if (GetAttributeValue(cu, attr, form_value, nullptr,
568 check_specification_or_abstract_origin))
569 return form_value.Address();
570 return fail_value;
571 }
572
573 // GetAttributeHighPC
574 //
575 // Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
576 // pc>.
577 //
578 // 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) const579 dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
580 const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
581 bool check_specification_or_abstract_origin) const {
582 DWARFFormValue form_value;
583 if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
584 check_specification_or_abstract_origin)) {
585 dw_form_t form = form_value.Form();
586 if (form == DW_FORM_addr || form == DW_FORM_addrx ||
587 form == DW_FORM_GNU_addr_index)
588 return form_value.Address();
589
590 // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
591 return lo_pc + form_value.Unsigned();
592 }
593 return fail_value;
594 }
595
596 // GetAttributeAddressRange
597 //
598 // Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
599 // from-low-pc>.
600 //
601 // 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) const602 bool DWARFDebugInfoEntry::GetAttributeAddressRange(
603 const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
604 uint64_t fail_value, bool check_specification_or_abstract_origin) const {
605 lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
606 check_specification_or_abstract_origin);
607 if (lo_pc != fail_value) {
608 hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
609 check_specification_or_abstract_origin);
610 if (hi_pc != fail_value)
611 return true;
612 }
613 lo_pc = fail_value;
614 hi_pc = fail_value;
615 return false;
616 }
617
GetAttributeAddressRanges(DWARFUnit * cu,DWARFRangeList & ranges,bool check_hi_lo_pc,bool check_specification_or_abstract_origin) const618 size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
619 DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
620 bool check_specification_or_abstract_origin) const {
621 ranges.Clear();
622
623 DWARFFormValue form_value;
624 if (GetAttributeValue(cu, DW_AT_ranges, form_value)) {
625 ranges = GetRangesOrReportError(*cu, *this, form_value);
626 } else if (check_hi_lo_pc) {
627 dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
628 dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
629 if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS,
630 check_specification_or_abstract_origin)) {
631 if (lo_pc < hi_pc)
632 ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
633 }
634 }
635 return ranges.GetSize();
636 }
637
638 // GetName
639 //
640 // Get value of the DW_AT_name attribute and return it if one exists, else
641 // return NULL.
GetName(const DWARFUnit * cu) const642 const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const {
643 return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
644 }
645
646 // GetMangledName
647 //
648 // Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
649 // exists, else return the value of the DW_AT_name attribute
650 const char *
GetMangledName(const DWARFUnit * cu,bool substitute_name_allowed) const651 DWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu,
652 bool substitute_name_allowed) const {
653 const char *name = nullptr;
654
655 name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
656 if (name)
657 return name;
658
659 name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
660 if (name)
661 return name;
662
663 if (!substitute_name_allowed)
664 return nullptr;
665
666 name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
667 return name;
668 }
669
670 // GetPubname
671 //
672 // Get value the name for a DIE as it should appear for a .debug_pubnames or
673 // .debug_pubtypes section.
GetPubname(const DWARFUnit * cu) const674 const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const {
675 const char *name = nullptr;
676 if (!cu)
677 return name;
678
679 name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true);
680 if (name)
681 return name;
682
683 name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true);
684 if (name)
685 return name;
686
687 name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true);
688 return name;
689 }
690
691 /// This function is builds a table very similar to the standard .debug_aranges
692 /// table, except that the actual DIE offset for the function is placed in the
693 /// table instead of the compile unit offset.
BuildFunctionAddressRangeTable(DWARFUnit * cu,DWARFDebugAranges * debug_aranges) const694 void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
695 DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const {
696 if (m_tag) {
697 if (m_tag == DW_TAG_subprogram) {
698 DWARFRangeList ranges;
699 GetAttributeAddressRanges(cu, ranges,
700 /*check_hi_lo_pc=*/true);
701 for (const auto &r : ranges) {
702 debug_aranges->AppendRange(GetOffset(), r.GetRangeBase(),
703 r.GetRangeEnd());
704 }
705 }
706
707 const DWARFDebugInfoEntry *child = GetFirstChild();
708 while (child) {
709 child->BuildFunctionAddressRangeTable(cu, debug_aranges);
710 child = child->GetSibling();
711 }
712 }
713 }
714
715 DWARFDeclContext
GetDWARFDeclContextStatic(const DWARFDebugInfoEntry * die,DWARFUnit * cu)716 DWARFDebugInfoEntry::GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die,
717 DWARFUnit *cu) {
718 DWARFDeclContext dwarf_decl_ctx;
719 for (;;) {
720 const dw_tag_t tag = die->Tag();
721 if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
722 return dwarf_decl_ctx;
723 dwarf_decl_ctx.AppendDeclContext(tag, die->GetName(cu));
724 DWARFDIE parent_decl_ctx_die = die->GetParentDeclContextDIE(cu);
725 if (!parent_decl_ctx_die || parent_decl_ctx_die.GetDIE() == die)
726 return dwarf_decl_ctx;
727 if (parent_decl_ctx_die.Tag() == DW_TAG_compile_unit ||
728 parent_decl_ctx_die.Tag() == DW_TAG_partial_unit)
729 return dwarf_decl_ctx;
730 die = parent_decl_ctx_die.GetDIE();
731 cu = parent_decl_ctx_die.GetCU();
732 }
733 }
734
GetDWARFDeclContext(DWARFUnit * cu) const735 DWARFDeclContext DWARFDebugInfoEntry::GetDWARFDeclContext(DWARFUnit *cu) const {
736 return GetDWARFDeclContextStatic(this, cu);
737 }
738
739 DWARFDIE
GetParentDeclContextDIE(DWARFUnit * cu) const740 DWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const {
741 DWARFAttributes attributes;
742 GetAttributes(cu, attributes, Recurse::yes);
743 return GetParentDeclContextDIE(cu, attributes);
744 }
745
746 DWARFDIE
GetParentDeclContextDIE(DWARFUnit * cu,const DWARFAttributes & attributes) const747 DWARFDebugInfoEntry::GetParentDeclContextDIE(
748 DWARFUnit *cu, const DWARFAttributes &attributes) const {
749 DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
750
751 while (die) {
752 // If this is the original DIE that we are searching for a declaration for,
753 // then don't look in the cache as we don't want our own decl context to be
754 // our decl context...
755 if (die.GetDIE() != this) {
756 switch (die.Tag()) {
757 case DW_TAG_compile_unit:
758 case DW_TAG_partial_unit:
759 case DW_TAG_namespace:
760 case DW_TAG_structure_type:
761 case DW_TAG_union_type:
762 case DW_TAG_class_type:
763 return die;
764
765 default:
766 break;
767 }
768 }
769
770 DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification);
771 if (spec_die) {
772 DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
773 if (decl_ctx_die)
774 return decl_ctx_die;
775 }
776
777 DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin);
778 if (abs_die) {
779 DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
780 if (decl_ctx_die)
781 return decl_ctx_die;
782 }
783
784 die = die.GetParent();
785 }
786 return DWARFDIE();
787 }
788
GetQualifiedName(DWARFUnit * cu,std::string & storage) const789 const char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
790 std::string &storage) const {
791 DWARFAttributes attributes;
792 GetAttributes(cu, attributes, Recurse::yes);
793 return GetQualifiedName(cu, attributes, storage);
794 }
795
796 const char *
GetQualifiedName(DWARFUnit * cu,const DWARFAttributes & attributes,std::string & storage) const797 DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
798 const DWARFAttributes &attributes,
799 std::string &storage) const {
800
801 const char *name = GetName(cu);
802
803 if (name) {
804 DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu);
805 storage.clear();
806 // TODO: change this to get the correct decl context parent....
807 while (parent_decl_ctx_die) {
808 const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();
809 switch (parent_tag) {
810 case DW_TAG_namespace: {
811 const char *namespace_name = parent_decl_ctx_die.GetName();
812 if (namespace_name) {
813 storage.insert(0, "::");
814 storage.insert(0, namespace_name);
815 } else {
816 storage.insert(0, "(anonymous namespace)::");
817 }
818 parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
819 } break;
820
821 case DW_TAG_class_type:
822 case DW_TAG_structure_type:
823 case DW_TAG_union_type: {
824 const char *class_union_struct_name = parent_decl_ctx_die.GetName();
825
826 if (class_union_struct_name) {
827 storage.insert(0, "::");
828 storage.insert(0, class_union_struct_name);
829 }
830 parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
831 } break;
832
833 default:
834 parent_decl_ctx_die.Clear();
835 break;
836 }
837 }
838
839 if (storage.empty())
840 storage.append("::");
841
842 storage.append(name);
843 }
844 if (storage.empty())
845 return nullptr;
846 return storage.c_str();
847 }
848
GetFirstAttributeOffset() const849 lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const {
850 return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
851 }
852
853 const DWARFAbbreviationDeclaration *
GetAbbreviationDeclarationPtr(const DWARFUnit * cu) const854 DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const {
855 if (cu) {
856 const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations();
857 if (abbrev_set)
858 return abbrev_set->GetAbbreviationDeclaration(m_abbr_idx);
859 }
860 return nullptr;
861 }
862
IsGlobalOrStaticScopeVariable() const863 bool DWARFDebugInfoEntry::IsGlobalOrStaticScopeVariable() const {
864 if (Tag() != DW_TAG_variable)
865 return false;
866 const DWARFDebugInfoEntry *parent_die = GetParent();
867 while (parent_die != nullptr) {
868 switch (parent_die->Tag()) {
869 case DW_TAG_subprogram:
870 case DW_TAG_lexical_block:
871 case DW_TAG_inlined_subroutine:
872 return false;
873
874 case DW_TAG_compile_unit:
875 case DW_TAG_partial_unit:
876 return true;
877
878 default:
879 break;
880 }
881 parent_die = parent_die->GetParent();
882 }
883 return false;
884 }
885
operator ==(const DWARFDebugInfoEntry & rhs) const886 bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
887 return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
888 m_sibling_idx == rhs.m_sibling_idx &&
889 m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
890 m_tag == rhs.m_tag;
891 }
892
operator !=(const DWARFDebugInfoEntry & rhs) const893 bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
894 return !(*this == rhs);
895 }
896