1 | //===-- LVDWARFReader.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 | // This implements the LVDWARFReader class. |
10 | // It supports ELF, Mach-O and Wasm binary formats. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h" |
15 | #include "llvm/DebugInfo/DIContext.h" |
16 | #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" |
17 | #include "llvm/DebugInfo/DWARF/DWARFExpression.h" |
18 | #include "llvm/DebugInfo/LogicalView/Core/LVLine.h" |
19 | #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" |
20 | #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" |
21 | #include "llvm/DebugInfo/LogicalView/Core/LVType.h" |
22 | #include "llvm/Object/Error.h" |
23 | #include "llvm/Object/MachO.h" |
24 | #include "llvm/Support/FormatVariadic.h" |
25 | |
26 | using namespace llvm; |
27 | using namespace llvm::object; |
28 | using namespace llvm::logicalview; |
29 | |
30 | #define DEBUG_TYPE "DWARFReader" |
31 | |
32 | LVElement *LVDWARFReader::createElement(dwarf::Tag Tag) { |
33 | CurrentScope = nullptr; |
34 | CurrentSymbol = nullptr; |
35 | CurrentType = nullptr; |
36 | CurrentRanges.clear(); |
37 | |
38 | if (!options().getPrintSymbols()) { |
39 | switch (Tag) { |
40 | // As the command line options did not specify a request to print |
41 | // logical symbols (--print=symbols or --print=all or --print=elements), |
42 | // skip its creation. |
43 | case dwarf::DW_TAG_formal_parameter: |
44 | case dwarf::DW_TAG_unspecified_parameters: |
45 | case dwarf::DW_TAG_member: |
46 | case dwarf::DW_TAG_variable: |
47 | case dwarf::DW_TAG_inheritance: |
48 | case dwarf::DW_TAG_constant: |
49 | case dwarf::DW_TAG_call_site_parameter: |
50 | case dwarf::DW_TAG_GNU_call_site_parameter: |
51 | return nullptr; |
52 | default: |
53 | break; |
54 | } |
55 | } |
56 | |
57 | switch (Tag) { |
58 | // Types. |
59 | case dwarf::DW_TAG_base_type: |
60 | CurrentType = createType(); |
61 | CurrentType->setIsBase(); |
62 | if (options().getAttributeBase()) |
63 | CurrentType->setIncludeInPrint(); |
64 | return CurrentType; |
65 | case dwarf::DW_TAG_const_type: |
66 | CurrentType = createType(); |
67 | CurrentType->setIsConst(); |
68 | CurrentType->setName("const" ); |
69 | return CurrentType; |
70 | case dwarf::DW_TAG_enumerator: |
71 | CurrentType = createTypeEnumerator(); |
72 | return CurrentType; |
73 | case dwarf::DW_TAG_imported_declaration: |
74 | CurrentType = createTypeImport(); |
75 | CurrentType->setIsImportDeclaration(); |
76 | return CurrentType; |
77 | case dwarf::DW_TAG_imported_module: |
78 | CurrentType = createTypeImport(); |
79 | CurrentType->setIsImportModule(); |
80 | return CurrentType; |
81 | case dwarf::DW_TAG_pointer_type: |
82 | CurrentType = createType(); |
83 | CurrentType->setIsPointer(); |
84 | CurrentType->setName("*" ); |
85 | return CurrentType; |
86 | case dwarf::DW_TAG_ptr_to_member_type: |
87 | CurrentType = createType(); |
88 | CurrentType->setIsPointerMember(); |
89 | CurrentType->setName("*" ); |
90 | return CurrentType; |
91 | case dwarf::DW_TAG_reference_type: |
92 | CurrentType = createType(); |
93 | CurrentType->setIsReference(); |
94 | CurrentType->setName("&" ); |
95 | return CurrentType; |
96 | case dwarf::DW_TAG_restrict_type: |
97 | CurrentType = createType(); |
98 | CurrentType->setIsRestrict(); |
99 | CurrentType->setName("restrict" ); |
100 | return CurrentType; |
101 | case dwarf::DW_TAG_rvalue_reference_type: |
102 | CurrentType = createType(); |
103 | CurrentType->setIsRvalueReference(); |
104 | CurrentType->setName("&&" ); |
105 | return CurrentType; |
106 | case dwarf::DW_TAG_subrange_type: |
107 | CurrentType = createTypeSubrange(); |
108 | return CurrentType; |
109 | case dwarf::DW_TAG_template_value_parameter: |
110 | CurrentType = createTypeParam(); |
111 | CurrentType->setIsTemplateValueParam(); |
112 | return CurrentType; |
113 | case dwarf::DW_TAG_template_type_parameter: |
114 | CurrentType = createTypeParam(); |
115 | CurrentType->setIsTemplateTypeParam(); |
116 | return CurrentType; |
117 | case dwarf::DW_TAG_GNU_template_template_param: |
118 | CurrentType = createTypeParam(); |
119 | CurrentType->setIsTemplateTemplateParam(); |
120 | return CurrentType; |
121 | case dwarf::DW_TAG_typedef: |
122 | CurrentType = createTypeDefinition(); |
123 | return CurrentType; |
124 | case dwarf::DW_TAG_unspecified_type: |
125 | CurrentType = createType(); |
126 | CurrentType->setIsUnspecified(); |
127 | return CurrentType; |
128 | case dwarf::DW_TAG_volatile_type: |
129 | CurrentType = createType(); |
130 | CurrentType->setIsVolatile(); |
131 | CurrentType->setName("volatile" ); |
132 | return CurrentType; |
133 | |
134 | // Symbols. |
135 | case dwarf::DW_TAG_formal_parameter: |
136 | CurrentSymbol = createSymbol(); |
137 | CurrentSymbol->setIsParameter(); |
138 | return CurrentSymbol; |
139 | case dwarf::DW_TAG_unspecified_parameters: |
140 | CurrentSymbol = createSymbol(); |
141 | CurrentSymbol->setIsUnspecified(); |
142 | CurrentSymbol->setName("..." ); |
143 | return CurrentSymbol; |
144 | case dwarf::DW_TAG_member: |
145 | CurrentSymbol = createSymbol(); |
146 | CurrentSymbol->setIsMember(); |
147 | return CurrentSymbol; |
148 | case dwarf::DW_TAG_variable: |
149 | CurrentSymbol = createSymbol(); |
150 | CurrentSymbol->setIsVariable(); |
151 | return CurrentSymbol; |
152 | case dwarf::DW_TAG_inheritance: |
153 | CurrentSymbol = createSymbol(); |
154 | CurrentSymbol->setIsInheritance(); |
155 | return CurrentSymbol; |
156 | case dwarf::DW_TAG_call_site_parameter: |
157 | case dwarf::DW_TAG_GNU_call_site_parameter: |
158 | CurrentSymbol = createSymbol(); |
159 | CurrentSymbol->setIsCallSiteParameter(); |
160 | return CurrentSymbol; |
161 | case dwarf::DW_TAG_constant: |
162 | CurrentSymbol = createSymbol(); |
163 | CurrentSymbol->setIsConstant(); |
164 | return CurrentSymbol; |
165 | |
166 | // Scopes. |
167 | case dwarf::DW_TAG_catch_block: |
168 | CurrentScope = createScope(); |
169 | CurrentScope->setIsCatchBlock(); |
170 | return CurrentScope; |
171 | case dwarf::DW_TAG_lexical_block: |
172 | CurrentScope = createScope(); |
173 | CurrentScope->setIsLexicalBlock(); |
174 | return CurrentScope; |
175 | case dwarf::DW_TAG_try_block: |
176 | CurrentScope = createScope(); |
177 | CurrentScope->setIsTryBlock(); |
178 | return CurrentScope; |
179 | case dwarf::DW_TAG_compile_unit: |
180 | case dwarf::DW_TAG_skeleton_unit: |
181 | CurrentScope = createScopeCompileUnit(); |
182 | CompileUnit = static_cast<LVScopeCompileUnit *>(CurrentScope); |
183 | return CurrentScope; |
184 | case dwarf::DW_TAG_inlined_subroutine: |
185 | CurrentScope = createScopeFunctionInlined(); |
186 | return CurrentScope; |
187 | case dwarf::DW_TAG_namespace: |
188 | CurrentScope = createScopeNamespace(); |
189 | return CurrentScope; |
190 | case dwarf::DW_TAG_template_alias: |
191 | CurrentScope = createScopeAlias(); |
192 | return CurrentScope; |
193 | case dwarf::DW_TAG_array_type: |
194 | CurrentScope = createScopeArray(); |
195 | return CurrentScope; |
196 | case dwarf::DW_TAG_call_site: |
197 | case dwarf::DW_TAG_GNU_call_site: |
198 | CurrentScope = createScopeFunction(); |
199 | CurrentScope->setIsCallSite(); |
200 | return CurrentScope; |
201 | case dwarf::DW_TAG_entry_point: |
202 | CurrentScope = createScopeFunction(); |
203 | CurrentScope->setIsEntryPoint(); |
204 | return CurrentScope; |
205 | case dwarf::DW_TAG_subprogram: |
206 | CurrentScope = createScopeFunction(); |
207 | CurrentScope->setIsSubprogram(); |
208 | return CurrentScope; |
209 | case dwarf::DW_TAG_subroutine_type: |
210 | CurrentScope = createScopeFunctionType(); |
211 | return CurrentScope; |
212 | case dwarf::DW_TAG_label: |
213 | CurrentScope = createScopeFunction(); |
214 | CurrentScope->setIsLabel(); |
215 | return CurrentScope; |
216 | case dwarf::DW_TAG_class_type: |
217 | CurrentScope = createScopeAggregate(); |
218 | CurrentScope->setIsClass(); |
219 | return CurrentScope; |
220 | case dwarf::DW_TAG_structure_type: |
221 | CurrentScope = createScopeAggregate(); |
222 | CurrentScope->setIsStructure(); |
223 | return CurrentScope; |
224 | case dwarf::DW_TAG_union_type: |
225 | CurrentScope = createScopeAggregate(); |
226 | CurrentScope->setIsUnion(); |
227 | return CurrentScope; |
228 | case dwarf::DW_TAG_enumeration_type: |
229 | CurrentScope = createScopeEnumeration(); |
230 | return CurrentScope; |
231 | case dwarf::DW_TAG_GNU_formal_parameter_pack: |
232 | CurrentScope = createScopeFormalPack(); |
233 | return CurrentScope; |
234 | case dwarf::DW_TAG_GNU_template_parameter_pack: |
235 | CurrentScope = createScopeTemplatePack(); |
236 | return CurrentScope; |
237 | default: |
238 | // Collect TAGs not implemented. |
239 | if (options().getInternalTag() && Tag) |
240 | CompileUnit->addDebugTag(Target: Tag, Offset: CurrentOffset); |
241 | break; |
242 | } |
243 | return nullptr; |
244 | } |
245 | |
246 | void LVDWARFReader::processOneAttribute(const DWARFDie &Die, |
247 | LVOffset *OffsetPtr, |
248 | const AttributeSpec &AttrSpec) { |
249 | uint64_t OffsetOnEntry = *OffsetPtr; |
250 | DWARFUnit *U = Die.getDwarfUnit(); |
251 | const DWARFFormValue &FormValue = |
252 | DWARFFormValue::createFromUnit(F: AttrSpec.Form, Unit: U, OffsetPtr); |
253 | |
254 | // We are processing .debug_info section, implicit_const attribute |
255 | // values are not really stored here, but in .debug_abbrev section. |
256 | auto GetAsUnsignedConstant = [&]() -> int64_t { |
257 | return AttrSpec.isImplicitConst() ? AttrSpec.getImplicitConstValue() |
258 | : *FormValue.getAsUnsignedConstant(); |
259 | }; |
260 | |
261 | auto GetFlag = [](const DWARFFormValue &FormValue) -> bool { |
262 | return FormValue.isFormClass(FC: DWARFFormValue::FC_Flag); |
263 | }; |
264 | |
265 | auto GetBoundValue = [](const DWARFFormValue &FormValue) -> int64_t { |
266 | switch (FormValue.getForm()) { |
267 | case dwarf::DW_FORM_ref_addr: |
268 | case dwarf::DW_FORM_ref1: |
269 | case dwarf::DW_FORM_ref2: |
270 | case dwarf::DW_FORM_ref4: |
271 | case dwarf::DW_FORM_ref8: |
272 | case dwarf::DW_FORM_ref_udata: |
273 | case dwarf::DW_FORM_ref_sig8: |
274 | return *FormValue.getAsReferenceUVal(); |
275 | case dwarf::DW_FORM_data1: |
276 | case dwarf::DW_FORM_flag: |
277 | case dwarf::DW_FORM_data2: |
278 | case dwarf::DW_FORM_data4: |
279 | case dwarf::DW_FORM_data8: |
280 | case dwarf::DW_FORM_udata: |
281 | case dwarf::DW_FORM_ref_sup4: |
282 | case dwarf::DW_FORM_ref_sup8: |
283 | return *FormValue.getAsUnsignedConstant(); |
284 | case dwarf::DW_FORM_sdata: |
285 | return *FormValue.getAsSignedConstant(); |
286 | default: |
287 | return 0; |
288 | } |
289 | }; |
290 | |
291 | LLVM_DEBUG({ |
292 | dbgs() << " " << hexValue(OffsetOnEntry) |
293 | << formatv(" {0}" , AttrSpec.Attr) << "\n" ; |
294 | }); |
295 | |
296 | switch (AttrSpec.Attr) { |
297 | case dwarf::DW_AT_accessibility: |
298 | CurrentElement->setAccessibilityCode(*FormValue.getAsUnsignedConstant()); |
299 | break; |
300 | case dwarf::DW_AT_artificial: |
301 | CurrentElement->setIsArtificial(); |
302 | break; |
303 | case dwarf::DW_AT_bit_size: |
304 | CurrentElement->setBitSize(*FormValue.getAsUnsignedConstant()); |
305 | break; |
306 | case dwarf::DW_AT_call_file: |
307 | CurrentElement->setCallFilenameIndex(GetAsUnsignedConstant()); |
308 | break; |
309 | case dwarf::DW_AT_call_line: |
310 | CurrentElement->setCallLineNumber(IncrementFileIndex |
311 | ? GetAsUnsignedConstant() + 1 |
312 | : GetAsUnsignedConstant()); |
313 | break; |
314 | case dwarf::DW_AT_comp_dir: |
315 | CompileUnit->setCompilationDirectory(dwarf::toStringRef(V: FormValue)); |
316 | break; |
317 | case dwarf::DW_AT_const_value: |
318 | if (FormValue.isFormClass(FC: DWARFFormValue::FC_Block)) { |
319 | ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); |
320 | // Store the expression as a hexadecimal string. |
321 | CurrentElement->setValue( |
322 | llvm::toHex(Input: llvm::toStringRef(Input: Expr), /*LowerCase=*/true)); |
323 | } else if (FormValue.isFormClass(FC: DWARFFormValue::FC_Constant)) { |
324 | // In the case of negative values, generate the string representation |
325 | // for a positive value prefixed with the negative sign. |
326 | if (FormValue.getForm() == dwarf::DW_FORM_sdata) { |
327 | std::stringstream Stream; |
328 | int64_t Value = *FormValue.getAsSignedConstant(); |
329 | if (Value < 0) { |
330 | Stream << "-" ; |
331 | Value = std::abs(i: Value); |
332 | } |
333 | Stream << hexString(Value, Width: 2); |
334 | CurrentElement->setValue(Stream.str()); |
335 | } else |
336 | CurrentElement->setValue( |
337 | hexString(Value: *FormValue.getAsUnsignedConstant(), Width: 2)); |
338 | } else |
339 | CurrentElement->setValue(dwarf::toStringRef(V: FormValue)); |
340 | break; |
341 | case dwarf::DW_AT_count: |
342 | CurrentElement->setCount(*FormValue.getAsUnsignedConstant()); |
343 | break; |
344 | case dwarf::DW_AT_decl_line: |
345 | CurrentElement->setLineNumber(GetAsUnsignedConstant()); |
346 | break; |
347 | case dwarf::DW_AT_decl_file: |
348 | CurrentElement->setFilenameIndex(IncrementFileIndex |
349 | ? GetAsUnsignedConstant() + 1 |
350 | : GetAsUnsignedConstant()); |
351 | break; |
352 | case dwarf::DW_AT_enum_class: |
353 | if (GetFlag(FormValue)) |
354 | CurrentElement->setIsEnumClass(); |
355 | break; |
356 | case dwarf::DW_AT_external: |
357 | if (GetFlag(FormValue)) |
358 | CurrentElement->setIsExternal(); |
359 | break; |
360 | case dwarf::DW_AT_GNU_discriminator: |
361 | CurrentElement->setDiscriminator(*FormValue.getAsUnsignedConstant()); |
362 | break; |
363 | case dwarf::DW_AT_inline: |
364 | CurrentElement->setInlineCode(*FormValue.getAsUnsignedConstant()); |
365 | break; |
366 | case dwarf::DW_AT_lower_bound: |
367 | CurrentElement->setLowerBound(GetBoundValue(FormValue)); |
368 | break; |
369 | case dwarf::DW_AT_name: |
370 | CurrentElement->setName(dwarf::toStringRef(V: FormValue)); |
371 | break; |
372 | case dwarf::DW_AT_linkage_name: |
373 | case dwarf::DW_AT_MIPS_linkage_name: |
374 | CurrentElement->setLinkageName(dwarf::toStringRef(V: FormValue)); |
375 | break; |
376 | case dwarf::DW_AT_producer: |
377 | if (options().getAttributeProducer()) |
378 | CurrentElement->setProducer(dwarf::toStringRef(V: FormValue)); |
379 | break; |
380 | case dwarf::DW_AT_upper_bound: |
381 | CurrentElement->setUpperBound(GetBoundValue(FormValue)); |
382 | break; |
383 | case dwarf::DW_AT_virtuality: |
384 | CurrentElement->setVirtualityCode(*FormValue.getAsUnsignedConstant()); |
385 | break; |
386 | |
387 | case dwarf::DW_AT_abstract_origin: |
388 | case dwarf::DW_AT_call_origin: |
389 | case dwarf::DW_AT_extension: |
390 | case dwarf::DW_AT_import: |
391 | case dwarf::DW_AT_specification: |
392 | case dwarf::DW_AT_type: |
393 | updateReference(Attr: AttrSpec.Attr, FormValue); |
394 | break; |
395 | |
396 | case dwarf::DW_AT_low_pc: |
397 | if (options().getGeneralCollectRanges()) { |
398 | FoundLowPC = true; |
399 | // For toolchains that support the removal of unused code, the linker |
400 | // marks functions that have been removed, by setting the value for the |
401 | // low_pc to the max address. |
402 | if (std::optional<uint64_t> Value = FormValue.getAsAddress()) { |
403 | CurrentLowPC = *Value; |
404 | } else { |
405 | uint64_t UValue = FormValue.getRawUValue(); |
406 | if (U->getAddrOffsetSectionItem(Index: UValue)) { |
407 | CurrentLowPC = *FormValue.getAsAddress(); |
408 | } else { |
409 | FoundLowPC = false; |
410 | // We are dealing with an index into the .debug_addr section. |
411 | LLVM_DEBUG({ |
412 | dbgs() << format("indexed (%8.8x) address = " , (uint32_t)UValue); |
413 | }); |
414 | } |
415 | } |
416 | if (FoundLowPC) { |
417 | if (CurrentLowPC == MaxAddress) |
418 | CurrentElement->setIsDiscarded(); |
419 | // Consider the case of WebAssembly. |
420 | CurrentLowPC += WasmCodeSectionOffset; |
421 | if (CurrentElement->isCompileUnit()) |
422 | setCUBaseAddress(CurrentLowPC); |
423 | } |
424 | } |
425 | break; |
426 | |
427 | case dwarf::DW_AT_high_pc: |
428 | if (options().getGeneralCollectRanges()) { |
429 | FoundHighPC = true; |
430 | if (std::optional<uint64_t> Address = FormValue.getAsAddress()) |
431 | // High PC is an address. |
432 | CurrentHighPC = *Address; |
433 | if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant()) |
434 | // High PC is an offset from LowPC. |
435 | // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as |
436 | // the CurrentLowPC has already that offset added. Basically, use the |
437 | // original DW_AT_loc_pc value. |
438 | CurrentHighPC = |
439 | (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) + |
440 | *Offset; |
441 | // Store the real upper limit for the address range. |
442 | if (UpdateHighAddress && CurrentHighPC > 0) |
443 | --CurrentHighPC; |
444 | // Consider the case of WebAssembly. |
445 | CurrentHighPC += WasmCodeSectionOffset; |
446 | if (CurrentElement->isCompileUnit()) |
447 | setCUHighAddress(CurrentHighPC); |
448 | } |
449 | break; |
450 | |
451 | case dwarf::DW_AT_ranges: |
452 | if (RangesDataAvailable && options().getGeneralCollectRanges()) { |
453 | auto GetRanges = [](const DWARFFormValue &FormValue, |
454 | DWARFUnit *U) -> Expected<DWARFAddressRangesVector> { |
455 | if (FormValue.getForm() == dwarf::DW_FORM_rnglistx) |
456 | return U->findRnglistFromIndex(Index: *FormValue.getAsSectionOffset()); |
457 | return U->findRnglistFromOffset(Offset: *FormValue.getAsSectionOffset()); |
458 | }; |
459 | Expected<DWARFAddressRangesVector> RangesOrError = |
460 | GetRanges(FormValue, U); |
461 | if (!RangesOrError) { |
462 | LLVM_DEBUG({ |
463 | std::string TheError(toString(RangesOrError.takeError())); |
464 | dbgs() << format("error decoding address ranges = " , |
465 | TheError.c_str()); |
466 | }); |
467 | consumeError(Err: RangesOrError.takeError()); |
468 | break; |
469 | } |
470 | // The address ranges are absolute. There is no need to add any addend. |
471 | DWARFAddressRangesVector Ranges = RangesOrError.get(); |
472 | for (DWARFAddressRange &Range : Ranges) { |
473 | // This seems to be a tombstone for empty ranges. |
474 | if (Range.LowPC == Range.HighPC) |
475 | continue; |
476 | // Store the real upper limit for the address range. |
477 | if (UpdateHighAddress && Range.HighPC > 0) |
478 | --Range.HighPC; |
479 | // Consider the case of WebAssembly. |
480 | Range.LowPC += WasmCodeSectionOffset; |
481 | Range.HighPC += WasmCodeSectionOffset; |
482 | // Add the pair of addresses. |
483 | CurrentScope->addObject(LowerAddress: Range.LowPC, UpperAddress: Range.HighPC); |
484 | // If the scope is the CU, do not update the ranges set. |
485 | if (!CurrentElement->isCompileUnit()) |
486 | CurrentRanges.emplace_back(args&: Range.LowPC, args&: Range.HighPC); |
487 | } |
488 | } |
489 | break; |
490 | |
491 | // Get the location list for the symbol. |
492 | case dwarf::DW_AT_data_member_location: |
493 | if (options().getAttributeAnyLocation()) |
494 | processLocationMember(Attr: AttrSpec.Attr, FormValue, Die, OffsetOnEntry); |
495 | break; |
496 | |
497 | // Get the location list for the symbol. |
498 | case dwarf::DW_AT_location: |
499 | case dwarf::DW_AT_string_length: |
500 | case dwarf::DW_AT_use_location: |
501 | if (options().getAttributeAnyLocation() && CurrentSymbol) |
502 | processLocationList(Attr: AttrSpec.Attr, FormValue, Die, OffsetOnEntry); |
503 | break; |
504 | |
505 | case dwarf::DW_AT_call_data_value: |
506 | case dwarf::DW_AT_call_value: |
507 | case dwarf::DW_AT_GNU_call_site_data_value: |
508 | case dwarf::DW_AT_GNU_call_site_value: |
509 | if (options().getAttributeAnyLocation() && CurrentSymbol) |
510 | processLocationList(Attr: AttrSpec.Attr, FormValue, Die, OffsetOnEntry, |
511 | /*CallSiteLocation=*/true); |
512 | break; |
513 | |
514 | default: |
515 | break; |
516 | } |
517 | } |
518 | |
519 | LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, |
520 | DWARFDie &SkeletonDie) { |
521 | // If the input DIE corresponds to the compile unit, it can be: |
522 | // a) Simple DWARF: a standard DIE. Ignore the skeleton DIE (is empty). |
523 | // b) Split DWARF: the DIE for the split DWARF. The skeleton is the DIE |
524 | // for the skeleton DWARF. Process both DIEs. |
525 | const DWARFDie &DIE = SkeletonDie.isValid() ? SkeletonDie : InputDIE; |
526 | DWARFDataExtractor DebugInfoData = |
527 | DIE.getDwarfUnit()->getDebugInfoExtractor(); |
528 | LVOffset Offset = DIE.getOffset(); |
529 | |
530 | // Reset values for the current DIE. |
531 | CurrentLowPC = 0; |
532 | CurrentHighPC = 0; |
533 | CurrentOffset = Offset; |
534 | CurrentEndOffset = 0; |
535 | FoundLowPC = false; |
536 | FoundHighPC = false; |
537 | |
538 | // Process supported attributes. |
539 | if (DebugInfoData.isValidOffset(offset: Offset)) { |
540 | |
541 | LLVM_DEBUG({ |
542 | dbgs() << "DIE: " << hexValue(Offset) << formatv(" {0}" , DIE.getTag()) |
543 | << "\n" ; |
544 | }); |
545 | |
546 | // Create the logical view element for the current DIE. |
547 | dwarf::Tag Tag = DIE.getTag(); |
548 | CurrentElement = createElement(Tag); |
549 | if (!CurrentElement) |
550 | return CurrentScope; |
551 | |
552 | CurrentElement->setTag(Tag); |
553 | CurrentElement->setOffset(Offset); |
554 | |
555 | if (options().getAttributeAnySource() && CurrentElement->isCompileUnit()) |
556 | addCompileUnitOffset(Offset, |
557 | CompileUnit: static_cast<LVScopeCompileUnit *>(CurrentElement)); |
558 | |
559 | // Insert the newly created element into the element symbol table. If the |
560 | // element is in the list, it means there are previously created elements |
561 | // referencing this element. |
562 | if (ElementTable.find(x: Offset) == ElementTable.end()) { |
563 | // No previous references to this offset. |
564 | ElementTable.emplace(args: std::piecewise_construct, |
565 | args: std::forward_as_tuple(args&: Offset), |
566 | args: std::forward_as_tuple(args&: CurrentElement)); |
567 | } else { |
568 | // There are previous references to this element. We need to update the |
569 | // element and all the references pointing to this element. |
570 | LVElementEntry &Reference = ElementTable[Offset]; |
571 | Reference.Element = CurrentElement; |
572 | // Traverse the element set and update the elements (backtracking). |
573 | for (LVElement *Target : Reference.References) |
574 | Target->setReference(CurrentElement); |
575 | for (LVElement *Target : Reference.Types) |
576 | Target->setType(CurrentElement); |
577 | // Clear the pending elements. |
578 | Reference.References.clear(); |
579 | Reference.Types.clear(); |
580 | } |
581 | |
582 | // Add the current element to its parent as there are attributes |
583 | // (locations) that require the scope level. |
584 | if (CurrentScope) |
585 | Parent->addElement(Scope: CurrentScope); |
586 | else if (CurrentSymbol) |
587 | Parent->addElement(Symbol: CurrentSymbol); |
588 | else if (CurrentType) |
589 | Parent->addElement(Type: CurrentType); |
590 | |
591 | // Process the attributes for the given DIE. |
592 | auto ProcessAttributes = [&](const DWARFDie &TheDIE, |
593 | DWARFDataExtractor &DebugData) { |
594 | CurrentEndOffset = Offset; |
595 | uint32_t abbrCode = DebugData.getULEB128(offset_ptr: &CurrentEndOffset); |
596 | if (abbrCode) { |
597 | if (const DWARFAbbreviationDeclaration *AbbrevDecl = |
598 | TheDIE.getAbbreviationDeclarationPtr()) |
599 | if (AbbrevDecl) |
600 | for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : |
601 | AbbrevDecl->attributes()) |
602 | processOneAttribute(Die: TheDIE, OffsetPtr: &CurrentEndOffset, AttrSpec); |
603 | } |
604 | }; |
605 | |
606 | ProcessAttributes(DIE, DebugInfoData); |
607 | |
608 | // If the input DIE is for a compile unit, process its attributes in |
609 | // the case of split DWARF, to override any common attribute values. |
610 | if (SkeletonDie.isValid()) { |
611 | DWARFDataExtractor DebugInfoData = |
612 | InputDIE.getDwarfUnit()->getDebugInfoExtractor(); |
613 | LVOffset Offset = InputDIE.getOffset(); |
614 | if (DebugInfoData.isValidOffset(offset: Offset)) |
615 | ProcessAttributes(InputDIE, DebugInfoData); |
616 | } |
617 | } |
618 | |
619 | if (CurrentScope) { |
620 | if (CurrentScope->getCanHaveRanges()) { |
621 | // If the scope has ranges, they are already added to the scope. |
622 | // Add any collected LowPC/HighPC values. |
623 | bool IsCompileUnit = CurrentScope->getIsCompileUnit(); |
624 | if (FoundLowPC && FoundHighPC) { |
625 | CurrentScope->addObject(LowerAddress: CurrentLowPC, UpperAddress: CurrentHighPC); |
626 | if (!IsCompileUnit) { |
627 | // If the scope is a function, add it to the public names. |
628 | if ((options().getAttributePublics() || |
629 | options().getPrintAnyLine()) && |
630 | CurrentScope->getIsFunction() && |
631 | !CurrentScope->getIsInlinedFunction()) |
632 | CompileUnit->addPublicName(Scope: CurrentScope, LowPC: CurrentLowPC, |
633 | HighPC: CurrentHighPC); |
634 | } |
635 | } |
636 | |
637 | // Look for scopes with ranges and no linkage name information that |
638 | // are referencing another scopes via DW_AT_specification. They are |
639 | // possible candidates for a comdat scope. |
640 | if (CurrentScope->getHasRanges() && |
641 | !CurrentScope->getLinkageNameIndex() && |
642 | CurrentScope->getHasReferenceSpecification()) { |
643 | // Get the linkage name in order to search for a possible comdat. |
644 | std::optional<DWARFFormValue> LinkageDIE = |
645 | DIE.findRecursively(Attrs: dwarf::DW_AT_linkage_name); |
646 | if (LinkageDIE.has_value()) { |
647 | StringRef Name(dwarf::toStringRef(V: LinkageDIE)); |
648 | if (!Name.empty()) |
649 | CurrentScope->setLinkageName(Name); |
650 | } |
651 | } |
652 | |
653 | // If the current scope is in the 'LinkageNames' table, update its |
654 | // logical scope. For other scopes, always we will assume the default |
655 | // ".text" section index. |
656 | LVSectionIndex SectionIndex = updateSymbolTable(Function: CurrentScope); |
657 | if (CurrentScope->getIsComdat()) |
658 | CompileUnit->setHasComdatScopes(); |
659 | |
660 | // Update section index contained ranges. |
661 | if (SectionIndex) { |
662 | if (!CurrentRanges.empty()) { |
663 | for (LVAddressRange &Range : CurrentRanges) |
664 | addSectionRange(SectionIndex, Scope: CurrentScope, LowerAddress: Range.first, |
665 | UpperAddress: Range.second); |
666 | CurrentRanges.clear(); |
667 | } |
668 | // If the scope is the CU, do not update the ranges set. |
669 | if (FoundLowPC && FoundHighPC && !IsCompileUnit) { |
670 | addSectionRange(SectionIndex, Scope: CurrentScope, LowerAddress: CurrentLowPC, |
671 | UpperAddress: CurrentHighPC); |
672 | } |
673 | } |
674 | } |
675 | // Mark member functions. |
676 | if (Parent->getIsAggregate()) |
677 | CurrentScope->setIsMember(); |
678 | } |
679 | |
680 | // Keep track of symbols with locations. |
681 | if (options().getAttributeAnyLocation() && CurrentSymbol && |
682 | CurrentSymbol->getHasLocation()) |
683 | SymbolsWithLocations.push_back(Elt: CurrentSymbol); |
684 | |
685 | // If we have template parameters, mark the parent as template. |
686 | if (CurrentType && CurrentType->getIsTemplateParam()) |
687 | Parent->setIsTemplate(); |
688 | |
689 | return CurrentScope; |
690 | } |
691 | |
692 | void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent, |
693 | DWARFDie &SkeletonDie) { |
694 | // Process the current DIE. |
695 | LVScope *Scope = processOneDie(InputDIE: DIE, Parent, SkeletonDie); |
696 | if (Scope) { |
697 | LVOffset Lower = DIE.getOffset(); |
698 | LVOffset Upper = CurrentEndOffset; |
699 | DWARFDie DummyDie; |
700 | // Traverse the children chain. |
701 | DWARFDie Child = DIE.getFirstChild(); |
702 | while (Child) { |
703 | traverseDieAndChildren(DIE&: Child, Parent: Scope, SkeletonDie&: DummyDie); |
704 | Upper = Child.getOffset(); |
705 | Child = Child.getSibling(); |
706 | } |
707 | // Calculate contributions to the debug info section. |
708 | if (options().getPrintSizes() && Upper) |
709 | CompileUnit->addSize(Scope, Lower, Upper); |
710 | } |
711 | } |
712 | |
713 | void LVDWARFReader::processLocationGaps() { |
714 | if (options().getAttributeAnyLocation()) |
715 | for (LVSymbol *Symbol : SymbolsWithLocations) |
716 | Symbol->fillLocationGaps(); |
717 | } |
718 | |
719 | void LVDWARFReader::createLineAndFileRecords( |
720 | const DWARFDebugLine::LineTable *Lines) { |
721 | if (!Lines) |
722 | return; |
723 | |
724 | // Get the source filenames. |
725 | if (!Lines->Prologue.FileNames.empty()) |
726 | for (const DWARFDebugLine::FileNameEntry &Entry : |
727 | Lines->Prologue.FileNames) { |
728 | std::string Directory; |
729 | if (Lines->getDirectoryForEntry(Entry, Directory)) |
730 | Directory = transformPath(Path: Directory); |
731 | if (Directory.empty()) |
732 | Directory = std::string(CompileUnit->getCompilationDirectory()); |
733 | std::string File = transformPath(Path: dwarf::toStringRef(V: Entry.Name)); |
734 | std::string String; |
735 | raw_string_ostream(String) << Directory << "/" << File; |
736 | CompileUnit->addFilename(Name: String); |
737 | } |
738 | |
739 | // In DWARF5 the file indexes start at 0; |
740 | bool IncrementIndex = Lines->Prologue.getVersion() >= 5; |
741 | |
742 | // Get the source lines if requested by command line option. |
743 | if (options().getPrintLines() && Lines->Rows.size()) |
744 | for (const DWARFDebugLine::Row &Row : Lines->Rows) { |
745 | // Here we collect logical debug lines in CULines. Later on, |
746 | // the 'processLines()' function will move each created logical line |
747 | // to its enclosing logical scope, using the debug ranges information |
748 | // and they will be released when its scope parent is deleted. |
749 | LVLineDebug *Line = createLineDebug(); |
750 | CULines.push_back(Elt: Line); |
751 | // Consider the case of WebAssembly. |
752 | Line->setAddress(Row.Address.Address + WasmCodeSectionOffset); |
753 | Line->setFilename( |
754 | CompileUnit->getFilename(Index: IncrementIndex ? Row.File + 1 : Row.File)); |
755 | Line->setLineNumber(Row.Line); |
756 | if (Row.Discriminator) |
757 | Line->setDiscriminator(Row.Discriminator); |
758 | if (Row.IsStmt) |
759 | Line->setIsNewStatement(); |
760 | if (Row.BasicBlock) |
761 | Line->setIsBasicBlock(); |
762 | if (Row.EndSequence) |
763 | Line->setIsEndSequence(); |
764 | if (Row.EpilogueBegin) |
765 | Line->setIsEpilogueBegin(); |
766 | if (Row.PrologueEnd) |
767 | Line->setIsPrologueEnd(); |
768 | LLVM_DEBUG({ |
769 | dbgs() << "Address: " << hexValue(Line->getAddress()) |
770 | << " Line: " << Line->lineNumberAsString(/*ShowZero=*/true) |
771 | << "\n" ; |
772 | }); |
773 | } |
774 | } |
775 | |
776 | std::string LVDWARFReader::getRegisterName(LVSmall Opcode, |
777 | ArrayRef<uint64_t> Operands) { |
778 | // The 'prettyPrintRegisterOp' function uses the DWARFUnit to support |
779 | // DW_OP_regval_type. At this point we are operating on a logical view |
780 | // item, with no access to the underlying DWARF data used by LLVM. |
781 | // We do not support DW_OP_regval_type here. |
782 | if (Opcode == dwarf::DW_OP_regval_type) |
783 | return {}; |
784 | |
785 | std::string string; |
786 | raw_string_ostream Stream(string); |
787 | DIDumpOptions DumpOpts; |
788 | auto *MCRegInfo = MRI.get(); |
789 | auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef { |
790 | if (!MCRegInfo) |
791 | return {}; |
792 | if (std::optional<unsigned> LLVMRegNum = |
793 | MCRegInfo->getLLVMRegNum(RegNum: DwarfRegNum, isEH: IsEH)) |
794 | if (const char *RegName = MCRegInfo->getName(RegNo: *LLVMRegNum)) |
795 | return StringRef(RegName); |
796 | return {}; |
797 | }; |
798 | DumpOpts.GetNameForDWARFReg = GetRegName; |
799 | DWARFExpression::prettyPrintRegisterOp(/*U=*/nullptr, OS&: Stream, DumpOpts, |
800 | Opcode, Operands); |
801 | return Stream.str(); |
802 | } |
803 | |
804 | Error LVDWARFReader::createScopes() { |
805 | LLVM_DEBUG({ |
806 | W.startLine() << "\n" ; |
807 | W.printString("File" , Obj.getFileName().str()); |
808 | W.printString("Format" , FileFormatName); |
809 | }); |
810 | |
811 | if (Error Err = LVReader::createScopes()) |
812 | return Err; |
813 | |
814 | // As the DwarfContext object is valid only during the scopes creation, |
815 | // we need to create our own Target information, to be used during the |
816 | // logical view printing, in the case of instructions being requested. |
817 | std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(Obj); |
818 | if (!DwarfContext) |
819 | return createStringError(EC: errc::invalid_argument, |
820 | Fmt: "Could not create DWARF information: %s" , |
821 | Vals: getFilename().str().c_str()); |
822 | |
823 | if (Error Err = loadTargetInfo(Obj)) |
824 | return Err; |
825 | |
826 | // Create a mapping for virtual addresses. |
827 | mapVirtualAddress(Obj); |
828 | |
829 | // Select the correct compile unit range, depending if we are dealing with |
830 | // a standard or split DWARF object. |
831 | DWARFContext::compile_unit_range CompileUnits = |
832 | DwarfContext->getNumCompileUnits() ? DwarfContext->compile_units() |
833 | : DwarfContext->dwo_compile_units(); |
834 | for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) { |
835 | |
836 | // Deduction of index used for the line records. |
837 | // |
838 | // For the following test case: test.cpp |
839 | // void foo(void ParamPtr) { } |
840 | |
841 | // Both GCC and Clang generate DWARF-5 .debug_line layout. |
842 | |
843 | // * GCC (GNU C++17 11.3.0) - All DW_AT_decl_file use index 1. |
844 | // |
845 | // .debug_info: |
846 | // format = DWARF32, version = 0x0005 |
847 | // DW_TAG_compile_unit |
848 | // DW_AT_name ("test.cpp") |
849 | // DW_TAG_subprogram ("foo") |
850 | // DW_AT_decl_file (1) |
851 | // DW_TAG_formal_parameter ("ParamPtr") |
852 | // DW_AT_decl_file (1) |
853 | // .debug_line: |
854 | // Line table prologue: format (DWARF32), version (5) |
855 | // include_directories[0] = "..." |
856 | // file_names[0]: name ("test.cpp"), dir_index (0) |
857 | // file_names[1]: name ("test.cpp"), dir_index (0) |
858 | |
859 | // * Clang (14.0.6) - All DW_AT_decl_file use index 0. |
860 | // |
861 | // .debug_info: |
862 | // format = DWARF32, version = 0x0005 |
863 | // DW_AT_producer ("clang version 14.0.6") |
864 | // DW_AT_name ("test.cpp") |
865 | // |
866 | // DW_TAG_subprogram ("foo") |
867 | // DW_AT_decl_file (0) |
868 | // DW_TAG_formal_parameter ("ParamPtr") |
869 | // DW_AT_decl_file (0) |
870 | // .debug_line: |
871 | // Line table prologue: format (DWARF32), version (5) |
872 | // include_directories[0] = "..." |
873 | // file_names[0]: name ("test.cpp"), dir_index (0) |
874 | |
875 | // From DWARFDebugLine::getFileNameByIndex documentation: |
876 | // In Dwarf 4, the files are 1-indexed. |
877 | // In Dwarf 5, the files are 0-indexed. |
878 | // Additional discussions here: |
879 | // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html |
880 | |
881 | // The DWARF reader is expecting the files are 1-indexed, so using |
882 | // the .debug_line header information decide if the indexed require |
883 | // an internal adjustment. |
884 | |
885 | // For the case of GCC (DWARF5), if the entries[0] and [1] are the |
886 | // same, do not perform any adjustment. |
887 | auto DeduceIncrementFileIndex = [&]() -> bool { |
888 | if (CU->getVersion() < 5) |
889 | // DWARF-4 or earlier -> Don't increment index. |
890 | return false; |
891 | |
892 | if (const DWARFDebugLine::LineTable *LT = |
893 | CU->getContext().getLineTableForUnit(U: CU.get())) { |
894 | // Check if there are at least 2 entries and if they are the same. |
895 | if (LT->hasFileAtIndex(FileIndex: 0) && LT->hasFileAtIndex(FileIndex: 1)) { |
896 | const DWARFDebugLine::FileNameEntry &EntryZero = |
897 | LT->Prologue.getFileNameEntry(Index: 0); |
898 | const DWARFDebugLine::FileNameEntry &EntryOne = |
899 | LT->Prologue.getFileNameEntry(Index: 1); |
900 | // Check directory indexes. |
901 | if (EntryZero.DirIdx != EntryOne.DirIdx) |
902 | // DWARF-5 -> Increment index. |
903 | return true; |
904 | // Check filename. |
905 | std::string FileZero; |
906 | std::string FileOne; |
907 | StringRef None; |
908 | LT->getFileNameByIndex( |
909 | FileIndex: 0, CompDir: None, Kind: DILineInfoSpecifier::FileLineInfoKind::RawValue, |
910 | Result&: FileZero); |
911 | LT->getFileNameByIndex( |
912 | FileIndex: 1, CompDir: None, Kind: DILineInfoSpecifier::FileLineInfoKind::RawValue, |
913 | Result&: FileOne); |
914 | return FileZero.compare(str: FileOne); |
915 | } |
916 | } |
917 | |
918 | // DWARF-5 -> Increment index. |
919 | return true; |
920 | }; |
921 | // The DWARF reader expects the indexes as 1-indexed. |
922 | IncrementFileIndex = DeduceIncrementFileIndex(); |
923 | |
924 | DWARFDie UnitDie = CU->getUnitDIE(); |
925 | SmallString<16> DWOAlternativeLocation; |
926 | if (UnitDie) { |
927 | std::optional<const char *> DWOFileName = |
928 | CU->getVersion() >= 5 |
929 | ? dwarf::toString(V: UnitDie.find(Attr: dwarf::DW_AT_dwo_name)) |
930 | : dwarf::toString(V: UnitDie.find(Attr: dwarf::DW_AT_GNU_dwo_name)); |
931 | StringRef From(DWOFileName.value_or(u: "" )); |
932 | DWOAlternativeLocation = createAlternativePath(From); |
933 | } |
934 | |
935 | // The current CU can be a normal compile unit (standard) or a skeleton |
936 | // compile unit (split). For both cases, the returned die, will be used |
937 | // to create the logical scopes. |
938 | DWARFDie CUDie = CU->getNonSkeletonUnitDIE( |
939 | /*ExtractUnitDIEOnly=*/false, |
940 | /*DWOAlternativeLocation=*/DWOAlternativeLocation); |
941 | if (!CUDie.isValid()) |
942 | continue; |
943 | |
944 | // The current unit corresponds to the .dwo file. We need to get the |
945 | // skeleton unit and query for any ranges that will enclose any ranges |
946 | // in the non-skeleton unit. |
947 | DWARFDie DummyDie; |
948 | DWARFDie SkeletonDie = |
949 | CUDie.getDwarfUnit()->isDWOUnit() ? CU->getUnitDIE(ExtractUnitDIEOnly: false) : DummyDie; |
950 | // Disable the ranges processing if we have just a single .dwo object, |
951 | // as any DW_AT_ranges will access not available range information. |
952 | RangesDataAvailable = |
953 | (!CUDie.getDwarfUnit()->isDWOUnit() || |
954 | (SkeletonDie.isValid() ? !SkeletonDie.getDwarfUnit()->isDWOUnit() |
955 | : true)); |
956 | |
957 | traverseDieAndChildren(DIE&: CUDie, Parent: Root, SkeletonDie); |
958 | |
959 | createLineAndFileRecords(Lines: DwarfContext->getLineTableForUnit(U: CU.get())); |
960 | if (Error Err = createInstructions()) |
961 | return Err; |
962 | |
963 | // Process the compilation unit, as there are cases where enclosed |
964 | // functions have the same ranges values. Insert the compilation unit |
965 | // ranges at the end, to allow enclosing ranges to be first in the list. |
966 | LVSectionIndex SectionIndex = getSectionIndex(Scope: CompileUnit); |
967 | addSectionRange(SectionIndex, Scope: CompileUnit); |
968 | LVRange *ScopesWithRanges = getSectionRanges(SectionIndex); |
969 | ScopesWithRanges->sort(); |
970 | |
971 | processLines(DebugLines: &CULines, SectionIndex); |
972 | processLocationGaps(); |
973 | |
974 | // These are per compile unit. |
975 | ScopesWithRanges->clear(); |
976 | SymbolsWithLocations.clear(); |
977 | CULines.clear(); |
978 | } |
979 | |
980 | return Error::success(); |
981 | } |
982 | |
983 | // Get the location information for the associated attribute. |
984 | void LVDWARFReader::processLocationList(dwarf::Attribute Attr, |
985 | const DWARFFormValue &FormValue, |
986 | const DWARFDie &Die, |
987 | uint64_t OffsetOnEntry, |
988 | bool CallSiteLocation) { |
989 | |
990 | auto ProcessLocationExpression = [&](const DWARFExpression &Expression) { |
991 | for (const DWARFExpression::Operation &Op : Expression) |
992 | CurrentSymbol->addLocationOperands(Opcode: Op.getCode(), Operands: Op.getRawOperands()); |
993 | }; |
994 | |
995 | DWARFUnit *U = Die.getDwarfUnit(); |
996 | DWARFContext &DwarfContext = U->getContext(); |
997 | bool IsLittleEndian = DwarfContext.isLittleEndian(); |
998 | if (FormValue.isFormClass(FC: DWARFFormValue::FC_Block) || |
999 | (DWARFAttribute::mayHaveLocationExpr(Attr) && |
1000 | FormValue.isFormClass(FC: DWARFFormValue::FC_Exprloc))) { |
1001 | ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); |
1002 | DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), |
1003 | IsLittleEndian, 0); |
1004 | DWARFExpression Expression(Data, U->getAddressByteSize(), |
1005 | U->getFormParams().Format); |
1006 | |
1007 | // Add location and operation entries. |
1008 | CurrentSymbol->addLocation(Attr, /*LowPC=*/0, /*HighPC=*/-1, |
1009 | /*SectionOffset=*/0, LocDescOffset: OffsetOnEntry, |
1010 | CallSiteLocation); |
1011 | ProcessLocationExpression(Expression); |
1012 | return; |
1013 | } |
1014 | |
1015 | if (DWARFAttribute::mayHaveLocationList(Attr) && |
1016 | FormValue.isFormClass(FC: DWARFFormValue::FC_SectionOffset)) { |
1017 | uint64_t Offset = *FormValue.getAsSectionOffset(); |
1018 | if (FormValue.getForm() == dwarf::DW_FORM_loclistx) { |
1019 | std::optional<uint64_t> LoclistOffset = U->getLoclistOffset(Index: Offset); |
1020 | if (!LoclistOffset) |
1021 | return; |
1022 | Offset = *LoclistOffset; |
1023 | } |
1024 | uint64_t BaseAddr = 0; |
1025 | if (std::optional<SectionedAddress> BA = U->getBaseAddress()) |
1026 | BaseAddr = BA->Address; |
1027 | LVAddress LowPC = 0; |
1028 | LVAddress HighPC = 0; |
1029 | |
1030 | auto ProcessLocationEntry = [&](const DWARFLocationEntry &Entry) { |
1031 | if (Entry.Kind == dwarf::DW_LLE_base_address) { |
1032 | BaseAddr = Entry.Value0; |
1033 | return; |
1034 | } |
1035 | if (Entry.Kind == dwarf::DW_LLE_offset_pair) { |
1036 | LowPC = BaseAddr + Entry.Value0; |
1037 | HighPC = BaseAddr + Entry.Value1; |
1038 | DWARFAddressRange Range{LowPC, HighPC, Entry.SectionIndex}; |
1039 | if (Range.SectionIndex == SectionedAddress::UndefSection) |
1040 | Range.SectionIndex = Entry.SectionIndex; |
1041 | DWARFLocationExpression Loc{.Range: Range, .Expr: Entry.Loc}; |
1042 | DWARFDataExtractor Data(Loc.Expr, IsLittleEndian, |
1043 | U->getAddressByteSize()); |
1044 | DWARFExpression Expression(Data, U->getAddressByteSize()); |
1045 | |
1046 | // Store the real upper limit for the address range. |
1047 | if (UpdateHighAddress && HighPC > 0) |
1048 | --HighPC; |
1049 | // Add location and operation entries. |
1050 | CurrentSymbol->addLocation(Attr, LowPC, HighPC, SectionOffset: Offset, LocDescOffset: OffsetOnEntry, |
1051 | CallSiteLocation); |
1052 | ProcessLocationExpression(Expression); |
1053 | } |
1054 | }; |
1055 | Error E = U->getLocationTable().visitLocationList( |
1056 | Offset: &Offset, Callback: [&](const DWARFLocationEntry &E) { |
1057 | ProcessLocationEntry(E); |
1058 | return true; |
1059 | }); |
1060 | if (E) |
1061 | consumeError(Err: std::move(E)); |
1062 | } |
1063 | } |
1064 | |
1065 | void LVDWARFReader::processLocationMember(dwarf::Attribute Attr, |
1066 | const DWARFFormValue &FormValue, |
1067 | const DWARFDie &Die, |
1068 | uint64_t OffsetOnEntry) { |
1069 | // Check if the value is an integer constant. |
1070 | if (FormValue.isFormClass(FC: DWARFFormValue::FC_Constant)) |
1071 | // Add a record to hold a constant as location. |
1072 | CurrentSymbol->addLocationConstant(Attr, Constant: *FormValue.getAsUnsignedConstant(), |
1073 | LocDescOffset: OffsetOnEntry); |
1074 | else |
1075 | // This is a location description, or a reference to one. |
1076 | processLocationList(Attr, FormValue, Die, OffsetOnEntry); |
1077 | } |
1078 | |
1079 | // Update the current element with the reference. |
1080 | void LVDWARFReader::updateReference(dwarf::Attribute Attr, |
1081 | const DWARFFormValue &FormValue) { |
1082 | // FIXME: We are assuming that at most one Reference (DW_AT_specification, |
1083 | // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type) |
1084 | // appear in any single DIE, but this may not be true. |
1085 | uint64_t Offset; |
1086 | if (std::optional<uint64_t> Off = FormValue.getAsRelativeReference()) |
1087 | Offset = FormValue.getUnit()->getOffset() + *Off; |
1088 | else if (Off = FormValue.getAsDebugInfoReference(); Off) |
1089 | Offset = *Off; |
1090 | else |
1091 | llvm_unreachable("Unsupported reference type" ); |
1092 | |
1093 | // Get target for the given reference, if already created. |
1094 | LVElement *Target = getElementForOffset( |
1095 | offset: Offset, Element: CurrentElement, |
1096 | /*IsType=*/Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type); |
1097 | // Check if we are dealing with cross CU references. |
1098 | if (FormValue.getForm() == dwarf::DW_FORM_ref_addr) { |
1099 | if (Target) { |
1100 | // The global reference is ready. Mark it as global. |
1101 | Target->setIsGlobalReference(); |
1102 | // Remove global reference from the unseen list. |
1103 | removeGlobalOffset(Offset); |
1104 | } else |
1105 | // Record the unseen cross CU reference. |
1106 | addGlobalOffset(Offset); |
1107 | } |
1108 | |
1109 | // At this point, 'Target' can be null, in the case of the target element |
1110 | // not being seen. But the correct bit is set, to indicate that the target |
1111 | // is being referenced by (abstract_origin, extension, specification) or |
1112 | // (import, type). |
1113 | // We must differentiate between the kind of reference. This is needed to |
1114 | // complete inlined function instances with dropped abstract references, |
1115 | // in order to facilitate a logical comparison. |
1116 | switch (Attr) { |
1117 | case dwarf::DW_AT_abstract_origin: |
1118 | case dwarf::DW_AT_call_origin: |
1119 | CurrentElement->setReference(Target); |
1120 | CurrentElement->setHasReferenceAbstract(); |
1121 | break; |
1122 | case dwarf::DW_AT_extension: |
1123 | CurrentElement->setReference(Target); |
1124 | CurrentElement->setHasReferenceExtension(); |
1125 | break; |
1126 | case dwarf::DW_AT_specification: |
1127 | CurrentElement->setReference(Target); |
1128 | CurrentElement->setHasReferenceSpecification(); |
1129 | break; |
1130 | case dwarf::DW_AT_import: |
1131 | case dwarf::DW_AT_type: |
1132 | CurrentElement->setType(Target); |
1133 | break; |
1134 | default: |
1135 | break; |
1136 | } |
1137 | } |
1138 | |
1139 | // Get an element given the DIE offset. |
1140 | LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset, |
1141 | LVElement *Element, bool IsType) { |
1142 | auto Iter = ElementTable.try_emplace(k: Offset).first; |
1143 | // Update the element and all the references pointing to this element. |
1144 | LVElementEntry &Entry = Iter->second; |
1145 | if (!Entry.Element) { |
1146 | if (IsType) |
1147 | Entry.Types.insert(x: Element); |
1148 | else |
1149 | Entry.References.insert(x: Element); |
1150 | } |
1151 | return Entry.Element; |
1152 | } |
1153 | |
1154 | Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) { |
1155 | // Detect the architecture from the object file. We usually don't need OS |
1156 | // info to lookup a target and create register info. |
1157 | Triple TT; |
1158 | TT.setArch(Kind: Triple::ArchType(Obj.getArch())); |
1159 | TT.setVendor(Triple::UnknownVendor); |
1160 | TT.setOS(Triple::UnknownOS); |
1161 | |
1162 | // Features to be passed to target/subtarget |
1163 | Expected<SubtargetFeatures> Features = Obj.getFeatures(); |
1164 | SubtargetFeatures FeaturesValue; |
1165 | if (!Features) { |
1166 | consumeError(Err: Features.takeError()); |
1167 | FeaturesValue = SubtargetFeatures(); |
1168 | } |
1169 | FeaturesValue = *Features; |
1170 | return loadGenericTargetInfo(TheTriple: TT.str(), TheFeatures: FeaturesValue.getString()); |
1171 | } |
1172 | |
1173 | void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) { |
1174 | for (auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) { |
1175 | const SymbolRef &Symbol = *Iter; |
1176 | |
1177 | Expected<SymbolRef::Type> TypeOrErr = Symbol.getType(); |
1178 | if (!TypeOrErr) { |
1179 | consumeError(Err: TypeOrErr.takeError()); |
1180 | continue; |
1181 | } |
1182 | |
1183 | // Process only symbols that represent a function. |
1184 | SymbolRef::Type Type = *TypeOrErr; |
1185 | if (Type != SymbolRef::ST_Function) |
1186 | continue; |
1187 | |
1188 | // In the case of a Mach-O STAB symbol, get its section only if |
1189 | // the STAB symbol's section field refers to a valid section index. |
1190 | // Otherwise the symbol may error trying to load a section that |
1191 | // does not exist. |
1192 | const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Val: &Obj); |
1193 | bool IsSTAB = false; |
1194 | if (MachO) { |
1195 | DataRefImpl SymDRI = Symbol.getRawDataRefImpl(); |
1196 | uint8_t NType = |
1197 | (MachO->is64Bit() ? MachO->getSymbol64TableEntry(DRI: SymDRI).n_type |
1198 | : MachO->getSymbolTableEntry(DRI: SymDRI).n_type); |
1199 | if (NType & MachO::N_STAB) |
1200 | IsSTAB = true; |
1201 | } |
1202 | |
1203 | Expected<section_iterator> IterOrErr = Symbol.getSection(); |
1204 | if (!IterOrErr) { |
1205 | consumeError(Err: IterOrErr.takeError()); |
1206 | continue; |
1207 | } |
1208 | section_iterator Section = IsSTAB ? Obj.section_end() : *IterOrErr; |
1209 | if (Section == Obj.section_end()) |
1210 | continue; |
1211 | |
1212 | // Get the symbol value. |
1213 | Expected<uint64_t> AddressOrErr = Symbol.getAddress(); |
1214 | if (!AddressOrErr) { |
1215 | consumeError(Err: AddressOrErr.takeError()); |
1216 | continue; |
1217 | } |
1218 | uint64_t Address = *AddressOrErr; |
1219 | |
1220 | // Get symbol name. |
1221 | StringRef Name; |
1222 | Expected<StringRef> NameOrErr = Symbol.getName(); |
1223 | if (!NameOrErr) { |
1224 | consumeError(Err: NameOrErr.takeError()); |
1225 | continue; |
1226 | } |
1227 | Name = *NameOrErr; |
1228 | |
1229 | // Check if the symbol is Comdat. |
1230 | Expected<uint32_t> FlagsOrErr = Symbol.getFlags(); |
1231 | if (!FlagsOrErr) { |
1232 | consumeError(Err: FlagsOrErr.takeError()); |
1233 | continue; |
1234 | } |
1235 | uint32_t Flags = *FlagsOrErr; |
1236 | |
1237 | // Mark the symbol as 'comdat' in any of the following cases: |
1238 | // - Symbol has the SF_Weak flag or |
1239 | // - Symbol section index different from the DotTextSectionIndex. |
1240 | LVSectionIndex SectionIndex = Section->getIndex(); |
1241 | bool IsComdat = |
1242 | (Flags & SymbolRef::SF_Weak) || (SectionIndex != DotTextSectionIndex); |
1243 | |
1244 | // Record the symbol name (linkage) and its loading address. |
1245 | addToSymbolTable(Name, Address, SectionIndex, IsComdat); |
1246 | } |
1247 | } |
1248 | |
1249 | void LVDWARFReader::sortScopes() { Root->sort(); } |
1250 | |
1251 | void LVDWARFReader::print(raw_ostream &OS) const { |
1252 | OS << "LVType\n" ; |
1253 | LLVM_DEBUG(dbgs() << "CreateReaders\n" ); |
1254 | } |
1255 | |