Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.cpp
35291 views
1
//===- DWARFLinkerUnit.cpp ------------------------------------------------===//
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
#include "DWARFLinkerUnit.h"
10
#include "DWARFEmitterImpl.h"
11
#include "DebugLineSectionEmitter.h"
12
13
using namespace llvm;
14
using namespace dwarf_linker;
15
using namespace dwarf_linker::parallel;
16
17
void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
18
// Check the set for priors.
19
FoldingSetNodeID ID;
20
Abbrev.Profile(ID);
21
void *InsertToken;
22
23
DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
24
// If it's newly added.
25
if (InSet) {
26
// Assign existing abbreviation number.
27
Abbrev.setNumber(InSet->getNumber());
28
} else {
29
// Add to abbreviation list.
30
Abbreviations.push_back(
31
std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
32
for (const auto &Attr : Abbrev.getData())
33
Abbreviations.back()->AddAttribute(Attr);
34
AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
35
// Assign the unique abbreviation number.
36
Abbrev.setNumber(Abbreviations.size());
37
Abbreviations.back()->setNumber(Abbreviations.size());
38
}
39
}
40
41
Error DwarfUnit::emitAbbreviations() {
42
const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();
43
if (Abbrevs.empty())
44
return Error::success();
45
46
SectionDescriptor &AbbrevSection =
47
getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);
48
49
// For each abbreviation.
50
for (const auto &Abbrev : Abbrevs)
51
emitDwarfAbbrevEntry(*Abbrev, AbbrevSection);
52
53
// Mark end of abbreviations.
54
encodeULEB128(0, AbbrevSection.OS);
55
56
return Error::success();
57
}
58
59
void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
60
SectionDescriptor &AbbrevSection) {
61
// Emit the abbreviations code (base 1 index.)
62
encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);
63
64
// Emit the abbreviations data.
65
// Emit its Dwarf tag type.
66
encodeULEB128(Abbrev.getTag(), AbbrevSection.OS);
67
68
// Emit whether it has children DIEs.
69
encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS);
70
71
// For each attribute description.
72
const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();
73
for (const DIEAbbrevData &AttrData : Data) {
74
// Emit attribute type.
75
encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS);
76
77
// Emit form type.
78
encodeULEB128(AttrData.getForm(), AbbrevSection.OS);
79
80
// Emit value for DW_FORM_implicit_const.
81
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
82
encodeSLEB128(AttrData.getValue(), AbbrevSection.OS);
83
}
84
85
// Mark end of abbreviation.
86
encodeULEB128(0, AbbrevSection.OS);
87
encodeULEB128(0, AbbrevSection.OS);
88
}
89
90
Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
91
DIE *OutUnitDIE = getOutUnitDIE();
92
if (OutUnitDIE == nullptr)
93
return Error::success();
94
95
// FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs
96
// directly.
97
98
SectionDescriptor &OutSection =
99
getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
100
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);
101
if (Error Err = Emitter.init(TargetTriple, "__DWARF"))
102
return Err;
103
104
// Emit compile unit header.
105
Emitter.emitCompileUnitHeader(*this);
106
size_t OffsetToAbbreviationTableOffset =
107
(getFormParams().Version >= 5) ? 8 : 6;
108
OutSection.notePatch(DebugOffsetPatch{
109
OffsetToAbbreviationTableOffset,
110
&getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)});
111
112
// Emit DIEs.
113
Emitter.emitDIE(*OutUnitDIE);
114
Emitter.finish();
115
116
// Set start offset ans size for .debug_info section.
117
OutSection.setSizesForSectionCreatedByAsmPrinter();
118
return Error::success();
119
}
120
121
Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,
122
const DWARFDebugLine::LineTable &OutLineTable) {
123
DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
124
125
return DebugLineEmitter.emit(OutLineTable);
126
}
127
128
Error DwarfUnit::emitDebugStringOffsetSection() {
129
if (getVersion() < 5)
130
return Error::success();
131
132
if (DebugStringIndexMap.empty())
133
return Error::success();
134
135
SectionDescriptor &OutDebugStrOffsetsSection =
136
getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);
137
138
// Emit section header.
139
140
// Emit length.
141
OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);
142
uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();
143
144
// Emit version.
145
OutDebugStrOffsetsSection.emitIntVal(5, 2);
146
147
// Emit padding.
148
OutDebugStrOffsetsSection.emitIntVal(0, 2);
149
150
// Emit index to offset map.
151
for (const StringEntry *String : DebugStringIndexMap.getValues()) {
152
// Note patch for string offset value.
153
OutDebugStrOffsetsSection.notePatch(
154
DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});
155
156
// Emit placeholder for offset value.
157
OutDebugStrOffsetsSection.emitOffset(0xBADDEF);
158
}
159
160
// Patch section length.
161
OutDebugStrOffsetsSection.apply(
162
OffsetAfterSectionLength -
163
OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),
164
dwarf::DW_FORM_sec_offset,
165
OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);
166
167
return Error::success();
168
}
169
170
/// Emit the pubnames or pubtypes section contribution for \p
171
/// Unit into \p Sec. The data is provided in \p Info.
172
std::optional<uint64_t>
173
DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
174
const DwarfUnit::AccelInfo &Info,
175
std::optional<uint64_t> LengthOffset) {
176
if (!LengthOffset) {
177
// Emit the header.
178
OutSection.emitIntVal(0xBADDEF,
179
getFormParams().getDwarfOffsetByteSize()); // Length
180
LengthOffset = OutSection.OS.tell();
181
182
OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version
183
184
OutSection.notePatch(DebugOffsetPatch{
185
OutSection.OS.tell(),
186
&getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)});
187
OutSection.emitOffset(0xBADDEF); // Unit offset
188
189
OutSection.emitIntVal(getUnitSize(), 4); // Size
190
}
191
OutSection.emitOffset(Info.OutOffset);
192
193
// Emit the string itself.
194
OutSection.emitInplaceString(Info.String->first());
195
196
return LengthOffset;
197
}
198
199
/// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
200
void DwarfUnit::emitPubAccelerators() {
201
std::optional<uint64_t> NamesLengthOffset;
202
std::optional<uint64_t> TypesLengthOffset;
203
204
forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
205
if (Info.AvoidForPubSections)
206
return;
207
208
switch (Info.Type) {
209
case DwarfUnit::AccelType::Name: {
210
NamesLengthOffset = emitPubAcceleratorEntry(
211
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info,
212
NamesLengthOffset);
213
} break;
214
case DwarfUnit::AccelType::Type: {
215
TypesLengthOffset = emitPubAcceleratorEntry(
216
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info,
217
TypesLengthOffset);
218
} break;
219
default: {
220
// Nothing to do.
221
} break;
222
}
223
});
224
225
if (NamesLengthOffset) {
226
SectionDescriptor &OutSection =
227
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);
228
OutSection.emitIntVal(0, 4); // End marker.
229
230
OutSection.apply(*NamesLengthOffset -
231
OutSection.getFormParams().getDwarfOffsetByteSize(),
232
dwarf::DW_FORM_sec_offset,
233
OutSection.OS.tell() - *NamesLengthOffset);
234
}
235
236
if (TypesLengthOffset) {
237
SectionDescriptor &OutSection =
238
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);
239
OutSection.emitIntVal(0, 4); // End marker.
240
241
OutSection.apply(*TypesLengthOffset -
242
OutSection.getFormParams().getDwarfOffsetByteSize(),
243
dwarf::DW_FORM_sec_offset,
244
OutSection.OS.tell() - *TypesLengthOffset);
245
}
246
}
247
248