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