1 //===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//
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 // This file implements functions and classes for handling debug info.
11 //===----------------------------------------------------------------------===//
13 #include "bolt/Core/DebugData.h"
14 #include "bolt/Core/BinaryContext.h"
15 #include "bolt/Core/DIEBuilder.h"
16 #include "bolt/Utils/Utils.h"
17 #include "llvm/BinaryFormat/Dwarf.h"
18 #include "llvm/CodeGen/DIE.h"
19 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
20 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
22 #include "llvm/MC/MCAssembler.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCObjectStreamer.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/EndianStream.h"
27 #include "llvm/Support/LEB128.h"
28 #include "llvm/Support/SHA1.h"
35 #include <unordered_map>
38 #define DEBUG_TYPE "bolt-debug-info"
41 extern llvm::cl::opt
<unsigned> Verbosity
;
49 static void replaceLocValbyForm(DIEBuilder
&DIEBldr
, DIE
&Die
, DIEValue DIEVal
,
50 dwarf::Form Format
, uint64_t NewVal
) {
51 if (Format
== dwarf::DW_FORM_loclistx
)
52 DIEBldr
.replaceValue(&Die
, DIEVal
.getAttribute(), Format
,
55 DIEBldr
.replaceValue(&Die
, DIEVal
.getAttribute(), Format
,
59 std::optional
<AttrInfo
>
60 findAttributeInfo(const DWARFDie DIE
,
61 const DWARFAbbreviationDeclaration
*AbbrevDecl
,
63 const DWARFUnit
&U
= *DIE
.getDwarfUnit();
65 AbbrevDecl
->getAttributeOffsetFromIndex(Index
, DIE
.getOffset(), U
);
66 std::optional
<DWARFFormValue
> Value
=
67 AbbrevDecl
->getAttributeValueFromOffset(Index
, Offset
, U
);
71 const DWARFAbbreviationDeclaration::AttributeSpec
*AttrVal
=
72 AbbrevDecl
->attributes().begin() + Index
;
74 std::optional
<int64_t> ValSizeOpt
= AttrVal
->getByteSize(U
);
76 ValSize
= static_cast<uint32_t>(*ValSizeOpt
);
78 DWARFDataExtractor DebugInfoData
= U
.getDebugInfoExtractor();
79 uint64_t NewOffset
= Offset
;
80 DWARFFormValue::skipValue(Value
->getForm(), DebugInfoData
, &NewOffset
,
82 // This includes entire size of the entry, which might not be just the
83 // encoding part. For example for DW_AT_loc it will include expression
85 ValSize
= NewOffset
- Offset
;
87 return AttrInfo
{*Value
, DIE
.getAbbreviationDeclarationPtr(), Offset
, ValSize
};
90 std::optional
<AttrInfo
> findAttributeInfo(const DWARFDie DIE
,
91 dwarf::Attribute Attr
) {
94 const DWARFAbbreviationDeclaration
*AbbrevDecl
=
95 DIE
.getAbbreviationDeclarationPtr();
98 std::optional
<uint32_t> Index
= AbbrevDecl
->findAttributeIndex(Attr
);
101 return findAttributeInfo(DIE
, AbbrevDecl
, *Index
);
104 const DebugLineTableRowRef
DebugLineTableRowRef::NULL_ROW
{0, 0};
106 LLVM_ATTRIBUTE_UNUSED
107 static void printLE64(const std::string
&S
) {
108 for (uint32_t I
= 0, Size
= S
.size(); I
< Size
; ++I
) {
109 errs() << Twine::utohexstr(S
[I
]);
110 errs() << Twine::utohexstr((int8_t)S
[I
]);
115 // Writes address ranges to Writer as pairs of 64-bit (address, size).
116 // If RelativeRange is true, assumes the address range to be written must be of
117 // the form (begin address, range size), otherwise (begin address, end address).
118 // Terminates the list by writing a pair of two zeroes.
119 // Returns the number of written bytes.
121 writeAddressRanges(raw_svector_ostream
&Stream
,
122 const DebugAddressRangesVector
&AddressRanges
,
123 const bool WriteRelativeRanges
= false) {
124 for (const DebugAddressRange
&Range
: AddressRanges
) {
125 support::endian::write(Stream
, Range
.LowPC
, llvm::endianness::little
);
126 support::endian::write(
127 Stream
, WriteRelativeRanges
? Range
.HighPC
- Range
.LowPC
: Range
.HighPC
,
128 llvm::endianness::little
);
130 // Finish with 0 entries.
131 support::endian::write(Stream
, 0ULL, llvm::endianness::little
);
132 support::endian::write(Stream
, 0ULL, llvm::endianness::little
);
133 return AddressRanges
.size() * 16 + 16;
136 DebugRangesSectionWriter::DebugRangesSectionWriter() {
137 RangesBuffer
= std::make_unique
<DebugBufferVector
>();
138 RangesStream
= std::make_unique
<raw_svector_ostream
>(*RangesBuffer
);
140 Kind
= RangesWriterKind::DebugRangesWriter
;
143 void DebugRangesSectionWriter::initSection() {
144 // Adds an empty range to the buffer.
145 writeAddressRanges(*RangesStream
.get(), DebugAddressRangesVector
{});
148 uint64_t DebugRangesSectionWriter::addRanges(
149 DebugAddressRangesVector
&&Ranges
,
150 std::map
<DebugAddressRangesVector
, uint64_t> &CachedRanges
) {
152 return getEmptyRangesOffset();
154 const auto RI
= CachedRanges
.find(Ranges
);
155 if (RI
!= CachedRanges
.end())
158 const uint64_t EntryOffset
= addRanges(Ranges
);
159 CachedRanges
.emplace(std::move(Ranges
), EntryOffset
);
164 uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector
&Ranges
) {
166 return getEmptyRangesOffset();
168 // Reading the SectionOffset and updating it should be atomic to guarantee
169 // unique and correct offsets in patches.
170 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
171 const uint32_t EntryOffset
= RangesBuffer
->size();
172 writeAddressRanges(*RangesStream
.get(), Ranges
);
177 uint64_t DebugRangesSectionWriter::getSectionOffset() {
178 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
179 return RangesBuffer
->size();
182 void DebugRangesSectionWriter::appendToRangeBuffer(
183 const DebugBufferVector
&CUBuffer
) {
184 *RangesStream
<< CUBuffer
;
187 uint64_t DebugRangeListsSectionWriter::addRanges(
188 DebugAddressRangesVector
&&Ranges
,
189 std::map
<DebugAddressRangesVector
, uint64_t> &CachedRanges
) {
190 return addRanges(Ranges
);
193 struct LocListsRangelistsHeader
{
194 UnitLengthType UnitLength
; // Size of loclist entries section, not including
197 AddressSizeType AddressSize
;
198 SegmentSelectorType SegmentSelector
;
199 OffsetEntryCountType OffsetEntryCount
;
202 static std::unique_ptr
<DebugBufferVector
>
203 getDWARF5Header(const LocListsRangelistsHeader
&Header
) {
204 std::unique_ptr
<DebugBufferVector
> HeaderBuffer
=
205 std::make_unique
<DebugBufferVector
>();
206 std::unique_ptr
<raw_svector_ostream
> HeaderStream
=
207 std::make_unique
<raw_svector_ostream
>(*HeaderBuffer
);
209 // 7.29 length of the set of entries for this compilation unit, not including
210 // the length field itself
211 const uint32_t HeaderSize
=
212 getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType
);
214 support::endian::write(*HeaderStream
, Header
.UnitLength
+ HeaderSize
,
215 llvm::endianness::little
);
216 support::endian::write(*HeaderStream
, Header
.Version
,
217 llvm::endianness::little
);
218 support::endian::write(*HeaderStream
, Header
.AddressSize
,
219 llvm::endianness::little
);
220 support::endian::write(*HeaderStream
, Header
.SegmentSelector
,
221 llvm::endianness::little
);
222 support::endian::write(*HeaderStream
, Header
.OffsetEntryCount
,
223 llvm::endianness::little
);
229 uint32_t StartOffset
;
232 template <typename DebugVector
, typename ListEntry
, typename DebugAddressEntry
>
233 static bool emitWithBase(raw_ostream
&OS
, const DebugVector
&Entries
,
234 DebugAddrWriter
&AddrWriter
, DWARFUnit
&CU
,
235 uint32_t &Index
, const ListEntry BaseAddressx
,
236 const ListEntry OffsetPair
,
237 const std::function
<void(uint32_t)> &Func
) {
238 if (Entries
.size() < 2)
240 uint64_t Base
= Entries
[Index
].LowPC
;
241 std::vector
<OffsetEntry
> Offsets
;
242 uint8_t TempBuffer
[64];
243 while (Index
< Entries
.size()) {
244 const DebugAddressEntry
&Entry
= Entries
[Index
];
245 if (Entry
.LowPC
== 0)
247 // In case rnglists or loclists are not sorted.
248 if (Base
> Entry
.LowPC
)
250 uint32_t StartOffset
= Entry
.LowPC
- Base
;
251 uint32_t EndOffset
= Entry
.HighPC
- Base
;
252 if (encodeULEB128(EndOffset
, TempBuffer
) > 2)
254 Offsets
.push_back({Index
, StartOffset
, EndOffset
});
258 if (Offsets
.size() < 2) {
259 Index
-= Offsets
.size();
263 support::endian::write(OS
, static_cast<uint8_t>(BaseAddressx
),
264 llvm::endianness::little
);
265 uint32_t BaseIndex
= AddrWriter
.getIndexFromAddress(Base
, CU
);
266 encodeULEB128(BaseIndex
, OS
);
267 for (auto &OffsetEntry
: Offsets
) {
268 support::endian::write(OS
, static_cast<uint8_t>(OffsetPair
),
269 llvm::endianness::little
);
270 encodeULEB128(OffsetEntry
.StartOffset
, OS
);
271 encodeULEB128(OffsetEntry
.EndOffset
, OS
);
272 Func(OffsetEntry
.Index
);
278 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector
&Ranges
) {
279 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
281 RangeEntries
.push_back(CurrentOffset
);
283 Ranges
.begin(), Ranges
.end(),
284 [](const DebugAddressRange
&R1
, const DebugAddressRange
&R2
) -> bool {
285 return R1
.LowPC
< R2
.LowPC
;
287 for (unsigned I
= 0; I
< Ranges
.size();) {
288 if (emitWithBase
<DebugAddressRangesVector
, dwarf::RnglistEntries
,
289 DebugAddressRange
>(*CUBodyStream
, Ranges
, *AddrWriter
, *CU
,
290 I
, dwarf::DW_RLE_base_addressx
,
291 dwarf::DW_RLE_offset_pair
,
292 [](uint32_t Index
) -> void {}))
295 const DebugAddressRange
&Range
= Ranges
[I
];
296 support::endian::write(*CUBodyStream
,
297 static_cast<uint8_t>(dwarf::DW_RLE_startx_length
),
298 llvm::endianness::little
);
299 uint32_t Index
= AddrWriter
->getIndexFromAddress(Range
.LowPC
, *CU
);
300 encodeULEB128(Index
, *CUBodyStream
);
301 encodeULEB128(Range
.HighPC
- Range
.LowPC
, *CUBodyStream
);
305 support::endian::write(*CUBodyStream
,
306 static_cast<uint8_t>(dwarf::DW_RLE_end_of_list
),
307 llvm::endianness::little
);
308 CurrentOffset
= CUBodyBuffer
->size();
309 return RangeEntries
.size() - 1;
312 void DebugRangeListsSectionWriter::finalizeSection() {
313 std::unique_ptr
<DebugBufferVector
> CUArrayBuffer
=
314 std::make_unique
<DebugBufferVector
>();
315 std::unique_ptr
<raw_svector_ostream
> CUArrayStream
=
316 std::make_unique
<raw_svector_ostream
>(*CUArrayBuffer
);
317 constexpr uint32_t SizeOfArrayEntry
= 4;
318 const uint32_t SizeOfArraySection
= RangeEntries
.size() * SizeOfArrayEntry
;
319 for (uint32_t Offset
: RangeEntries
)
320 support::endian::write(*CUArrayStream
, Offset
+ SizeOfArraySection
,
321 llvm::endianness::little
);
323 std::unique_ptr
<DebugBufferVector
> Header
= getDWARF5Header(
324 {static_cast<uint32_t>(SizeOfArraySection
+ CUBodyBuffer
.get()->size()),
325 5, 8, 0, static_cast<uint32_t>(RangeEntries
.size())});
326 *RangesStream
<< *Header
;
327 *RangesStream
<< *CUArrayBuffer
;
328 *RangesStream
<< *CUBodyBuffer
;
331 void DebugRangeListsSectionWriter::initSection(DWARFUnit
&Unit
) {
332 CUBodyBuffer
= std::make_unique
<DebugBufferVector
>();
333 CUBodyStream
= std::make_unique
<raw_svector_ostream
>(*CUBodyBuffer
);
334 RangeEntries
.clear();
339 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset
,
340 DebugAddressRangesVector
&&Ranges
) {
341 std::lock_guard
<std::mutex
> Lock(CUAddressRangesMutex
);
342 CUAddressRanges
.emplace(CUOffset
, std::move(Ranges
));
345 void DebugARangesSectionWriter::writeARangesSection(
346 raw_svector_ostream
&RangesStream
, const CUOffsetMap
&CUMap
) const {
347 // For reference on the format of the .debug_aranges section, see the DWARF4
348 // specification, section 6.1.4 Lookup by Address
349 // http://www.dwarfstd.org/doc/DWARF4.pdf
350 for (const auto &CUOffsetAddressRangesPair
: CUAddressRanges
) {
351 const uint64_t Offset
= CUOffsetAddressRangesPair
.first
;
352 const DebugAddressRangesVector
&AddressRanges
=
353 CUOffsetAddressRangesPair
.second
;
357 // Size of this set: 8 (size of the header) + 4 (padding after header)
358 // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
359 // pair of uint64_t's for the terminating, zero-length range.
360 // Does not include size field itself.
361 uint32_t Size
= 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges
.size() + 1);
363 // Header field #1: set size.
364 support::endian::write(RangesStream
, Size
, llvm::endianness::little
);
366 // Header field #2: version number, 2 as per the specification.
367 support::endian::write(RangesStream
, static_cast<uint16_t>(2),
368 llvm::endianness::little
);
370 assert(CUMap
.count(Offset
) && "Original CU offset is not found in CU Map");
371 // Header field #3: debug info offset of the correspondent compile unit.
372 support::endian::write(
373 RangesStream
, static_cast<uint32_t>(CUMap
.find(Offset
)->second
.Offset
),
374 llvm::endianness::little
);
376 // Header field #4: address size.
377 // 8 since we only write ELF64 binaries for now.
378 RangesStream
<< char(8);
380 // Header field #5: segment size of target architecture.
381 RangesStream
<< char(0);
383 // Padding before address table - 4 bytes in the 64-bit-pointer case.
384 support::endian::write(RangesStream
, static_cast<uint32_t>(0),
385 llvm::endianness::little
);
387 writeAddressRanges(RangesStream
, AddressRanges
, true);
391 DebugAddrWriter::DebugAddrWriter(BinaryContext
*BC
,
392 const uint8_t AddressByteSize
)
393 : BC(BC
), AddressByteSize(AddressByteSize
) {
394 Buffer
= std::make_unique
<AddressSectionBuffer
>();
395 AddressStream
= std::make_unique
<raw_svector_ostream
>(*Buffer
);
398 void DebugAddrWriter::AddressForDWOCU::dump() {
399 std::vector
<IndexAddressPair
> SortedMap(indexToAddressBegin(),
400 indexToAdddessEnd());
401 // Sorting address in increasing order of indices.
402 llvm::sort(SortedMap
, llvm::less_first());
403 for (auto &Pair
: SortedMap
)
404 dbgs() << Twine::utohexstr(Pair
.second
) << "\t" << Pair
.first
<< "\n";
406 uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address
, DWARFUnit
&CU
) {
407 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
408 auto Entry
= Map
.find(Address
);
409 if (Entry
== Map
.end()) {
410 auto Index
= Map
.getNextIndex();
411 Entry
= Map
.insert(Address
, Index
).first
;
413 return Entry
->second
;
416 static void updateAddressBase(DIEBuilder
&DIEBlder
, DebugAddrWriter
&AddrWriter
,
417 DWARFUnit
&CU
, const uint64_t Offset
) {
418 DIE
*Die
= DIEBlder
.getUnitDIEbyUnit(CU
);
419 DIEValue GnuAddrBaseAttrInfo
= Die
->findAttribute(dwarf::DW_AT_GNU_addr_base
);
420 DIEValue AddrBaseAttrInfo
= Die
->findAttribute(dwarf::DW_AT_addr_base
);
421 dwarf::Form BaseAttrForm
;
422 dwarf::Attribute BaseAttr
;
423 // For cases where Skeleton CU does not have DW_AT_GNU_addr_base
424 if (!GnuAddrBaseAttrInfo
&& CU
.getVersion() < 5)
427 if (GnuAddrBaseAttrInfo
) {
428 BaseAttrForm
= GnuAddrBaseAttrInfo
.getForm();
429 BaseAttr
= GnuAddrBaseAttrInfo
.getAttribute();
432 if (AddrBaseAttrInfo
) {
433 BaseAttrForm
= AddrBaseAttrInfo
.getForm();
434 BaseAttr
= AddrBaseAttrInfo
.getAttribute();
437 if (GnuAddrBaseAttrInfo
|| AddrBaseAttrInfo
) {
438 DIEBlder
.replaceValue(Die
, BaseAttr
, BaseAttrForm
, DIEInteger(Offset
));
439 } else if (CU
.getVersion() >= 5) {
440 // A case where we were not using .debug_addr section, but after update
442 DIEBlder
.addValue(Die
, dwarf::DW_AT_addr_base
, dwarf::DW_FORM_sec_offset
,
447 void DebugAddrWriter::updateAddrBase(DIEBuilder
&DIEBlder
, DWARFUnit
&CU
,
448 const uint64_t Offset
) {
449 updateAddressBase(DIEBlder
, *this, CU
, Offset
);
452 std::optional
<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize
) {
453 if (Map
.begin() == Map
.end())
455 std::vector
<IndexAddressPair
> SortedMap(Map
.indexToAddressBegin(),
456 Map
.indexToAdddessEnd());
457 // Sorting address in increasing order of indices.
458 llvm::sort(SortedMap
, llvm::less_first());
460 uint32_t Counter
= 0;
461 auto WriteAddress
= [&](uint64_t Address
) -> void {
463 switch (AddressByteSize
) {
465 assert(false && "Address Size is invalid.");
468 support::endian::write(*AddressStream
, static_cast<uint32_t>(Address
),
469 llvm::endianness::little
);
472 support::endian::write(*AddressStream
, Address
, llvm::endianness::little
);
477 for (const IndexAddressPair
&Val
: SortedMap
) {
478 while (Val
.first
> Counter
)
480 WriteAddress(Val
.second
);
485 void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder
&DIEBlder
, DWARFUnit
&CU
,
486 const uint64_t Offset
) {
487 /// Header for DWARF5 has size 8, so we add it to the offset.
488 updateAddressBase(DIEBlder
, *this, CU
, Offset
+ HeaderSize
);
491 DenseMap
<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets
;
493 std::optional
<uint64_t>
494 DebugAddrWriterDwarf5::finalize(const size_t BufferSize
) {
495 // Need to layout all sections within .debug_addr
496 // Within each section sort Address by index.
497 const endianness Endian
= BC
->DwCtx
->isLittleEndian()
498 ? llvm::endianness::little
499 : llvm::endianness::big
;
500 const DWARFSection
&AddrSec
= BC
->DwCtx
->getDWARFObj().getAddrSection();
501 DWARFDataExtractor
AddrData(BC
->DwCtx
->getDWARFObj(), AddrSec
,
502 Endian
== llvm::endianness::little
, 0);
503 DWARFDebugAddrTable AddrTable
;
504 DIDumpOptions DumpOpts
;
505 // A case where CU has entry in .debug_addr, but we don't modify addresses
507 if (Map
.begin() == Map
.end()) {
508 if (!AddrOffsetSectionBase
)
510 // Address base offset is to the first entry.
511 // The size of header is 8 bytes.
512 uint64_t Offset
= *AddrOffsetSectionBase
- HeaderSize
;
513 auto Iter
= UnmodifiedAddressOffsets
.find(Offset
);
514 if (Iter
!= UnmodifiedAddressOffsets
.end())
516 UnmodifiedAddressOffsets
[Offset
] = BufferSize
;
517 if (Error Err
= AddrTable
.extract(AddrData
, &Offset
, 5, AddressByteSize
,
518 DumpOpts
.WarningHandler
)) {
519 DumpOpts
.RecoverableErrorHandler(std::move(Err
));
523 for (uint64_t Addr
: AddrTable
.getAddressEntries())
524 Map
.insert(Addr
, Index
++);
527 std::vector
<IndexAddressPair
> SortedMap(Map
.indexToAddressBegin(),
528 Map
.indexToAdddessEnd());
529 // Sorting address in increasing order of indices.
530 llvm::sort(SortedMap
, llvm::less_first());
531 // Writing out Header
532 const uint32_t Length
= SortedMap
.size() * AddressByteSize
+ 4;
533 support::endian::write(*AddressStream
, Length
, Endian
);
534 support::endian::write(*AddressStream
, static_cast<uint16_t>(5), Endian
);
535 support::endian::write(*AddressStream
, static_cast<uint8_t>(AddressByteSize
),
537 support::endian::write(*AddressStream
, static_cast<uint8_t>(0), Endian
);
539 uint32_t Counter
= 0;
540 auto writeAddress
= [&](uint64_t Address
) -> void {
542 switch (AddressByteSize
) {
544 llvm_unreachable("Address Size is invalid.");
547 support::endian::write(*AddressStream
, static_cast<uint32_t>(Address
),
551 support::endian::write(*AddressStream
, Address
, Endian
);
556 for (const IndexAddressPair
&Val
: SortedMap
) {
557 while (Val
.first
> Counter
)
559 writeAddress(Val
.second
);
564 void DebugLocWriter::init() {
565 LocBuffer
= std::make_unique
<DebugBufferVector
>();
566 LocStream
= std::make_unique
<raw_svector_ostream
>(*LocBuffer
);
567 // Writing out empty location list to which all references to empty location
569 if (!LocSectionOffset
&& DwarfVersion
< 5) {
570 const char Zeroes
[16] = {0};
571 *LocStream
<< StringRef(Zeroes
, 16);
572 LocSectionOffset
+= 16;
576 uint32_t DebugLocWriter::LocSectionOffset
= 0;
577 void DebugLocWriter::addList(DIEBuilder
&DIEBldr
, DIE
&Die
, DIEValue
&AttrInfo
,
578 DebugLocationsVector
&LocList
) {
579 if (LocList
.empty()) {
580 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(),
581 DebugLocWriter::EmptyListOffset
);
584 // Since there is a separate DebugLocWriter for each thread,
585 // we don't need a lock to read the SectionOffset and update it.
586 const uint32_t EntryOffset
= LocSectionOffset
;
588 for (const DebugLocationEntry
&Entry
: LocList
) {
589 support::endian::write(*LocStream
, static_cast<uint64_t>(Entry
.LowPC
),
590 llvm::endianness::little
);
591 support::endian::write(*LocStream
, static_cast<uint64_t>(Entry
.HighPC
),
592 llvm::endianness::little
);
593 support::endian::write(*LocStream
, static_cast<uint16_t>(Entry
.Expr
.size()),
594 llvm::endianness::little
);
595 *LocStream
<< StringRef(reinterpret_cast<const char *>(Entry
.Expr
.data()),
597 LocSectionOffset
+= 2 * 8 + 2 + Entry
.Expr
.size();
599 LocStream
->write_zeros(16);
600 LocSectionOffset
+= 16;
601 LocListDebugInfoPatches
.push_back({0xdeadbeee, EntryOffset
}); // never seen
603 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(), EntryOffset
);
606 std::unique_ptr
<DebugBufferVector
> DebugLocWriter::getBuffer() {
607 return std::move(LocBuffer
);
611 void DebugLocWriter::finalize(DIEBuilder
&DIEBldr
, DIE
&Die
) {}
613 static void writeEmptyListDwarf5(raw_svector_ostream
&Stream
) {
614 support::endian::write(Stream
, static_cast<uint32_t>(4),
615 llvm::endianness::little
);
616 support::endian::write(Stream
, static_cast<uint8_t>(dwarf::DW_LLE_start_end
),
617 llvm::endianness::little
);
619 const char Zeroes
[16] = {0};
620 Stream
<< StringRef(Zeroes
, 16);
621 encodeULEB128(0, Stream
);
622 support::endian::write(Stream
,
623 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list
),
624 llvm::endianness::little
);
627 static void writeLegacyLocList(DIEValue
&AttrInfo
,
628 DebugLocationsVector
&LocList
,
629 DIEBuilder
&DIEBldr
, DIE
&Die
,
630 DebugAddrWriter
&AddrWriter
,
631 DebugBufferVector
&LocBuffer
, DWARFUnit
&CU
,
632 raw_svector_ostream
&LocStream
) {
633 if (LocList
.empty()) {
634 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(),
635 DebugLocWriter::EmptyListOffset
);
639 const uint32_t EntryOffset
= LocBuffer
.size();
640 for (const DebugLocationEntry
&Entry
: LocList
) {
641 support::endian::write(LocStream
,
642 static_cast<uint8_t>(dwarf::DW_LLE_startx_length
),
643 llvm::endianness::little
);
644 const uint32_t Index
= AddrWriter
.getIndexFromAddress(Entry
.LowPC
, CU
);
645 encodeULEB128(Index
, LocStream
);
647 support::endian::write(LocStream
,
648 static_cast<uint32_t>(Entry
.HighPC
- Entry
.LowPC
),
649 llvm::endianness::little
);
650 support::endian::write(LocStream
, static_cast<uint16_t>(Entry
.Expr
.size()),
651 llvm::endianness::little
);
652 LocStream
<< StringRef(reinterpret_cast<const char *>(Entry
.Expr
.data()),
655 support::endian::write(LocStream
,
656 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list
),
657 llvm::endianness::little
);
658 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(), EntryOffset
);
661 static void writeDWARF5LocList(uint32_t &NumberOfEntries
, DIEValue
&AttrInfo
,
662 DebugLocationsVector
&LocList
, DIE
&Die
,
663 DIEBuilder
&DIEBldr
, DebugAddrWriter
&AddrWriter
,
664 DebugBufferVector
&LocBodyBuffer
,
665 std::vector
<uint32_t> &RelativeLocListOffsets
,
667 raw_svector_ostream
&LocBodyStream
) {
669 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, dwarf::DW_FORM_loclistx
,
672 RelativeLocListOffsets
.push_back(LocBodyBuffer
.size());
674 if (LocList
.empty()) {
675 writeEmptyListDwarf5(LocBodyStream
);
679 std::vector
<uint64_t> OffsetsArray
;
680 auto writeExpression
= [&](uint32_t Index
) -> void {
681 const DebugLocationEntry
&Entry
= LocList
[Index
];
682 encodeULEB128(Entry
.Expr
.size(), LocBodyStream
);
683 LocBodyStream
<< StringRef(
684 reinterpret_cast<const char *>(Entry
.Expr
.data()), Entry
.Expr
.size());
686 for (unsigned I
= 0; I
< LocList
.size();) {
687 if (emitWithBase
<DebugLocationsVector
, dwarf::LoclistEntries
,
688 DebugLocationEntry
>(LocBodyStream
, LocList
, AddrWriter
, CU
,
689 I
, dwarf::DW_LLE_base_addressx
,
690 dwarf::DW_LLE_offset_pair
,
694 const DebugLocationEntry
&Entry
= LocList
[I
];
695 support::endian::write(LocBodyStream
,
696 static_cast<uint8_t>(dwarf::DW_LLE_startx_length
),
697 llvm::endianness::little
);
698 const uint32_t Index
= AddrWriter
.getIndexFromAddress(Entry
.LowPC
, CU
);
699 encodeULEB128(Index
, LocBodyStream
);
700 encodeULEB128(Entry
.HighPC
- Entry
.LowPC
, LocBodyStream
);
705 support::endian::write(LocBodyStream
,
706 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list
),
707 llvm::endianness::little
);
710 void DebugLoclistWriter::addList(DIEBuilder
&DIEBldr
, DIE
&Die
,
712 DebugLocationsVector
&LocList
) {
713 if (DwarfVersion
< 5)
714 writeLegacyLocList(AttrInfo
, LocList
, DIEBldr
, Die
, AddrWriter
, *LocBuffer
,
717 writeDWARF5LocList(NumberOfEntries
, AttrInfo
, LocList
, Die
, DIEBldr
,
718 AddrWriter
, *LocBodyBuffer
, RelativeLocListOffsets
, CU
,
722 uint32_t DebugLoclistWriter::LoclistBaseOffset
= 0;
723 void DebugLoclistWriter::finalizeDWARF5(DIEBuilder
&DIEBldr
, DIE
&Die
) {
724 if (LocBodyBuffer
->empty()) {
725 DIEValue LocListBaseAttrInfo
=
726 Die
.findAttribute(dwarf::DW_AT_loclists_base
);
727 // Pointing to first one, because it doesn't matter. There are no uses of it
729 if (!isSplitDwarf() && LocListBaseAttrInfo
.getType())
730 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_loclists_base
,
731 LocListBaseAttrInfo
.getForm(),
732 DIEInteger(getDWARF5RngListLocListHeaderSize()));
736 std::unique_ptr
<DebugBufferVector
> LocArrayBuffer
=
737 std::make_unique
<DebugBufferVector
>();
738 std::unique_ptr
<raw_svector_ostream
> LocArrayStream
=
739 std::make_unique
<raw_svector_ostream
>(*LocArrayBuffer
);
741 const uint32_t SizeOfArraySection
= NumberOfEntries
* sizeof(uint32_t);
742 // Write out IndexArray
743 for (uint32_t RelativeOffset
: RelativeLocListOffsets
)
744 support::endian::write(
746 static_cast<uint32_t>(SizeOfArraySection
+ RelativeOffset
),
747 llvm::endianness::little
);
749 std::unique_ptr
<DebugBufferVector
> Header
= getDWARF5Header(
750 {static_cast<uint32_t>(SizeOfArraySection
+ LocBodyBuffer
.get()->size()),
751 5, 8, 0, NumberOfEntries
});
752 *LocStream
<< *Header
;
753 *LocStream
<< *LocArrayBuffer
;
754 *LocStream
<< *LocBodyBuffer
;
756 if (!isSplitDwarf()) {
757 DIEValue LocListBaseAttrInfo
=
758 Die
.findAttribute(dwarf::DW_AT_loclists_base
);
759 if (LocListBaseAttrInfo
.getType()) {
760 DIEBldr
.replaceValue(
761 &Die
, dwarf::DW_AT_loclists_base
, LocListBaseAttrInfo
.getForm(),
762 DIEInteger(LoclistBaseOffset
+ getDWARF5RngListLocListHeaderSize()));
764 DIEBldr
.addValue(&Die
, dwarf::DW_AT_loclists_base
,
765 dwarf::DW_FORM_sec_offset
,
766 DIEInteger(LoclistBaseOffset
+ Header
->size()));
768 LoclistBaseOffset
+= LocBuffer
->size();
770 clearList(RelativeLocListOffsets
);
771 clearList(*LocArrayBuffer
);
772 clearList(*LocBodyBuffer
);
775 void DebugLoclistWriter::finalize(DIEBuilder
&DIEBldr
, DIE
&Die
) {
776 if (DwarfVersion
>= 5)
777 finalizeDWARF5(DIEBldr
, Die
);
780 static std::string
encodeLE(size_t ByteSize
, uint64_t NewValue
) {
781 std::string
LE64(ByteSize
, 0);
782 for (size_t I
= 0; I
< ByteSize
; ++I
) {
783 LE64
[I
] = NewValue
& 0xff;
789 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset
,
790 std::string
&&NewValue
,
791 uint32_t OldValueSize
) {
792 Patches
.emplace_back(Offset
, std::move(NewValue
));
795 void SimpleBinaryPatcher::addBytePatch(uint64_t Offset
, uint8_t Value
) {
796 auto Str
= std::string(1, Value
);
797 Patches
.emplace_back(Offset
, std::move(Str
));
800 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset
, uint64_t NewValue
,
802 Patches
.emplace_back(Offset
, encodeLE(ByteSize
, NewValue
));
805 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset
, uint64_t Value
,
806 uint32_t OldValueSize
) {
808 raw_string_ostream
OS(Buff
);
809 encodeULEB128(Value
, OS
, OldValueSize
);
811 Patches
.emplace_back(Offset
, std::move(Buff
));
814 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset
, uint64_t NewValue
) {
815 addLEPatch(Offset
, NewValue
, 8);
818 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset
, uint32_t NewValue
,
819 uint32_t OldValueSize
) {
820 addLEPatch(Offset
, NewValue
, 4);
823 std::string
SimpleBinaryPatcher::patchBinary(StringRef BinaryContents
) {
824 std::string BinaryContentsStr
= std::string(BinaryContents
);
825 for (const auto &Patch
: Patches
) {
826 uint32_t Offset
= Patch
.first
;
827 const std::string
&ByteSequence
= Patch
.second
;
828 assert(Offset
+ ByteSequence
.size() <= BinaryContents
.size() &&
829 "Applied patch runs over binary size.");
830 for (uint64_t I
= 0, Size
= ByteSequence
.size(); I
< Size
; ++I
) {
831 BinaryContentsStr
[Offset
+ I
] = ByteSequence
[I
];
834 return BinaryContentsStr
;
837 void DebugStrOffsetsWriter::initialize(DWARFUnit
&Unit
) {
838 if (Unit
.getVersion() < 5)
840 const DWARFSection
&StrOffsetsSection
= Unit
.getStringOffsetSection();
841 const std::optional
<StrOffsetsContributionDescriptor
> &Contr
=
842 Unit
.getStringOffsetsTableContribution();
845 const uint8_t DwarfOffsetByteSize
= Contr
->getDwarfOffsetByteSize();
846 assert(DwarfOffsetByteSize
== 4 &&
847 "Dwarf String Offsets Byte Size is not supported.");
848 StrOffsets
.reserve(Contr
->Size
);
849 for (uint64_t Offset
= 0; Offset
< Contr
->Size
; Offset
+= DwarfOffsetByteSize
)
850 StrOffsets
.push_back(support::endian::read32le(
851 StrOffsetsSection
.Data
.data() + Contr
->Base
+ Offset
));
854 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index
, uint32_t Address
,
855 const DWARFUnit
&Unit
) {
856 assert(DebugStrOffsetFinalized
.count(Unit
.getOffset()) == 0 &&
857 "Cannot update address map since debug_str_offsets was already "
858 "finalized for this CU.");
859 IndexToAddressMap
[Index
] = Address
;
860 StrOffsetSectionWasModified
= true;
863 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit
&Unit
,
864 DIEBuilder
&DIEBldr
) {
865 std::optional
<AttrInfo
> AttrVal
=
866 findAttributeInfo(Unit
.getUnitDIE(), dwarf::DW_AT_str_offsets_base
);
867 if (!AttrVal
&& !Unit
.isDWOUnit())
869 std::optional
<uint64_t> Val
= std::nullopt
;
871 Val
= AttrVal
->V
.getAsSectionOffset();
873 if (!Unit
.isDWOUnit())
874 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
875 "DW_AT_str_offsets_base Value not present\n";
878 DIE
&Die
= *DIEBldr
.getUnitDIEbyUnit(Unit
);
879 DIEValue StrListBaseAttrInfo
=
880 Die
.findAttribute(dwarf::DW_AT_str_offsets_base
);
881 auto RetVal
= ProcessedBaseOffsets
.find(*Val
);
882 // Handling re-use of str-offsets section.
883 if (RetVal
== ProcessedBaseOffsets
.end() || StrOffsetSectionWasModified
) {
885 // Update String Offsets that were modified.
886 for (const auto &Entry
: IndexToAddressMap
)
887 StrOffsets
[Entry
.first
] = Entry
.second
;
888 // Writing out the header for each section.
889 support::endian::write(*StrOffsetsStream
,
890 static_cast<uint32_t>(StrOffsets
.size() * 4 + 4),
891 llvm::endianness::little
);
892 support::endian::write(*StrOffsetsStream
, static_cast<uint16_t>(5),
893 llvm::endianness::little
);
894 support::endian::write(*StrOffsetsStream
, static_cast<uint16_t>(0),
895 llvm::endianness::little
);
897 uint64_t BaseOffset
= StrOffsetsBuffer
->size();
898 ProcessedBaseOffsets
[*Val
] = BaseOffset
;
899 if (StrListBaseAttrInfo
.getType())
900 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_str_offsets_base
,
901 StrListBaseAttrInfo
.getForm(),
902 DIEInteger(BaseOffset
));
903 for (const uint32_t Offset
: StrOffsets
)
904 support::endian::write(*StrOffsetsStream
, Offset
,
905 llvm::endianness::little
);
907 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_str_offsets_base
,
908 StrListBaseAttrInfo
.getForm(),
909 DIEInteger(RetVal
->second
));
912 StrOffsetSectionWasModified
= false;
913 assert(DebugStrOffsetFinalized
.insert(Unit
.getOffset()).second
&&
914 "debug_str_offsets was already finalized for this CU.");
918 void DebugStrWriter::create() {
919 StrBuffer
= std::make_unique
<DebugStrBufferVector
>();
920 StrStream
= std::make_unique
<raw_svector_ostream
>(*StrBuffer
);
923 void DebugStrWriter::initialize() {
924 StringRef StrSection
;
926 StrSection
= DwCtx
.getDWARFObj().getStrDWOSection();
928 StrSection
= DwCtx
.getDWARFObj().getStrSection();
929 (*StrStream
) << StrSection
;
932 uint32_t DebugStrWriter::addString(StringRef Str
) {
933 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
934 if (StrBuffer
->empty())
936 auto Offset
= StrBuffer
->size();
938 StrStream
->write_zeros(1);
942 static void emitDwarfSetLineAddrAbs(MCStreamer
&OS
,
943 MCDwarfLineTableParams Params
,
944 int64_t LineDelta
, uint64_t Address
,
946 // emit the sequence to set the address
947 OS
.emitIntValue(dwarf::DW_LNS_extended_op
, 1);
948 OS
.emitULEB128IntValue(PointerSize
+ 1);
949 OS
.emitIntValue(dwarf::DW_LNE_set_address
, 1);
950 OS
.emitIntValue(Address
, PointerSize
);
952 // emit the sequence for the LineDelta (from 1) and a zero address delta.
953 MCDwarfLineAddr::Emit(&OS
, Params
, LineDelta
, 0);
956 static inline void emitBinaryDwarfLineTable(
957 MCStreamer
*MCOS
, MCDwarfLineTableParams Params
,
958 const DWARFDebugLine::LineTable
*Table
,
959 const std::vector
<DwarfLineTable::RowSequence
> &InputSequences
) {
960 if (InputSequences
.empty())
963 constexpr uint64_t InvalidAddress
= UINT64_MAX
;
964 unsigned FileNum
= 1;
965 unsigned LastLine
= 1;
967 unsigned Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
969 unsigned Discriminator
= 0;
970 uint64_t LastAddress
= InvalidAddress
;
971 uint64_t PrevEndOfSequence
= InvalidAddress
;
972 const MCAsmInfo
*AsmInfo
= MCOS
->getContext().getAsmInfo();
974 auto emitEndOfSequence
= [&](uint64_t Address
) {
975 MCDwarfLineAddr::Emit(MCOS
, Params
, INT64_MAX
, Address
- LastAddress
);
979 Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
982 LastAddress
= InvalidAddress
;
985 for (const DwarfLineTable::RowSequence
&Sequence
: InputSequences
) {
986 const uint64_t SequenceStart
=
987 Table
->Rows
[Sequence
.FirstIndex
].Address
.Address
;
989 // Check if we need to mark the end of the sequence.
990 if (PrevEndOfSequence
!= InvalidAddress
&& LastAddress
!= InvalidAddress
&&
991 PrevEndOfSequence
!= SequenceStart
) {
992 emitEndOfSequence(PrevEndOfSequence
);
995 for (uint32_t RowIndex
= Sequence
.FirstIndex
;
996 RowIndex
<= Sequence
.LastIndex
; ++RowIndex
) {
997 const DWARFDebugLine::Row
&Row
= Table
->Rows
[RowIndex
];
998 int64_t LineDelta
= static_cast<int64_t>(Row
.Line
) - LastLine
;
999 const uint64_t Address
= Row
.Address
.Address
;
1001 if (FileNum
!= Row
.File
) {
1003 MCOS
->emitInt8(dwarf::DW_LNS_set_file
);
1004 MCOS
->emitULEB128IntValue(FileNum
);
1006 if (Column
!= Row
.Column
) {
1007 Column
= Row
.Column
;
1008 MCOS
->emitInt8(dwarf::DW_LNS_set_column
);
1009 MCOS
->emitULEB128IntValue(Column
);
1011 if (Discriminator
!= Row
.Discriminator
&&
1012 MCOS
->getContext().getDwarfVersion() >= 4) {
1013 Discriminator
= Row
.Discriminator
;
1014 unsigned Size
= getULEB128Size(Discriminator
);
1015 MCOS
->emitInt8(dwarf::DW_LNS_extended_op
);
1016 MCOS
->emitULEB128IntValue(Size
+ 1);
1017 MCOS
->emitInt8(dwarf::DW_LNE_set_discriminator
);
1018 MCOS
->emitULEB128IntValue(Discriminator
);
1020 if (Isa
!= Row
.Isa
) {
1022 MCOS
->emitInt8(dwarf::DW_LNS_set_isa
);
1023 MCOS
->emitULEB128IntValue(Isa
);
1025 if (Row
.IsStmt
!= Flags
) {
1027 MCOS
->emitInt8(dwarf::DW_LNS_negate_stmt
);
1030 MCOS
->emitInt8(dwarf::DW_LNS_set_basic_block
);
1031 if (Row
.PrologueEnd
)
1032 MCOS
->emitInt8(dwarf::DW_LNS_set_prologue_end
);
1033 if (Row
.EpilogueBegin
)
1034 MCOS
->emitInt8(dwarf::DW_LNS_set_epilogue_begin
);
1036 // The end of the sequence is not normal in the middle of the input
1037 // sequence, but could happen, e.g. for assembly code.
1038 if (Row
.EndSequence
) {
1039 emitEndOfSequence(Address
);
1041 if (LastAddress
== InvalidAddress
)
1042 emitDwarfSetLineAddrAbs(*MCOS
, Params
, LineDelta
, Address
,
1043 AsmInfo
->getCodePointerSize());
1045 MCDwarfLineAddr::Emit(MCOS
, Params
, LineDelta
, Address
- LastAddress
);
1047 LastAddress
= Address
;
1048 LastLine
= Row
.Line
;
1053 PrevEndOfSequence
= Sequence
.EndAddress
;
1056 // Finish with the end of the sequence.
1057 if (LastAddress
!= InvalidAddress
)
1058 emitEndOfSequence(PrevEndOfSequence
);
1061 // This function is similar to the one from MCDwarfLineTable, except it handles
1062 // end-of-sequence entries differently by utilizing line entries with
1063 // DWARF2_FLAG_END_SEQUENCE flag.
1064 static inline void emitDwarfLineTable(
1065 MCStreamer
*MCOS
, MCSection
*Section
,
1066 const MCLineSection::MCDwarfLineEntryCollection
&LineEntries
) {
1067 unsigned FileNum
= 1;
1068 unsigned LastLine
= 1;
1069 unsigned Column
= 0;
1070 unsigned Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
1072 unsigned Discriminator
= 0;
1073 MCSymbol
*LastLabel
= nullptr;
1074 const MCAsmInfo
*AsmInfo
= MCOS
->getContext().getAsmInfo();
1076 // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1077 for (const MCDwarfLineEntry
&LineEntry
: LineEntries
) {
1078 if (LineEntry
.getFlags() & DWARF2_FLAG_END_SEQUENCE
) {
1079 MCOS
->emitDwarfAdvanceLineAddr(INT64_MAX
, LastLabel
, LineEntry
.getLabel(),
1080 AsmInfo
->getCodePointerSize());
1084 Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
1087 LastLabel
= nullptr;
1091 int64_t LineDelta
= static_cast<int64_t>(LineEntry
.getLine()) - LastLine
;
1093 if (FileNum
!= LineEntry
.getFileNum()) {
1094 FileNum
= LineEntry
.getFileNum();
1095 MCOS
->emitInt8(dwarf::DW_LNS_set_file
);
1096 MCOS
->emitULEB128IntValue(FileNum
);
1098 if (Column
!= LineEntry
.getColumn()) {
1099 Column
= LineEntry
.getColumn();
1100 MCOS
->emitInt8(dwarf::DW_LNS_set_column
);
1101 MCOS
->emitULEB128IntValue(Column
);
1103 if (Discriminator
!= LineEntry
.getDiscriminator() &&
1104 MCOS
->getContext().getDwarfVersion() >= 2) {
1105 Discriminator
= LineEntry
.getDiscriminator();
1106 unsigned Size
= getULEB128Size(Discriminator
);
1107 MCOS
->emitInt8(dwarf::DW_LNS_extended_op
);
1108 MCOS
->emitULEB128IntValue(Size
+ 1);
1109 MCOS
->emitInt8(dwarf::DW_LNE_set_discriminator
);
1110 MCOS
->emitULEB128IntValue(Discriminator
);
1112 if (Isa
!= LineEntry
.getIsa()) {
1113 Isa
= LineEntry
.getIsa();
1114 MCOS
->emitInt8(dwarf::DW_LNS_set_isa
);
1115 MCOS
->emitULEB128IntValue(Isa
);
1117 if ((LineEntry
.getFlags() ^ Flags
) & DWARF2_FLAG_IS_STMT
) {
1118 Flags
= LineEntry
.getFlags();
1119 MCOS
->emitInt8(dwarf::DW_LNS_negate_stmt
);
1121 if (LineEntry
.getFlags() & DWARF2_FLAG_BASIC_BLOCK
)
1122 MCOS
->emitInt8(dwarf::DW_LNS_set_basic_block
);
1123 if (LineEntry
.getFlags() & DWARF2_FLAG_PROLOGUE_END
)
1124 MCOS
->emitInt8(dwarf::DW_LNS_set_prologue_end
);
1125 if (LineEntry
.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN
)
1126 MCOS
->emitInt8(dwarf::DW_LNS_set_epilogue_begin
);
1128 MCSymbol
*Label
= LineEntry
.getLabel();
1130 // At this point we want to emit/create the sequence to encode the delta
1131 // in line numbers and the increment of the address from the previous
1132 // Label and the current Label.
1133 MCOS
->emitDwarfAdvanceLineAddr(LineDelta
, LastLabel
, Label
,
1134 AsmInfo
->getCodePointerSize());
1136 LastLine
= LineEntry
.getLine();
1140 assert(LastLabel
== nullptr && "end of sequence expected");
1143 void DwarfLineTable::emitCU(MCStreamer
*MCOS
, MCDwarfLineTableParams Params
,
1144 std::optional
<MCDwarfLineStr
> &LineStr
,
1145 BinaryContext
&BC
) const {
1146 if (!RawData
.empty()) {
1147 assert(MCLineSections
.getMCLineEntries().empty() &&
1148 InputSequences
.empty() &&
1149 "cannot combine raw data with new line entries");
1150 MCOS
->emitLabel(getLabel());
1151 MCOS
->emitBytes(RawData
);
1155 MCSymbol
*LineEndSym
= Header
.Emit(MCOS
, Params
, LineStr
).second
;
1157 // Put out the line tables.
1158 for (const auto &LineSec
: MCLineSections
.getMCLineEntries())
1159 emitDwarfLineTable(MCOS
, LineSec
.first
, LineSec
.second
);
1161 // Emit line tables for the original code.
1162 emitBinaryDwarfLineTable(MCOS
, Params
, InputTable
, InputSequences
);
1164 // This is the end of the section, so set the value of the symbol at the end
1165 // of this section (that was used in a previous expression).
1166 MCOS
->emitLabel(LineEndSym
);
1169 // Helper function to parse .debug_line_str, and populate one we are using.
1170 // For functions that we do not modify we output them as raw data.
1171 // Re-constructing .debug_line_str so that offsets are correct for those
1172 // debug line tables.
1173 // Bonus is that when we output a final binary we can re-use .debug_line_str
1174 // section. So we don't have to do the SHF_ALLOC trick we did with
1176 static void parseAndPopulateDebugLineStr(BinarySection
&LineStrSection
,
1177 MCDwarfLineStr
&LineStr
,
1178 BinaryContext
&BC
) {
1179 DataExtractor
StrData(LineStrSection
.getContents(),
1180 BC
.DwCtx
->isLittleEndian(), 0);
1181 uint64_t Offset
= 0;
1182 while (StrData
.isValidOffset(Offset
)) {
1183 const uint64_t StrOffset
= Offset
;
1184 Error Err
= Error::success();
1185 const char *CStr
= StrData
.getCStr(&Offset
, &Err
);
1187 BC
.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1190 const size_t NewOffset
= LineStr
.addString(CStr
);
1191 assert(StrOffset
== NewOffset
&&
1192 "New offset in .debug_line_str doesn't match original offset");
1198 void DwarfLineTable::emit(BinaryContext
&BC
, MCStreamer
&Streamer
) {
1199 MCAssembler
&Assembler
=
1200 static_cast<MCObjectStreamer
*>(&Streamer
)->getAssembler();
1202 MCDwarfLineTableParams Params
= Assembler
.getDWARFLinetableParams();
1204 auto &LineTables
= BC
.getDwarfLineTables();
1206 // Bail out early so we don't switch to the debug_line section needlessly and
1207 // in doing so create an unnecessary (if empty) section.
1208 if (LineTables
.empty())
1210 // In a v5 non-split line table, put the strings in a separate section.
1211 std::optional
<MCDwarfLineStr
> LineStr
;
1212 ErrorOr
<BinarySection
&> LineStrSection
=
1213 BC
.getUniqueSectionByName(".debug_line_str");
1215 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
1216 // .debug_line, so need to check if section exists.
1217 if (LineStrSection
) {
1218 LineStr
.emplace(*BC
.Ctx
);
1219 parseAndPopulateDebugLineStr(*LineStrSection
, *LineStr
, BC
);
1222 // Switch to the section where the table will be emitted into.
1223 Streamer
.switchSection(BC
.MOFI
->getDwarfLineSection());
1225 const uint16_t DwarfVersion
= BC
.Ctx
->getDwarfVersion();
1226 // Handle the rest of the Compile Units.
1227 for (auto &CUIDTablePair
: LineTables
) {
1228 Streamer
.getContext().setDwarfVersion(
1229 CUIDTablePair
.second
.getDwarfVersion());
1230 CUIDTablePair
.second
.emitCU(&Streamer
, Params
, LineStr
, BC
);
1233 // Resetting DWARF version for rest of the flow.
1234 BC
.Ctx
->setDwarfVersion(DwarfVersion
);
1236 // Still need to write the section out for the ExecutionEngine, and temp in
1237 // memory object we are constructing.
1239 LineStr
->emitSection(&Streamer
);