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