1//===- DWARFDie.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 "llvm/DebugInfo/DWARF/DWARFDie.h"
10#include "llvm/ADT/SmallPtrSet.h"
11#include "llvm/ADT/SmallSet.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/BinaryFormat/Dwarf.h"
14#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
15#include "llvm/DebugInfo/DWARF/DWARFContext.h"
16#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
17#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
18#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
19#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
20#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
21#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
22#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
23#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
24#include "llvm/Object/ObjectFile.h"
25#include "llvm/Support/DataExtractor.h"
26#include "llvm/Support/Format.h"
27#include "llvm/Support/FormatVariadic.h"
28#include "llvm/Support/WithColor.h"
29#include "llvm/Support/raw_ostream.h"
30#include <cassert>
31#include <cinttypes>
32#include <cstdint>
33#include <string>
34
35using namespace llvm;
36using namespace dwarf;
37using namespace object;
38
39static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
40 OS << " (";
41 do {
42 uint64_t Shift = llvm::countr_zero(Val);
43 assert(Shift < 64 && "undefined behavior");
44 uint64_t Bit = 1ULL << Shift;
45 auto PropName = ApplePropertyString(Bit);
46 if (!PropName.empty())
47 OS << PropName;
48 else
49 OS << formatv(Fmt: "DW_APPLE_PROPERTY_{0:x}", Vals&: Bit);
50 if (!(Val ^= Bit))
51 break;
52 OS << ", ";
53 } while (true);
54 OS << ")";
55}
56
57static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS,
58 const DWARFAddressRangesVector &Ranges,
59 unsigned AddressSize, unsigned Indent,
60 const DIDumpOptions &DumpOpts) {
61 if (!DumpOpts.ShowAddresses)
62 return;
63
64 for (const DWARFAddressRange &R : Ranges) {
65 OS << '\n';
66 OS.indent(NumSpaces: Indent);
67 R.dump(OS, AddressSize, DumpOpts, Obj: &Obj);
68 }
69}
70
71static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,
72 DWARFUnit *U, unsigned Indent,
73 DIDumpOptions DumpOpts) {
74 assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) &&
75 "bad FORM for location list");
76 DWARFContext &Ctx = U->getContext();
77 uint64_t Offset = *FormValue.getAsSectionOffset();
78
79 if (FormValue.getForm() == DW_FORM_loclistx) {
80 FormValue.dump(OS, DumpOpts);
81
82 if (auto LoclistOffset = U->getLoclistOffset(Index: Offset))
83 Offset = *LoclistOffset;
84 else
85 return;
86 }
87 U->getLocationTable().dumpLocationList(
88 Offset: &Offset, OS, BaseAddr: U->getBaseAddress(), Obj: Ctx.getDWARFObj(), U, DumpOpts, Indent);
89}
90
91static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
92 DWARFUnit *U, unsigned Indent,
93 DIDumpOptions DumpOpts) {
94 assert((FormValue.isFormClass(DWARFFormValue::FC_Block) ||
95 FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) &&
96 "bad FORM for location expression");
97 DWARFContext &Ctx = U->getContext();
98 ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
99 DataExtractor Data(Expr, Ctx.isLittleEndian());
100 DWARFExpression DE(Data, U->getAddressByteSize(), U->getFormParams().Format);
101 printDwarfExpression(E: &DE, OS, DumpOpts, U);
102}
103
104static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
105 return D.getAttributeValueAsReferencedDie(V: F).resolveTypeUnitReference();
106}
107
108static llvm::StringRef
109prettyLanguageVersionString(const DWARFAttribute &AttrValue,
110 const DWARFDie &Die) {
111 if (AttrValue.Attr != DW_AT_language_version)
112 return {};
113
114 auto NameForm = Die.find(Attr: DW_AT_language_name);
115 if (!NameForm)
116 return {};
117
118 auto LName = NameForm->getAsUnsignedConstant();
119 if (!LName)
120 return {};
121
122 auto LVersion = AttrValue.Value.getAsUnsignedConstant();
123 if (!LVersion)
124 return {};
125
126 return llvm::dwarf::LanguageDescription(
127 Name: static_cast<SourceLanguageName>(*LName), Version: *LVersion);
128}
129
130static llvm::Expected<llvm::StringRef>
131getApplePropertyName(const DWARFDie &PropDIE) {
132 if (!PropDIE)
133 return llvm::createStringError(Fmt: "invalid DIE");
134
135 if (PropDIE.getTag() != DW_TAG_APPLE_property)
136 return llvm::createStringError(Fmt: "not referencing a DW_TAG_APPLE_property");
137
138 auto PropNameForm = PropDIE.find(Attr: DW_AT_APPLE_property_name);
139 if (!PropNameForm)
140 return "";
141
142 auto NameOrErr = PropNameForm->getAsCString();
143 if (!NameOrErr)
144 return NameOrErr.takeError();
145
146 return *NameOrErr;
147}
148
149static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
150 const DWARFAttribute &AttrValue, unsigned Indent,
151 DIDumpOptions DumpOpts) {
152 if (!Die.isValid())
153 return;
154 const char BaseIndent[] = " ";
155 OS << BaseIndent;
156 OS.indent(NumSpaces: Indent + 2);
157 dwarf::Attribute Attr = AttrValue.Attr;
158 WithColor(OS, HighlightColor::Attribute) << formatv(Fmt: "{0}", Vals&: Attr);
159
160 dwarf::Form Form = AttrValue.Value.getForm();
161 if (DumpOpts.Verbose || DumpOpts.ShowForm)
162 OS << formatv(Fmt: " [{0}]", Vals&: Form);
163
164 DWARFUnit *U = Die.getDwarfUnit();
165 const DWARFFormValue &FormValue = AttrValue.Value;
166
167 OS << "\t(";
168
169 StringRef Name;
170 std::string File;
171 auto Color = HighlightColor::Enumerator;
172 if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
173 Color = HighlightColor::String;
174 if (const auto *LT = U->getContext().getLineTableForUnit(U)) {
175 if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) {
176 if (LT->getFileNameByIndex(
177 FileIndex: *Val, CompDir: U->getCompilationDir(),
178 Kind: DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
179 Result&: File)) {
180 File = '"' + File + '"';
181 Name = File;
182 }
183 }
184 }
185 } else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
186 Name = AttributeValueString(Attr, Val: *Val);
187
188 auto DumpUnsignedConstant = [&OS,
189 &DumpOpts](const DWARFFormValue &FormValue) {
190 if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
191 OS << *Val;
192 else
193 FormValue.dump(OS, DumpOpts);
194 };
195
196 llvm::StringRef PrettyVersionName =
197 prettyLanguageVersionString(AttrValue, Die);
198 bool ShouldDumpRawLanguageVersion =
199 Attr == DW_AT_language_version &&
200 (DumpOpts.Verbose || PrettyVersionName.empty());
201
202 if (!Name.empty())
203 WithColor(OS, Color) << Name;
204 else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||
205 Attr == DW_AT_call_line || Attr == DW_AT_call_column) {
206 DumpUnsignedConstant(FormValue);
207 } else if (Attr == DW_AT_language_version) {
208 if (ShouldDumpRawLanguageVersion)
209 DumpUnsignedConstant(FormValue);
210 } else if (Attr == DW_AT_low_pc &&
211 (FormValue.getAsAddress() ==
212 dwarf::computeTombstoneAddress(AddressByteSize: U->getAddressByteSize()))) {
213 if (DumpOpts.Verbose) {
214 FormValue.dump(OS, DumpOpts);
215 OS << " (";
216 }
217 OS << "dead code";
218 if (DumpOpts.Verbose)
219 OS << ')';
220 } else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&
221 FormValue.getAsUnsignedConstant()) {
222 if (DumpOpts.ShowAddresses) {
223 // Print the actual address rather than the offset.
224 uint64_t LowPC, HighPC, Index;
225 if (Die.getLowAndHighPC(LowPC, HighPC, SectionIndex&: Index))
226 DWARFFormValue::dumpAddress(OS, AddressSize: U->getAddressByteSize(), Address: HighPC);
227 else
228 FormValue.dump(OS, DumpOpts);
229 }
230 } else if (DWARFAttribute::mayHaveLocationList(Attr) &&
231 FormValue.isFormClass(FC: DWARFFormValue::FC_SectionOffset))
232 dumpLocationList(OS, FormValue, U, Indent: sizeof(BaseIndent) + Indent + 4,
233 DumpOpts);
234 else if (FormValue.isFormClass(FC: DWARFFormValue::FC_Exprloc) ||
235 (DWARFAttribute::mayHaveLocationExpr(Attr) &&
236 FormValue.isFormClass(FC: DWARFFormValue::FC_Block)))
237 dumpLocationExpr(OS, FormValue, U, Indent: sizeof(BaseIndent) + Indent + 4,
238 DumpOpts);
239 else
240 FormValue.dump(OS, DumpOpts);
241
242 std::string Space = DumpOpts.ShowAddresses ? " " : "";
243
244 // We have dumped the attribute raw value. For some attributes
245 // having both the raw value and the pretty-printed value is
246 // interesting. These attributes are handled below.
247 if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin ||
248 Attr == DW_AT_call_origin || Attr == DW_AT_import ||
249 Attr == DW_AT_LLVM_virtual_call_origin) {
250 if (const char *Name =
251 Die.getAttributeValueAsReferencedDie(V: FormValue).getName(
252 Kind: DINameKind::LinkageName))
253 OS << Space << "\"" << Name << '\"';
254 } else if (Attr == DW_AT_property_forward) {
255 if (const char *Name =
256 Die.getAttributeValueAsReferencedDie(V: FormValue).getName(
257 Kind: DINameKind::ShortName))
258 OS << Space << "\"" << Name << '\"';
259 } else if (Attr == DW_AT_APPLE_property) {
260 auto PropDIE = Die.getAttributeValueAsReferencedDie(V: FormValue);
261 if (auto PropNameOrErr = getApplePropertyName(PropDIE))
262 OS << Space << "\"" << *PropNameOrErr << '\"';
263 else
264 DumpOpts.RecoverableErrorHandler(createStringError(
265 EC: errc::invalid_argument,
266 S: llvm::formatv(Fmt: "decoding DW_AT_APPLE_property_name: {}",
267 Vals: toString(E: PropNameOrErr.takeError()))));
268 } else if (Attr == DW_AT_type || Attr == DW_AT_containing_type) {
269 DWARFDie D = resolveReferencedType(D: Die, F: FormValue);
270 if (D && !D.isNULL()) {
271 OS << Space << "\"";
272 dumpTypeQualifiedName(DIE: D, OS);
273 OS << '"';
274 }
275 } else if (Attr == DW_AT_APPLE_property_attribute) {
276 if (std::optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant())
277 dumpApplePropertyAttribute(OS, Val: *OptVal);
278 } else if (Attr == DW_AT_ranges) {
279 const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();
280 // For DW_FORM_rnglistx we need to dump the offset separately, since
281 // we have only dumped the index so far.
282 if (FormValue.getForm() == DW_FORM_rnglistx)
283 if (auto RangeListOffset =
284 U->getRnglistOffset(Index: *FormValue.getAsSectionOffset())) {
285 DWARFFormValue FV = DWARFFormValue::createFromUValue(
286 F: dwarf::DW_FORM_sec_offset, V: *RangeListOffset);
287 FV.dump(OS, DumpOpts);
288 }
289 if (auto RangesOrError = Die.getAddressRanges())
290 dumpRanges(Obj, OS, Ranges: RangesOrError.get(), AddressSize: U->getAddressByteSize(),
291 Indent: sizeof(BaseIndent) + Indent + 4, DumpOpts);
292 else
293 DumpOpts.RecoverableErrorHandler(createStringError(
294 EC: errc::invalid_argument, Fmt: "decoding address ranges: %s",
295 Vals: toString(E: RangesOrError.takeError()).c_str()));
296 } else if (Attr == DW_AT_language_version) {
297 if (!PrettyVersionName.empty())
298 WithColor(OS, Color) << (ShouldDumpRawLanguageVersion ? " " : "")
299 << PrettyVersionName;
300 }
301
302 OS << ")\n";
303}
304
305void DWARFDie::getFullName(raw_string_ostream &OS,
306 std::string *OriginalFullName) const {
307 const char *NamePtr = getShortName();
308 if (!NamePtr)
309 return;
310 if (getTag() == DW_TAG_GNU_template_parameter_pack)
311 return;
312 dumpTypeUnqualifiedName(DIE: *this, OS, OriginalFullName);
313}
314
315bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }
316
317bool DWARFDie::isSubroutineDIE() const {
318 auto Tag = getTag();
319 return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
320}
321
322std::optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {
323 if (!isValid())
324 return std::nullopt;
325 auto AbbrevDecl = getAbbreviationDeclarationPtr();
326 if (AbbrevDecl)
327 return AbbrevDecl->getAttributeValue(DIEOffset: getOffset(), Attr, U: *U);
328 return std::nullopt;
329}
330
331std::optional<DWARFFormValue>
332DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
333 if (!isValid())
334 return std::nullopt;
335 auto AbbrevDecl = getAbbreviationDeclarationPtr();
336 if (AbbrevDecl) {
337 for (auto Attr : Attrs) {
338 if (auto Value = AbbrevDecl->getAttributeValue(DIEOffset: getOffset(), Attr, U: *U))
339 return Value;
340 }
341 }
342 return std::nullopt;
343}
344
345std::optional<DWARFFormValue>
346DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
347 SmallVector<DWARFDie, 3> Worklist;
348 Worklist.push_back(Elt: *this);
349
350 // Keep track if DIEs already seen to prevent infinite recursion.
351 // Empirically we rarely see a depth of more than 3 when dealing with valid
352 // DWARF. This corresponds to following the DW_AT_abstract_origin and
353 // DW_AT_specification just once.
354 SmallSet<DWARFDie, 3> Seen;
355 Seen.insert(V: *this);
356
357 while (!Worklist.empty()) {
358 DWARFDie Die = Worklist.pop_back_val();
359
360 if (!Die.isValid())
361 continue;
362
363 if (auto Value = Die.find(Attrs))
364 return Value;
365
366 for (dwarf::Attribute Attr :
367 {DW_AT_abstract_origin, DW_AT_specification, DW_AT_signature}) {
368 if (auto D = Die.getAttributeValueAsReferencedDie(Attr))
369 if (Seen.insert(V: D).second)
370 Worklist.push_back(Elt: D);
371 }
372 }
373
374 return std::nullopt;
375}
376
377DWARFDie
378DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
379 if (std::optional<DWARFFormValue> F = find(Attr))
380 return getAttributeValueAsReferencedDie(V: *F);
381 return DWARFDie();
382}
383
384DWARFDie
385DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
386 DWARFDie Result;
387 if (std::optional<uint64_t> Offset = V.getAsRelativeReference()) {
388 Result = const_cast<DWARFUnit *>(V.getUnit())
389 ->getDIEForOffset(Offset: V.getUnit()->getOffset() + *Offset);
390 } else if (Offset = V.getAsDebugInfoReference(); Offset) {
391 if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(Offset: *Offset))
392 Result = SpecUnit->getDIEForOffset(Offset: *Offset);
393 } else if (std::optional<uint64_t> Sig = V.getAsSignatureReference()) {
394 if (DWARFTypeUnit *TU =
395 U->getContext().getTypeUnitForHash(Hash: *Sig, IsDWO: U->isDWOUnit()))
396 Result = TU->getDIEForOffset(Offset: TU->getTypeOffset() + TU->getOffset());
397 }
398 return Result;
399}
400
401DWARFDie DWARFDie::resolveTypeUnitReference() const {
402 if (auto Attr = find(Attr: DW_AT_signature)) {
403 if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
404 if (DWARFTypeUnit *TU =
405 U->getContext().getTypeUnitForHash(Hash: *Sig, IsDWO: U->isDWOUnit()))
406 return TU->getDIEForOffset(Offset: TU->getTypeOffset() + TU->getOffset());
407 }
408 }
409 return *this;
410}
411
412DWARFDie DWARFDie::resolveReferencedType(dwarf::Attribute Attr) const {
413 return getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
414}
415DWARFDie DWARFDie::resolveReferencedType(const DWARFFormValue &V) const {
416 return getAttributeValueAsReferencedDie(V).resolveTypeUnitReference();
417}
418
419std::optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {
420 return toSectionOffset(V: find(Attrs: {DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
421}
422
423std::optional<uint64_t> DWARFDie::getLocBaseAttribute() const {
424 return toSectionOffset(V: find(Attr: DW_AT_loclists_base));
425}
426
427std::optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
428 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize: U->getAddressByteSize());
429 if (LowPC == Tombstone)
430 return std::nullopt;
431 if (auto FormValue = find(Attr: DW_AT_high_pc)) {
432 if (auto Address = FormValue->getAsAddress()) {
433 // High PC is an address.
434 return Address;
435 }
436 if (auto Offset = FormValue->getAsUnsignedConstant()) {
437 // High PC is an offset from LowPC.
438 return LowPC + *Offset;
439 }
440 }
441 return std::nullopt;
442}
443
444bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
445 uint64_t &SectionIndex) const {
446 auto F = find(Attr: DW_AT_low_pc);
447 auto LowPcAddr = toSectionedAddress(V: F);
448 if (!LowPcAddr)
449 return false;
450 if (auto HighPcAddr = getHighPC(LowPC: LowPcAddr->Address)) {
451 LowPC = LowPcAddr->Address;
452 HighPC = *HighPcAddr;
453 SectionIndex = LowPcAddr->SectionIndex;
454 return true;
455 }
456 return false;
457}
458
459Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {
460 if (isNULL())
461 return DWARFAddressRangesVector();
462 // Single range specified by low/high PC.
463 uint64_t LowPC, HighPC, Index;
464 if (getLowAndHighPC(LowPC, HighPC, SectionIndex&: Index))
465 return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
466
467 std::optional<DWARFFormValue> Value = find(Attr: DW_AT_ranges);
468 if (Value) {
469 if (Value->getForm() == DW_FORM_rnglistx)
470 return U->findRnglistFromIndex(Index: *Value->getAsSectionOffset());
471 return U->findRnglistFromOffset(Offset: *Value->getAsSectionOffset());
472 }
473 return DWARFAddressRangesVector();
474}
475
476bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
477 auto RangesOrError = getAddressRanges();
478 if (!RangesOrError) {
479 llvm::consumeError(Err: RangesOrError.takeError());
480 return false;
481 }
482
483 for (const auto &R : RangesOrError.get())
484 if (R.LowPC <= Address && Address < R.HighPC)
485 return true;
486 return false;
487}
488
489// FIXME: should we return a structure akin to DISourceLanguageName here
490// encapsulates an unversioned (dwarf::SourceLanguage) and versioned
491// (dwarf::SourceLanguageName) language, and put the burden on the
492// user to determine which to use?
493std::optional<uint64_t> DWARFDie::getLanguage() const {
494 if (!isValid())
495 return std::nullopt;
496
497 DWARFDie Unit = U->getUnitDIE();
498
499 if (std::optional<DWARFFormValue> LV = Unit.find(Attr: dwarf::DW_AT_language))
500 return LV->getAsUnsignedConstant();
501
502 uint16_t Name =
503 dwarf::toUnsigned(V: Unit.find(Attr: dwarf::DW_AT_language_name), /*Default=*/0);
504 uint32_t Version = dwarf::toUnsigned(V: Unit.find(Attr: dwarf::DW_AT_language_version),
505 /*Default=*/0);
506
507 return llvm::dwarf::toDW_LANG(name: static_cast<SourceLanguageName>(Name), version: Version);
508}
509
510Expected<DWARFLocationExpressionsVector>
511DWARFDie::getLocations(dwarf::Attribute Attr) const {
512 std::optional<DWARFFormValue> Location = find(Attr);
513 if (!Location)
514 return createStringError(EC: inconvertibleErrorCode(), Fmt: "No %s",
515 Vals: dwarf::AttributeString(Attribute: Attr).data());
516
517 if (std::optional<uint64_t> Off = Location->getAsSectionOffset()) {
518 uint64_t Offset = *Off;
519
520 if (Location->getForm() == DW_FORM_loclistx) {
521 if (auto LoclistOffset = U->getLoclistOffset(Index: Offset))
522 Offset = *LoclistOffset;
523 else
524 return createStringError(EC: inconvertibleErrorCode(),
525 S: "Loclist table not found");
526 }
527 return U->findLoclistFromOffset(Offset);
528 }
529
530 if (std::optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) {
531 return DWARFLocationExpressionsVector{
532 DWARFLocationExpression{.Range: std::nullopt, .Expr: to_vector<4>(Range&: *Expr)}};
533 }
534
535 return createStringError(
536 EC: inconvertibleErrorCode(), Fmt: "Unsupported %s encoding: %s",
537 Vals: dwarf::AttributeString(Attribute: Attr).data(),
538 Vals: dwarf::FormEncodingString(Encoding: Location->getForm()).data());
539}
540
541const char *DWARFDie::getSubroutineName(DINameKind Kind) const {
542 if (!isSubroutineDIE())
543 return nullptr;
544 return getName(Kind);
545}
546
547const char *DWARFDie::getName(DINameKind Kind) const {
548 if (!isValid() || Kind == DINameKind::None)
549 return nullptr;
550 // Try to get mangled name only if it was asked for.
551 if (Kind == DINameKind::LinkageName) {
552 if (auto Name = getLinkageName())
553 return Name;
554 }
555 return getShortName();
556}
557
558const char *DWARFDie::getShortName() const {
559 if (!isValid())
560 return nullptr;
561
562 return dwarf::toString(V: findRecursively(Attrs: dwarf::DW_AT_name), Default: nullptr);
563}
564
565const char *DWARFDie::getLinkageName() const {
566 if (!isValid())
567 return nullptr;
568
569 return dwarf::toString(V: findRecursively(Attrs: {dwarf::DW_AT_MIPS_linkage_name,
570 dwarf::DW_AT_linkage_name}),
571 Default: nullptr);
572}
573
574uint64_t DWARFDie::getDeclLine() const {
575 return toUnsigned(V: findRecursively(Attrs: DW_AT_decl_line), Default: 0);
576}
577
578std::string
579DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
580 if (auto FormValue = findRecursively(Attrs: DW_AT_decl_file))
581 if (auto OptString = FormValue->getAsFile(Kind))
582 return *OptString;
583 return {};
584}
585
586void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
587 uint32_t &CallColumn,
588 uint32_t &CallDiscriminator) const {
589 CallFile = toUnsigned(V: find(Attr: DW_AT_call_file), Default: 0);
590 CallLine = toUnsigned(V: find(Attr: DW_AT_call_line), Default: 0);
591 CallColumn = toUnsigned(V: find(Attr: DW_AT_call_column), Default: 0);
592 CallDiscriminator = toUnsigned(V: find(Attr: DW_AT_GNU_discriminator), Default: 0);
593}
594
595static std::optional<uint64_t>
596getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize,
597 SmallPtrSetImpl<const DWARFDebugInfoEntry *> &Visited) {
598 // Cycle detected?
599 if (!Visited.insert(Ptr: Die.getDebugInfoEntry()).second)
600 return {};
601 if (auto SizeAttr = Die.find(Attr: DW_AT_byte_size))
602 if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())
603 return Size;
604
605 switch (Die.getTag()) {
606 case DW_TAG_pointer_type:
607 case DW_TAG_reference_type:
608 case DW_TAG_rvalue_reference_type:
609 return PointerSize;
610 case DW_TAG_ptr_to_member_type: {
611 if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(Attr: DW_AT_type))
612 if (BaseType.getTag() == DW_TAG_subroutine_type)
613 return 2 * PointerSize;
614 return PointerSize;
615 }
616 case DW_TAG_const_type:
617 case DW_TAG_immutable_type:
618 case DW_TAG_volatile_type:
619 case DW_TAG_restrict_type:
620 case DW_TAG_template_alias:
621 case DW_TAG_typedef: {
622 if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(Attr: DW_AT_type))
623 return getTypeSizeImpl(Die: BaseType, PointerSize, Visited);
624 break;
625 }
626 case DW_TAG_array_type: {
627 DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(Attr: DW_AT_type);
628 if (!BaseType)
629 return std::nullopt;
630 std::optional<uint64_t> BaseSize =
631 getTypeSizeImpl(Die: BaseType, PointerSize, Visited);
632 if (!BaseSize)
633 return std::nullopt;
634 uint64_t Size = *BaseSize;
635 for (DWARFDie Child : Die) {
636 if (Child.getTag() != DW_TAG_subrange_type)
637 continue;
638
639 if (auto ElemCountAttr = Child.find(Attr: DW_AT_count))
640 if (std::optional<uint64_t> ElemCount =
641 ElemCountAttr->getAsUnsignedConstant())
642 Size *= *ElemCount;
643 if (auto UpperBoundAttr = Child.find(Attr: DW_AT_upper_bound))
644 if (std::optional<int64_t> UpperBound =
645 UpperBoundAttr->getAsSignedConstant()) {
646 int64_t LowerBound = 0;
647 if (auto LowerBoundAttr = Child.find(Attr: DW_AT_lower_bound))
648 LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(u: 0);
649 Size *= *UpperBound - LowerBound + 1;
650 }
651 }
652 return Size;
653 }
654 default:
655 if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(Attr: DW_AT_type))
656 return getTypeSizeImpl(Die: BaseType, PointerSize, Visited);
657 break;
658 }
659 return std::nullopt;
660}
661
662std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
663 SmallPtrSet<const DWARFDebugInfoEntry *, 4> Visited;
664 return getTypeSizeImpl(Die: *this, PointerSize, Visited);
665}
666
667/// Helper to dump a DIE with all of its parents, but no siblings.
668static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,
669 DIDumpOptions DumpOpts, unsigned Depth = 0) {
670 if (!Die)
671 return Indent;
672 if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth)
673 return Indent;
674 Indent = dumpParentChain(Die: Die.getParent(), OS, Indent, DumpOpts, Depth: Depth + 1);
675 Die.dump(OS, indent: Indent, DumpOpts);
676 return Indent + 2;
677}
678
679void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
680 DIDumpOptions DumpOpts) const {
681 if (!isValid())
682 return;
683 DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();
684 const uint64_t Offset = getOffset();
685 uint64_t offset = Offset;
686 if (DumpOpts.ShowParents) {
687 DIDumpOptions ParentDumpOpts = DumpOpts;
688 ParentDumpOpts.ShowParents = false;
689 ParentDumpOpts.ShowChildren = false;
690 Indent = dumpParentChain(Die: getParent(), OS, Indent, DumpOpts: ParentDumpOpts);
691 }
692
693 if (debug_info_data.isValidOffset(offset)) {
694 uint32_t abbrCode = debug_info_data.getULEB128(offset_ptr: &offset);
695 if (DumpOpts.ShowAddresses)
696 WithColor(OS, HighlightColor::Address).get()
697 << formatv(Fmt: "\n{0:x8}: ", Vals: Offset);
698
699 if (abbrCode) {
700 auto AbbrevDecl = getAbbreviationDeclarationPtr();
701 if (AbbrevDecl) {
702 WithColor(OS, HighlightColor::Tag).get().indent(NumSpaces: Indent)
703 << formatv(Fmt: "{0}", Vals: getTag());
704 if (DumpOpts.Verbose) {
705 OS << formatv(Fmt: " [{0}] {1}", Vals&: abbrCode,
706 Vals: AbbrevDecl->hasChildren() ? '*' : ' ');
707 if (std::optional<uint32_t> ParentIdx = Die->getParentIdx())
708 OS << formatv(Fmt: " ({0:x8})",
709 Vals: U->getDIEAtIndex(Index: *ParentIdx).getOffset());
710 }
711 OS << '\n';
712
713 // Dump all data in the DIE for the attributes.
714 for (const DWARFAttribute &AttrValue : attributes())
715 dumpAttribute(OS, Die: *this, AttrValue, Indent, DumpOpts);
716
717 if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) {
718 DWARFDie Child = getFirstChild();
719 DumpOpts.ChildRecurseDepth--;
720 DIDumpOptions ChildDumpOpts = DumpOpts;
721 ChildDumpOpts.ShowParents = false;
722 while (Child) {
723 if (DumpOpts.FilterChildTag.empty() ||
724 llvm::is_contained(Range&: DumpOpts.FilterChildTag, Element: Child.getTag()))
725 Child.dump(OS, Indent: Indent + 2, DumpOpts: ChildDumpOpts);
726 Child = Child.getSibling();
727 }
728 }
729 } else {
730 OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
731 << abbrCode << '\n';
732 }
733 } else {
734 OS.indent(NumSpaces: Indent) << "NULL\n";
735 }
736 }
737}
738
739LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(OS&: llvm::errs(), Indent: 0); }
740
741DWARFDie DWARFDie::getParent() const {
742 if (isValid())
743 return U->getParent(Die);
744 return DWARFDie();
745}
746
747DWARFDie DWARFDie::getSibling() const {
748 if (isValid())
749 return U->getSibling(Die);
750 return DWARFDie();
751}
752
753DWARFDie DWARFDie::getPreviousSibling() const {
754 if (isValid())
755 return U->getPreviousSibling(Die);
756 return DWARFDie();
757}
758
759DWARFDie DWARFDie::getFirstChild() const {
760 if (isValid())
761 return U->getFirstChild(Die);
762 return DWARFDie();
763}
764
765DWARFDie DWARFDie::getLastChild() const {
766 if (isValid())
767 return U->getLastChild(Die);
768 return DWARFDie();
769}
770
771iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const {
772 return make_range(x: attribute_iterator(*this, false),
773 y: attribute_iterator(*this, true));
774}
775
776DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End)
777 : Die(D), Index(0) {
778 auto AbbrDecl = Die.getAbbreviationDeclarationPtr();
779 assert(AbbrDecl && "Must have abbreviation declaration");
780 if (End) {
781 // This is the end iterator so we set the index to the attribute count.
782 Index = AbbrDecl->getNumAttributes();
783 } else {
784 // This is the begin iterator so we extract the value for this->Index.
785 AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();
786 updateForIndex(AbbrDecl: *AbbrDecl, I: 0);
787 }
788}
789
790void DWARFDie::attribute_iterator::updateForIndex(
791 const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {
792 Index = I;
793 // AbbrDecl must be valid before calling this function.
794 auto NumAttrs = AbbrDecl.getNumAttributes();
795 if (Index < NumAttrs) {
796 AttrValue.Attr = AbbrDecl.getAttrByIndex(idx: Index);
797 // Add the previous byte size of any previous attribute value.
798 AttrValue.Offset += AttrValue.ByteSize;
799 uint64_t ParseOffset = AttrValue.Offset;
800 if (AbbrDecl.getAttrIsImplicitConstByIndex(idx: Index))
801 AttrValue.Value = DWARFFormValue::createFromSValue(
802 F: AbbrDecl.getFormByIndex(idx: Index),
803 V: AbbrDecl.getAttrImplicitConstValueByIndex(idx: Index));
804 else {
805 auto U = Die.getDwarfUnit();
806 assert(U && "Die must have valid DWARF unit");
807 AttrValue.Value = DWARFFormValue::createFromUnit(
808 F: AbbrDecl.getFormByIndex(idx: Index), Unit: U, OffsetPtr: &ParseOffset);
809 }
810 AttrValue.ByteSize = ParseOffset - AttrValue.Offset;
811 } else {
812 assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");
813 AttrValue = {};
814 }
815}
816
817DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {
818 if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())
819 updateForIndex(AbbrDecl: *AbbrDecl, I: Index + 1);
820 return *this;
821}
822
823bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr) {
824 switch(Attr) {
825 case DW_AT_location:
826 case DW_AT_string_length:
827 case DW_AT_return_addr:
828 case DW_AT_data_member_location:
829 case DW_AT_frame_base:
830 case DW_AT_static_link:
831 case DW_AT_segment:
832 case DW_AT_use_location:
833 case DW_AT_vtable_elem_location:
834 return true;
835 default:
836 return false;
837 }
838}
839
840bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) {
841 switch (Attr) {
842 // From the DWARF v5 specification.
843 case DW_AT_location:
844 case DW_AT_byte_size:
845 case DW_AT_bit_offset:
846 case DW_AT_bit_size:
847 case DW_AT_string_length:
848 case DW_AT_lower_bound:
849 case DW_AT_return_addr:
850 case DW_AT_bit_stride:
851 case DW_AT_upper_bound:
852 case DW_AT_count:
853 case DW_AT_data_member_location:
854 case DW_AT_frame_base:
855 case DW_AT_segment:
856 case DW_AT_static_link:
857 case DW_AT_use_location:
858 case DW_AT_vtable_elem_location:
859 case DW_AT_allocated:
860 case DW_AT_associated:
861 case DW_AT_data_location:
862 case DW_AT_byte_stride:
863 case DW_AT_rank:
864 case DW_AT_call_value:
865 case DW_AT_call_origin:
866 case DW_AT_call_target:
867 case DW_AT_call_target_clobbered:
868 case DW_AT_call_data_location:
869 case DW_AT_call_data_value:
870 // Extensions.
871 case DW_AT_GNU_call_site_value:
872 case DW_AT_GNU_call_site_target:
873 case DW_AT_GNU_call_site_target_clobbered:
874 return true;
875 default:
876 return false;
877 }
878}
879
880namespace llvm {
881
882void dumpTypeQualifiedName(const DWARFDie &DIE, raw_ostream &OS) {
883 DWARFTypePrinter<DWARFDie>(OS).appendQualifiedName(D: DIE);
884}
885
886void dumpTypeUnqualifiedName(const DWARFDie &DIE, raw_ostream &OS,
887 std::string *OriginalFullName) {
888 DWARFTypePrinter<DWARFDie>(OS).appendUnqualifiedName(D: DIE, OriginalFullName);
889}
890
891} // namespace llvm
892