LLVM 23.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
15
16namespace llvm {
17
18using namespace dwarf_linker;
19using namespace dwarf_linker::classic;
20
21#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
23 llvm::errs() << "{\n";
24 llvm::errs() << " AddrAdjust: " << AddrAdjust << '\n';
25 llvm::errs() << " Ctxt: " << formatv("{0:x}", Ctxt) << '\n';
26 llvm::errs() << " Clone: " << formatv("{0:x}", Clone) << '\n';
27 llvm::errs() << " ParentIdx: " << ParentIdx << '\n';
28 llvm::errs() << " Keep: " << Keep << '\n';
29 llvm::errs() << " InDebugMap: " << InDebugMap << '\n';
30 llvm::errs() << " Prune: " << Prune << '\n';
31 llvm::errs() << " Incomplete: " << Incomplete << '\n';
32 llvm::errs() << " InModuleScope: " << InModuleScope << '\n';
33 llvm::errs() << " ODRMarkingDone: " << ODRMarkingDone << '\n';
34 llvm::errs() << " UnclonedReference: " << UnclonedReference << '\n';
35 llvm::errs() << "}\n";
36}
37#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
38
39/// Check if the DIE at \p Idx is in the scope of a function.
40static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
41 while (Idx) {
42 if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
43 return true;
44 Idx = U.getInfo(Idx).ParentIdx;
45 }
46 return false;
47}
48
50 if (!Language) {
52 Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
53 }
54 return Language;
55}
56
58 if (SysRoot.empty()) {
60 SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
61 }
62 return SysRoot;
63}
64
66 unsigned Idx = 0;
67
68 for (auto &I : Info) {
69 // Mark everything that wasn't explicit marked for pruning.
70 I.Keep = !I.Prune;
71 auto DIE = OrigUnit.getDIEAtIndex(Idx++);
72 DWARFUnit *U = DIE.getDwarfUnit();
73
74 // Try to guess which DIEs must go to the accelerator tables. We do that
75 // just for variables, because functions will be handled depending on
76 // whether they carry a DW_AT_low_pc attribute or not.
77 if (DIE.getTag() != dwarf::DW_TAG_variable &&
78 DIE.getTag() != dwarf::DW_TAG_constant)
79 continue;
80
81 std::optional<DWARFFormValue> Value;
82 if (!(Value = DIE.find(dwarf::DW_AT_location))) {
83 if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
84 !inFunctionScope(*this, I.ParentIdx))
85 I.InDebugMap = true;
86 continue;
87 }
88
89 if (auto ExprLockBlock = Value->getAsBlock()) {
90 // Parse 'exprloc' expression.
91 DataExtractor Data(*ExprLockBlock, U->getContext().isLittleEndian());
92 DWARFExpression Expression(Data, U->getAddressByteSize(),
93 U->getFormParams().Format);
94
95 for (DWARFExpression::iterator It = Expression.begin();
96 (It != Expression.end()) && !I.InDebugMap; ++It) {
97 DWARFExpression::iterator NextIt = It;
98 ++NextIt;
99
100 switch (It->getCode()) {
101 case dwarf::DW_OP_const2u:
102 case dwarf::DW_OP_const4u:
103 case dwarf::DW_OP_const8u:
104 case dwarf::DW_OP_const2s:
105 case dwarf::DW_OP_const4s:
106 case dwarf::DW_OP_const8s:
107 if (NextIt == Expression.end() ||
108 !dwarf::isTlsAddressOp(NextIt->getCode()))
109 break;
110 [[fallthrough]];
111 case dwarf::DW_OP_constx:
112 case dwarf::DW_OP_addr:
113 case dwarf::DW_OP_addrx:
114 I.InDebugMap = true;
115 break;
116 default:
117 // Nothing to do.
118 break;
119 }
120 }
121 }
122 }
123}
124
126 NextUnitOffset = StartOffset;
127 if (NewUnit) {
128 NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
129 NextUnitOffset += NewUnit->getUnitDie().getSize();
130 }
131 return NextUnitOffset;
132}
133
134/// Keep track of a forward cross-cu reference from this unit
135/// to \p Die that lives in \p RefUnit.
137 DeclContext *Ctxt, PatchLocation Attr) {
138 ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
139}
140
142 for (const auto &Ref : ForwardDIEReferences) {
143 DIE *RefDie;
144 const CompileUnit *RefUnit;
145 PatchLocation Attr;
146 DeclContext *Ctxt;
147 std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
148 if (Ctxt && Ctxt->hasCanonicalDIE()) {
150 "Canonical die offset is not set");
151 Attr.set(Ctxt->getCanonicalDIEOffset());
152 } else {
153 assert(RefDie->getOffset() && "Referenced die offset is not set");
154 Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
155 }
156 }
157}
158
159void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
160 Labels.insert({LabelLowPc, PcOffset});
161}
162
164 int64_t PcOffset) {
165 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
166 if (LowPc)
167 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
168 else
169 LowPc = FuncLowPc + PcOffset;
170 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
171}
172
174 if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
175 UnitRangeAttribute = Attr;
176 return;
177 }
178
179 RangeAttributes.emplace_back(Attr);
180}
181
183 LocationAttributes.emplace_back(Attr);
184}
185
187 StmtSeqListAttributes.emplace_back(Attr);
188}
189
192 Namespaces.emplace_back(Name, Die);
193}
194
197 bool SkipPubSection) {
198 ObjC.emplace_back(Name, Die, SkipPubSection);
199}
200
203 bool SkipPubSection) {
204 Pubnames.emplace_back(Name, Die, SkipPubSection);
205}
206
209 bool ObjcClassImplementation,
210 uint32_t QualifiedNameHash) {
211 Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
212}
213
214} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:661
#define I(x, y, z)
Definition MD5.cpp:57
This file contains some functions that are useful when dealing with strings.
A structured debug information entry.
Definition DIE.h:828
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:866
dwarf::Tag getTag() const
Definition DIE.h:864
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
An iterator to go through the expression operations.
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition DWARFUnit.h:450
DwarfStringPoolEntryRef: Dwarf string pool entry reference.
Class representing an expression and its matching format.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
LLVM Value Representation.
Definition Value.h:75
Stores all information relating to a compile unit, be it in its original instance in the object file ...
LLVM_ABI void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset)
Add a function range [LowPC, HighPC) that is relocated by applying offset PCOffset.
LLVM_ABI void noteStmtSeqListAttribute(PatchLocation Attr)
LLVM_ABI void fixupForwardReferences()
Apply all fixups recorded by noteForwardReference().
LLVM_ABI void noteForwardReference(DIE *Die, const CompileUnit *RefUnit, DeclContext *Ctxt, PatchLocation Attr)
Keep track of a forward reference to DIE Die in RefUnit by Attr.
LLVM_ABI void noteLocationAttribute(PatchLocation Attr)
Keep track of a location attribute pointing to a location list in the debug_loc section.
LLVM_ABI void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name, bool SkipPubnamesSection=false)
Add a name accelerator entry for Die with Name.
LLVM_ABI void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name)
Add a name accelerator entry for Die with Name.
LLVM_ABI StringRef getSysRoot()
Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
LLVM_ABI void noteRangeAttribute(const DIE &Die, PatchLocation Attr)
Keep track of a DW_AT_range attribute that we will need to patch up later.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI uint64_t computeNextUnitOffset(uint16_t DwarfVersion)
Compute the end offset for this unit.
LLVM_ABI void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset)
Add the low_pc of a label that is relocated by applying offset PCOffset.
LLVM_ABI void markEverythingAsKept()
Mark every DIE in this unit as kept.
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)
A DeclContext is a named program scope that is used for ODR uniquing of types.
bool isTlsAddressOp(uint8_t O)
Definition Dwarf.h:1102
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.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
static bool inFunctionScope(CompileUnit &U, unsigned Idx)
Check if the DIE at Idx is in the scope of a function.
LLVM_ABI 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.
Definition ModRef.h:32
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
@ Keep
No function return thunk.
Definition CodeGen.h:162