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", "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
);
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
,
91 : SectionPatch({PatchOffset
}),
92 RefCU(RefCU
, SrcCU
->getUniqueID() == RefCU
->getUniqueID()),
93 RefDieIdxOrClonedOffset(RefIdx
) {}
95 void SectionDescriptor::clearAllSectionData() {
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())
113 MemoryBufferRef
Mem(Contents
, "obj");
114 Expected
<std::unique_ptr
<object::ObjectFile
>> Obj
=
115 object::ObjectFile::createObjectFile(Mem
);
117 consumeError(Obj
.takeError());
122 for (const object::SectionRef
&Sect
: (*Obj
).get()->sections()) {
123 Expected
<StringRef
> SectNameOrErr
= Sect
.getName();
124 if (!SectNameOrErr
) {
125 consumeError(SectNameOrErr
.takeError());
128 if (std::optional
<DebugSectionKind
> SectKind
=
129 parseDebugTableName(*SectNameOrErr
)) {
130 if (*SectKind
== SectionKind
) {
131 Expected
<StringRef
> Data
= Sect
.getContents();
133 consumeError(SectNameOrErr
.takeError());
138 SectionOffsetInsideAsmPrinterOutputStart
=
139 Data
->data() - Contents
.data();
140 SectionOffsetInsideAsmPrinterOutputEnd
=
141 SectionOffsetInsideAsmPrinterOutputStart
+ Data
->size();
147 void SectionDescriptor::emitIntVal(uint64_t Val
, unsigned Size
) {
150 OS
.write(static_cast<uint8_t>(Val
));
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
);
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
);
165 if (Endianess
!= llvm::endianness::native
)
166 sys::swapByteOrder(Val
);
167 OS
.write(reinterpret_cast<const char *>(&Val
), Size
);
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
);
182 case dwarf::DW_FORM_strp
: {
183 notePatch(DebugStrPatch
{
184 {OS
.tell()}, GlobalData
.getStringPool().insert(StringVal
).first
});
185 emitStringPlaceholder();
187 case dwarf::DW_FORM_line_strp
: {
188 notePatch(DebugLineStrPatch
{
189 {OS
.tell()}, GlobalData
.getStringPool().insert(StringVal
).first
});
190 emitStringPlaceholder();
193 llvm_unreachable("Unsupported string form");
198 void SectionDescriptor::apply(uint64_t PatchOffset
, dwarf::Form AttrForm
,
201 case dwarf::DW_FORM_strp
:
202 case dwarf::DW_FORM_line_strp
: {
203 applyIntVal(PatchOffset
, Val
, Format
.getDwarfOffsetByteSize());
206 case dwarf::DW_FORM_ref_addr
: {
207 applyIntVal(PatchOffset
, Val
, Format
.getRefAddrByteSize());
209 case dwarf::DW_FORM_ref1
: {
210 applyIntVal(PatchOffset
, Val
, 1);
212 case dwarf::DW_FORM_ref2
: {
213 applyIntVal(PatchOffset
, Val
, 2);
215 case dwarf::DW_FORM_ref4
: {
216 applyIntVal(PatchOffset
, Val
, 4);
218 case dwarf::DW_FORM_ref8
: {
219 applyIntVal(PatchOffset
, Val
, 8);
222 case dwarf::DW_FORM_data1
: {
223 applyIntVal(PatchOffset
, Val
, 1);
225 case dwarf::DW_FORM_data2
: {
226 applyIntVal(PatchOffset
, Val
, 2);
228 case dwarf::DW_FORM_data4
: {
229 applyIntVal(PatchOffset
, Val
, 4);
231 case dwarf::DW_FORM_data8
: {
232 applyIntVal(PatchOffset
, Val
, 8);
234 case dwarf::DW_FORM_udata
: {
235 applyULEB128(PatchOffset
, Val
);
237 case dwarf::DW_FORM_sdata
: {
238 applySLEB128(PatchOffset
, Val
);
240 case dwarf::DW_FORM_sec_offset
: {
241 applyIntVal(PatchOffset
, Val
, Format
.getDwarfOffsetByteSize());
243 case dwarf::DW_FORM_flag
: {
244 applyIntVal(PatchOffset
, Val
, 1);
248 llvm_unreachable("Unsupported attribute form");
253 uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset
, unsigned Size
) {
254 assert(PatchOffset
< getContents().size());
257 return *reinterpret_cast<const uint8_t *>(
258 (getContents().data() + PatchOffset
));
261 return support::endian::read16(getContents().data() + PatchOffset
,
265 return support::endian::read32(getContents().data() + PatchOffset
,
269 return support::endian::read64(getContents().data() + PatchOffset
,
273 llvm_unreachable("Unsupported integer type size");
277 void SectionDescriptor::applyIntVal(uint64_t PatchOffset
, uint64_t Val
,
279 assert(PatchOffset
< getContents().size());
283 support::endian::write(
284 const_cast<char *>(getContents().data() + PatchOffset
),
285 static_cast<uint8_t>(Val
), Endianess
);
288 support::endian::write(
289 const_cast<char *>(getContents().data() + PatchOffset
),
290 static_cast<uint16_t>(Val
), Endianess
);
293 support::endian::write(
294 const_cast<char *>(getContents().data() + PatchOffset
),
295 static_cast<uint32_t>(Val
), Endianess
);
298 support::endian::write(
299 const_cast<char *>(getContents().data() + PatchOffset
),
300 static_cast<uint64_t>(Val
), Endianess
);
303 llvm_unreachable("Unsupported integer type size");
307 void SectionDescriptor::applyULEB128(uint64_t PatchOffset
, uint64_t Val
) {
308 assert(PatchOffset
< getContents().size());
311 uint8_t DestSize
= Format
.getDwarfOffsetByteSize() + 1;
312 uint8_t RealSize
= encodeULEB128(Val
, ULEB
, DestSize
);
314 memcpy(const_cast<char *>(getContents().data() + PatchOffset
), ULEB
,
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());
323 uint8_t DestSize
= Format
.getDwarfOffsetByteSize() + 1;
324 uint8_t RealSize
= encodeSLEB128(Val
, SLEB
, DestSize
);
326 memcpy(const_cast<char *>(getContents().data() + PatchOffset
), SLEB
,
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
);
355 RangeSection
= tryGetSectionDescriptor(DebugSectionKind::DebugRange
);
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
);
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())
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