LLVM 19.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"
13
14using namespace llvm;
15using namespace dwarf_linker;
16using namespace dwarf_linker::parallel;
17
19 CompileUnit *RefCU, uint32_t RefIdx)
21 RefCU(RefCU, (SrcCU != nullptr) &&
22 (SrcCU->getUniqueID() == RefCU->getUniqueID())),
23 RefDieIdxOrClonedOffset(RefIdx) {}
24
26 CompileUnit *SrcCU,
27 CompileUnit *RefCU,
28 uint32_t RefIdx)
30 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
31 RefDieIdxOrClonedOffset(RefIdx) {}
32
34 TypeEntry *RefTypeName)
35 : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}
36
38 DIE *Die,
39 TypeEntry *TypeName,
40 TypeEntry *RefTypeName)
41 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
42 RefTypeName(RefTypeName) {}
43
45 TypeEntry *TypeName, StringEntry *String)
46 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
47 String(String) {}
48
50 TypeEntry *TypeName,
52 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
53 String(String) {}
54
56 StringEntry *Directory,
57 StringEntry *FilePath)
58 : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}
59
61 StartOffset = 0;
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
77
79 if (Contents.empty())
80 return;
81
82 MemoryBufferRef Mem(Contents, "obj");
85 if (!Obj) {
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
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
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
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
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
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.
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(
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();
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 FinalValue +=
466 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
467
468 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
469 });
470}
uint64_t Size
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
A structured debug information entry.
Definition: DIE.h:819
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition: DIE.h:857
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
SectionKind - This is a simple POD value that classifies the properties of a section.
Definition: SectionKind.h:22
bool empty() const
Definition: SmallVector.h:94
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:299
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
Stores all information related to a compile unit, be it in its original instance of the object file o...
StringPool & getStringPool()
Returns global string pool.
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:30
DIE & getFinalDie() const
Returns copy of type DIE which should be emitted into resulting file.
Definition: TypePool.h:33
Type Unit is used to represent an artificial compilation unit which keeps all type information.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:209
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:81
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:150
raw_ostream & write(unsigned char C)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallString< 0 > OutSectionDataTy
Type for section data.
std::optional< DebugSectionKind > parseDebugTableName(StringRef Name)
Recognise the table name and match it with the DebugSectionKind.
uint32_t read32(const void *P, endianness E)
Definition: Endian.h:404
uint64_t read64(const void *P, endianness E)
Definition: Endian.h:407
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:91
uint16_t read16(const void *P, endianness E)
Definition: Endian.h:401
void swapByteOrder(T &Value)
Definition: SwapByteOrder.h:61
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1680
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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:23
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:80
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1041
DwarfStringPoolEntry with string keeping externally.
uint8_t getDwarfOffsetByteSize() const
The size of a reference is determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:770
uint8_t getRefAddrByteSize() const
The definition of the size of form DW_FORM_ref_addr depends on the version.
Definition: Dwarf.h:763
This structure is used to update reference to the DIE.
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)
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.