LLVM 17.0.0git
DWARFLinkerCompileUnit.cpp
Go to the documentation of this file.
1//===- DWARFLinkerCompileUnit.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
12
13namespace llvm {
14
15#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
17 llvm::errs() << "{\n";
18 llvm::errs() << " AddrAdjust: " << AddrAdjust << '\n';
19 llvm::errs() << " Ctxt: " << formatv("{0:x}", Ctxt) << '\n';
20 llvm::errs() << " Clone: " << formatv("{0:x}", Clone) << '\n';
21 llvm::errs() << " ParentIdx: " << ParentIdx << '\n';
22 llvm::errs() << " Keep: " << Keep << '\n';
23 llvm::errs() << " InDebugMap: " << InDebugMap << '\n';
24 llvm::errs() << " Prune: " << Prune << '\n';
25 llvm::errs() << " Incomplete: " << Incomplete << '\n';
26 llvm::errs() << " InModuleScope: " << InModuleScope << '\n';
27 llvm::errs() << " ODRMarkingDone: " << ODRMarkingDone << '\n';
28 llvm::errs() << " UnclonedReference: " << UnclonedReference << '\n';
29 llvm::errs() << "}\n";
30}
31#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
32
33/// Check if the DIE at \p Idx is in the scope of a function.
34static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
35 while (Idx) {
36 if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
37 return true;
38 Idx = U.getInfo(Idx).ParentIdx;
39 }
40 return false;
41}
42
44 if (!Language) {
46 Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
47 }
48 return Language;
49}
50
52 if (SysRoot.empty()) {
54 SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
55 }
56 return SysRoot;
57}
58
60 unsigned Idx = 0;
61
62 for (auto &I : Info) {
63 // Mark everything that wasn't explicit marked for pruning.
64 I.Keep = !I.Prune;
65 auto DIE = OrigUnit.getDIEAtIndex(Idx++);
66
67 // Try to guess which DIEs must go to the accelerator tables. We do that
68 // just for variables, because functions will be handled depending on
69 // whether they carry a DW_AT_low_pc attribute or not.
70 if (DIE.getTag() != dwarf::DW_TAG_variable &&
71 DIE.getTag() != dwarf::DW_TAG_constant)
72 continue;
73
74 std::optional<DWARFFormValue> Value;
75 if (!(Value = DIE.find(dwarf::DW_AT_location))) {
76 if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
77 !inFunctionScope(*this, I.ParentIdx))
78 I.InDebugMap = true;
79 continue;
80 }
81 if (auto Block = Value->getAsBlock()) {
82 if (Block->size() > OrigUnit.getAddressByteSize() &&
83 (*Block)[0] == dwarf::DW_OP_addr)
84 I.InDebugMap = true;
85 }
86 }
87}
88
90 NextUnitOffset = StartOffset;
91 if (NewUnit) {
92 NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
93 NextUnitOffset += NewUnit->getUnitDie().getSize();
94 }
95 return NextUnitOffset;
96}
97
98/// Keep track of a forward cross-cu reference from this unit
99/// to \p Die that lives in \p RefUnit.
101 DeclContext *Ctxt, PatchLocation Attr) {
102 ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
103}
104
106 for (const auto &Ref : ForwardDIEReferences) {
107 DIE *RefDie;
108 const CompileUnit *RefUnit;
109 PatchLocation Attr;
110 DeclContext *Ctxt;
111 std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
112 if (Ctxt && Ctxt->hasCanonicalDIE()) {
114 "Canonical die offset is not set");
115 Attr.set(Ctxt->getCanonicalDIEOffset());
116 } else {
117 assert(RefDie->getOffset() && "Referenced die offset is not set");
118 Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
119 }
120 }
121}
122
123void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
124 Labels.insert({LabelLowPc, PcOffset});
125}
126
128 int64_t PcOffset) {
129 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
130 if (LowPc)
131 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
132 else
133 LowPc = FuncLowPc + PcOffset;
134 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
135}
136
138 if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
139 UnitRangeAttribute = Attr;
140 return;
141 }
142
143 RangeAttributes.emplace_back(Attr);
144}
145
147 LocationAttributes.emplace_back(Attr, PcOffset);
148}
149
152 Namespaces.emplace_back(Name, Die);
153}
154
157 bool SkipPubSection) {
158 ObjC.emplace_back(Name, Die, SkipPubSection);
159}
160
163 bool SkipPubSection) {
164 Pubnames.emplace_back(Name, Die, SkipPubSection);
165}
166
169 bool ObjcClassImplementation,
170 uint32_t QualifiedNameHash) {
171 Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
172}
173
174} // namespace llvm
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:492
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
std::string Name
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(AddressRange Range, int64_t Value)
Stores all information relating to a compile unit, be it in its original instance in the object file ...
void fixupForwardReferences()
Apply all fixups recorded by noteForwardReference().
void noteForwardReference(DIE *Die, const CompileUnit *RefUnit, DeclContext *Ctxt, PatchLocation Attr)
Keep track of a forward reference to DIE Die in RefUnit by Attr.
void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name, bool SkipPubnamesSection=false)
Add a name accelerator entry for Die with Name.
void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name)
Add a name accelerator entry for Die with Name.
DWARFUnit & getOrigUnit() const
StringRef getSysRoot()
Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
void noteRangeAttribute(const DIE &Die, PatchLocation Attr)
Keep track of a DW_AT_range attribute that we will need to patch up later.
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset)
Add a function range [LowPC, HighPC) that is relocated by applying offset PCOffset.
void addObjCAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name, bool SkipPubnamesSection=false)
Add various accelerator entries for Die with Name which is stored in the string table at Offset.
void addTypeAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name, bool ObjcClassImplementation, uint32_t QualifiedNameHash)
Add a type accelerator entry for Die with Name which is stored in the string table at Offset.
uint64_t getStartOffset() const
uint64_t computeNextUnitOffset(uint16_t DwarfVersion)
Compute the end offset for this unit.
void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset)
Keep track of a location attribute pointing to a location list in the debug_loc section.
void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset)
Add the low_pc of a label that is relocated by applying offset PCOffset.
void markEverythingAsKept()
Mark every DIE in this unit as kept.
A structured debug information entry.
Definition: DIE.h:744
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition: DIE.h:782
dwarf::Tag getTag() const
Definition: DIE.h:780
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:426
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:319
DWARFDie getDIEAtIndex(unsigned Index)
Return the DIE object at the given index Index.
Definition: DWARFUnit.h:504
A DeclContext is a named program scope that is used for ODR uniquing of types.
uint32_t getCanonicalDIEOffset() const
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:220
DwarfStringPoolEntryRef: Dwarf string pool entry reference.
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:941
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
LLVM Value Representation.
Definition: Value.h:74
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
static bool inFunctionScope(CompileUnit &U, unsigned Idx)
Check if the DIE at Idx is in the scope of a function.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
DeclContext * Ctxt
ODR Declaration context.
bool InModuleScope
Is DIE in the clang module scope?
DIE * Clone
Cloned version of that DIE.
int64_t AddrAdjust
Address offset to apply to the described entity.
uint32_t ParentIdx
The index of this DIE's parent.
bool UnclonedReference
Is this a reference to a DIE that hasn't been cloned yet?
bool ODRMarkingDone
Is ODR marking done?
bool InDebugMap
Was this DIE's entity found in the map?
bool Prune
Is this a pure forward declaration we can strip?
bool Keep
Is the DIE part of the linked output?
bool Incomplete
Does DIE transitively refer an incomplete decl?
void set(uint64_t New) const