LLVM 24.0.0git
OutputSections.cpp
Go to the documentation of this file.
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"
11#include "DWARFLinkerTypeUnit.h"
12
13using namespace llvm;
14using namespace dwarf_linker;
15using namespace dwarf_linker::parallel;
16
18 CompileUnit *RefCU, uint32_t RefIdx)
20 RefCU(RefCU, (SrcCU != nullptr) &&
21 (SrcCU->getUniqueID() == RefCU->getUniqueID())),
22 RefDieIdxOrClonedOffset(RefIdx) {}
23
25 CompileUnit *SrcCU,
27 uint32_t RefIdx)
29 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
30 RefDieIdxOrClonedOffset(RefIdx) {}
31
35
37 DIE *Die,
40 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
41 RefTypeName(RefTypeName) {}
42
47
53
58
60 StartOffset = 0;
62 ListDebugStrPatch.erase();
63 ListDebugLineStrPatch.erase();
64 ListDebugRangePatch.erase();
65 ListDebugLocPatch.erase();
66 ListDebugDieRefPatch.erase();
67 ListDebugULEB128DieRefPatch.erase();
68 ListDebugOffsetPatch.erase();
69 ListDebugDieTypeRefPatch.erase();
70 ListDebugType2TypeDieRefPatch.erase();
71 ListDebugTypeDeclFilePatch.erase();
72 ListDebugTypeLineStrPatch.erase();
73 ListDebugTypeStrPatch.erase();
74}
75
77
79 if (Contents.empty())
80 return;
81
82 MemoryBufferRef Mem(Contents, "obj");
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
108 Data->data() - Contents.data();
111 }
112 }
113 }
114}
115
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});
128 } break;
129 case dwarf::DW_FORM_line_strp: {
130 notePatch(DebugLineStrPatch{
131 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
133 } break;
134 default:
135 llvm_unreachable("Unsupported string form");
136 break;
137 };
138}
139
140void 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);
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);
154 sys::swapByteOrder(ShortVal);
155 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
156 } break;
157 case 8: {
160 OS.write(reinterpret_cast<const char *>(&Val), Size);
161 } break;
162 default:
163 llvm_unreachable("Unsupported integer type size");
164 }
165}
166
168 OS.write(Data.data(), Data.size());
169}
170
171void 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
226uint64_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
250void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
251 unsigned Size) {
252 assert(PatchOffset < getContents().size());
253
254 switch (Size) {
255 case 1: {
257 const_cast<char *>(getContents().data() + PatchOffset),
258 static_cast<uint8_t>(Val), Endianess);
259 } break;
260 case 2: {
262 const_cast<char *>(getContents().data() + PatchOffset),
263 static_cast<uint16_t>(Val), Endianess);
264 } break;
265 case 4: {
267 const_cast<char *>(getContents().data() + PatchOffset),
268 static_cast<uint32_t>(Val), Endianess);
269 } break;
270 case 8: {
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
280void 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.
292void 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
304 SectionDescriptor &Section,
306 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
307 TypeUnit *TypeUnitPtr) {
308 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
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();
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
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) {
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();
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
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)
367 else
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)
383 else
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(
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();
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();
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();
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 uint64_t LocalValue =
466 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
467 // DebugOffsetPatch treats the DWARF "invalid offset" sentinel
468 // (0xffffffff for DWARF32) as pass-through: callers that can't
469 // resolve the target write that value and expect it to survive
470 // section combination unchanged. Adding StartOffset would turn it
471 // into a plausible-looking but meaningless offset. Callers that
472 // genuinely want `StartOffset + MaxOffset` don't exist today and
473 // would need a different patch type.
474 if (LocalValue == Format.getDwarfMaxOffset())
475 FinalValue = LocalValue;
476 else
477 FinalValue += LocalValue;
478 }
479
480 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
481 });
482}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Split data
A structured debug information entry.
Definition DIE.h:840
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:878
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
Stores all information related to a compile unit, be it in its original instance of the object file o...
void applyPatches(SectionDescriptor &Section, StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, TypeUnit *TypeUnitPtr)
Enumerate all sections, for each section apply all section patches.
dwarf::FormParams Format
Format for sections.
std::optional< const SectionDescriptor * > tryGetSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
This class creates a DwarfStringPoolEntry for the corresponding StringEntry.
DwarfStringPoolEntryWithExtString * getExistingEntry(const StringEntry *String) const
Returns already existed DwarfStringPoolEntry for the specified StringEntry.
Keeps cloned data for the type DIE.
Definition TypePool.h:31
DIE & getFinalDie() const
Returns copy of type DIE which should be emitted into resulting file.
Definition TypePool.h:34
Type Unit is used to represent an artificial compilation unit which keeps all type information.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
This is a value type class that represents a single section in the list of sections in the object fil...
Definition ObjectFile.h:83
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallString< 0 > OutSectionDataTy
Type for section data.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:28
LLVM_ABI std::optional< DebugSectionKind > parseDebugTableName(StringRef Name)
Recognise the table name and match it with the DebugSectionKind.
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
Definition StringPool.h:23
uint32_t read32(const void *P, endianness E)
Definition Endian.h:392
uint64_t read64(const void *P, endianness E)
Definition Endian.h:395
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:82
uint16_t read16(const void *P, endianness E)
Definition Endian.h:389
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition LEB128.cpp:19
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
Definition LEB128.h:24
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition LEB128.h:79
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
DwarfStringPoolEntry with string keeping externally.
This structure is used to update reference to the DIE.
PointerIntPair< CompileUnit *, 1 > RefCU
DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, uint32_t RefIdx)
This structure is used to update reference to the type DIE.
DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName)
This structure is used to update strings offsets into .debug_line_str.
This structure is used to update location list offset into .debug_loc/.debug_loclists.
This structure is used to update range list offset into .debug_ranges/.debug_rnglists.
This structure is used to update strings offsets into .debug_str.
This structure is used to update reference to the type DIE.
DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, TypeEntry *RefTypeName)
DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory, StringEntry *FilePath)
DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, StringEntry *String)
DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, StringEntry *String)
This structure is used to update reference to the DIE of ULEB128 form.
DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, uint32_t RefIdx)
DebugSectionKind SectionKind
The section kind.
This structure is used to keep data of the concrete section.
raw_svector_ostream OS
Stream which stores data to the Contents.
void setSizesForSectionCreatedByAsmPrinter()
Some sections are emitted using AsmPrinter.
OutSectionDataTy Contents
Section data bits.
void emitString(dwarf::Form StringForm, const char *StringVal)
void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size)
Writes integer value Val of Size by specified PatchOffset.
void emitIntVal(uint64_t Val, unsigned Size)
Emit specified integer value into the current section contents.
void applySLEB128(uint64_t PatchOffset, uint64_t Val)
Writes integer value Val of SLEB128 format by specified PatchOffset.
void applyULEB128(uint64_t PatchOffset, uint64_t Val)
Writes integer value Val of ULEB128 format by specified PatchOffset.
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)
Write specified Value of AttrForm to the PatchOffset.
void emitInplaceString(StringRef String)
Emit specified inplace string value into the current section contents.
uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)
Returns integer value of Size located by specified PatchOffset.
void clearSectionContent()
Erase only section output data bits.
StringRef getContents() override
Returns section content.
size_t SectionOffsetInsideAsmPrinterOutputStart
Some sections are generated using AsmPrinter.
void clearAllSectionData()
Erase whole section content(data bits, list of patches).
void emitStringPlaceholder()
Emit string placeholder into the current section contents.
There are fields(sizes, offsets) which should be updated after sections are generated.