Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / DWARFLinkerParallel / OutputSections.cpp
blob8e7caa7bb4074250f2d807ab38c2e046053afc7c
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 //===----------------------------------------------------------------------===//
9 #include "OutputSections.h"
10 #include "DWARFLinkerCompileUnit.h"
11 #include "llvm/ADT/StringSwitch.h"
13 namespace llvm {
14 namespace dwarflinker_parallel {
16 static constexpr StringLiteral SectionNames[SectionKindsNum] = {
17 "debug_info", "debug_line", "debug_frame", "debug_ranges",
18 "debug_rnglists", "debug_loc", "debug_loclists", "debug_aranges",
19 "debug_abbrev", "debug_macinfo", "debug_macro", "debug_addr",
20 "debug_str", "debug_line_str", "debug_str_offsets", "debug_pubnames",
21 "debug_pubtypes", "debug_names", "apple_names", "apple_namespac",
22 "apple_objc", "apple_types"};
24 const StringLiteral &getSectionName(DebugSectionKind SectionKind) {
25 return SectionNames[static_cast<uint8_t>(SectionKind)];
28 std::optional<DebugSectionKind> parseDebugTableName(llvm::StringRef SecName) {
29 return llvm::StringSwitch<std::optional<DebugSectionKind>>(
30 SecName.substr(SecName.find_first_not_of("._")))
31 .Case(getSectionName(DebugSectionKind::DebugInfo),
32 DebugSectionKind::DebugInfo)
33 .Case(getSectionName(DebugSectionKind::DebugLine),
34 DebugSectionKind::DebugLine)
35 .Case(getSectionName(DebugSectionKind::DebugFrame),
36 DebugSectionKind::DebugFrame)
37 .Case(getSectionName(DebugSectionKind::DebugRange),
38 DebugSectionKind::DebugRange)
39 .Case(getSectionName(DebugSectionKind::DebugRngLists),
40 DebugSectionKind::DebugRngLists)
41 .Case(getSectionName(DebugSectionKind::DebugLoc),
42 DebugSectionKind::DebugLoc)
43 .Case(getSectionName(DebugSectionKind::DebugLocLists),
44 DebugSectionKind::DebugLocLists)
45 .Case(getSectionName(DebugSectionKind::DebugARanges),
46 DebugSectionKind::DebugARanges)
47 .Case(getSectionName(DebugSectionKind::DebugAbbrev),
48 DebugSectionKind::DebugAbbrev)
49 .Case(getSectionName(DebugSectionKind::DebugMacinfo),
50 DebugSectionKind::DebugMacinfo)
51 .Case(getSectionName(DebugSectionKind::DebugMacro),
52 DebugSectionKind::DebugMacro)
53 .Case(getSectionName(DebugSectionKind::DebugAddr),
54 DebugSectionKind::DebugAddr)
55 .Case(getSectionName(DebugSectionKind::DebugStr),
56 DebugSectionKind::DebugStr)
57 .Case(getSectionName(DebugSectionKind::DebugLineStr),
58 DebugSectionKind::DebugLineStr)
59 .Case(getSectionName(DebugSectionKind::DebugStrOffsets),
60 DebugSectionKind::DebugStrOffsets)
61 .Case(getSectionName(DebugSectionKind::DebugPubNames),
62 DebugSectionKind::DebugPubNames)
63 .Case(getSectionName(DebugSectionKind::DebugPubTypes),
64 DebugSectionKind::DebugPubTypes)
65 .Case(getSectionName(DebugSectionKind::DebugNames),
66 DebugSectionKind::DebugNames)
67 .Case(getSectionName(DebugSectionKind::AppleNames),
68 DebugSectionKind::AppleNames)
69 .Case(getSectionName(DebugSectionKind::AppleNamespaces),
70 DebugSectionKind::AppleNamespaces)
71 .Case(getSectionName(DebugSectionKind::AppleObjC),
72 DebugSectionKind::AppleObjC)
73 .Case(getSectionName(DebugSectionKind::AppleTypes),
74 DebugSectionKind::AppleTypes)
75 .Default(std::nullopt);
77 return std::nullopt;
80 DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
81 CompileUnit *RefCU, uint32_t RefIdx)
82 : SectionPatch({PatchOffset}),
83 RefCU(RefCU, (SrcCU != nullptr) &&
84 (SrcCU->getUniqueID() == RefCU->getUniqueID())),
85 RefDieIdxOrClonedOffset(RefIdx) {}
87 DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,
88 CompileUnit *SrcCU,
89 CompileUnit *RefCU,
90 uint32_t RefIdx)
91 : SectionPatch({PatchOffset}),
92 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
93 RefDieIdxOrClonedOffset(RefIdx) {}
95 void SectionDescriptor::clearAllSectionData() {
96 StartOffset = 0;
97 clearSectionContent();
98 ListDebugStrPatch.erase();
99 ListDebugLineStrPatch.erase();
100 ListDebugRangePatch.erase();
101 ListDebugLocPatch.erase();
102 ListDebugDieRefPatch.erase();
103 ListDebugULEB128DieRefPatch.erase();
104 ListDebugOffsetPatch.erase();
107 void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }
109 void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
110 if (Contents.empty())
111 return;
113 MemoryBufferRef Mem(Contents, "obj");
114 Expected<std::unique_ptr<object::ObjectFile>> Obj =
115 object::ObjectFile::createObjectFile(Mem);
116 if (!Obj) {
117 consumeError(Obj.takeError());
118 Contents.clear();
119 return;
122 for (const object::SectionRef &Sect : (*Obj).get()->sections()) {
123 Expected<StringRef> SectNameOrErr = Sect.getName();
124 if (!SectNameOrErr) {
125 consumeError(SectNameOrErr.takeError());
126 continue;
128 if (std::optional<DebugSectionKind> SectKind =
129 parseDebugTableName(*SectNameOrErr)) {
130 if (*SectKind == SectionKind) {
131 Expected<StringRef> Data = Sect.getContents();
132 if (!Data) {
133 consumeError(SectNameOrErr.takeError());
134 Contents.clear();
135 return;
138 SectionOffsetInsideAsmPrinterOutputStart =
139 Data->data() - Contents.data();
140 SectionOffsetInsideAsmPrinterOutputEnd =
141 SectionOffsetInsideAsmPrinterOutputStart + Data->size();
147 void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
148 switch (Size) {
149 case 1: {
150 OS.write(static_cast<uint8_t>(Val));
151 } break;
152 case 2: {
153 uint16_t ShortVal = static_cast<uint16_t>(Val);
154 if (Endianess != llvm::endianness::native)
155 sys::swapByteOrder(ShortVal);
156 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
157 } break;
158 case 4: {
159 uint32_t ShortVal = static_cast<uint32_t>(Val);
160 if (Endianess != llvm::endianness::native)
161 sys::swapByteOrder(ShortVal);
162 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
163 } break;
164 case 8: {
165 if (Endianess != llvm::endianness::native)
166 sys::swapByteOrder(Val);
167 OS.write(reinterpret_cast<const char *>(&Val), Size);
168 } break;
169 default:
170 llvm_unreachable("Unsupported integer type size");
174 void SectionDescriptor::emitString(dwarf::Form StringForm,
175 const char *StringVal) {
176 assert(StringVal != nullptr);
178 switch (StringForm) {
179 case dwarf::DW_FORM_string: {
180 emitInplaceString(StringVal);
181 } break;
182 case dwarf::DW_FORM_strp: {
183 notePatch(DebugStrPatch{
184 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
185 emitStringPlaceholder();
186 } break;
187 case dwarf::DW_FORM_line_strp: {
188 notePatch(DebugLineStrPatch{
189 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
190 emitStringPlaceholder();
191 } break;
192 default:
193 llvm_unreachable("Unsupported string form");
194 break;
198 void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,
199 uint64_t Val) {
200 switch (AttrForm) {
201 case dwarf::DW_FORM_strp:
202 case dwarf::DW_FORM_line_strp: {
203 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
204 } break;
206 case dwarf::DW_FORM_ref_addr: {
207 applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());
208 } break;
209 case dwarf::DW_FORM_ref1: {
210 applyIntVal(PatchOffset, Val, 1);
211 } break;
212 case dwarf::DW_FORM_ref2: {
213 applyIntVal(PatchOffset, Val, 2);
214 } break;
215 case dwarf::DW_FORM_ref4: {
216 applyIntVal(PatchOffset, Val, 4);
217 } break;
218 case dwarf::DW_FORM_ref8: {
219 applyIntVal(PatchOffset, Val, 8);
220 } break;
222 case dwarf::DW_FORM_data1: {
223 applyIntVal(PatchOffset, Val, 1);
224 } break;
225 case dwarf::DW_FORM_data2: {
226 applyIntVal(PatchOffset, Val, 2);
227 } break;
228 case dwarf::DW_FORM_data4: {
229 applyIntVal(PatchOffset, Val, 4);
230 } break;
231 case dwarf::DW_FORM_data8: {
232 applyIntVal(PatchOffset, Val, 8);
233 } break;
234 case dwarf::DW_FORM_udata: {
235 applyULEB128(PatchOffset, Val);
236 } break;
237 case dwarf::DW_FORM_sdata: {
238 applySLEB128(PatchOffset, Val);
239 } break;
240 case dwarf::DW_FORM_sec_offset: {
241 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
242 } break;
243 case dwarf::DW_FORM_flag: {
244 applyIntVal(PatchOffset, Val, 1);
245 } break;
247 default:
248 llvm_unreachable("Unsupported attribute form");
249 break;
253 uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {
254 assert(PatchOffset < getContents().size());
255 switch (Size) {
256 case 1: {
257 return *reinterpret_cast<const uint8_t *>(
258 (getContents().data() + PatchOffset));
260 case 2: {
261 return support::endian::read16(getContents().data() + PatchOffset,
262 Endianess);
264 case 4: {
265 return support::endian::read32(getContents().data() + PatchOffset,
266 Endianess);
268 case 8: {
269 return support::endian::read64(getContents().data() + PatchOffset,
270 Endianess);
273 llvm_unreachable("Unsupported integer type size");
274 return 0;
277 void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
278 unsigned Size) {
279 assert(PatchOffset < getContents().size());
281 switch (Size) {
282 case 1: {
283 support::endian::write(
284 const_cast<char *>(getContents().data() + PatchOffset),
285 static_cast<uint8_t>(Val), Endianess);
286 } break;
287 case 2: {
288 support::endian::write(
289 const_cast<char *>(getContents().data() + PatchOffset),
290 static_cast<uint16_t>(Val), Endianess);
291 } break;
292 case 4: {
293 support::endian::write(
294 const_cast<char *>(getContents().data() + PatchOffset),
295 static_cast<uint32_t>(Val), Endianess);
296 } break;
297 case 8: {
298 support::endian::write(
299 const_cast<char *>(getContents().data() + PatchOffset),
300 static_cast<uint64_t>(Val), Endianess);
301 } break;
302 default:
303 llvm_unreachable("Unsupported integer type size");
307 void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {
308 assert(PatchOffset < getContents().size());
310 uint8_t ULEB[16];
311 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
312 uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);
314 memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
315 RealSize);
318 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
319 void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {
320 assert(PatchOffset < getContents().size());
322 uint8_t SLEB[16];
323 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
324 uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);
326 memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
327 RealSize);
330 void OutputSections::applyPatches(
331 SectionDescriptor &Section,
332 StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
333 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings) {
335 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
336 DwarfStringPoolEntryWithExtString *Entry =
337 DebugStrStrings.getExistingEntry(Patch.String);
338 assert(Entry != nullptr);
340 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
343 Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
344 DwarfStringPoolEntryWithExtString *Entry =
345 DebugLineStrStrings.getExistingEntry(Patch.String);
346 assert(Entry != nullptr);
348 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
351 std::optional<SectionDescriptor *> RangeSection;
352 if (Format.Version >= 5)
353 RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRngLists);
354 else
355 RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRange);
357 if (RangeSection) {
358 Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
359 uint64_t FinalValue =
360 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
361 FinalValue += (*RangeSection)->StartOffset;
363 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
367 std::optional<SectionDescriptor *> LocationSection;
368 if (Format.Version >= 5)
369 LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLocLists);
370 else
371 LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLoc);
373 if (LocationSection) {
374 Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
375 uint64_t FinalValue =
376 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
377 FinalValue += (*LocationSection)->StartOffset;
379 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
383 Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
384 uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;
385 dwarf::Form FinalForm = dwarf::DW_FORM_ref4;
387 // Check whether it is local or inter-CU reference.
388 if (!Patch.RefCU.getInt()) {
389 SectionDescriptor &ReferencedSectionDescriptor =
390 Patch.RefCU.getPointer()->getSectionDescriptor(
391 DebugSectionKind::DebugInfo);
393 FinalForm = dwarf::DW_FORM_ref_addr;
394 FinalOffset += ReferencedSectionDescriptor.StartOffset;
397 Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);
400 Section.ListDebugULEB128DieRefPatch.forEach(
401 [&](DebugULEB128DieRefPatch &Patch) {
402 assert(Patch.RefCU.getInt());
403 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,
404 Patch.RefDieIdxOrClonedOffset);
407 Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {
408 uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;
410 // Check whether we need to read value from the original location.
411 if (Patch.SectionPtr.getInt())
412 FinalValue +=
413 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
415 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
419 } // end of namespace dwarflinker_parallel
420 } // end of namespace llvm