Skip to content

Commit 2701a66

Browse files
committed
[BOLT][DWARF] Numerous fixes for a new DWARFRewriter
Summary: * Some cleanup and minor fixes for the new debug information re-writer before moving on to productatization. * The new rewriter wasn't handling binary with DWARF5 and DWARF4 with -fdebug-types-sections. * Removed dead cross cu reference code. * Added support for DW_AT_sibling. * With the new re-writer abbrev number can change which can lead to offset of Type Units changing. Before we would just copy raw data. Changed to write out Type Unit List. This is generated by gdb-add-index. * Fixed how bolt handles gdb-index generated by gdb-11 with types sections. Simplified logic that handles variations of gdb-index. * Clang can generate two type units with the same hash, but different content. LLD does not de-duplicate when ThinLTO is involved. Changed so that TU hash and offset are used to make TU's unique. * It is possible to have references within location expression to another DIE. Fixed it so that relative offset is updated correctly. * Removed all the code related to patching. * Removed dead code. Changed how we handling writting out TUs and TU Index. It now should fully work for DWARF4 and DWARF5. * Removed unused arguments from some APIs, changed return type to void, and other small cleanups. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D46168257
1 parent 460a224 commit 2701a66

File tree

57 files changed

+12837
-1679
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+12837
-1679
lines changed

bolt/include/bolt/Core/DIEBuilder.h

Lines changed: 140 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -16,223 +16,233 @@
1616
#define BOLT_CORE_DIE_BUILDER_H
1717

1818
#include "llvm/CodeGen/DIE.h"
19-
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
2019
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
2120
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
2221
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
2322
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
24-
#include "llvm/IR/Type.h"
2523
#include "llvm/Support/Allocator.h"
2624
#include "llvm/Support/ErrorHandling.h"
2725

28-
#include <cstdint>
29-
#include <forward_list>
3026
#include <list>
3127
#include <memory>
32-
#include <mutex>
3328
#include <optional>
34-
#include <set>
35-
#include <shared_mutex>
36-
#include <sys/types.h>
3729
#include <unordered_map>
38-
#include <utility>
3930
#include <vector>
4031

4132
namespace llvm {
4233

4334
namespace bolt {
35+
class DIEStreamer;
4436

4537
class DIEBuilder {
38+
friend DIEStreamer;
39+
40+
public:
41+
/// Wrapper around DIE so we can access DIEs easily.
4642
struct DIEInfo {
4743
DIE *Die;
4844
uint32_t DieId;
4945
uint32_t UnitId;
50-
uint32_t CanonicalDIEOffset;
5146
};
5247

53-
struct UnitInfo {
54-
std::list<DIEInfo> DieInfoList;
55-
uint32_t UnitId;
56-
uint32_t UnitOffset;
57-
bool Isconstructed = false;
58-
uint32_t NewDieId = 0;
48+
/// Contains information for the CU level of DWARF.
49+
struct DWARFUnitInfo {
50+
// Contains all the DIEs for the current unit.
51+
// Accessed by DIE ID.
52+
std::vector<std::unique_ptr<DIEInfo>> DieInfoVector;
53+
DIE *UnitDie = nullptr;
54+
uint32_t UnitId = 0;
55+
uint32_t UnitOffset = 0;
56+
uint32_t UnitLength = 0;
57+
bool IsConstructed = false;
58+
// A map of DIE offsets in original DWARF section to DIE ID.
59+
// Whih is used to access DieInfoVector.
5960
std::unordered_map<uint64_t, uint32_t> DIEIDMap;
60-
std::unordered_map<uint32_t, DIEInfo *> DIEId2InfoMap;
6161
};
6262

63-
struct ForwardReferenceInfo {
64-
ForwardReferenceInfo(DIEInfo *Die,
65-
DWARFAbbreviationDeclaration::AttributeSpec spec)
66-
: Dst(Die), AttrSpec(spec) {}
63+
private:
64+
/// Contains information so that we we can update references in locexpr after
65+
/// we calculated all the final DIE offsets.
66+
struct LocWithReference {
67+
LocWithReference(std::vector<uint8_t> &&BlockData, DWARFUnit &U, DIE &Die,
68+
dwarf::Form Form, dwarf::Attribute Attr)
69+
: BlockData(BlockData), U(U), Die(Die), Form(Form), Attr(Attr) {}
70+
std::vector<uint8_t> BlockData;
71+
DWARFUnit &U;
72+
DIE &Die;
73+
dwarf::Form Form;
74+
dwarf::Attribute Attr;
75+
};
76+
/// Contains information so that we can update cross CU references, after we
77+
/// calculated all the final DIE offsets.
78+
struct AddrReferenceInfo {
79+
AddrReferenceInfo(DIEInfo *Die,
80+
DWARFAbbreviationDeclaration::AttributeSpec Spec)
81+
: Dst(Die), AttrSpec(Spec) {}
6782
DIEInfo *Dst;
6883
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec;
6984
};
7085

71-
bool IsBuilt = false;
72-
std::unordered_map<DWARFUnit *, std::vector<DIE *>> UnitDIEs;
73-
std::unordered_map<DWARFUnit *, uint32_t> UnitIDMap;
86+
/// A map of Units to Unit Index.
87+
std::unordered_map<uint64_t, uint32_t> UnitIDMap;
88+
/// A map of Type Units to Type DIEs.
7489
std::unordered_map<DWARFUnit *, DIE *> TypeDIEMap;
7590
std::vector<DWARFUnit *> DUList;
76-
std::vector<UnitInfo> CloneUnitCtxMap;
77-
std::vector<std::pair<DIEInfo *, ForwardReferenceInfo>> ForwardReferences;
91+
std::vector<DWARFUnitInfo> CloneUnitCtxMap;
92+
std::vector<std::pair<DIEInfo *, AddrReferenceInfo>> AddrReferences;
7893
FoldingSet<DIEAbbrev> AbbreviationsSet;
7994
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
8095
std::vector<DWARFUnit *> DWARF4TUVector;
81-
std::vector<DWARFUnit *> DWARF4CUVector;
96+
std::vector<LocWithReference> LocWithReferencesToProcess;
8297
BumpPtrAllocator DIEAlloc;
8398

8499
/// Resolve the reference in DIE, if target is not loaded into IR,
85100
/// pre-allocate it. \p RefCU will be updated to the Unit specific by \p
86101
/// RefValue.
87-
DWARFDie
88-
resolveDIEReference(const DWARFFormValue &RefValue,
89-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
90-
DWARFUnit *&RefCU,
91-
DWARFDebugInfoEntry &DwarfDebugInfoEntry,
92-
const std::vector<DWARFUnit *> &DUOffsetList);
93-
94-
/// Clone one attribute according the format. \return the size of this
102+
DWARFDie resolveDIEReference(const DWARFFormValue &RefValue,
103+
DWARFUnit *&RefCU,
104+
DWARFDebugInfoEntry &DwarfDebugInfoEntry,
105+
const std::vector<DWARFUnit *> &DUOffsetList);
106+
107+
/// Resolve the reference in DIE, if target is not loaded into IR,
108+
/// pre-allocate it. \p RefCU will be updated to the Unit specific by \p
109+
/// RefValue.
110+
DWARFDie resolveDIEReference(const uint64_t ReffOffset, DWARFUnit *&RefCU,
111+
DWARFDebugInfoEntry &DwarfDebugInfoEntry,
112+
const std::vector<DWARFUnit *> &DUOffsetList);
113+
114+
/// Clone one attribute according to the format. \return the size of this
95115
/// attribute.
96-
uint32_t
116+
void
97117
cloneAttribute(DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U,
98118
const DWARFFormValue &Val,
99119
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
100-
unsigned AttrSize, bool IsLittleEndian,
101-
std::vector<DWARFUnit *> &DUOffsetList);
120+
const std::vector<DWARFUnit *> &DUOffsetList);
102121

103122
/// Clone an attribute in string format.
104-
uint32_t cloneStringAttribute(
105-
DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
106-
unsigned AttrSize, const DWARFFormValue &Val, const DWARFUnit &U);
123+
void cloneStringAttribute(
124+
DIE &Die, const DWARFUnit &U,
125+
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
126+
const DWARFFormValue &Val);
107127

108128
/// Clone an attribute in reference format.
109-
uint32_t cloneDieReferenceAttribute(
110-
DIE &Die, const DWARFDie &InputDIE,
111-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, unsigned AttrSize,
112-
const DWARFFormValue &Val, DWARFUnit &U,
113-
std::vector<DWARFUnit *> &DUOffsetList);
129+
void cloneDieReferenceAttribute(
130+
DIE &Die, const DWARFUnit &U, const DWARFDie &InputDIE,
131+
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
132+
const DWARFFormValue &Val, const std::vector<DWARFUnit *> &DUOffsetList);
114133

115134
/// Clone an attribute in block format.
116-
uint32_t
117-
cloneBlockAttribute(DIE &Die, DWARFUnit &U,
118-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
119-
const DWARFFormValue &Val, unsigned AttrSize,
120-
bool IsLittleEndian);
135+
void cloneBlockAttribute(
136+
DIE &Die, DWARFUnit &U,
137+
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
138+
const DWARFFormValue &Val);
121139

140+
enum class CloneExpressionStage { INIT, PATCH };
122141
/// Clone an attribute in expression format. \p OutputBuffer will hold the
123142
/// output content.
124-
void cloneExpression(DataExtractor &Data, DWARFExpression &Expression,
125-
DWARFUnit &U, SmallVectorImpl<uint8_t> &OutputBuffer);
143+
/// Returns true if Expression contains a reference.
144+
bool cloneExpression(const DataExtractor &Data,
145+
const DWARFExpression &Expression, DWARFUnit &U,
146+
SmallVectorImpl<uint8_t> &OutputBuffer,
147+
const CloneExpressionStage &Stage);
126148

127149
/// Clone an attribute in address format.
128-
uint32_t
129-
cloneAddressAttribute(DIE &Die,
130-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
131-
const DWARFFormValue &Val, const DWARFUnit &U);
150+
void cloneAddressAttribute(
151+
DIE &Die, const DWARFUnit &U,
152+
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
153+
const DWARFFormValue &Val);
132154

133-
/// Clone an attribute in Refsig format.
134-
uint32_t
135-
cloneRefsigAttribute(DIE &Die,
136-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
137-
unsigned AttrSize, const DWARFFormValue &Val);
155+
/// Clone an attribute in refsig format.
156+
void cloneRefsigAttribute(
157+
DIE &Die, const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
158+
const DWARFFormValue &Val);
138159

139160
/// Clone an attribute in scalar format.
140-
uint32_t
141-
cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
142-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
143-
const DWARFFormValue &Val, unsigned AttrSize);
161+
void cloneScalarAttribute(
162+
DIE &Die, const DWARFDie &InputDIE,
163+
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
164+
const DWARFFormValue &Val);
144165

145166
/// Clone an attribute in loclist format.
146-
uint32_t
147-
cloneLoclistAttrubute(DIE &Die, const DWARFDie &InputDIE,
148-
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
149-
const DWARFFormValue &Val, unsigned AttrSize);
167+
void cloneLoclistAttrubute(
168+
DIE &Die, const DWARFDie &InputDIE,
169+
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
170+
const DWARFFormValue &Val);
150171

151-
/// Update the Cross-CU reference offset.
152-
void computeReference();
172+
/// Update references once the layout is finalized.
173+
void updateReferences();
153174

154175
/// Update the Offset and Size of DIE.
155-
uint32_t computeDIEOffset(DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
176+
uint32_t computeDIEOffset(const DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
156177

157-
void registerUnit(DWARFUnit &Unit) {
158-
UnitIDMap[&Unit] = DUList.size();
159-
DUList.push_back(&Unit);
160-
}
178+
void registerUnit(DWARFUnit &DU);
161179

162180
/// \return the unique ID of \p U if it exists.
163-
std::optional<uint32_t> getUnitId(DWARFUnit &DU) {
164-
if (UnitIDMap.count(&DU))
165-
return UnitIDMap[&DU];
166-
return std::nullopt;
167-
}
181+
std::optional<uint32_t> getUnitId(const DWARFUnit &DU);
168182

169-
UnitInfo &getUnitInfo(uint32_t UnitId) { return CloneUnitCtxMap[UnitId]; }
183+
DWARFUnitInfo &getUnitInfo(uint32_t UnitId) {
184+
return CloneUnitCtxMap[UnitId];
185+
}
170186

171187
DIEInfo &getDIEInfo(uint32_t UnitId, uint32_t DIEId) {
172-
if (CloneUnitCtxMap[UnitId].DIEId2InfoMap.count(DIEId))
173-
return *CloneUnitCtxMap[UnitId].DIEId2InfoMap[DIEId];
188+
if (CloneUnitCtxMap[UnitId].DieInfoVector.size() > DIEId)
189+
return *CloneUnitCtxMap[UnitId].DieInfoVector[DIEId].get();
174190

175-
errs() << "BOLT-ERROR: The DIE is not allocated before looking up, some"
191+
errs() << "BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated "
192+
"before looking up, some"
176193
<< "unexpected corner cases happened.\n";
177-
return CloneUnitCtxMap[UnitId].DieInfoList.front();
194+
return *CloneUnitCtxMap[UnitId].DieInfoVector.front().get();
178195
}
179196

180-
UnitInfo &getUnitInfoByDwarfUnit(DWARFUnit &DwarfUnit) {
181-
std::optional<uint32_t> UnitId = getUnitId(DwarfUnit);
182-
return getUnitInfo(*UnitId);
183-
}
184-
185-
std::optional<uint32_t> getAllocDIEId(DWARFUnit &DU, DWARFDie &DDie) {
186-
UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU);
187-
uint64_t Offset = DDie.getOffset();
188-
189-
if (!UnitInfo.DIEIDMap.count(Offset))
190-
return std::nullopt;
191-
return UnitInfo.DIEIDMap[Offset];
197+
std::optional<uint32_t> getAllocDIEId(const DWARFUnit &DU,
198+
const uint64_t Offset) {
199+
const DWARFUnitInfo &DWARFUnitInfo = getUnitInfoByDwarfUnit(DU);
200+
auto Iter = DWARFUnitInfo.DIEIDMap.find(Offset);
201+
return (Iter == DWARFUnitInfo.DIEIDMap.end())
202+
? std::nullopt
203+
: std::optional<uint32_t>(Iter->second);
192204
}
193-
194-
std::optional<uint32_t> getAllocDIEId(DWARFUnit &DU, uint64_t Offset) {
195-
UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU);
196-
197-
if (!UnitInfo.DIEIDMap.count(Offset))
198-
return std::nullopt;
199-
return UnitInfo.DIEIDMap[Offset];
205+
std::optional<uint32_t> getAllocDIEId(const DWARFUnit &DU,
206+
const DWARFDie &DDie) {
207+
return getAllocDIEId(DU, DDie.getOffset());
200208
}
201209

202-
// To avoid overhead, do not use this unless we do get the UnitInfo first.
203-
// We can use getDIEInfo with UnitId and DieId
204-
DIEInfo &getDIEInfoByDwarfDie(DWARFDie *DwarfDie) {
205-
DWARFUnit *DwarfUnit = DwarfDie->getDwarfUnit();
206-
std::optional<uint32_t> UnitId = getUnitId(*DwarfUnit);
207-
std::optional<uint32_t> hasDIEId = getAllocDIEId(*DwarfUnit, *DwarfDie);
208-
assert(hasDIEId.has_value());
210+
// To avoid overhead, do not use this unless we do get the DWARFUnitInfo
211+
// first. We can use getDIEInfo with UnitId and DieId
212+
DIEInfo &getDIEInfoByDwarfDie(DWARFDie &DwarfDie) {
213+
DWARFUnit &DwarfUnit = *DwarfDie.getDwarfUnit();
214+
std::optional<uint32_t> UnitId = getUnitId(DwarfUnit);
215+
std::optional<uint32_t> HasDieId = getAllocDIEId(DwarfUnit, DwarfDie);
216+
assert(HasDieId);
209217

210-
return getDIEInfo(*UnitId, *hasDIEId);
218+
return getDIEInfo(*UnitId, *HasDieId);
211219
}
212220

213-
std::optional<uint32_t> allocDIE(DWARFUnit &DU, DWARFDie &DDie,
214-
BumpPtrAllocator &Alloc, uint32_t UId,
215-
uint32_t offset = 0);
216-
217-
uint32_t AllocDIEId(DWARFUnit &DU) {
218-
UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU);
219-
return UnitInfo.NewDieId++;
220-
}
221+
uint32_t allocDIE(const DWARFUnit &DU, const DWARFDie &DDie,
222+
BumpPtrAllocator &Alloc, const uint32_t UId);
221223

222224
/// Construct IR for \p DU. \p DUOffsetList specific the Unit in current
223225
/// Section.
224226
void constructFromUnit(DWARFUnit &DU, std::vector<DWARFUnit *> &DUOffsetList);
225227

226228
/// Construct a DIE for \p DDie in \p U. \p DUOffsetList specific the Unit in
227229
/// current Section.
228-
DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, bool IsLittleEndian,
229-
uint32_t UnitId,
230+
DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, uint32_t UnitId,
230231
std::vector<DWARFUnit *> &DUOffsetList);
231232

232233
public:
233234
DIEBuilder(DWARFContext *DwarfContext, bool IsDWO = false);
234235

235-
std::vector<DIE *> getDIEsByUnit(DWARFUnit &DU) { return UnitDIEs[&DU]; }
236+
/// Returns DWARFUnitInfo for DWARFUnit
237+
DWARFUnitInfo &getUnitInfoByDwarfUnit(const DWARFUnit &DwarfUnit) {
238+
std::optional<uint32_t> UnitId = getUnitId(DwarfUnit);
239+
return getUnitInfo(*UnitId);
240+
}
241+
242+
const std::vector<std::unique_ptr<DIEInfo>> &getDIEsByUnit(DWARFUnit &DU) {
243+
DWARFUnitInfo &U = getUnitInfoByDwarfUnit(DU);
244+
return U.DieInfoVector;
245+
}
236246
std::vector<std::unique_ptr<DIEAbbrev>> &getAbbrevs() {
237247
return Abbreviations;
238248
}
@@ -246,17 +256,16 @@ class DIEBuilder {
246256
}
247257

248258
std::vector<DWARFUnit *> getDWARF4TUVector() { return DWARF4TUVector; }
249-
bool isEmpty() { return !IsBuilt; }
259+
bool isEmpty() { return CloneUnitCtxMap.empty(); }
250260

251-
DIE *getUnitDIEbyUnit(DWARFUnit &DU) {
252-
assert(UnitDIEs.count(&DU) && UnitDIEs[&DU].size() &&
253-
"DU is not constructed in IR");
254-
return UnitDIEs[&DU].front();
261+
DIE *getUnitDIEbyUnit(const DWARFUnit &DU) {
262+
const DWARFUnitInfo &U = getUnitInfoByDwarfUnit(DU);
263+
return U.UnitDie;
255264
}
256265

257266
/// Generate and populate all Abbrevs.
258267
void generateAbbrevs();
259-
void generateUnitAbbrevs(DIE *die);
268+
void generateUnitAbbrevs(DIE *Die);
260269
void assignAbbrev(DIEAbbrev &Abbrev);
261270

262271
/// Finish current DIE construction.

0 commit comments

Comments
 (0)