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
DebugDieRefPatch(uint64_t PatchOffset,CompileUnit * SrcCU,CompileUnit * RefCU,uint32_t RefIdx)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
DebugULEB128DieRefPatch(uint64_t PatchOffset,CompileUnit * SrcCU,CompileUnit * RefCU,uint32_t RefIdx)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
DebugDieTypeRefPatch(uint64_t PatchOffset,TypeEntry * RefTypeName)33 DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,
34 TypeEntry *RefTypeName)
35 : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}
36
DebugType2TypeDieRefPatch(uint64_t PatchOffset,DIE * Die,TypeEntry * TypeName,TypeEntry * RefTypeName)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
DebugTypeStrPatch(uint64_t PatchOffset,DIE * Die,TypeEntry * TypeName,StringEntry * String)44 DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,
45 TypeEntry *TypeName, StringEntry *String)
46 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
47 String(String) {}
48
DebugTypeLineStrPatch(uint64_t PatchOffset,DIE * Die,TypeEntry * TypeName,StringEntry * String)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
DebugTypeDeclFilePatch(DIE * Die,TypeEntry * TypeName,StringEntry * Directory,StringEntry * FilePath)55 DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,
56 StringEntry *Directory,
57 StringEntry *FilePath)
58 : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}
59
clearAllSectionData()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
clearSectionContent()76 void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }
77
setSizesForSectionCreatedByAsmPrinter()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
emitString(dwarf::Form StringForm,const char * StringVal)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
emitIntVal(uint64_t Val,unsigned Size)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
emitBinaryData(llvm::StringRef Data)167 void SectionDescriptor::emitBinaryData(llvm::StringRef Data) {
168 OS.write(Data.data(), Data.size());
169 }
170
apply(uint64_t PatchOffset,dwarf::Form AttrForm,uint64_t Val)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
getIntVal(uint64_t PatchOffset,unsigned Size)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
applyIntVal(uint64_t PatchOffset,uint64_t Val,unsigned Size)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
applyULEB128(uint64_t PatchOffset,uint64_t Val)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.
applySLEB128(uint64_t PatchOffset,uint64_t Val)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
applyPatches(SectionDescriptor & Section,StringEntryToDwarfStringPoolEntryMap & DebugStrStrings,StringEntryToDwarfStringPoolEntryMap & DebugLineStrStrings,TypeUnit * TypeUnitPtr)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