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 ListDebugDieModuleRefPatch.erase();
71 ListDebugType2TypeDieRefPatch.erase();
72 ListDebugTypeDeclFilePatch.erase();
73 ListDebugTypeLineStrPatch.erase();
74 ListDebugTypeStrPatch.erase();
75}
76
78
80 if (Contents.empty())
81 return;
82
83 MemoryBufferRef Mem(Contents, "obj");
86 if (!Obj) {
87 consumeError(Obj.takeError());
88 Contents.clear();
89 return;
90 }
91
92 for (const object::SectionRef &Sect : (*Obj).get()->sections()) {
93 Expected<StringRef> SectNameOrErr = Sect.getName();
94 if (!SectNameOrErr) {
95 consumeError(SectNameOrErr.takeError());
96 continue;
97 }
98 if (std::optional<DebugSectionKind> SectKind =
99 parseDebugTableName(*SectNameOrErr)) {
100 if (*SectKind == SectionKind) {
101 Expected<StringRef> Data = Sect.getContents();
102 if (!Data) {
103 consumeError(SectNameOrErr.takeError());
104 Contents.clear();
105 return;
106 }
107
109 Data->data() - Contents.data();
112 }
113 }
114 }
115}
116
118 const char *StringVal) {
119 assert(StringVal != nullptr);
120
121 switch (StringForm) {
122 case dwarf::DW_FORM_string: {
123 emitInplaceString(StringVal);
124 } break;
125 case dwarf::DW_FORM_strp: {
126 notePatch(DebugStrPatch{
127 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
129 } break;
130 case dwarf::DW_FORM_line_strp: {
131 notePatch(DebugLineStrPatch{
132 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
134 } break;
135 default:
136 llvm_unreachable("Unsupported string form");
137 break;
138 };
139}
140
141void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
142 switch (Size) {
143 case 1: {
144 OS.write(static_cast<uint8_t>(Val));
145 } break;
146 case 2: {
147 uint16_t ShortVal = static_cast<uint16_t>(Val);
149 sys::swapByteOrder(ShortVal);
150 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
151 } break;
152 case 4: {
153 uint32_t ShortVal = static_cast<uint32_t>(Val);
155 sys::swapByteOrder(ShortVal);
156 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
157 } break;
158 case 8: {
161 OS.write(reinterpret_cast<const char *>(&Val), Size);
162 } break;
163 default:
164 llvm_unreachable("Unsupported integer type size");
165 }
166}
167
169 OS.write(Data.data(), Data.size());
170}
171
172void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,
173 uint64_t Val) {
174 switch (AttrForm) {
175 case dwarf::DW_FORM_strp:
176 case dwarf::DW_FORM_line_strp: {
177 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
178 } break;
179
180 case dwarf::DW_FORM_ref_addr: {
181 applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());
182 } break;
183 case dwarf::DW_FORM_ref1: {
184 applyIntVal(PatchOffset, Val, 1);
185 } break;
186 case dwarf::DW_FORM_ref2: {
187 applyIntVal(PatchOffset, Val, 2);
188 } break;
189 case dwarf::DW_FORM_ref4: {
190 applyIntVal(PatchOffset, Val, 4);
191 } break;
192 case dwarf::DW_FORM_ref8: {
193 applyIntVal(PatchOffset, Val, 8);
194 } break;
195
196 case dwarf::DW_FORM_data1: {
197 applyIntVal(PatchOffset, Val, 1);
198 } break;
199 case dwarf::DW_FORM_data2: {
200 applyIntVal(PatchOffset, Val, 2);
201 } break;
202 case dwarf::DW_FORM_data4: {
203 applyIntVal(PatchOffset, Val, 4);
204 } break;
205 case dwarf::DW_FORM_data8: {
206 applyIntVal(PatchOffset, Val, 8);
207 } break;
208 case dwarf::DW_FORM_udata: {
209 applyULEB128(PatchOffset, Val);
210 } break;
211 case dwarf::DW_FORM_sdata: {
212 applySLEB128(PatchOffset, Val);
213 } break;
214 case dwarf::DW_FORM_sec_offset: {
215 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
216 } break;
217 case dwarf::DW_FORM_flag: {
218 applyIntVal(PatchOffset, Val, 1);
219 } break;
220
221 default:
222 llvm_unreachable("Unsupported attribute form");
223 break;
224 }
225}
226
227uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {
228 assert(PatchOffset < getContents().size());
229 switch (Size) {
230 case 1: {
231 return *reinterpret_cast<const uint8_t *>(
232 (getContents().data() + PatchOffset));
233 }
234 case 2: {
235 return support::endian::read16(getContents().data() + PatchOffset,
236 Endianess);
237 }
238 case 4: {
239 return support::endian::read32(getContents().data() + PatchOffset,
240 Endianess);
241 }
242 case 8: {
243 return support::endian::read64(getContents().data() + PatchOffset,
244 Endianess);
245 }
246 }
247 llvm_unreachable("Unsupported integer type size");
248 return 0;
249}
250
251void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
252 unsigned Size) {
253 assert(PatchOffset < getContents().size());
254
255 switch (Size) {
256 case 1: {
258 const_cast<char *>(getContents().data() + PatchOffset),
259 static_cast<uint8_t>(Val), Endianess);
260 } break;
261 case 2: {
263 const_cast<char *>(getContents().data() + PatchOffset),
264 static_cast<uint16_t>(Val), Endianess);
265 } break;
266 case 4: {
268 const_cast<char *>(getContents().data() + PatchOffset),
269 static_cast<uint32_t>(Val), Endianess);
270 } break;
271 case 8: {
273 const_cast<char *>(getContents().data() + PatchOffset),
274 static_cast<uint64_t>(Val), Endianess);
275 } break;
276 default:
277 llvm_unreachable("Unsupported integer type size");
278 }
279}
280
281void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {
282 assert(PatchOffset < getContents().size());
283
284 uint8_t ULEB[16];
285 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
286 uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);
287
288 memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
289 RealSize);
290}
291
292/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
293void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {
294 assert(PatchOffset < getContents().size());
295
296 uint8_t SLEB[16];
297 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
298 uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);
299
300 memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
301 RealSize);
302}
303
305 SectionDescriptor &Section,
307 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
308 TypeUnit *TypeUnitPtr) {
309 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
311 DebugStrStrings.getExistingEntry(Patch.String);
312 assert(Entry != nullptr);
313
314 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
315 });
316 Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
317 assert(TypeUnitPtr != nullptr);
318 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
320 formatv("No data for type {0}", Patch.TypeName->getKey())
321 .str()
322 .c_str());
323
324 if (&TypeEntry->getFinalDie() != Patch.Die)
325 return;
326
328 DebugStrStrings.getExistingEntry(Patch.String);
329 assert(Entry != nullptr);
330
331 Patch.PatchOffset +=
332 Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
333
334 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
335 });
336
337 Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
339 DebugLineStrStrings.getExistingEntry(Patch.String);
340 assert(Entry != nullptr);
341
342 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
343 });
344 Section.ListDebugTypeLineStrPatch.forEach([&](DebugTypeLineStrPatch &Patch) {
345 assert(TypeUnitPtr != nullptr);
346 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
348 formatv("No data for type {0}", Patch.TypeName->getKey())
349 .str()
350 .c_str());
351
352 if (&TypeEntry->getFinalDie() != Patch.Die)
353 return;
354
356 DebugLineStrStrings.getExistingEntry(Patch.String);
357 assert(Entry != nullptr);
358
359 Patch.PatchOffset +=
360 Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
361
362 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
363 });
364
365 std::optional<SectionDescriptor *> RangeSection;
366 if (Format.Version >= 5)
368 else
370
371 if (RangeSection) {
372 Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
373 uint64_t FinalValue =
374 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
375 FinalValue += (*RangeSection)->StartOffset;
376
377 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
378 });
379 }
380
381 std::optional<SectionDescriptor *> LocationSection;
382 if (Format.Version >= 5)
384 else
386
387 if (LocationSection) {
388 Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
389 uint64_t FinalValue =
390 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
391 FinalValue += (*LocationSection)->StartOffset;
392
393 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
394 });
395 }
396
397 Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
398 uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;
399 dwarf::Form FinalForm = dwarf::DW_FORM_ref4;
400
401 // Check whether it is local or inter-CU reference.
402 if (!Patch.RefCU.getInt()) {
403 SectionDescriptor &ReferencedSectionDescriptor =
404 Patch.RefCU.getPointer()->getSectionDescriptor(
406
407 FinalForm = dwarf::DW_FORM_ref_addr;
408 FinalOffset += ReferencedSectionDescriptor.StartOffset;
409 }
410
411 Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);
412 });
413
414 Section.ListDebugULEB128DieRefPatch.forEach(
415 [&](DebugULEB128DieRefPatch &Patch) {
416 assert(Patch.RefCU.getInt());
417 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,
418 Patch.RefDieIdxOrClonedOffset);
419 });
420
421 Section.ListDebugDieTypeRefPatch.forEach([&](DebugDieTypeRefPatch &Patch) {
422 assert(TypeUnitPtr != nullptr);
423 assert(Patch.RefTypeName != nullptr);
424
425 TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load();
427 formatv("No data for type {0}", Patch.RefTypeName->getKey())
428 .str()
429 .c_str());
430
431 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,
432 TypeEntry->getFinalDie().getOffset());
433 });
434
435 Section.ListDebugDieModuleRefPatch.forEach(
436 [&](DebugDieModuleRefPatch &Patch) {
437 const ModuleAnchor &Anchor = *Patch.Anchor;
438
439 uint64_t FinalOffset;
440 if (Anchor.TypeName) {
441 assert(TypeUnitPtr != nullptr);
442 TypeEntryBody *TypeEntry = Anchor.TypeName->getValue().load();
444 formatv("No data for type {0}", Anchor.TypeName->getKey())
445 .str()
446 .c_str());
447
448 FinalOffset = TypeEntry->getFinalDie().getOffset();
449 } else if (Anchor.Section) {
450 FinalOffset = Anchor.Section->StartOffset + Anchor.LocalOffset;
451 } else {
452 // No unit describes this module in full, so the importer's own
453 // skeleton is all the output has.
454 FinalOffset = Patch.RefDieIdxOrClonedOffset +
455 Patch.RefCU.getPointer()
456 ->getSectionDescriptor(DebugSectionKind::DebugInfo)
457 .StartOffset;
458 }
459
460 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr, FinalOffset);
461 });
462
463 Section.ListDebugType2TypeDieRefPatch.forEach(
464 [&](DebugType2TypeDieRefPatch &Patch) {
465 assert(TypeUnitPtr != nullptr);
466 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
468 formatv("No data for type {0}", Patch.TypeName->getKey())
469 .str()
470 .c_str());
471
472 if (&TypeEntry->getFinalDie() != Patch.Die)
473 return;
474
475 Patch.PatchOffset += Patch.Die->getOffset() +
476 getULEB128Size(Patch.Die->getAbbrevNumber());
477
478 assert(Patch.RefTypeName != nullptr);
479 TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();
481 formatv("No data for type {0}", Patch.RefTypeName->getKey())
482 .str()
483 .c_str());
484
485 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,
486 RefTypeEntry->getFinalDie().getOffset());
487 });
488
489 Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {
490 uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;
491
492 // Check whether we need to read value from the original location.
493 if (Patch.SectionPtr.getInt()) {
494 uint64_t LocalValue =
495 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
496 // DebugOffsetPatch treats the DWARF "invalid offset" sentinel
497 // (0xffffffff for DWARF32) as pass-through: callers that can't
498 // resolve the target write that value and expect it to survive
499 // section combination unchanged. Adding StartOffset would turn it
500 // into a plausible-looking but meaningless offset. Callers that
501 // genuinely want `StartOffset + MaxOffset` don't exist today and
502 // would need a different patch type.
503 if (LocalValue == Format.getDwarfMaxOffset())
504 FinalValue = LocalValue;
505 else
506 FinalValue += LocalValue;
507 }
508
509 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
510 });
511}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Split data
A structured debug information entry.
Definition DIE.h:842
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:880
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
const ValueTy & getValue() const
StringRef getKey() const
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 a DW_AT_import reference to a DW_TAG_module.
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)
Where the DW_TAG_module DIE describing a clang module ended up in the output.
Definition ModulePool.h:30
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.