LLVM 17.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#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
100#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
101 };
102
103 CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
104 StringRef ClangModuleName)
105 : OrigUnit(OrigUnit), ID(ID), ClangModuleName(ClangModuleName) {
106 Info.resize(OrigUnit.getNumDIEs());
107
108 auto CUDie = OrigUnit.getUnitDIE(false);
109 if (!CUDie) {
110 HasODR = false;
111 return;
112 }
113 if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
114 HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
115 *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
116 *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
117 *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
118 *Lang == dwarf::DW_LANG_ObjC_plus_plus);
119 else
120 HasODR = false;
121 }
122
123 DWARFUnit &getOrigUnit() const { return OrigUnit; }
124
125 unsigned getUniqueID() const { return ID; }
126
127 void createOutputDIE() { NewUnit.emplace(OrigUnit.getUnitDIE().getTag()); }
128
130 if (NewUnit)
131 return &const_cast<BasicDIEUnit &>(*NewUnit).getUnitDie();
132 return nullptr;
133 }
134
135 bool hasODR() const { return HasODR; }
136 bool isClangModule() const { return !ClangModuleName.empty(); }
138 /// Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
140
141 const std::string &getClangModuleName() const { return ClangModuleName; }
142
143 DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
144 const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
145
146 DIEInfo &getInfo(const DWARFDie &Die) {
147 unsigned Idx = getOrigUnit().getDIEIndex(Die);
148 return Info[Idx];
149 }
150
151 uint64_t getStartOffset() const { return StartOffset; }
152 uint64_t getNextUnitOffset() const { return NextUnitOffset; }
154
155 std::optional<uint64_t> getLowPc() const { return LowPc; }
156 uint64_t getHighPc() const { return HighPc; }
157 bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
158
159 const RangesTy &getFunctionRanges() const { return Ranges; }
160
161 const RngListAttributesTy &getRangesAttributes() { return RangeAttributes; }
162
163 std::optional<PatchLocation> getUnitRangesAttribute() const {
164 return UnitRangeAttribute;
165 }
166
168 return LocationAttributes;
169 }
170
171 /// Mark every DIE in this unit as kept. This function also
172 /// marks variables as InDebugMap so that they appear in the
173 /// reconstructed accelerator tables.
175
176 /// Compute the end offset for this unit. Must be called after the CU's DIEs
177 /// have been cloned. \returns the next unit offset (which is also the
178 /// current debug_info section size).
180
181 /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p
182 /// Attr. The attribute should be fixed up later to point to the absolute
183 /// offset of \p Die in the debug_info section or to the canonical offset of
184 /// \p Ctxt if it is non-null.
185 void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
186 DeclContext *Ctxt, PatchLocation Attr);
187
188 /// Apply all fixups recorded by noteForwardReference().
190
191 /// Add the low_pc of a label that is relocated by applying
192 /// offset \p PCOffset.
193 void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
194
195 /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
196 /// offset \p PCOffset.
197 void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
198
199 /// Keep track of a DW_AT_range attribute that we will need to patch up later.
200 void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
201
202 /// Keep track of a location attribute pointing to a location list in the
203 /// debug_loc section.
205
206 /// Add a name accelerator entry for \a Die with \a Name.
208
209 /// Add a name accelerator entry for \a Die with \a Name.
211 bool SkipPubnamesSection = false);
212
213 /// Add various accelerator entries for \p Die with \p Name which is stored
214 /// in the string table at \p Offset. \p Name must be an Objective-C
215 /// selector.
217 bool SkipPubnamesSection = false);
218
219 /// Add a type accelerator entry for \p Die with \p Name which is stored in
220 /// the string table at \p Offset.
222 bool ObjcClassImplementation,
223 uint32_t QualifiedNameHash);
224
225 struct AccelInfo {
226 /// Name of the entry.
228
229 /// DIE this entry describes.
230 const DIE *Die;
231
232 /// Hash of the fully qualified name.
234
235 /// Emit this entry only in the apple_* sections.
237
238 /// Is this an ObjC class implementation?
240
242 bool SkipPubSection = false)
244
246 uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
249 ObjcClassImplementation(ObjCClassIsImplementation) {}
250 };
251
252 const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
253 const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
254 const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
255 const std::vector<AccelInfo> &getObjC() const { return ObjC; }
256
257 MCSymbol *getLabelBegin() { return LabelBegin; }
258 void setLabelBegin(MCSymbol *S) { LabelBegin = S; }
259
260private:
261 DWARFUnit &OrigUnit;
262 unsigned ID;
263 std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
264 std::optional<BasicDIEUnit> NewUnit;
265 MCSymbol *LabelBegin = nullptr;
266
267 uint64_t StartOffset;
268 uint64_t NextUnitOffset;
269
270 std::optional<uint64_t> LowPc;
271 uint64_t HighPc = 0;
272
273 /// A list of attributes to fixup with the absolute offset of
274 /// a DIE in the debug_info section.
275 ///
276 /// The offsets for the attributes in this array couldn't be set while
277 /// cloning because for cross-cu forward references the target DIE's offset
278 /// isn't known you emit the reference attribute.
279 std::vector<
280 std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
281 ForwardDIEReferences;
282
283 /// The ranges in that map are the PC ranges for functions in this unit,
284 /// associated with the PC offset to apply to the addresses to get
285 /// the linked address.
286 RangesTy Ranges;
287
288 /// The DW_AT_low_pc of each DW_TAG_label.
290
291 /// 'rnglist'(DW_AT_ranges, DW_AT_start_scope) attributes to patch after
292 /// we have gathered all the unit's function addresses.
293 /// @{
294 RngListAttributesTy RangeAttributes;
295 std::optional<PatchLocation> UnitRangeAttribute;
296 /// @}
297
298 /// Location attributes that need to be transferred from the
299 /// original debug_loc section to the linked one. They are stored
300 /// along with the PC offset that is to be applied to their
301 /// function's address or to be applied to address operands of
302 /// location expression.
303 LocListAttributesTy LocationAttributes;
304
305 /// Accelerator entries for the unit, both for the pub*
306 /// sections and the apple* ones.
307 /// @{
308 std::vector<AccelInfo> Pubnames;
309 std::vector<AccelInfo> Pubtypes;
310 std::vector<AccelInfo> Namespaces;
311 std::vector<AccelInfo> ObjC;
312 /// @}
313
314 /// Is this unit subject to the ODR rule?
315 bool HasODR;
316
317 /// The DW_AT_language of this unit.
318 uint16_t Language = 0;
319
320 /// The DW_AT_LLVM_sysroot of this unit.
321 std::string SysRoot;
322
323 /// If this is a Clang module, this holds the module's name.
324 std::string ClangModuleName;
325};
326
327} // end namespace llvm
328
329#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: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
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 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 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.
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)
std::optional< PatchLocation > getUnitRangesAttribute() const
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.
uint64_t getHighPc() const
void setStartOffset(uint64_t DebugInfoSize)
An integer value DIE.
Definition: DIE.h:168
DIE & getUnitDie()
Definition: DIE.h:926
A structured debug information entry.
Definition: DIE.h:746
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:488
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:426
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
Return the index of a Die entry inside the unit's DIE vector.
Definition: DWARFUnit.h:262
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 Incomplete
Does DIE transitively refer an incomplete decl?
Hold the input and output of the debug info size in bytes.
Definition: DWARFLinker.cpp:40
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