LLVM 22.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,
26 CompileUnit *RefCU,
27 uint32_t RefIdx)
29 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
30 RefDieIdxOrClonedOffset(RefIdx) {}
31
33 TypeEntry *RefTypeName)
34 : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}
35
37 DIE *Die,
38 TypeEntry *TypeName,
39 TypeEntry *RefTypeName)
40 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
41 RefTypeName(RefTypeName) {}
42
44 TypeEntry *TypeName, StringEntry *String)
45 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
46 String(String) {}
47
49 TypeEntry *TypeName,
51 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
52 String(String) {}
53
55 StringEntry *Directory,
56 StringEntry *FilePath)
57 : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}
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 ListDebugType2TypeDieRefPatch.erase();
70 ListDebugTypeDeclFilePatch.erase();
71 ListDebugTypeLineStrPatch.erase();
72 ListDebugTypeStrPatch.erase();
73}
74
76
78 if (Contents.empty())
79 return;
80
81 MemoryBufferRef Mem(Contents, "obj");
84 if (!Obj) {
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
107 Data->data() - Contents.data();
110 }
111 }
112 }
113}
114
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});
127 } break;
128 case dwarf::DW_FORM_line_strp: {
129 notePatch(DebugLineStrPatch{
130 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
132 } break;
133 default:
134 llvm_unreachable("Unsupported string form");
135 break;
136 };
137}
138
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);
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);
153 sys::swapByteOrder(ShortVal);
154 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
155 } break;
156 case 8: {
159 OS.write(reinterpret_cast<const char *>(&Val), Size);
160 } break;
161 default:
162 llvm_unreachable("Unsupported integer type size");
163 }
164}
165
167 OS.write(Data.data(), Data.size());
168}
169
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
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
250 unsigned Size) {
251 assert(PatchOffset < getContents().size());
252
253 switch (Size) {
254 case 1: {
256 const_cast<char *>(getContents().data() + PatchOffset),
257 static_cast<uint8_t>(Val), Endianess);
258 } break;
259 case 2: {
261 const_cast<char *>(getContents().data() + PatchOffset),
262 static_cast<uint16_t>(Val), Endianess);
263 } break;
264 case 4: {
266 const_cast<char *>(getContents().data() + PatchOffset),
267 static_cast<uint32_t>(Val), Endianess);
268 } break;
269 case 8: {
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
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.
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
303 SectionDescriptor &Section,
305 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
306 TypeUnit *TypeUnitPtr) {
307 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
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();
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
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) {
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();
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
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)
366 else
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)
382 else
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();
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();
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();
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}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Size
static Split data
A structured debug information entry.
Definition: DIE.h:828
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition: DIE.h:866
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
SectionKind - This is a simple POD value that classifies the properties of a section.
Definition: SectionKind.h:22
bool empty() const
Definition: SmallVector.h:82
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:287
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:55
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:148
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:211
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:83
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:148
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.
LLVM_ABI 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:409
uint64_t read64(const void *P, endianness E)
Definition: Endian.h:412
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:92
uint16_t read16(const void *P, endianness E)
Definition: Endian.h:406
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:1702
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:81
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1083
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:1111
uint8_t getRefAddrByteSize() const
The definition of the size of form DW_FORM_ref_addr depends on the version.
Definition: Dwarf.h:1104
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.