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