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