xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp (revision e0919a4bac2b57a086688ae8ec58058b91f61d86)
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