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/OutputSections.cpp
35291 views
1
//=== OutputSections.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 "OutputSections.h"
10
#include "DWARFLinkerCompileUnit.h"
11
#include "DWARFLinkerTypeUnit.h"
12
#include "llvm/ADT/StringSwitch.h"
13
14
using namespace llvm;
15
using namespace dwarf_linker;
16
using namespace dwarf_linker::parallel;
17
18
DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
19
CompileUnit *RefCU, uint32_t RefIdx)
20
: SectionPatch({PatchOffset}),
21
RefCU(RefCU, (SrcCU != nullptr) &&
22
(SrcCU->getUniqueID() == RefCU->getUniqueID())),
23
RefDieIdxOrClonedOffset(RefIdx) {}
24
25
DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,
26
CompileUnit *SrcCU,
27
CompileUnit *RefCU,
28
uint32_t RefIdx)
29
: SectionPatch({PatchOffset}),
30
RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
31
RefDieIdxOrClonedOffset(RefIdx) {}
32
33
DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,
34
TypeEntry *RefTypeName)
35
: SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}
36
37
DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset,
38
DIE *Die,
39
TypeEntry *TypeName,
40
TypeEntry *RefTypeName)
41
: SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
42
RefTypeName(RefTypeName) {}
43
44
DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,
45
TypeEntry *TypeName, StringEntry *String)
46
: SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
47
String(String) {}
48
49
DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die,
50
TypeEntry *TypeName,
51
StringEntry *String)
52
: SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
53
String(String) {}
54
55
DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,
56
StringEntry *Directory,
57
StringEntry *FilePath)
58
: Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}
59
60
void SectionDescriptor::clearAllSectionData() {
61
StartOffset = 0;
62
clearSectionContent();
63
ListDebugStrPatch.erase();
64
ListDebugLineStrPatch.erase();
65
ListDebugRangePatch.erase();
66
ListDebugLocPatch.erase();
67
ListDebugDieRefPatch.erase();
68
ListDebugULEB128DieRefPatch.erase();
69
ListDebugOffsetPatch.erase();
70
ListDebugType2TypeDieRefPatch.erase();
71
ListDebugTypeDeclFilePatch.erase();
72
ListDebugTypeLineStrPatch.erase();
73
ListDebugTypeStrPatch.erase();
74
}
75
76
void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }
77
78
void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
79
if (Contents.empty())
80
return;
81
82
MemoryBufferRef Mem(Contents, "obj");
83
Expected<std::unique_ptr<object::ObjectFile>> Obj =
84
object::ObjectFile::createObjectFile(Mem);
85
if (!Obj) {
86
consumeError(Obj.takeError());
87
Contents.clear();
88
return;
89
}
90
91
for (const object::SectionRef &Sect : (*Obj).get()->sections()) {
92
Expected<StringRef> SectNameOrErr = Sect.getName();
93
if (!SectNameOrErr) {
94
consumeError(SectNameOrErr.takeError());
95
continue;
96
}
97
if (std::optional<DebugSectionKind> SectKind =
98
parseDebugTableName(*SectNameOrErr)) {
99
if (*SectKind == SectionKind) {
100
Expected<StringRef> Data = Sect.getContents();
101
if (!Data) {
102
consumeError(SectNameOrErr.takeError());
103
Contents.clear();
104
return;
105
}
106
107
SectionOffsetInsideAsmPrinterOutputStart =
108
Data->data() - Contents.data();
109
SectionOffsetInsideAsmPrinterOutputEnd =
110
SectionOffsetInsideAsmPrinterOutputStart + Data->size();
111
}
112
}
113
}
114
}
115
116
void SectionDescriptor::emitString(dwarf::Form StringForm,
117
const char *StringVal) {
118
assert(StringVal != nullptr);
119
120
switch (StringForm) {
121
case dwarf::DW_FORM_string: {
122
emitInplaceString(StringVal);
123
} break;
124
case dwarf::DW_FORM_strp: {
125
notePatch(DebugStrPatch{
126
{OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
127
emitStringPlaceholder();
128
} break;
129
case dwarf::DW_FORM_line_strp: {
130
notePatch(DebugLineStrPatch{
131
{OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
132
emitStringPlaceholder();
133
} break;
134
default:
135
llvm_unreachable("Unsupported string form");
136
break;
137
};
138
}
139
140
void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
141
switch (Size) {
142
case 1: {
143
OS.write(static_cast<uint8_t>(Val));
144
} break;
145
case 2: {
146
uint16_t ShortVal = static_cast<uint16_t>(Val);
147
if (Endianess != llvm::endianness::native)
148
sys::swapByteOrder(ShortVal);
149
OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
150
} break;
151
case 4: {
152
uint32_t ShortVal = static_cast<uint32_t>(Val);
153
if (Endianess != llvm::endianness::native)
154
sys::swapByteOrder(ShortVal);
155
OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
156
} break;
157
case 8: {
158
if (Endianess != llvm::endianness::native)
159
sys::swapByteOrder(Val);
160
OS.write(reinterpret_cast<const char *>(&Val), Size);
161
} break;
162
default:
163
llvm_unreachable("Unsupported integer type size");
164
}
165
}
166
167
void SectionDescriptor::emitBinaryData(llvm::StringRef Data) {
168
OS.write(Data.data(), Data.size());
169
}
170
171
void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,
172
uint64_t Val) {
173
switch (AttrForm) {
174
case dwarf::DW_FORM_strp:
175
case dwarf::DW_FORM_line_strp: {
176
applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
177
} break;
178
179
case dwarf::DW_FORM_ref_addr: {
180
applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());
181
} break;
182
case dwarf::DW_FORM_ref1: {
183
applyIntVal(PatchOffset, Val, 1);
184
} break;
185
case dwarf::DW_FORM_ref2: {
186
applyIntVal(PatchOffset, Val, 2);
187
} break;
188
case dwarf::DW_FORM_ref4: {
189
applyIntVal(PatchOffset, Val, 4);
190
} break;
191
case dwarf::DW_FORM_ref8: {
192
applyIntVal(PatchOffset, Val, 8);
193
} break;
194
195
case dwarf::DW_FORM_data1: {
196
applyIntVal(PatchOffset, Val, 1);
197
} break;
198
case dwarf::DW_FORM_data2: {
199
applyIntVal(PatchOffset, Val, 2);
200
} break;
201
case dwarf::DW_FORM_data4: {
202
applyIntVal(PatchOffset, Val, 4);
203
} break;
204
case dwarf::DW_FORM_data8: {
205
applyIntVal(PatchOffset, Val, 8);
206
} break;
207
case dwarf::DW_FORM_udata: {
208
applyULEB128(PatchOffset, Val);
209
} break;
210
case dwarf::DW_FORM_sdata: {
211
applySLEB128(PatchOffset, Val);
212
} break;
213
case dwarf::DW_FORM_sec_offset: {
214
applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
215
} break;
216
case dwarf::DW_FORM_flag: {
217
applyIntVal(PatchOffset, Val, 1);
218
} break;
219
220
default:
221
llvm_unreachable("Unsupported attribute form");
222
break;
223
}
224
}
225
226
uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {
227
assert(PatchOffset < getContents().size());
228
switch (Size) {
229
case 1: {
230
return *reinterpret_cast<const uint8_t *>(
231
(getContents().data() + PatchOffset));
232
}
233
case 2: {
234
return support::endian::read16(getContents().data() + PatchOffset,
235
Endianess);
236
}
237
case 4: {
238
return support::endian::read32(getContents().data() + PatchOffset,
239
Endianess);
240
}
241
case 8: {
242
return support::endian::read64(getContents().data() + PatchOffset,
243
Endianess);
244
}
245
}
246
llvm_unreachable("Unsupported integer type size");
247
return 0;
248
}
249
250
void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
251
unsigned Size) {
252
assert(PatchOffset < getContents().size());
253
254
switch (Size) {
255
case 1: {
256
support::endian::write(
257
const_cast<char *>(getContents().data() + PatchOffset),
258
static_cast<uint8_t>(Val), Endianess);
259
} break;
260
case 2: {
261
support::endian::write(
262
const_cast<char *>(getContents().data() + PatchOffset),
263
static_cast<uint16_t>(Val), Endianess);
264
} break;
265
case 4: {
266
support::endian::write(
267
const_cast<char *>(getContents().data() + PatchOffset),
268
static_cast<uint32_t>(Val), Endianess);
269
} break;
270
case 8: {
271
support::endian::write(
272
const_cast<char *>(getContents().data() + PatchOffset),
273
static_cast<uint64_t>(Val), Endianess);
274
} break;
275
default:
276
llvm_unreachable("Unsupported integer type size");
277
}
278
}
279
280
void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {
281
assert(PatchOffset < getContents().size());
282
283
uint8_t ULEB[16];
284
uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
285
uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);
286
287
memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
288
RealSize);
289
}
290
291
/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
292
void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {
293
assert(PatchOffset < getContents().size());
294
295
uint8_t SLEB[16];
296
uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
297
uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);
298
299
memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
300
RealSize);
301
}
302
303
void OutputSections::applyPatches(
304
SectionDescriptor &Section,
305
StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
306
StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
307
TypeUnit *TypeUnitPtr) {
308
Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
309
DwarfStringPoolEntryWithExtString *Entry =
310
DebugStrStrings.getExistingEntry(Patch.String);
311
assert(Entry != nullptr);
312
313
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
314
});
315
Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
316
assert(TypeUnitPtr != nullptr);
317
TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
318
assert(TypeEntry &&
319
formatv("No data for type {0}", Patch.TypeName->getKey())
320
.str()
321
.c_str());
322
323
if (&TypeEntry->getFinalDie() != Patch.Die)
324
return;
325
326
DwarfStringPoolEntryWithExtString *Entry =
327
DebugStrStrings.getExistingEntry(Patch.String);
328
assert(Entry != nullptr);
329
330
Patch.PatchOffset +=
331
Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
332
333
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
334
});
335
336
Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
337
DwarfStringPoolEntryWithExtString *Entry =
338
DebugLineStrStrings.getExistingEntry(Patch.String);
339
assert(Entry != nullptr);
340
341
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
342
});
343
Section.ListDebugTypeLineStrPatch.forEach([&](DebugTypeLineStrPatch &Patch) {
344
assert(TypeUnitPtr != nullptr);
345
TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
346
assert(TypeEntry &&
347
formatv("No data for type {0}", Patch.TypeName->getKey())
348
.str()
349
.c_str());
350
351
if (&TypeEntry->getFinalDie() != Patch.Die)
352
return;
353
354
DwarfStringPoolEntryWithExtString *Entry =
355
DebugLineStrStrings.getExistingEntry(Patch.String);
356
assert(Entry != nullptr);
357
358
Patch.PatchOffset +=
359
Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
360
361
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
362
});
363
364
std::optional<SectionDescriptor *> RangeSection;
365
if (Format.Version >= 5)
366
RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRngLists);
367
else
368
RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRange);
369
370
if (RangeSection) {
371
Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
372
uint64_t FinalValue =
373
Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
374
FinalValue += (*RangeSection)->StartOffset;
375
376
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
377
});
378
}
379
380
std::optional<SectionDescriptor *> LocationSection;
381
if (Format.Version >= 5)
382
LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLocLists);
383
else
384
LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLoc);
385
386
if (LocationSection) {
387
Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
388
uint64_t FinalValue =
389
Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
390
FinalValue += (*LocationSection)->StartOffset;
391
392
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
393
});
394
}
395
396
Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
397
uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;
398
dwarf::Form FinalForm = dwarf::DW_FORM_ref4;
399
400
// Check whether it is local or inter-CU reference.
401
if (!Patch.RefCU.getInt()) {
402
SectionDescriptor &ReferencedSectionDescriptor =
403
Patch.RefCU.getPointer()->getSectionDescriptor(
404
DebugSectionKind::DebugInfo);
405
406
FinalForm = dwarf::DW_FORM_ref_addr;
407
FinalOffset += ReferencedSectionDescriptor.StartOffset;
408
}
409
410
Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);
411
});
412
413
Section.ListDebugULEB128DieRefPatch.forEach(
414
[&](DebugULEB128DieRefPatch &Patch) {
415
assert(Patch.RefCU.getInt());
416
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,
417
Patch.RefDieIdxOrClonedOffset);
418
});
419
420
Section.ListDebugDieTypeRefPatch.forEach([&](DebugDieTypeRefPatch &Patch) {
421
assert(TypeUnitPtr != nullptr);
422
assert(Patch.RefTypeName != nullptr);
423
424
TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load();
425
assert(TypeEntry &&
426
formatv("No data for type {0}", Patch.RefTypeName->getKey())
427
.str()
428
.c_str());
429
430
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,
431
TypeEntry->getFinalDie().getOffset());
432
});
433
434
Section.ListDebugType2TypeDieRefPatch.forEach(
435
[&](DebugType2TypeDieRefPatch &Patch) {
436
assert(TypeUnitPtr != nullptr);
437
TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
438
assert(TypeEntry &&
439
formatv("No data for type {0}", Patch.TypeName->getKey())
440
.str()
441
.c_str());
442
443
if (&TypeEntry->getFinalDie() != Patch.Die)
444
return;
445
446
Patch.PatchOffset += Patch.Die->getOffset() +
447
getULEB128Size(Patch.Die->getAbbrevNumber());
448
449
assert(Patch.RefTypeName != nullptr);
450
TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();
451
assert(TypeEntry &&
452
formatv("No data for type {0}", Patch.RefTypeName->getKey())
453
.str()
454
.c_str());
455
456
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,
457
RefTypeEntry->getFinalDie().getOffset());
458
});
459
460
Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {
461
uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;
462
463
// Check whether we need to read value from the original location.
464
if (Patch.SectionPtr.getInt())
465
FinalValue +=
466
Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
467
468
Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
469
});
470
}
471
472