LLVM: lib/DWARFLinker/Parallel/OutputSections.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12
13using namespace llvm;
16
20 RefCU(RefCU, (SrcCU != nullptr) &&
21 (SrcCU->getUniqueID() == RefCU->getUniqueID())),
22 RefDieIdxOrClonedOffset(RefIdx) {}
23
29 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
30 RefDieIdxOrClonedOffset(RefIdx) {}
31
35
41 RefTypeName(RefTypeName) {}
42
47
53
58
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
79 return;
80
84 if (!Obj) {
87 return;
88 }
89
92 if (!SectNameOrErr) {
94 continue;
95 }
96 if (std::optional SectKind =
103 return;
104 }
105
110 }
111 }
112 }
113}
114
116 const char *StringVal) {
117 assert(StringVal != nullptr);
118
119 switch (StringForm) {
120 case dwarf::DW_FORM_string: {
122 } break;
123 case dwarf::DW_FORM_strp: {
125 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
127 } break;
128 case dwarf::DW_FORM_line_strp: {
130 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
132 } break;
133 default:
135 break;
136 };
137}
138
140 switch (Size) {
141 case 1: {
142 OS.write(static_cast<uint8_t>(Val));
143 } break;
144 case 2: {
148 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
149 } break;
150 case 4: {
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:
163 }
164}
165
169
172 switch (AttrForm) {
173 case dwarf::DW_FORM_strp:
174 case dwarf::DW_FORM_line_strp: {
176 } break;
177
178 case dwarf::DW_FORM_ref_addr: {
180 } break;
181 case dwarf::DW_FORM_ref1: {
183 } break;
184 case dwarf::DW_FORM_ref2: {
186 } break;
187 case dwarf::DW_FORM_ref4: {
189 } break;
190 case dwarf::DW_FORM_ref8: {
192 } break;
193
194 case dwarf::DW_FORM_data1: {
196 } break;
197 case dwarf::DW_FORM_data2: {
199 } break;
200 case dwarf::DW_FORM_data4: {
202 } break;
203 case dwarf::DW_FORM_data8: {
205 } break;
206 case dwarf::DW_FORM_udata: {
208 } break;
209 case dwarf::DW_FORM_sdata: {
211 } break;
212 case dwarf::DW_FORM_sec_offset: {
214 } break;
215 case dwarf::DW_FORM_flag: {
217 } break;
218
219 default:
221 break;
222 }
223}
224
227 switch (Size) {
228 case 1: {
229 return *reinterpret_cast<const uint8_t *>(
231 }
232 case 2: {
235 }
236 case 4: {
239 }
240 case 8: {
243 }
244 }
246 return 0;
247}
248
250 unsigned Size) {
252
253 switch (Size) {
254 case 1: {
258 } break;
259 case 2: {
263 } break;
264 case 4: {
268 } break;
269 case 8: {
273 } break;
274 default:
276 }
277}
278
281
283 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
285
286 memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
287 RealSize);
288}
289
290
293
295 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
297
298 memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
299 RealSize);
300}
301
307 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
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);
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
327 assert(Entry != nullptr);
328
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) {
338 assert(Entry != nullptr);
339
340 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
341 });
343 assert(TypeUnitPtr != nullptr);
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
355 assert(Entry != nullptr);
356
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) {
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) {
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
400 if (!Patch.RefCU.getInt()) {
402 Patch.RefCU.getPointer()->getSectionDescriptor(
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(
414 assert(Patch.RefCU.getInt());
415 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,
416 Patch.RefDieIdxOrClonedOffset);
417 });
418
420 assert(TypeUnitPtr != nullptr);
421 assert(Patch.RefTypeName != nullptr);
422
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(
435 assert(TypeUnitPtr != nullptr);
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() +
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,
457 });
458
459 Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {
460 uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;
461
462
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!")
A structured debug information entry.
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
StringRef - Represent a constant reference to a string, i.e.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
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.
Definition OutputSections.cpp:302
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.
DIE & getFinalDie() const
Returns copy of type DIE which should be emitted into resulting file.
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...
#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
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...
uint32_t read32(const void *P, endianness E)
uint64_t read64(const void *P, endianness E)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
uint16_t read16(const void *P, endianness E)
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.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
void consumeError(Error Err)
Consume a Error without doing anything.
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)
Definition OutputSections.cpp:17
This structure is used to update reference to the type DIE.
DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName)
Definition OutputSections.cpp:32
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.
const StringEntry * String
This structure is used to update reference to the type DIE.
DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, TypeEntry *RefTypeName)
Definition OutputSections.cpp:36
DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory, StringEntry *FilePath)
Definition OutputSections.cpp:54
DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, StringEntry *String)
Definition OutputSections.cpp:48
DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, StringEntry *String)
Definition OutputSections.cpp:43
This structure is used to update reference to the DIE of ULEB128 form.
DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, uint32_t RefIdx)
Definition OutputSections.cpp:24
PointerIntPair< CompileUnit *, 1 > RefCU
DebugSectionKind SectionKind
The section kind.
llvm::endianness Endianess
dwarf::FormParams Format
Output format.
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.
Definition OutputSections.cpp:77
OutSectionDataTy Contents
Section data bits.
void emitString(dwarf::Form StringForm, const char *StringVal)
Definition OutputSections.cpp:115
void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size)
Writes integer value Val of Size by specified PatchOffset.
Definition OutputSections.cpp:249
void emitIntVal(uint64_t Val, unsigned Size)
Emit specified integer value into the current section contents.
Definition OutputSections.cpp:139
void applySLEB128(uint64_t PatchOffset, uint64_t Val)
Writes integer value Val of SLEB128 format by specified PatchOffset.
Definition OutputSections.cpp:291
void applyULEB128(uint64_t PatchOffset, uint64_t Val)
Writes integer value Val of ULEB128 format by specified PatchOffset.
Definition OutputSections.cpp:279
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)
Write specified Value of AttrForm to the PatchOffset.
Definition OutputSections.cpp:170
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.
Definition OutputSections.cpp:225
void clearSectionContent()
Erase only section output data bits.
Definition OutputSections.cpp:75
void emitBinaryData(llvm::StringRef Data)
Definition OutputSections.cpp:166
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).
Definition OutputSections.cpp:59
size_t SectionOffsetInsideAsmPrinterOutputEnd
void emitStringPlaceholder()
Emit string placeholder into the current section contents.
LinkingGlobalData & GlobalData
uint64_t StartOffset
When objects(f.e.
There are fields(sizes, offsets) which should be updated after sections are generated.