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" |
10 | #include "DWARFLinkerCompileUnit.h" |
11 | #include "DWARFLinkerTypeUnit.h" |
12 | |
13 | using namespace llvm; |
14 | using namespace dwarf_linker; |
15 | using namespace dwarf_linker::parallel; |
16 | |
17 | DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, |
18 | CompileUnit *RefCU, uint32_t RefIdx) |
19 | : SectionPatch({.PatchOffset: PatchOffset}), |
20 | RefCU(RefCU, (SrcCU != nullptr) && |
21 | (SrcCU->getUniqueID() == RefCU->getUniqueID())), |
22 | RefDieIdxOrClonedOffset(RefIdx) {} |
23 | |
24 | DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset, |
25 | CompileUnit *SrcCU, |
26 | CompileUnit *RefCU, |
27 | uint32_t RefIdx) |
28 | : SectionPatch({.PatchOffset: PatchOffset}), |
29 | RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()), |
30 | RefDieIdxOrClonedOffset(RefIdx) {} |
31 | |
32 | DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset, |
33 | TypeEntry *RefTypeName) |
34 | : SectionPatch({.PatchOffset: PatchOffset}), RefTypeName(RefTypeName) {} |
35 | |
36 | DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset, |
37 | DIE *Die, |
38 | TypeEntry *TypeName, |
39 | TypeEntry *RefTypeName) |
40 | : SectionPatch({.PatchOffset: PatchOffset}), Die(Die), TypeName(TypeName), |
41 | RefTypeName(RefTypeName) {} |
42 | |
43 | DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, |
44 | TypeEntry *TypeName, StringEntry *String) |
45 | : SectionPatch({.PatchOffset: PatchOffset}), Die(Die), TypeName(TypeName), |
46 | String(String) {} |
47 | |
48 | DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, |
49 | TypeEntry *TypeName, |
50 | StringEntry *String) |
51 | : SectionPatch({.PatchOffset: PatchOffset}), Die(Die), TypeName(TypeName), |
52 | String(String) {} |
53 | |
54 | DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, |
55 | StringEntry *Directory, |
56 | StringEntry *FilePath) |
57 | : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {} |
58 | |
59 | void SectionDescriptor::clearAllSectionData() { |
60 | StartOffset = 0; |
61 | clearSectionContent(); |
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 | |
75 | void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); } |
76 | |
77 | void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() { |
78 | if (Contents.empty()) |
79 | return; |
80 | |
81 | MemoryBufferRef Mem(Contents, "obj" ); |
82 | Expected<std::unique_ptr<object::ObjectFile>> Obj = |
83 | object::ObjectFile::createObjectFile(Object: Mem); |
84 | if (!Obj) { |
85 | consumeError(Err: Obj.takeError()); |
86 | Contents.clear(); |
87 | return; |
88 | } |
89 | |
90 | for (const object::SectionRef &Sect : (*Obj).get()->sections()) { |
91 | Expected<StringRef> SectNameOrErr = Sect.getName(); |
92 | if (!SectNameOrErr) { |
93 | consumeError(Err: SectNameOrErr.takeError()); |
94 | continue; |
95 | } |
96 | if (std::optional<DebugSectionKind> SectKind = |
97 | parseDebugTableName(Name: *SectNameOrErr)) { |
98 | if (*SectKind == SectionKind) { |
99 | Expected<StringRef> Data = Sect.getContents(); |
100 | if (!Data) { |
101 | consumeError(Err: SectNameOrErr.takeError()); |
102 | Contents.clear(); |
103 | return; |
104 | } |
105 | |
106 | SectionOffsetInsideAsmPrinterOutputStart = |
107 | Data->data() - Contents.data(); |
108 | SectionOffsetInsideAsmPrinterOutputEnd = |
109 | SectionOffsetInsideAsmPrinterOutputStart + Data->size(); |
110 | } |
111 | } |
112 | } |
113 | } |
114 | |
115 | void SectionDescriptor::emitString(dwarf::Form StringForm, |
116 | const char *StringVal) { |
117 | assert(StringVal != nullptr); |
118 | |
119 | switch (StringForm) { |
120 | case dwarf::DW_FORM_string: { |
121 | emitInplaceString(String: StringVal); |
122 | } break; |
123 | case dwarf::DW_FORM_strp: { |
124 | notePatch(Patch: DebugStrPatch{ |
125 | {.PatchOffset: OS.tell()}, .String: GlobalData.getStringPool().insert(NewValue: StringVal).first}); |
126 | emitStringPlaceholder(); |
127 | } break; |
128 | case dwarf::DW_FORM_line_strp: { |
129 | notePatch(Patch: DebugLineStrPatch{ |
130 | {.PatchOffset: OS.tell()}, .String: GlobalData.getStringPool().insert(NewValue: StringVal).first}); |
131 | emitStringPlaceholder(); |
132 | } break; |
133 | default: |
134 | llvm_unreachable("Unsupported string form" ); |
135 | break; |
136 | }; |
137 | } |
138 | |
139 | void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) { |
140 | switch (Size) { |
141 | case 1: { |
142 | OS.write(C: static_cast<uint8_t>(Val)); |
143 | } break; |
144 | case 2: { |
145 | uint16_t ShortVal = static_cast<uint16_t>(Val); |
146 | if (Endianess != llvm::endianness::native) |
147 | sys::swapByteOrder(Value&: ShortVal); |
148 | OS.write(Ptr: reinterpret_cast<const char *>(&ShortVal), Size); |
149 | } break; |
150 | case 4: { |
151 | uint32_t ShortVal = static_cast<uint32_t>(Val); |
152 | if (Endianess != llvm::endianness::native) |
153 | sys::swapByteOrder(Value&: ShortVal); |
154 | OS.write(Ptr: reinterpret_cast<const char *>(&ShortVal), Size); |
155 | } break; |
156 | case 8: { |
157 | if (Endianess != llvm::endianness::native) |
158 | sys::swapByteOrder(Value&: Val); |
159 | OS.write(Ptr: reinterpret_cast<const char *>(&Val), Size); |
160 | } break; |
161 | default: |
162 | llvm_unreachable("Unsupported integer type size" ); |
163 | } |
164 | } |
165 | |
166 | void SectionDescriptor::emitBinaryData(llvm::StringRef Data) { |
167 | OS.write(Ptr: Data.data(), Size: Data.size()); |
168 | } |
169 | |
170 | void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm, |
171 | uint64_t Val) { |
172 | switch (AttrForm) { |
173 | case dwarf::DW_FORM_strp: |
174 | case dwarf::DW_FORM_line_strp: { |
175 | applyIntVal(PatchOffset, Val, Size: Format.getDwarfOffsetByteSize()); |
176 | } break; |
177 | |
178 | case dwarf::DW_FORM_ref_addr: { |
179 | applyIntVal(PatchOffset, Val, Size: Format.getRefAddrByteSize()); |
180 | } break; |
181 | case dwarf::DW_FORM_ref1: { |
182 | applyIntVal(PatchOffset, Val, Size: 1); |
183 | } break; |
184 | case dwarf::DW_FORM_ref2: { |
185 | applyIntVal(PatchOffset, Val, Size: 2); |
186 | } break; |
187 | case dwarf::DW_FORM_ref4: { |
188 | applyIntVal(PatchOffset, Val, Size: 4); |
189 | } break; |
190 | case dwarf::DW_FORM_ref8: { |
191 | applyIntVal(PatchOffset, Val, Size: 8); |
192 | } break; |
193 | |
194 | case dwarf::DW_FORM_data1: { |
195 | applyIntVal(PatchOffset, Val, Size: 1); |
196 | } break; |
197 | case dwarf::DW_FORM_data2: { |
198 | applyIntVal(PatchOffset, Val, Size: 2); |
199 | } break; |
200 | case dwarf::DW_FORM_data4: { |
201 | applyIntVal(PatchOffset, Val, Size: 4); |
202 | } break; |
203 | case dwarf::DW_FORM_data8: { |
204 | applyIntVal(PatchOffset, Val, Size: 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, Size: Format.getDwarfOffsetByteSize()); |
214 | } break; |
215 | case dwarf::DW_FORM_flag: { |
216 | applyIntVal(PatchOffset, Val, Size: 1); |
217 | } break; |
218 | |
219 | default: |
220 | llvm_unreachable("Unsupported attribute form" ); |
221 | break; |
222 | } |
223 | } |
224 | |
225 | uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) { |
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(P: getContents().data() + PatchOffset, |
234 | E: Endianess); |
235 | } |
236 | case 4: { |
237 | return support::endian::read32(P: getContents().data() + PatchOffset, |
238 | E: Endianess); |
239 | } |
240 | case 8: { |
241 | return support::endian::read64(P: getContents().data() + PatchOffset, |
242 | E: Endianess); |
243 | } |
244 | } |
245 | llvm_unreachable("Unsupported integer type size" ); |
246 | return 0; |
247 | } |
248 | |
249 | void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val, |
250 | unsigned Size) { |
251 | assert(PatchOffset < getContents().size()); |
252 | |
253 | switch (Size) { |
254 | case 1: { |
255 | support::endian::write( |
256 | memory: const_cast<char *>(getContents().data() + PatchOffset), |
257 | value: static_cast<uint8_t>(Val), endian: Endianess); |
258 | } break; |
259 | case 2: { |
260 | support::endian::write( |
261 | memory: const_cast<char *>(getContents().data() + PatchOffset), |
262 | value: static_cast<uint16_t>(Val), endian: Endianess); |
263 | } break; |
264 | case 4: { |
265 | support::endian::write( |
266 | memory: const_cast<char *>(getContents().data() + PatchOffset), |
267 | value: static_cast<uint32_t>(Val), endian: Endianess); |
268 | } break; |
269 | case 8: { |
270 | support::endian::write( |
271 | memory: const_cast<char *>(getContents().data() + PatchOffset), |
272 | value: static_cast<uint64_t>(Val), endian: Endianess); |
273 | } break; |
274 | default: |
275 | llvm_unreachable("Unsupported integer type size" ); |
276 | } |
277 | } |
278 | |
279 | void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) { |
280 | assert(PatchOffset < getContents().size()); |
281 | |
282 | uint8_t ULEB[16]; |
283 | uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1; |
284 | uint8_t RealSize = encodeULEB128(Value: Val, p: ULEB, PadTo: DestSize); |
285 | |
286 | memcpy(dest: const_cast<char *>(getContents().data() + PatchOffset), src: ULEB, |
287 | n: RealSize); |
288 | } |
289 | |
290 | /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset. |
291 | void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) { |
292 | assert(PatchOffset < getContents().size()); |
293 | |
294 | uint8_t SLEB[16]; |
295 | uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1; |
296 | uint8_t RealSize = encodeSLEB128(Value: Val, p: SLEB, PadTo: DestSize); |
297 | |
298 | memcpy(dest: const_cast<char *>(getContents().data() + PatchOffset), src: SLEB, |
299 | n: RealSize); |
300 | } |
301 | |
302 | void OutputSections::applyPatches( |
303 | SectionDescriptor &Section, |
304 | StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, |
305 | StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, |
306 | TypeUnit *TypeUnitPtr) { |
307 | Section.ListDebugStrPatch.forEach(Handler: [&](DebugStrPatch &Patch) { |
308 | DwarfStringPoolEntryWithExtString *Entry = |
309 | DebugStrStrings.getExistingEntry(String: Patch.String); |
310 | assert(Entry != nullptr); |
311 | |
312 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_strp, Val: Entry->Offset); |
313 | }); |
314 | Section.ListDebugTypeStrPatch.forEach(Handler: [&](DebugTypeStrPatch &Patch) { |
315 | assert(TypeUnitPtr != nullptr); |
316 | TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load(); |
317 | assert(TypeEntry && |
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 | |
325 | DwarfStringPoolEntryWithExtString *Entry = |
326 | DebugStrStrings.getExistingEntry(String: Patch.String); |
327 | assert(Entry != nullptr); |
328 | |
329 | Patch.PatchOffset += |
330 | Patch.Die->getOffset() + getULEB128Size(Value: Patch.Die->getAbbrevNumber()); |
331 | |
332 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_strp, Val: Entry->Offset); |
333 | }); |
334 | |
335 | Section.ListDebugLineStrPatch.forEach(Handler: [&](DebugLineStrPatch &Patch) { |
336 | DwarfStringPoolEntryWithExtString *Entry = |
337 | DebugLineStrStrings.getExistingEntry(String: Patch.String); |
338 | assert(Entry != nullptr); |
339 | |
340 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_line_strp, Val: Entry->Offset); |
341 | }); |
342 | Section.ListDebugTypeLineStrPatch.forEach(Handler: [&](DebugTypeLineStrPatch &Patch) { |
343 | assert(TypeUnitPtr != nullptr); |
344 | TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load(); |
345 | assert(TypeEntry && |
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 | |
353 | DwarfStringPoolEntryWithExtString *Entry = |
354 | DebugLineStrStrings.getExistingEntry(String: Patch.String); |
355 | assert(Entry != nullptr); |
356 | |
357 | Patch.PatchOffset += |
358 | Patch.Die->getOffset() + getULEB128Size(Value: Patch.Die->getAbbrevNumber()); |
359 | |
360 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_line_strp, Val: Entry->Offset); |
361 | }); |
362 | |
363 | std::optional<SectionDescriptor *> RangeSection; |
364 | if (Format.Version >= 5) |
365 | RangeSection = tryGetSectionDescriptor(SectionKind: DebugSectionKind::DebugRngLists); |
366 | else |
367 | RangeSection = tryGetSectionDescriptor(SectionKind: DebugSectionKind::DebugRange); |
368 | |
369 | if (RangeSection) { |
370 | Section.ListDebugRangePatch.forEach(Handler: [&](DebugRangePatch &Patch) { |
371 | uint64_t FinalValue = |
372 | Section.getIntVal(PatchOffset: Patch.PatchOffset, Size: Format.getDwarfOffsetByteSize()); |
373 | FinalValue += (*RangeSection)->StartOffset; |
374 | |
375 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_sec_offset, Val: FinalValue); |
376 | }); |
377 | } |
378 | |
379 | std::optional<SectionDescriptor *> LocationSection; |
380 | if (Format.Version >= 5) |
381 | LocationSection = tryGetSectionDescriptor(SectionKind: DebugSectionKind::DebugLocLists); |
382 | else |
383 | LocationSection = tryGetSectionDescriptor(SectionKind: DebugSectionKind::DebugLoc); |
384 | |
385 | if (LocationSection) { |
386 | Section.ListDebugLocPatch.forEach(Handler: [&](DebugLocPatch &Patch) { |
387 | uint64_t FinalValue = |
388 | Section.getIntVal(PatchOffset: Patch.PatchOffset, Size: Format.getDwarfOffsetByteSize()); |
389 | FinalValue += (*LocationSection)->StartOffset; |
390 | |
391 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_sec_offset, Val: FinalValue); |
392 | }); |
393 | } |
394 | |
395 | Section.ListDebugDieRefPatch.forEach(Handler: [&](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 | SectionKind: DebugSectionKind::DebugInfo); |
404 | |
405 | FinalForm = dwarf::DW_FORM_ref_addr; |
406 | FinalOffset += ReferencedSectionDescriptor.StartOffset; |
407 | } |
408 | |
409 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: FinalForm, Val: FinalOffset); |
410 | }); |
411 | |
412 | Section.ListDebugULEB128DieRefPatch.forEach( |
413 | Handler: [&](DebugULEB128DieRefPatch &Patch) { |
414 | assert(Patch.RefCU.getInt()); |
415 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_udata, |
416 | Val: Patch.RefDieIdxOrClonedOffset); |
417 | }); |
418 | |
419 | Section.ListDebugDieTypeRefPatch.forEach(Handler: [&](DebugDieTypeRefPatch &Patch) { |
420 | assert(TypeUnitPtr != nullptr); |
421 | assert(Patch.RefTypeName != nullptr); |
422 | |
423 | TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load(); |
424 | assert(TypeEntry && |
425 | formatv("No data for type {0}" , Patch.RefTypeName->getKey()) |
426 | .str() |
427 | .c_str()); |
428 | |
429 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_ref_addr, |
430 | Val: TypeEntry->getFinalDie().getOffset()); |
431 | }); |
432 | |
433 | Section.ListDebugType2TypeDieRefPatch.forEach( |
434 | Handler: [&](DebugType2TypeDieRefPatch &Patch) { |
435 | assert(TypeUnitPtr != nullptr); |
436 | TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load(); |
437 | assert(TypeEntry && |
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(Value: Patch.Die->getAbbrevNumber()); |
447 | |
448 | assert(Patch.RefTypeName != nullptr); |
449 | TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load(); |
450 | assert(TypeEntry && |
451 | formatv("No data for type {0}" , Patch.RefTypeName->getKey()) |
452 | .str() |
453 | .c_str()); |
454 | |
455 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_ref4, |
456 | Val: RefTypeEntry->getFinalDie().getOffset()); |
457 | }); |
458 | |
459 | Section.ListDebugOffsetPatch.forEach(Handler: [&](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(PatchOffset: Patch.PatchOffset, Size: Format.getDwarfOffsetByteSize()); |
466 | |
467 | Section.apply(PatchOffset: Patch.PatchOffset, AttrForm: dwarf::DW_FORM_sec_offset, Val: FinalValue); |
468 | }); |
469 | } |
470 | |