LLVM 18.0.0git
DWARFLinkerCompileUnit.h
Go to the documentation of this file.
1//===- DWARFLinkerCompileUnit.h ---------------------------------*- C++ -*-===//
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#ifndef LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
10#define LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
11
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/CodeGen/DIE.h"
16#include <optional>
17
18namespace llvm {
19
20class DeclContext;
21
22/// Mapped value in the address map is the offset to apply to the
23/// linked address.
25
26// This structure keeps patch for the attribute and, optionally,
27// the value of relocation which should be applied. Currently,
28// only location attribute needs to have relocation: either to the
29// function ranges if location attribute is of type 'loclist',
30// either to the operand of DW_OP_addr/DW_OP_addrx if location attribute
31// is of type 'exprloc'.
32// ASSUMPTION: Location attributes of 'loclist' type containing 'exprloc'
33// with address expression operands are not supported yet.
36 int64_t RelocAdjustment = 0;
37
38 PatchLocation() = default;
41 : I(I), RelocAdjustment(Reloc) {}
42
43 void set(uint64_t New) const {
44 assert(I);
45 const auto &Old = *I;
46 assert(Old.getType() == DIEValue::isInteger);
47 *I = DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New));
48 }
49
50 uint64_t get() const {
51 assert(I);
52 return I->getDIEInteger().getValue();
53 }
54};
55
58
59/// Stores all information relating to a compile unit, be it in its original
60/// instance in the object file to its brand new cloned and generated DIE tree.
62public:
63 /// Information gathered about a DIE in the object file.
64 struct DIEInfo {
65 /// Address offset to apply to the described entity.
66 int64_t AddrAdjust;
67
68 /// ODR Declaration context.
70
71 /// Cloned version of that DIE.
73
74 /// The index of this DIE's parent.
76
77 /// Is the DIE part of the linked output?
78 bool Keep : 1;
79
80 /// Was this DIE's entity found in the map?
81 bool InDebugMap : 1;
82
83 /// Is this a pure forward declaration we can strip?
84 bool Prune : 1;
85
86 /// Does DIE transitively refer an incomplete decl?
87 bool Incomplete : 1;
88
89 /// Is DIE in the clang module scope?
90 bool InModuleScope : 1;
91
92 /// Is ODR marking done?
94
95 /// Is this a reference to a DIE that hasn't been cloned yet?
97
98 /// Is this a variable with a location attribute referencing address?
100
101#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
102 LLVM_DUMP_METHOD void dump();
103#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
104 };
105
106 CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
107 StringRef ClangModuleName)
108 : OrigUnit(OrigUnit), ID(ID), ClangModuleName(ClangModuleName) {
109 Info.resize(OrigUnit.getNumDIEs());
110
111 auto CUDie = OrigUnit.getUnitDIE(false);
112 if (!CUDie) {
113 HasODR = false;
114 return;
115 }
116 if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
117 HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
118 *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
119 *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
120 *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
121 *Lang == dwarf::DW_LANG_ObjC_plus_plus);
122 else
123 HasODR = false;
124 }
125
126 DWARFUnit &getOrigUnit() const { return OrigUnit; }
127
128 unsigned getUniqueID() const { return ID; }
129
130 void createOutputDIE() { NewUnit.emplace(OrigUnit.getUnitDIE().getTag()); }
131
133 if (NewUnit)
134 return &const_cast<BasicDIEUnit &>(*NewUnit).getUnitDie();
135 return nullptr;
136 }
137
138 bool hasODR() const { return HasODR; }
139 bool isClangModule() const { return !ClangModuleName.empty(); }
141 /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
143
144 const std::string &getClangModuleName() const { return ClangModuleName; }
145
146 DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
147 const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
148
149 DIEInfo &getInfo(const DWARFDie &Die) {
150 unsigned Idx = getOrigUnit().getDIEIndex(Die);
151 return Info[Idx];
152 }
153
154 uint64_t getStartOffset() const { return StartOffset; }
155 uint64_t getNextUnitOffset() const { return NextUnitOffset; }
157
158 std::optional<uint64_t> getLowPc() const { return LowPc; }
159 uint64_t getHighPc() const { return HighPc; }
160 bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
161
162 const RangesTy &getFunctionRanges() const { return Ranges; }
163
164 const RngListAttributesTy &getRangesAttributes() { return RangeAttributes; }
165
166 std::optional<PatchLocation> getUnitRangesAttribute() const {
167 return UnitRangeAttribute;
168 }
169
171 return LocationAttributes;
172 }
173
174 /// Mark every DIE in this unit as kept. This function also
175 /// marks variables as InDebugMap so that they appear in the
176 /// reconstructed accelerator tables.
178
179 /// Compute the end offset for this unit. Must be called after the CU's DIEs
180 /// have been cloned. \returns the next unit offset (which is also the
181 /// current debug_info section size).
183
184 /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p
185 /// Attr. The attribute should be fixed up later to point to the absolute
186 /// offset of \p Die in the debug_info section or to the canonical offset of
187 /// \p Ctxt if it is non-null.
188 void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
189 DeclContext *Ctxt, PatchLocation Attr);
190
191 /// Apply all fixups recorded by noteForwardReference().
193
194 /// Add the low_pc of a label that is relocated by applying
195 /// offset \p PCOffset.
196 void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
197
198 /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
199 /// offset \p PCOffset.
200 void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
201
202 /// Keep track of a DW_AT_range attribute that we will need to patch up later.
203 void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
204
205 /// Keep track of a location attribute pointing to a location list in the
206 /// debug_loc section.
208
209 /// Add a name accelerator entry for \a Die with \a Name.
211
212 /// Add a name accelerator entry for \a Die with \a Name.
214 bool SkipPubnamesSection = false);
215
216 /// Add various accelerator entries for \p Die with \p Name which is stored
217 /// in the string table at \p Offset. \p Name must be an Objective-C
218 /// selector.
220 bool SkipPubnamesSection = false);
221
222 /// Add a type accelerator entry for \p Die with \p Name which is stored in
223 /// the string table at \p Offset.
225 bool ObjcClassImplementation,
226 uint32_t QualifiedNameHash);
227
228 struct AccelInfo {
229 /// Name of the entry.
231
232 /// DIE this entry describes.
233 const DIE *Die;
234
235 /// Hash of the fully qualified name.
237
238 /// Emit this entry only in the apple_* sections.
240
241 /// Is this an ObjC class implementation?
243
245 bool SkipPubSection = false)
247
249 uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
252 ObjcClassImplementation(ObjCClassIsImplementation) {}
253 };
254
255 const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
256 const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
257 const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
258 const std::vector<AccelInfo> &getObjC() const { return ObjC; }
259
260 MCSymbol *getLabelBegin() { return LabelBegin; }
261 void setLabelBegin(MCSymbol *S) { LabelBegin = S; }
262
263private:
264 DWARFUnit &OrigUnit;
265 unsigned ID;
266 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
267 std::optional<BasicDIEUnit> NewUnit;
268 MCSymbol *LabelBegin = nullptr;
269
270 uint64_t StartOffset;
271 uint64_t NextUnitOffset;
272
273 std::optional<uint64_t> LowPc;
274 uint64_t HighPc = 0;
275
276 /// A list of attributes to fixup with the absolute offset of
277 /// a DIE in the debug_info section.
278 ///
279 /// The offsets for the attributes in this array couldn't be set while
280 /// cloning because for cross-cu forward references the target DIE's offset
281 /// isn't known you emit the reference attribute.
282 std::vector<
283 std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
284 ForwardDIEReferences;
285
286 /// The ranges in that map are the PC ranges for functions in this unit,
287 /// associated with the PC offset to apply to the addresses to get
288 /// the linked address.
289 RangesTy Ranges;
290
291 /// The DW_AT_low_pc of each DW_TAG_label.
293
294 /// 'rnglist'(DW_AT_ranges, DW_AT_start_scope) attributes to patch after
295 /// we have gathered all the unit's function addresses.
296 /// @{
297 RngListAttributesTy RangeAttributes;
298 std::optional<PatchLocation> UnitRangeAttribute;
299 /// @}
300
301 /// Location attributes that need to be transferred from the
302 /// original debug_loc section to the linked one. They are stored
303 /// along with the PC offset that is to be applied to their
304 /// function's address or to be applied to address operands of
305 /// location expression.
306 LocListAttributesTy LocationAttributes;
307
308 /// Accelerator entries for the unit, both for the pub*
309 /// sections and the apple* ones.
310 /// @{
311 std::vector<AccelInfo> Pubnames;
312 std::vector<AccelInfo> Pubtypes;
313 std::vector<AccelInfo> Namespaces;
314 std::vector<AccelInfo> ObjC;
315 /// @}
316
317 /// Is this unit subject to the ODR rule?
318 bool HasODR;
319
320 /// The DW_AT_language of this unit.
321 uint16_t Language = 0;
322
323 /// The DW_AT_LLVM_sysroot of this unit.
324 std::string SysRoot;
325
326 /// If this is a Clang module, this holds the module's name.
327 std::string ClangModuleName;
328};
329
330} // end namespace llvm
331
332#endif // LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:510
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
This file defines the DenseMap class.
uint64_t Addr
std::string Name
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
AddressRangesMap class maps values to the address ranges.
Stores all information relating to a compile unit, be it in its original instance in the object file ...
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 fixupForwardReferences()
Apply all fixups recorded by noteForwardReference().
const DIEInfo & getInfo(unsigned Idx) const
DIEInfo & getInfo(const DWARFDie &Die)
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 noteLocationAttribute(PatchLocation Attr)
Keep track of a location attribute pointing to a location list in the debug_loc section.
bool hasLabelAt(uint64_t Addr) const
const std::vector< AccelInfo > & getPubnames() const
const LocListAttributesTy & getLocationAttributes() const
const std::string & getClangModuleName() const
const RngListAttributesTy & getRangesAttributes()
void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name, bool SkipPubnamesSection=false)
Add a name accelerator entry for Die with Name.
unsigned getUniqueID() const
void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name)
Add a name accelerator entry for Die with Name.
DIEInfo & getInfo(unsigned Idx)
const std::vector< AccelInfo > & getObjC() const
DIE * getOutputUnitDIE() const
DWARFUnit & getOrigUnit() const
StringRef getSysRoot()
Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
void setLabelBegin(MCSymbol *S)
const RangesTy & getFunctionRanges() const
void noteRangeAttribute(const DIE &Die, PatchLocation Attr)
Keep track of a DW_AT_range attribute that we will need to patch up later.
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.
const std::vector< AccelInfo > & getPubtypes() const
uint64_t getNextUnitOffset() const
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
const std::vector< AccelInfo > & getNamespaces() const
uint64_t computeNextUnitOffset(uint16_t DwarfVersion)
Compute the end offset for this unit.
std::optional< uint64_t > getLowPc() const
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)
void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset)
Add the low_pc of a label that is relocated by applying offset PCOffset.
std::optional< PatchLocation > getUnitRangesAttribute() const
void markEverythingAsKept()
Mark every DIE in this unit as kept.
uint64_t getHighPc() const
void setStartOffset(uint64_t DebugInfoSize)
An integer value DIE.
Definition: DIE.h:168
DIE & getUnitDie()
Definition: DIE.h:999
A structured debug information entry.
Definition: DIE.h:819
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
dwarf::Tag getTag() const
Definition: DWARFDie.h:71
unsigned getNumDIEs()
Returns the number of DIEs in the unit.
Definition: DWARFUnit.h:503
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:441
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
Return the index of a Die entry inside the unit's DIE vector.
Definition: DWARFUnit.h:267
A DeclContext is a named program scope that is used for ODR uniquing of types.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:151
DwarfStringPoolEntryRef: Dwarf string pool entry reference.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
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
const DIE * Die
DIE this entry describes.
DwarfStringPoolEntryRef Name
Name of the entry.
bool ObjcClassImplementation
Is this an ObjC class implementation?
uint32_t QualifiedNameHash
Hash of the fully qualified name.
AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die, bool SkipPubSection=false)
bool SkipPubSection
Emit this entry only in the apple_* sections.
AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die, uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
Information gathered about a DIE in the object file.
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 HasLocationExpressionAddr
Is this a variable with a location attribute referencing address?
bool Incomplete
Does DIE transitively refer an incomplete decl?
Hold the input and output of the debug info size in bytes.
Definition: DWARFLinker.cpp:43
PatchLocation()=default
PatchLocation(DIE::value_iterator I)
DIE::value_iterator I
PatchLocation(DIE::value_iterator I, int64_t Reloc)
void set(uint64_t New) const