xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
13 using namespace llvm;
14 using namespace dwarf_linker;
15 using namespace dwarf_linker::parallel;
16 
17 DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
18                                    CompileUnit *RefCU, uint32_t RefIdx)
19     : SectionPatch({PatchOffset}),
20       RefCU(RefCU, (SrcCU != nullptr) &&
21                        (SrcCU->getUniqueID() == RefCU->getUniqueID())),
22       RefDieIdxOrClonedOffset(RefIdx) {}
23 
24 DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,
25                                                  CompileUnit *SrcCU,
26                                                  CompileUnit *RefCU,
27                                                  uint32_t RefIdx)
28     : SectionPatch({PatchOffset}),
29       RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
30       RefDieIdxOrClonedOffset(RefIdx) {}
31 
32 DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,
33                                            TypeEntry *RefTypeName)
34     : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}
35 
36 DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset,
37                                                      DIE *Die,
38                                                      TypeEntry *TypeName,
39                                                      TypeEntry *RefTypeName)
40     : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
41       RefTypeName(RefTypeName) {}
42 
43 DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,
44                                      TypeEntry *TypeName, StringEntry *String)
45     : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
46       String(String) {}
47 
48 DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die,
49                                              TypeEntry *TypeName,
50                                              StringEntry *String)
51     : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
52       String(String) {}
53 
54 DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,
55                                                StringEntry *Directory,
56                                                StringEntry *FilePath)
57     : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}
58 
59 void 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 
75 void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }
76 
77 void 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(Mem);
84   if (!Obj) {
85     consumeError(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(SectNameOrErr.takeError());
94       continue;
95     }
96     if (std::optional<DebugSectionKind> SectKind =
97             parseDebugTableName(*SectNameOrErr)) {
98       if (*SectKind == SectionKind) {
99         Expected<StringRef> Data = Sect.getContents();
100         if (!Data) {
101           consumeError(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 
115 void 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(StringVal);
122   } break;
123   case dwarf::DW_FORM_strp: {
124     notePatch(DebugStrPatch{
125         {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
126     emitStringPlaceholder();
127   } break;
128   case dwarf::DW_FORM_line_strp: {
129     notePatch(DebugLineStrPatch{
130         {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
131     emitStringPlaceholder();
132   } break;
133   default:
134     llvm_unreachable("Unsupported string form");
135     break;
136   };
137 }
138 
139 void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
140   switch (Size) {
141   case 1: {
142     OS.write(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(ShortVal);
148     OS.write(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(ShortVal);
154     OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
155   } break;
156   case 8: {
157     if (Endianess != llvm::endianness::native)
158       sys::swapByteOrder(Val);
159     OS.write(reinterpret_cast<const char *>(&Val), Size);
160   } break;
161   default:
162     llvm_unreachable("Unsupported integer type size");
163   }
164 }
165 
166 void SectionDescriptor::emitBinaryData(llvm::StringRef Data) {
167   OS.write(Data.data(), Data.size());
168 }
169 
170 void 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, Format.getDwarfOffsetByteSize());
176   } break;
177 
178   case dwarf::DW_FORM_ref_addr: {
179     applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());
180   } break;
181   case dwarf::DW_FORM_ref1: {
182     applyIntVal(PatchOffset, Val, 1);
183   } break;
184   case dwarf::DW_FORM_ref2: {
185     applyIntVal(PatchOffset, Val, 2);
186   } break;
187   case dwarf::DW_FORM_ref4: {
188     applyIntVal(PatchOffset, Val, 4);
189   } break;
190   case dwarf::DW_FORM_ref8: {
191     applyIntVal(PatchOffset, Val, 8);
192   } break;
193 
194   case dwarf::DW_FORM_data1: {
195     applyIntVal(PatchOffset, Val, 1);
196   } break;
197   case dwarf::DW_FORM_data2: {
198     applyIntVal(PatchOffset, Val, 2);
199   } break;
200   case dwarf::DW_FORM_data4: {
201     applyIntVal(PatchOffset, Val, 4);
202   } break;
203   case dwarf::DW_FORM_data8: {
204     applyIntVal(PatchOffset, Val, 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, Format.getDwarfOffsetByteSize());
214   } break;
215   case dwarf::DW_FORM_flag: {
216     applyIntVal(PatchOffset, Val, 1);
217   } break;
218 
219   default:
220     llvm_unreachable("Unsupported attribute form");
221     break;
222   }
223 }
224 
225 uint64_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(getContents().data() + PatchOffset,
234                                    Endianess);
235   }
236   case 4: {
237     return support::endian::read32(getContents().data() + PatchOffset,
238                                    Endianess);
239   }
240   case 8: {
241     return support::endian::read64(getContents().data() + PatchOffset,
242                                    Endianess);
243   }
244   }
245   llvm_unreachable("Unsupported integer type size");
246   return 0;
247 }
248 
249 void 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         const_cast<char *>(getContents().data() + PatchOffset),
257         static_cast<uint8_t>(Val), Endianess);
258   } break;
259   case 2: {
260     support::endian::write(
261         const_cast<char *>(getContents().data() + PatchOffset),
262         static_cast<uint16_t>(Val), Endianess);
263   } break;
264   case 4: {
265     support::endian::write(
266         const_cast<char *>(getContents().data() + PatchOffset),
267         static_cast<uint32_t>(Val), Endianess);
268   } break;
269   case 8: {
270     support::endian::write(
271         const_cast<char *>(getContents().data() + PatchOffset),
272         static_cast<uint64_t>(Val), Endianess);
273   } break;
274   default:
275     llvm_unreachable("Unsupported integer type size");
276   }
277 }
278 
279 void 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(Val, ULEB, DestSize);
285 
286   memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
287          RealSize);
288 }
289 
290 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
291 void 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(Val, SLEB, DestSize);
297 
298   memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
299          RealSize);
300 }
301 
302 void OutputSections::applyPatches(
303     SectionDescriptor &Section,
304     StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
305     StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
306     TypeUnit *TypeUnitPtr) {
307   Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
308     DwarfStringPoolEntryWithExtString *Entry =
309         DebugStrStrings.getExistingEntry(Patch.String);
310     assert(Entry != nullptr);
311 
312     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
313   });
314   Section.ListDebugTypeStrPatch.forEach([&](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(Patch.String);
327     assert(Entry != nullptr);
328 
329     Patch.PatchOffset +=
330         Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
331 
332     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
333   });
334 
335   Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
336     DwarfStringPoolEntryWithExtString *Entry =
337         DebugLineStrStrings.getExistingEntry(Patch.String);
338     assert(Entry != nullptr);
339 
340     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
341   });
342   Section.ListDebugTypeLineStrPatch.forEach([&](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(Patch.String);
355     assert(Entry != nullptr);
356 
357     Patch.PatchOffset +=
358         Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
359 
360     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
361   });
362 
363   std::optional<SectionDescriptor *> RangeSection;
364   if (Format.Version >= 5)
365     RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRngLists);
366   else
367     RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRange);
368 
369   if (RangeSection) {
370     Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
371       uint64_t FinalValue =
372           Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
373       FinalValue += (*RangeSection)->StartOffset;
374 
375       Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
376     });
377   }
378 
379   std::optional<SectionDescriptor *> LocationSection;
380   if (Format.Version >= 5)
381     LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLocLists);
382   else
383     LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLoc);
384 
385   if (LocationSection) {
386     Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
387       uint64_t FinalValue =
388           Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
389       FinalValue += (*LocationSection)->StartOffset;
390 
391       Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
392     });
393   }
394 
395   Section.ListDebugDieRefPatch.forEach([&](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               DebugSectionKind::DebugInfo);
404 
405       FinalForm = dwarf::DW_FORM_ref_addr;
406       FinalOffset += ReferencedSectionDescriptor.StartOffset;
407     }
408 
409     Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);
410   });
411 
412   Section.ListDebugULEB128DieRefPatch.forEach(
413       [&](DebugULEB128DieRefPatch &Patch) {
414         assert(Patch.RefCU.getInt());
415         Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,
416                       Patch.RefDieIdxOrClonedOffset);
417       });
418 
419   Section.ListDebugDieTypeRefPatch.forEach([&](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(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,
430                   TypeEntry->getFinalDie().getOffset());
431   });
432 
433   Section.ListDebugType2TypeDieRefPatch.forEach(
434       [&](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(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(Patch.PatchOffset, dwarf::DW_FORM_ref4,
456                       RefTypeEntry->getFinalDie().getOffset());
457       });
458 
459   Section.ListDebugOffsetPatch.forEach([&](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(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
466 
467     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
468   });
469 }
470