LLVM 23.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_CLASSIC_DWARFLINKERCOMPILEUNIT_H
10#define LLVM_DWARFLINKER_CLASSIC_DWARFLINKERCOMPILEUNIT_H
11
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/CodeGen/DIE.h"
17#include <optional>
18
19namespace llvm {
20namespace dwarf_linker {
21namespace classic {
22
23class DeclContext;
24
25/// Mapped value in the address map is the offset to apply to the
26/// linked address.
28
29// This structure keeps patch for the attribute and, optionally,
30// the value of relocation which should be applied. Currently,
31// only location attribute needs to have relocation: either to the
32// function ranges if location attribute is of type 'loclist',
33// either to the operand of DW_OP_addr/DW_OP_addrx if location attribute
34// is of type 'exprloc'.
35// ASSUMPTION: Location attributes of 'loclist' type containing 'exprloc'
36// with address expression operands are not supported yet.
39 int64_t RelocAdjustment = 0;
40
41 PatchLocation() = default;
45
46 void set(uint64_t New) const {
47 assert(I);
48 const auto &Old = *I;
49 assert(Old.getType() == DIEValue::isInteger);
50 *I = DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New));
51 }
52
53 uint64_t get() const {
54 assert(I);
55 return I->getDIEInteger().getValue();
56 }
57};
58
62
63/// Stores all information relating to a compile unit, be it in its original
64/// instance in the object file to its brand new cloned and generated DIE tree.
66public:
67 /// Information gathered about a DIE in the object file.
68 struct DIEInfo {
69 /// Address offset to apply to the described entity.
70 int64_t AddrAdjust;
71
72 /// ODR Declaration context.
74
75 /// Cloned version of that DIE.
77
78 /// The index of this DIE's parent.
80
81 /// Is the DIE part of the linked output?
82 bool Keep : 1;
83
84 /// Was this DIE's entity found in the map?
85 bool InDebugMap : 1;
86
87 /// Is this a pure forward declaration we can strip?
88 bool Prune : 1;
89
90 /// Does DIE transitively refer an incomplete decl?
91 bool Incomplete : 1;
92
93 /// Is DIE in the clang module scope?
94 bool InModuleScope : 1;
95
96 /// Is ODR marking done?
98
99 /// Is this a reference to a DIE that hasn't been cloned yet?
101
102 /// Is this a variable with a location attribute referencing address?
104
105#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
106 LLVM_DUMP_METHOD void dump();
107#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
108 };
109
110 CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
111 StringRef ClangModuleName)
112 : OrigUnit(OrigUnit), ID(ID), ClangModuleName(ClangModuleName) {
113 Info.resize(OrigUnit.getNumDIEs());
114
115 auto CUDie = OrigUnit.getUnitDIE(false);
116 if (!CUDie) {
117 HasODR = false;
118 return;
119 }
120 if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
121 HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
122 *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
123 *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
124 *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
125 *Lang == dwarf::DW_LANG_ObjC_plus_plus);
126 else
127 HasODR = false;
128 }
129
130 DWARFUnit &getOrigUnit() const { return OrigUnit; }
131
132 unsigned getUniqueID() const { return ID; }
133
135 NewUnit.emplace(OrigUnit.getUnitDIE().getTag());
136
137 // Propogate the section offset so that DIEntry can compute
138 // correct absolute offsets for DW_FORM_ref_addr references
139 NewUnit->setDebugSectionOffset(StartOffset);
140 }
141
143 if (NewUnit)
144 return &const_cast<BasicDIEUnit &>(*NewUnit).getUnitDie();
145 return nullptr;
146 }
147
148 dwarf::Tag getTag() const { return OrigUnit.getUnitDIE().getTag(); }
149
150 bool hasODR() const { return HasODR; }
151 bool isClangModule() const { return !ClangModuleName.empty(); }
153 /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
155
156 const std::string &getClangModuleName() const { return ClangModuleName; }
157
158 DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
159 const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
160
161 DIEInfo &getInfo(const DWARFDie &Die) {
162 unsigned Idx = getOrigUnit().getDIEIndex(Die);
163 return Info[Idx];
164 }
165
166 uint64_t getStartOffset() const { return StartOffset; }
167 uint64_t getNextUnitOffset() const { return NextUnitOffset; }
169 StartOffset = DebugInfoSize;
170 if (NewUnit)
171 NewUnit->setDebugSectionOffset(DebugInfoSize);
172 }
173
174 std::optional<uint64_t> getLowPc() const { return LowPc; }
175 uint64_t getHighPc() const { return HighPc; }
176 bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
177
178 const RangesTy &getFunctionRanges() const { return Ranges; }
179
180 const RngListAttributesTy &getRangesAttributes() { return RangeAttributes; }
181
182 std::optional<PatchLocation> getUnitRangesAttribute() const {
183 return UnitRangeAttribute;
184 }
185
187 return LocationAttributes;
188 }
189
190 // Provide access to the list of DW_AT_LLVM_stmt_sequence attributes that may
191 // need to be patched.
193 return StmtSeqListAttributes;
194 }
195
196 /// Mark every DIE in this unit as kept. This function also
197 /// marks variables as InDebugMap so that they appear in the
198 /// reconstructed accelerator tables.
200
201 /// Compute the end offset for this unit. Must be called after the CU's DIEs
202 /// have been cloned. \returns the next unit offset (which is also the
203 /// current debug_info section size).
205
206 /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p
207 /// Attr. The attribute should be fixed up later to point to the absolute
208 /// offset of \p Die in the debug_info section or to the canonical offset of
209 /// \p Ctxt if it is non-null.
210 LLVM_ABI void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
211 DeclContext *Ctxt, PatchLocation Attr);
212
213 /// Apply all fixups recorded by noteForwardReference().
215
216 /// Add the low_pc of a label that is relocated by applying
217 /// offset \p PCOffset.
218 LLVM_ABI void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
219
220 /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
221 /// offset \p PCOffset.
222 LLVM_ABI void addFunctionRange(uint64_t LowPC, uint64_t HighPC,
223 int64_t PCOffset);
224
225 /// Keep track of a DW_AT_range attribute that we will need to patch up later.
226 LLVM_ABI void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
227
228 /// Keep track of a location attribute pointing to a location list in the
229 /// debug_loc section.
231
232 // Record that the given DW_AT_LLVM_stmt_sequence attribute may need to be
233 // patched later.
235
236 /// Add a name accelerator entry for \a Die with \a Name.
237 LLVM_ABI void addNamespaceAccelerator(const DIE *Die,
239
240 /// Add a name accelerator entry for \a Die with \a Name.
242 bool SkipPubnamesSection = false);
243
244 /// Add various accelerator entries for \p Die with \p Name which is stored
245 /// in the string table at \p Offset. \p Name must be an Objective-C
246 /// selector.
248 bool SkipPubnamesSection = false);
249
250 /// Add a type accelerator entry for \p Die with \p Name which is stored in
251 /// the string table at \p Offset.
253 bool ObjcClassImplementation,
254 uint32_t QualifiedNameHash);
255
256 struct AccelInfo {
257 /// Name of the entry.
259
260 /// DIE this entry describes.
261 const DIE *Die;
262
263 /// Hash of the fully qualified name.
265
266 /// Emit this entry only in the apple_* sections.
268
269 /// Is this an ObjC class implementation?
271
275
277 uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
280 ObjcClassImplementation(ObjCClassIsImplementation) {}
281 };
282
283 const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
284 const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
285 const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
286 const std::vector<AccelInfo> &getObjC() const { return ObjC; }
287
288 MCSymbol *getLabelBegin() { return LabelBegin; }
289 void setLabelBegin(MCSymbol *S) { LabelBegin = S; }
290
291private:
292 DWARFUnit &OrigUnit;
293 unsigned ID;
294 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
295 std::optional<BasicDIEUnit> NewUnit;
296 MCSymbol *LabelBegin = nullptr;
297
298 uint64_t StartOffset;
299 uint64_t NextUnitOffset;
300
301 std::optional<uint64_t> LowPc;
302 uint64_t HighPc = 0;
303
304 /// A list of attributes to fixup with the absolute offset of
305 /// a DIE in the debug_info section.
306 ///
307 /// The offsets for the attributes in this array couldn't be set while
308 /// cloning because for cross-cu forward references the target DIE's offset
309 /// isn't known you emit the reference attribute.
310 std::vector<
311 std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
312 ForwardDIEReferences;
313
314 /// The ranges in that map are the PC ranges for functions in this unit,
315 /// associated with the PC offset to apply to the addresses to get
316 /// the linked address.
317 RangesTy Ranges;
318
319 /// The DW_AT_low_pc of each DW_TAG_label.
321
322 /// 'rnglist'(DW_AT_ranges, DW_AT_start_scope) attributes to patch after
323 /// we have gathered all the unit's function addresses.
324 /// @{
325 RngListAttributesTy RangeAttributes;
326 std::optional<PatchLocation> UnitRangeAttribute;
327 /// @}
328
329 /// Location attributes that need to be transferred from the
330 /// original debug_loc section to the linked one. They are stored
331 /// along with the PC offset that is to be applied to their
332 /// function's address or to be applied to address operands of
333 /// location expression.
334 LocListAttributesTy LocationAttributes;
335
336 // List of DW_AT_LLVM_stmt_sequence attributes that may need to be patched
337 // after the dwarf linker rewrites the line table. During line table rewrite
338 // the line table format might change, so we have to patch any offsets that
339 // reference its contents.
340 StmtSeqListAttributesTy StmtSeqListAttributes;
341
342 /// Accelerator entries for the unit, both for the pub*
343 /// sections and the apple* ones.
344 /// @{
345 std::vector<AccelInfo> Pubnames;
346 std::vector<AccelInfo> Pubtypes;
347 std::vector<AccelInfo> Namespaces;
348 std::vector<AccelInfo> ObjC;
349 /// @}
350
351 /// Is this unit subject to the ODR rule?
352 bool HasODR;
353
354 /// The DW_AT_language of this unit.
355 uint16_t Language = 0;
356
357 /// The DW_AT_LLVM_sysroot of this unit.
358 std::string SysRoot;
359
360 /// If this is a Clang module, this holds the module's name.
361 std::string ClangModuleName;
362};
363
364} // end of namespace classic
365} // end of namespace dwarf_linker
366} // end of namespace llvm
367
368#endif // LLVM_DWARFLINKER_CLASSIC_DWARFLINKERCOMPILEUNIT_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:661
This file defines the DenseMap class.
if(PassOpts->AAPipeline)
AddressRangesMap class maps values to the address ranges.
An integer value DIE.
Definition DIE.h:169
DIE & getUnitDie()
Definition DIE.h:1009
A structured debug information entry.
Definition DIE.h:828
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
Return the index of a Die entry inside the unit's DIE vector.
Definition DWARFUnit.h:276
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:42
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Stores all information relating to a compile unit, be it in its original instance in the object file ...
const std::vector< AccelInfo > & getNamespaces() const
const std::vector< AccelInfo > & getPubnames() const
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)
const std::vector< AccelInfo > & getPubtypes() const
const std::vector< AccelInfo > & getObjC() const
LLVM_ABI void fixupForwardReferences()
Apply all fixups recorded by noteForwardReference().
const DIEInfo & getInfo(unsigned Idx) const
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.
std::optional< uint64_t > getLowPc() const
LLVM_ABI void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name, bool SkipPubnamesSection=false)
Add a name accelerator entry for Die with Name.
const StmtSeqListAttributesTy & getStmtSeqListAttributes() const
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.
std::optional< PatchLocation > getUnitRangesAttribute() const
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.
const LocListAttributesTy & getLocationAttributes() const
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)
const RngListAttributesTy & getRangesAttributes()
A DeclContext is a named program scope that is used for ODR uniquing of types.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
SmallVector< PatchLocation > RngListAttributesTy
SmallVector< PatchLocation > StmtSeqListAttributesTy
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
SmallVector< PatchLocation > LocListAttributesTy
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 Types.h:26
Hold the input and output of the debug info size in bytes.
AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die, uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die, bool SkipPubSection=false)
DwarfStringPoolEntryRef Name
Name of the entry.
uint32_t QualifiedNameHash
Hash of the fully qualified name.
bool ObjcClassImplementation
Is this an ObjC class implementation?
bool SkipPubSection
Emit this entry only in the apple_* sections.
Information gathered about a DIE in the object file.
uint32_t ParentIdx
The index of this DIE's parent.
bool Prune
Is this a pure forward declaration we can strip?
int64_t AddrAdjust
Address offset to apply to the described entity.
bool HasLocationExpressionAddr
Is this a variable with a location attribute referencing address?
bool InDebugMap
Was this DIE's entity found in the map?
bool UnclonedReference
Is this a reference to a DIE that hasn't been cloned yet?
bool InModuleScope
Is DIE in the clang module scope?
bool Incomplete
Does DIE transitively refer an incomplete decl?
bool Keep
Is the DIE part of the linked output?
PatchLocation(DIE::value_iterator I, int64_t Reloc)