/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 | } |