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