1 //=== OutputSections.cpp --------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "OutputSections.h"
10 #include "DWARFLinkerCompileUnit.h"
11 #include "llvm/ADT/StringSwitch.h"
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"};
22 const StringLiteral
&getSectionName(DebugSectionKind SectionKind
) {
23 return SectionNames
[static_cast<uint8_t>(SectionKind
)];
26 std::optional
<DebugSectionKind
> parseDebugTableName(llvm::StringRef SecName
) {
27 return llvm::StringSwitch
<std::optional
<DebugSectionKind
>>(
28 SecName
.substr(SecName
.find_first_not_of("._")))
29 .Case(getSectionName(DebugSectionKind::DebugInfo
),
30 DebugSectionKind::DebugInfo
)
31 .Case(getSectionName(DebugSectionKind::DebugLine
),
32 DebugSectionKind::DebugLine
)
33 .Case(getSectionName(DebugSectionKind::DebugFrame
),
34 DebugSectionKind::DebugFrame
)
35 .Case(getSectionName(DebugSectionKind::DebugRange
),
36 DebugSectionKind::DebugRange
)
37 .Case(getSectionName(DebugSectionKind::DebugRngLists
),
38 DebugSectionKind::DebugRngLists
)
39 .Case(getSectionName(DebugSectionKind::DebugLoc
),
40 DebugSectionKind::DebugLoc
)
41 .Case(getSectionName(DebugSectionKind::DebugLocLists
),
42 DebugSectionKind::DebugLocLists
)
43 .Case(getSectionName(DebugSectionKind::DebugARanges
),
44 DebugSectionKind::DebugARanges
)
45 .Case(getSectionName(DebugSectionKind::DebugAbbrev
),
46 DebugSectionKind::DebugAbbrev
)
47 .Case(getSectionName(DebugSectionKind::DebugMacinfo
),
48 DebugSectionKind::DebugMacinfo
)
49 .Case(getSectionName(DebugSectionKind::DebugMacro
),
50 DebugSectionKind::DebugMacro
)
51 .Case(getSectionName(DebugSectionKind::DebugAddr
),
52 DebugSectionKind::DebugAddr
)
53 .Case(getSectionName(DebugSectionKind::DebugStr
),
54 DebugSectionKind::DebugStr
)
55 .Case(getSectionName(DebugSectionKind::DebugLineStr
),
56 DebugSectionKind::DebugLineStr
)
57 .Case(getSectionName(DebugSectionKind::DebugStrOffsets
),
58 DebugSectionKind::DebugStrOffsets
)
59 .Default(std::nullopt
);
64 DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset
, CompileUnit
*SrcCU
,
65 CompileUnit
*RefCU
, uint32_t RefIdx
)
66 : SectionPatch({PatchOffset
}),
67 RefCU(RefCU
, (SrcCU
!= nullptr) &&
68 (SrcCU
->getUniqueID() == RefCU
->getUniqueID())),
69 RefDieIdxOrClonedOffset(RefIdx
) {}
71 DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset
,
75 : SectionPatch({PatchOffset
}),
76 RefCU(RefCU
, SrcCU
->getUniqueID() == RefCU
->getUniqueID()),
77 RefDieIdxOrClonedOffset(RefIdx
) {}
79 void SectionDescriptor::erase() {
81 Contents
= OutSectionDataTy();
82 ListDebugStrPatch
.erase();
83 ListDebugLineStrPatch
.erase();
84 ListDebugRangePatch
.erase();
85 ListDebugLocPatch
.erase();
86 ListDebugDieRefPatch
.erase();
87 ListDebugULEB128DieRefPatch
.erase();
88 ListDebugOffsetPatch
.erase();
91 void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
95 MemoryBufferRef
Mem(Contents
, "obj");
96 Expected
<std::unique_ptr
<object::ObjectFile
>> Obj
=
97 object::ObjectFile::createObjectFile(Mem
);
99 consumeError(Obj
.takeError());
104 for (const object::SectionRef
&Sect
: (*Obj
).get()->sections()) {
105 Expected
<StringRef
> SectNameOrErr
= Sect
.getName();
106 if (!SectNameOrErr
) {
107 consumeError(SectNameOrErr
.takeError());
111 if (std::optional
<DebugSectionKind
> SectKind
=
112 parseDebugTableName(*SectNameOrErr
)) {
113 if (*SectKind
== SectionKind
) {
114 Expected
<StringRef
> Data
= Sect
.getContents();
116 consumeError(SectNameOrErr
.takeError());
121 SectionOffsetInsideAsmPrinterOutputStart
=
122 Data
->data() - Contents
.data();
123 SectionOffsetInsideAsmPrinterOutputEnd
=
124 SectionOffsetInsideAsmPrinterOutputStart
+ Data
->size();
130 void SectionDescriptor::emitIntVal(uint64_t Val
, unsigned Size
) {
133 OS
.write(static_cast<uint8_t>(Val
));
136 uint16_t ShortVal
= static_cast<uint16_t>(Val
);
137 if ((Endianess
== support::endianness::little
) != sys::IsLittleEndianHost
)
138 sys::swapByteOrder(ShortVal
);
139 OS
.write(reinterpret_cast<const char *>(&ShortVal
), Size
);
142 uint32_t ShortVal
= static_cast<uint32_t>(Val
);
143 if ((Endianess
== support::endianness::little
) != sys::IsLittleEndianHost
)
144 sys::swapByteOrder(ShortVal
);
145 OS
.write(reinterpret_cast<const char *>(&ShortVal
), Size
);
148 if ((Endianess
== support::endianness::little
) != sys::IsLittleEndianHost
)
149 sys::swapByteOrder(Val
);
150 OS
.write(reinterpret_cast<const char *>(&Val
), Size
);
153 llvm_unreachable("Unsupported integer type size");
157 void SectionDescriptor::emitString(dwarf::Form StringForm
,
158 const char *StringVal
) {
159 assert(StringVal
!= nullptr);
161 switch (StringForm
) {
162 case dwarf::DW_FORM_string
: {
163 emitInplaceString(GlobalData
.translateString(StringVal
));
165 case dwarf::DW_FORM_strp
: {
166 notePatch(DebugStrPatch
{
167 {OS
.tell()}, GlobalData
.getStringPool().insert(StringVal
).first
});
168 emitStringPlaceholder();
170 case dwarf::DW_FORM_line_strp
: {
171 notePatch(DebugLineStrPatch
{
172 {OS
.tell()}, GlobalData
.getStringPool().insert(StringVal
).first
});
173 emitStringPlaceholder();
176 llvm_unreachable("Unsupported string form");
181 void SectionDescriptor::apply(uint64_t PatchOffset
, dwarf::Form AttrForm
,
184 case dwarf::DW_FORM_strp
:
185 case dwarf::DW_FORM_line_strp
: {
186 applyIntVal(PatchOffset
, Val
, Format
.getDwarfOffsetByteSize());
189 case dwarf::DW_FORM_ref_addr
: {
190 applyIntVal(PatchOffset
, Val
, Format
.getRefAddrByteSize());
192 case dwarf::DW_FORM_ref1
: {
193 applyIntVal(PatchOffset
, Val
, 1);
195 case dwarf::DW_FORM_ref2
: {
196 applyIntVal(PatchOffset
, Val
, 2);
198 case dwarf::DW_FORM_ref4
: {
199 applyIntVal(PatchOffset
, Val
, 4);
201 case dwarf::DW_FORM_ref8
: {
202 applyIntVal(PatchOffset
, Val
, 8);
205 case dwarf::DW_FORM_data1
: {
206 applyIntVal(PatchOffset
, Val
, 1);
208 case dwarf::DW_FORM_data2
: {
209 applyIntVal(PatchOffset
, Val
, 2);
211 case dwarf::DW_FORM_data4
: {
212 applyIntVal(PatchOffset
, Val
, 4);
214 case dwarf::DW_FORM_data8
: {
215 applyIntVal(PatchOffset
, Val
, 8);
217 case dwarf::DW_FORM_udata
: {
218 applyULEB128(PatchOffset
, Val
);
220 case dwarf::DW_FORM_sdata
: {
221 applySLEB128(PatchOffset
, Val
);
223 case dwarf::DW_FORM_sec_offset
: {
224 applyIntVal(PatchOffset
, Val
, Format
.getDwarfOffsetByteSize());
226 case dwarf::DW_FORM_flag
: {
227 applyIntVal(PatchOffset
, Val
, 1);
231 llvm_unreachable("Unsupported attribute form");
236 uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset
, unsigned Size
) {
237 assert(PatchOffset
< getContents().size());
240 return *reinterpret_cast<const uint8_t *>(
241 (getContents().data() + PatchOffset
));
244 return support::endian::read16(getContents().data() + PatchOffset
,
248 return support::endian::read32(getContents().data() + PatchOffset
,
252 return support::endian::read64(getContents().data() + PatchOffset
,
256 llvm_unreachable("Unsupported integer type size");
260 void SectionDescriptor::applyIntVal(uint64_t PatchOffset
, uint64_t Val
,
262 assert(PatchOffset
< getContents().size());
266 support::endian::write(
267 const_cast<char *>(getContents().data() + PatchOffset
),
268 static_cast<uint8_t>(Val
), Endianess
);
271 support::endian::write(
272 const_cast<char *>(getContents().data() + PatchOffset
),
273 static_cast<uint16_t>(Val
), Endianess
);
276 support::endian::write(
277 const_cast<char *>(getContents().data() + PatchOffset
),
278 static_cast<uint32_t>(Val
), Endianess
);
281 support::endian::write(
282 const_cast<char *>(getContents().data() + PatchOffset
),
283 static_cast<uint64_t>(Val
), Endianess
);
286 llvm_unreachable("Unsupported integer type size");
290 void SectionDescriptor::applyULEB128(uint64_t PatchOffset
, uint64_t Val
) {
291 assert(PatchOffset
< getContents().size());
294 uint8_t DestSize
= Format
.getDwarfOffsetByteSize() + 1;
295 uint8_t RealSize
= encodeULEB128(Val
, ULEB
, DestSize
);
297 memcpy(const_cast<char *>(getContents().data() + PatchOffset
), ULEB
,
301 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
302 void SectionDescriptor::applySLEB128(uint64_t PatchOffset
, uint64_t Val
) {
303 assert(PatchOffset
< getContents().size());
306 uint8_t DestSize
= Format
.getDwarfOffsetByteSize() + 1;
307 uint8_t RealSize
= encodeSLEB128(Val
, SLEB
, DestSize
);
309 memcpy(const_cast<char *>(getContents().data() + PatchOffset
), SLEB
,
313 void OutputSections::applyPatches(
314 SectionDescriptor
&Section
,
315 StringEntryToDwarfStringPoolEntryMap
&DebugStrStrings
,
316 StringEntryToDwarfStringPoolEntryMap
&DebugLineStrStrings
) {
318 Section
.ListDebugStrPatch
.forEach([&](DebugStrPatch
&Patch
) {
319 DwarfStringPoolEntryWithExtString
*Entry
=
320 DebugStrStrings
.getExistingEntry(Patch
.String
);
321 assert(Entry
!= nullptr);
323 Section
.apply(Patch
.PatchOffset
, dwarf::DW_FORM_strp
, Entry
->Offset
);
326 Section
.ListDebugLineStrPatch
.forEach([&](DebugLineStrPatch
&Patch
) {
327 DwarfStringPoolEntryWithExtString
*Entry
=
328 DebugLineStrStrings
.getExistingEntry(Patch
.String
);
329 assert(Entry
!= nullptr);
331 Section
.apply(Patch
.PatchOffset
, dwarf::DW_FORM_line_strp
, Entry
->Offset
);
334 std::optional
<SectionDescriptor
*> RangeSection
;
335 if (Format
.Version
>= 5)
336 RangeSection
= getSectionDescriptor(DebugSectionKind::DebugRngLists
);
338 RangeSection
= getSectionDescriptor(DebugSectionKind::DebugRange
);
341 Section
.ListDebugRangePatch
.forEach([&](DebugRangePatch
&Patch
) {
342 uint64_t FinalValue
=
343 Section
.getIntVal(Patch
.PatchOffset
, Format
.getDwarfOffsetByteSize());
344 FinalValue
+= (*RangeSection
)->StartOffset
;
346 Section
.apply(Patch
.PatchOffset
, dwarf::DW_FORM_sec_offset
, FinalValue
);
350 std::optional
<SectionDescriptor
*> LocationSection
;
351 if (Format
.Version
>= 5)
352 LocationSection
= getSectionDescriptor(DebugSectionKind::DebugLocLists
);
354 LocationSection
= getSectionDescriptor(DebugSectionKind::DebugLoc
);
356 if (LocationSection
) {
357 Section
.ListDebugLocPatch
.forEach([&](DebugLocPatch
&Patch
) {
358 uint64_t FinalValue
=
359 Section
.getIntVal(Patch
.PatchOffset
, Format
.getDwarfOffsetByteSize());
360 FinalValue
+= (*LocationSection
)->StartOffset
;
362 Section
.apply(Patch
.PatchOffset
, dwarf::DW_FORM_sec_offset
, FinalValue
);
366 Section
.ListDebugDieRefPatch
.forEach([&](DebugDieRefPatch
&Patch
) {
367 uint64_t FinalOffset
= Patch
.RefDieIdxOrClonedOffset
;
368 dwarf::Form FinalForm
= dwarf::DW_FORM_ref4
;
370 if (!Patch
.RefCU
.getInt()) {
371 std::optional
<SectionDescriptor
*> ReferencedSectionDescriptor
=
372 Patch
.RefCU
.getPointer()->getSectionDescriptor(
373 DebugSectionKind::DebugInfo
);
374 if (!ReferencedSectionDescriptor
) {
375 // Referenced section should be already created at this point.
376 llvm_unreachable("Referenced section does not exist");
379 FinalForm
= dwarf::DW_FORM_ref_addr
;
380 FinalOffset
+= (*ReferencedSectionDescriptor
)->StartOffset
;
383 Section
.apply(Patch
.PatchOffset
, FinalForm
, FinalOffset
);
386 Section
.ListDebugULEB128DieRefPatch
.forEach(
387 [&](DebugULEB128DieRefPatch
&Patch
) {
388 assert(Patch
.RefCU
.getInt());
389 Section
.apply(Patch
.PatchOffset
, dwarf::DW_FORM_udata
,
390 Patch
.RefDieIdxOrClonedOffset
);
393 Section
.ListDebugOffsetPatch
.forEach([&](DebugOffsetPatch
&Patch
) {
394 uint64_t FinalValue
= Patch
.SectionPtr
.getPointer()->StartOffset
;
395 if (Patch
.SectionPtr
.getInt())
397 Section
.getIntVal(Patch
.PatchOffset
, Format
.getDwarfOffsetByteSize());
399 Section
.apply(Patch
.PatchOffset
, dwarf::DW_FORM_sec_offset
, FinalValue
);
403 } // end of namespace dwarflinker_parallel
404 } // end of namespace llvm