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/Rewrite/RewriteInstance.h"
17 #include "bolt/Utils/Utils.h"
18 #include "llvm/BinaryFormat/Dwarf.h"
19 #include "llvm/CodeGen/DIE.h"
20 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
22 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
23 #include "llvm/MC/MCAssembler.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCObjectStreamer.h"
26 #include "llvm/Support/Allocator.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/EndianStream.h"
29 #include "llvm/Support/LEB128.h"
30 #include "llvm/Support/SHA1.h"
37 #include <unordered_map>
40 #define DEBUG_TYPE "bolt-debug-info"
43 extern llvm::cl::opt
<unsigned> Verbosity
;
51 static void replaceLocValbyForm(DIEBuilder
&DIEBldr
, DIE
&Die
, DIEValue DIEVal
,
52 dwarf::Form Format
, uint64_t NewVal
) {
53 if (Format
== dwarf::DW_FORM_loclistx
)
54 DIEBldr
.replaceValue(&Die
, DIEVal
.getAttribute(), Format
,
57 DIEBldr
.replaceValue(&Die
, DIEVal
.getAttribute(), Format
,
61 std::optional
<AttrInfo
>
62 findAttributeInfo(const DWARFDie DIE
,
63 const DWARFAbbreviationDeclaration
*AbbrevDecl
,
65 const DWARFUnit
&U
= *DIE
.getDwarfUnit();
67 AbbrevDecl
->getAttributeOffsetFromIndex(Index
, DIE
.getOffset(), U
);
68 std::optional
<DWARFFormValue
> Value
=
69 AbbrevDecl
->getAttributeValueFromOffset(Index
, Offset
, U
);
73 const DWARFAbbreviationDeclaration::AttributeSpec
*AttrVal
=
74 AbbrevDecl
->attributes().begin() + Index
;
76 std::optional
<int64_t> ValSizeOpt
= AttrVal
->getByteSize(U
);
78 ValSize
= static_cast<uint32_t>(*ValSizeOpt
);
80 DWARFDataExtractor DebugInfoData
= U
.getDebugInfoExtractor();
81 uint64_t NewOffset
= Offset
;
82 DWARFFormValue::skipValue(Value
->getForm(), DebugInfoData
, &NewOffset
,
84 // This includes entire size of the entry, which might not be just the
85 // encoding part. For example for DW_AT_loc it will include expression
87 ValSize
= NewOffset
- Offset
;
89 return AttrInfo
{*Value
, DIE
.getAbbreviationDeclarationPtr(), Offset
, ValSize
};
92 std::optional
<AttrInfo
> findAttributeInfo(const DWARFDie DIE
,
93 dwarf::Attribute Attr
) {
96 const DWARFAbbreviationDeclaration
*AbbrevDecl
=
97 DIE
.getAbbreviationDeclarationPtr();
100 std::optional
<uint32_t> Index
= AbbrevDecl
->findAttributeIndex(Attr
);
103 return findAttributeInfo(DIE
, AbbrevDecl
, *Index
);
106 const DebugLineTableRowRef
DebugLineTableRowRef::NULL_ROW
{0, 0};
108 LLVM_ATTRIBUTE_UNUSED
109 static void printLE64(const std::string
&S
) {
110 for (uint32_t I
= 0, Size
= S
.size(); I
< Size
; ++I
) {
111 errs() << Twine::utohexstr(S
[I
]);
112 errs() << Twine::utohexstr((int8_t)S
[I
]);
117 // Writes address ranges to Writer as pairs of 64-bit (address, size).
118 // If RelativeRange is true, assumes the address range to be written must be of
119 // the form (begin address, range size), otherwise (begin address, end address).
120 // Terminates the list by writing a pair of two zeroes.
121 // Returns the number of written bytes.
123 writeAddressRanges(raw_svector_ostream
&Stream
,
124 const DebugAddressRangesVector
&AddressRanges
,
125 const bool WriteRelativeRanges
= false) {
126 for (const DebugAddressRange
&Range
: AddressRanges
) {
127 support::endian::write(Stream
, Range
.LowPC
, llvm::endianness::little
);
128 support::endian::write(
129 Stream
, WriteRelativeRanges
? Range
.HighPC
- Range
.LowPC
: Range
.HighPC
,
130 llvm::endianness::little
);
132 // Finish with 0 entries.
133 support::endian::write(Stream
, 0ULL, llvm::endianness::little
);
134 support::endian::write(Stream
, 0ULL, llvm::endianness::little
);
135 return AddressRanges
.size() * 16 + 16;
138 DebugRangesSectionWriter::DebugRangesSectionWriter() {
139 RangesBuffer
= std::make_unique
<DebugBufferVector
>();
140 RangesStream
= std::make_unique
<raw_svector_ostream
>(*RangesBuffer
);
142 // Add an empty range as the first entry;
144 writeAddressRanges(*RangesStream
.get(), DebugAddressRangesVector
{});
145 Kind
= RangesWriterKind::DebugRangesWriter
;
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
= SectionOffset
;
172 SectionOffset
+= writeAddressRanges(*RangesStream
.get(), Ranges
);
177 uint64_t DebugRangesSectionWriter::getSectionOffset() {
178 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
179 return SectionOffset
;
182 DebugAddrWriter
*DebugRangeListsSectionWriter::AddrWriter
= nullptr;
184 uint64_t DebugRangeListsSectionWriter::addRanges(
185 DebugAddressRangesVector
&&Ranges
,
186 std::map
<DebugAddressRangesVector
, uint64_t> &CachedRanges
) {
187 return addRanges(Ranges
);
190 struct LocListsRangelistsHeader
{
191 UnitLengthType UnitLength
; // Size of loclist entris section, not including
194 AddressSizeType AddressSize
;
195 SegmentSelectorType SegmentSelector
;
196 OffsetEntryCountType OffsetEntryCount
;
199 static std::unique_ptr
<DebugBufferVector
>
200 getDWARF5Header(const LocListsRangelistsHeader
&Header
) {
201 std::unique_ptr
<DebugBufferVector
> HeaderBuffer
=
202 std::make_unique
<DebugBufferVector
>();
203 std::unique_ptr
<raw_svector_ostream
> HeaderStream
=
204 std::make_unique
<raw_svector_ostream
>(*HeaderBuffer
);
206 // 7.29 length of the set of entries for this compilation unit, not including
207 // the length field itself
208 const uint32_t HeaderSize
=
209 getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType
);
211 support::endian::write(*HeaderStream
, Header
.UnitLength
+ HeaderSize
,
212 llvm::endianness::little
);
213 support::endian::write(*HeaderStream
, Header
.Version
,
214 llvm::endianness::little
);
215 support::endian::write(*HeaderStream
, Header
.AddressSize
,
216 llvm::endianness::little
);
217 support::endian::write(*HeaderStream
, Header
.SegmentSelector
,
218 llvm::endianness::little
);
219 support::endian::write(*HeaderStream
, Header
.OffsetEntryCount
,
220 llvm::endianness::little
);
226 uint32_t StartOffset
;
229 template <typename DebugVector
, typename ListEntry
, typename DebugAddressEntry
>
230 static bool emitWithBase(raw_ostream
&OS
, const DebugVector
&Entries
,
231 DebugAddrWriter
&AddrWriter
, DWARFUnit
&CU
,
232 uint32_t &Index
, const ListEntry BaseAddressx
,
233 const ListEntry OffsetPair
, const ListEntry EndOfList
,
234 const std::function
<void(uint32_t)> &Func
) {
235 if (Entries
.size() < 2)
237 uint64_t Base
= Entries
[Index
].LowPC
;
238 std::vector
<OffsetEntry
> Offsets
;
239 uint8_t TempBuffer
[64];
240 while (Index
< Entries
.size()) {
241 const DebugAddressEntry
&Entry
= Entries
[Index
];
242 if (Entry
.LowPC
== 0)
244 assert(Base
<= Entry
.LowPC
&& "Entry base is higher than low PC");
245 uint32_t StartOffset
= Entry
.LowPC
- Base
;
246 uint32_t EndOffset
= Entry
.HighPC
- Base
;
247 if (encodeULEB128(EndOffset
, TempBuffer
) > 2)
249 Offsets
.push_back({Index
, StartOffset
, EndOffset
});
253 if (Offsets
.size() < 2) {
254 Index
-= Offsets
.size();
258 support::endian::write(OS
, static_cast<uint8_t>(BaseAddressx
),
259 llvm::endianness::little
);
260 uint32_t BaseIndex
= AddrWriter
.getIndexFromAddress(Base
, CU
);
261 encodeULEB128(BaseIndex
, OS
);
262 for (auto &OffsetEntry
: Offsets
) {
263 support::endian::write(OS
, static_cast<uint8_t>(OffsetPair
),
264 llvm::endianness::little
);
265 encodeULEB128(OffsetEntry
.StartOffset
, OS
);
266 encodeULEB128(OffsetEntry
.EndOffset
, OS
);
267 Func(OffsetEntry
.Index
);
269 support::endian::write(OS
, static_cast<uint8_t>(EndOfList
),
270 llvm::endianness::little
);
275 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector
&Ranges
) {
276 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
278 RangeEntries
.push_back(CurrentOffset
);
279 bool WrittenStartxLength
= false;
281 Ranges
.begin(), Ranges
.end(),
282 [](const DebugAddressRange
&R1
, const DebugAddressRange
&R2
) -> bool {
283 return R1
.LowPC
< R2
.LowPC
;
285 for (unsigned I
= 0; I
< Ranges
.size();) {
286 WrittenStartxLength
= false;
287 if (emitWithBase
<DebugAddressRangesVector
, dwarf::RnglistEntries
,
289 *CUBodyStream
, Ranges
, *AddrWriter
, *CU
, I
,
290 dwarf::DW_RLE_base_addressx
, dwarf::DW_RLE_offset_pair
,
291 dwarf::DW_RLE_end_of_list
, [](uint32_t Index
) -> void {}))
294 const DebugAddressRange
&Range
= Ranges
[I
];
295 support::endian::write(*CUBodyStream
,
296 static_cast<uint8_t>(dwarf::DW_RLE_startx_length
),
297 llvm::endianness::little
);
298 uint32_t Index
= AddrWriter
->getIndexFromAddress(Range
.LowPC
, *CU
);
299 encodeULEB128(Index
, *CUBodyStream
);
300 encodeULEB128(Range
.HighPC
- Range
.LowPC
, *CUBodyStream
);
302 WrittenStartxLength
= true;
304 if (WrittenStartxLength
)
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
;
329 SectionOffset
= RangesBuffer
->size();
332 void DebugRangeListsSectionWriter::initSection(DWARFUnit
&Unit
) {
333 CUBodyBuffer
= std::make_unique
<DebugBufferVector
>();
334 CUBodyStream
= std::make_unique
<raw_svector_ostream
>(*CUBodyBuffer
);
335 RangeEntries
.clear();
340 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset
,
341 DebugAddressRangesVector
&&Ranges
) {
342 std::lock_guard
<std::mutex
> Lock(CUAddressRangesMutex
);
343 CUAddressRanges
.emplace(CUOffset
, std::move(Ranges
));
346 void DebugARangesSectionWriter::writeARangesSection(
347 raw_svector_ostream
&RangesStream
, const CUOffsetMap
&CUMap
) const {
348 // For reference on the format of the .debug_aranges section, see the DWARF4
349 // specification, section 6.1.4 Lookup by Address
350 // http://www.dwarfstd.org/doc/DWARF4.pdf
351 for (const auto &CUOffsetAddressRangesPair
: CUAddressRanges
) {
352 const uint64_t Offset
= CUOffsetAddressRangesPair
.first
;
353 const DebugAddressRangesVector
&AddressRanges
=
354 CUOffsetAddressRangesPair
.second
;
358 // Size of this set: 8 (size of the header) + 4 (padding after header)
359 // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
360 // pair of uint64_t's for the terminating, zero-length range.
361 // Does not include size field itself.
362 uint32_t Size
= 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges
.size() + 1);
364 // Header field #1: set size.
365 support::endian::write(RangesStream
, Size
, llvm::endianness::little
);
367 // Header field #2: version number, 2 as per the specification.
368 support::endian::write(RangesStream
, static_cast<uint16_t>(2),
369 llvm::endianness::little
);
371 assert(CUMap
.count(Offset
) && "Original CU offset is not found in CU Map");
372 // Header field #3: debug info offset of the correspondent compile unit.
373 support::endian::write(
374 RangesStream
, static_cast<uint32_t>(CUMap
.find(Offset
)->second
.Offset
),
375 llvm::endianness::little
);
377 // Header field #4: address size.
378 // 8 since we only write ELF64 binaries for now.
379 RangesStream
<< char(8);
381 // Header field #5: segment size of target architecture.
382 RangesStream
<< char(0);
384 // Padding before address table - 4 bytes in the 64-bit-pointer case.
385 support::endian::write(RangesStream
, static_cast<uint32_t>(0),
386 llvm::endianness::little
);
388 writeAddressRanges(RangesStream
, AddressRanges
, true);
392 DebugAddrWriter::DebugAddrWriter(BinaryContext
*BC
) : BC(BC
) {
393 Buffer
= std::make_unique
<AddressSectionBuffer
>();
394 AddressStream
= std::make_unique
<raw_svector_ostream
>(*Buffer
);
397 void DebugAddrWriter::AddressForDWOCU::dump() {
398 std::vector
<IndexAddressPair
> SortedMap(indexToAddressBegin(),
399 indexToAdddessEnd());
400 // Sorting address in increasing order of indices.
401 llvm::sort(SortedMap
, llvm::less_first());
402 for (auto &Pair
: SortedMap
)
403 dbgs() << Twine::utohexstr(Pair
.second
) << "\t" << Pair
.first
<< "\n";
405 uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address
, DWARFUnit
&CU
) {
406 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
407 const uint64_t CUID
= getCUID(CU
);
408 if (!AddressMaps
.count(CUID
))
409 AddressMaps
[CUID
] = AddressForDWOCU();
411 AddressForDWOCU
&Map
= AddressMaps
[CUID
];
412 auto Entry
= Map
.find(Address
);
413 if (Entry
== Map
.end()) {
414 auto Index
= Map
.getNextIndex();
415 Entry
= Map
.insert(Address
, Index
).first
;
417 return Entry
->second
;
420 static void updateAddressBase(DIEBuilder
&DIEBlder
, DebugAddrWriter
&AddrWriter
,
421 DWARFUnit
&CU
, const uint64_t Offset
) {
422 DIE
*Die
= DIEBlder
.getUnitDIEbyUnit(CU
);
423 DIEValue GnuAddrBaseAttrInfo
= Die
->findAttribute(dwarf::DW_AT_GNU_addr_base
);
424 DIEValue AddrBaseAttrInfo
= Die
->findAttribute(dwarf::DW_AT_addr_base
);
425 dwarf::Form BaseAttrForm
;
426 dwarf::Attribute BaseAttr
;
427 // For cases where Skeleton CU does not have DW_AT_GNU_addr_base
428 if (!GnuAddrBaseAttrInfo
&& CU
.getVersion() < 5)
431 if (GnuAddrBaseAttrInfo
) {
432 BaseAttrForm
= GnuAddrBaseAttrInfo
.getForm();
433 BaseAttr
= GnuAddrBaseAttrInfo
.getAttribute();
436 if (AddrBaseAttrInfo
) {
437 BaseAttrForm
= AddrBaseAttrInfo
.getForm();
438 BaseAttr
= AddrBaseAttrInfo
.getAttribute();
441 if (GnuAddrBaseAttrInfo
|| AddrBaseAttrInfo
) {
442 DIEBlder
.replaceValue(Die
, BaseAttr
, BaseAttrForm
, DIEInteger(Offset
));
443 } else if (CU
.getVersion() >= 5) {
444 // A case where we were not using .debug_addr section, but after update
446 DIEBlder
.addValue(Die
, dwarf::DW_AT_addr_base
, dwarf::DW_FORM_sec_offset
,
451 void DebugAddrWriter::update(DIEBuilder
&DIEBlder
, DWARFUnit
&CU
) {
452 // Handling the case wehre debug information is a mix of Debug fission and
456 const uint64_t CUID
= getCUID(CU
);
457 auto AM
= AddressMaps
.find(CUID
);
458 // Adding to map even if it did not contribute to .debug_addr.
459 // The Skeleton CU might still have DW_AT_GNU_addr_base.
460 uint64_t Offset
= Buffer
->size();
461 // If does not exist this CUs DWO section didn't contribute to .debug_addr.
462 if (AM
== AddressMaps
.end())
464 std::vector
<IndexAddressPair
> SortedMap(AM
->second
.indexToAddressBegin(),
465 AM
->second
.indexToAdddessEnd());
466 // Sorting address in increasing order of indices.
467 llvm::sort(SortedMap
, llvm::less_first());
469 uint8_t AddrSize
= CU
.getAddressByteSize();
470 uint32_t Counter
= 0;
471 auto WriteAddress
= [&](uint64_t Address
) -> void {
475 assert(false && "Address Size is invalid.");
478 support::endian::write(*AddressStream
, static_cast<uint32_t>(Address
),
479 llvm::endianness::little
);
482 support::endian::write(*AddressStream
, Address
, llvm::endianness::little
);
487 for (const IndexAddressPair
&Val
: SortedMap
) {
488 while (Val
.first
> Counter
)
490 WriteAddress(Val
.second
);
492 updateAddressBase(DIEBlder
, *this, CU
, Offset
);
495 void DebugAddrWriterDwarf5::update(DIEBuilder
&DIEBlder
, DWARFUnit
&CU
) {
496 // Need to layout all sections within .debug_addr
497 // Within each section sort Address by index.
498 const endianness Endian
= BC
->DwCtx
->isLittleEndian()
499 ? llvm::endianness::little
500 : llvm::endianness::big
;
501 const DWARFSection
&AddrSec
= BC
->DwCtx
->getDWARFObj().getAddrSection();
502 DWARFDataExtractor
AddrData(BC
->DwCtx
->getDWARFObj(), AddrSec
,
503 Endian
== llvm::endianness::little
, 0);
504 DWARFDebugAddrTable AddrTable
;
505 DIDumpOptions DumpOpts
;
506 constexpr uint32_t HeaderSize
= 8;
507 const uint64_t CUID
= getCUID(CU
);
508 const uint8_t AddrSize
= CU
.getAddressByteSize();
509 auto AMIter
= AddressMaps
.find(CUID
);
510 // A case where CU has entry in .debug_addr, but we don't modify addresses
512 if (AMIter
== AddressMaps
.end()) {
513 AMIter
= AddressMaps
.insert({CUID
, AddressForDWOCU()}).first
;
514 std::optional
<uint64_t> BaseOffset
= CU
.getAddrOffsetSectionBase();
517 // Address base offset is to the first entry.
518 // The size of header is 8 bytes.
519 uint64_t Offset
= *BaseOffset
- HeaderSize
;
520 auto Iter
= UnmodifiedAddressOffsets
.find(Offset
);
521 if (Iter
!= UnmodifiedAddressOffsets
.end()) {
522 updateAddressBase(DIEBlder
, *this, CU
, Iter
->getSecond());
525 UnmodifiedAddressOffsets
[Offset
] = Buffer
->size() + HeaderSize
;
526 if (Error Err
= AddrTable
.extract(AddrData
, &Offset
, 5, AddrSize
,
527 DumpOpts
.WarningHandler
)) {
528 DumpOpts
.RecoverableErrorHandler(std::move(Err
));
533 for (uint64_t Addr
: AddrTable
.getAddressEntries())
534 AMIter
->second
.insert(Addr
, Index
++);
537 updateAddressBase(DIEBlder
, *this, CU
, Buffer
->size() + HeaderSize
);
539 std::vector
<IndexAddressPair
> SortedMap(AMIter
->second
.indexToAddressBegin(),
540 AMIter
->second
.indexToAdddessEnd());
541 // Sorting address in increasing order of indices.
542 llvm::sort(SortedMap
, llvm::less_first());
543 // Writing out Header
544 const uint32_t Length
= SortedMap
.size() * AddrSize
+ 4;
545 support::endian::write(*AddressStream
, Length
, Endian
);
546 support::endian::write(*AddressStream
, static_cast<uint16_t>(5), Endian
);
547 support::endian::write(*AddressStream
, static_cast<uint8_t>(AddrSize
),
549 support::endian::write(*AddressStream
, static_cast<uint8_t>(0), Endian
);
551 uint32_t Counter
= 0;
552 auto writeAddress
= [&](uint64_t Address
) -> void {
556 llvm_unreachable("Address Size is invalid.");
559 support::endian::write(*AddressStream
, static_cast<uint32_t>(Address
),
563 support::endian::write(*AddressStream
, Address
, Endian
);
568 for (const IndexAddressPair
&Val
: SortedMap
) {
569 while (Val
.first
> Counter
)
571 writeAddress(Val
.second
);
575 void DebugLocWriter::init() {
576 LocBuffer
= std::make_unique
<DebugBufferVector
>();
577 LocStream
= std::make_unique
<raw_svector_ostream
>(*LocBuffer
);
578 // Writing out empty location list to which all references to empty location
580 if (!LocSectionOffset
&& DwarfVersion
< 5) {
581 const char Zeroes
[16] = {0};
582 *LocStream
<< StringRef(Zeroes
, 16);
583 LocSectionOffset
+= 16;
587 uint32_t DebugLocWriter::LocSectionOffset
= 0;
588 void DebugLocWriter::addList(DIEBuilder
&DIEBldr
, DIE
&Die
, DIEValue
&AttrInfo
,
589 DebugLocationsVector
&LocList
) {
590 if (LocList
.empty()) {
591 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(),
592 DebugLocWriter::EmptyListOffset
);
595 // Since there is a separate DebugLocWriter for each thread,
596 // we don't need a lock to read the SectionOffset and update it.
597 const uint32_t EntryOffset
= LocSectionOffset
;
599 for (const DebugLocationEntry
&Entry
: LocList
) {
600 support::endian::write(*LocStream
, static_cast<uint64_t>(Entry
.LowPC
),
601 llvm::endianness::little
);
602 support::endian::write(*LocStream
, static_cast<uint64_t>(Entry
.HighPC
),
603 llvm::endianness::little
);
604 support::endian::write(*LocStream
, static_cast<uint16_t>(Entry
.Expr
.size()),
605 llvm::endianness::little
);
606 *LocStream
<< StringRef(reinterpret_cast<const char *>(Entry
.Expr
.data()),
608 LocSectionOffset
+= 2 * 8 + 2 + Entry
.Expr
.size();
610 LocStream
->write_zeros(16);
611 LocSectionOffset
+= 16;
612 LocListDebugInfoPatches
.push_back({0xdeadbeee, EntryOffset
}); // never seen
614 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(), EntryOffset
);
617 std::unique_ptr
<DebugBufferVector
> DebugLocWriter::getBuffer() {
618 return std::move(LocBuffer
);
622 void DebugLocWriter::finalize(DIEBuilder
&DIEBldr
, DIE
&Die
) {}
624 static void writeEmptyListDwarf5(raw_svector_ostream
&Stream
) {
625 support::endian::write(Stream
, static_cast<uint32_t>(4),
626 llvm::endianness::little
);
627 support::endian::write(Stream
, static_cast<uint8_t>(dwarf::DW_LLE_start_end
),
628 llvm::endianness::little
);
630 const char Zeroes
[16] = {0};
631 Stream
<< StringRef(Zeroes
, 16);
632 encodeULEB128(0, Stream
);
633 support::endian::write(Stream
,
634 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list
),
635 llvm::endianness::little
);
638 static void writeLegacyLocList(DIEValue
&AttrInfo
,
639 DebugLocationsVector
&LocList
,
640 DIEBuilder
&DIEBldr
, DIE
&Die
,
641 DebugAddrWriter
&AddrWriter
,
642 DebugBufferVector
&LocBuffer
, DWARFUnit
&CU
,
643 raw_svector_ostream
&LocStream
) {
644 if (LocList
.empty()) {
645 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(),
646 DebugLocWriter::EmptyListOffset
);
650 const uint32_t EntryOffset
= LocBuffer
.size();
651 for (const DebugLocationEntry
&Entry
: LocList
) {
652 support::endian::write(LocStream
,
653 static_cast<uint8_t>(dwarf::DW_LLE_startx_length
),
654 llvm::endianness::little
);
655 const uint32_t Index
= AddrWriter
.getIndexFromAddress(Entry
.LowPC
, CU
);
656 encodeULEB128(Index
, LocStream
);
658 support::endian::write(LocStream
,
659 static_cast<uint32_t>(Entry
.HighPC
- Entry
.LowPC
),
660 llvm::endianness::little
);
661 support::endian::write(LocStream
, static_cast<uint16_t>(Entry
.Expr
.size()),
662 llvm::endianness::little
);
663 LocStream
<< StringRef(reinterpret_cast<const char *>(Entry
.Expr
.data()),
666 support::endian::write(LocStream
,
667 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list
),
668 llvm::endianness::little
);
669 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, AttrInfo
.getForm(), EntryOffset
);
672 static void writeDWARF5LocList(uint32_t &NumberOfEntries
, DIEValue
&AttrInfo
,
673 DebugLocationsVector
&LocList
, DIE
&Die
,
674 DIEBuilder
&DIEBldr
, DebugAddrWriter
&AddrWriter
,
675 DebugBufferVector
&LocBodyBuffer
,
676 std::vector
<uint32_t> &RelativeLocListOffsets
,
678 raw_svector_ostream
&LocBodyStream
) {
680 replaceLocValbyForm(DIEBldr
, Die
, AttrInfo
, dwarf::DW_FORM_loclistx
,
683 RelativeLocListOffsets
.push_back(LocBodyBuffer
.size());
685 if (LocList
.empty()) {
686 writeEmptyListDwarf5(LocBodyStream
);
690 std::vector
<uint64_t> OffsetsArray
;
691 bool WrittenStartxLength
= false;
692 auto writeExpression
= [&](uint32_t Index
) -> void {
693 const DebugLocationEntry
&Entry
= LocList
[Index
];
694 encodeULEB128(Entry
.Expr
.size(), LocBodyStream
);
695 LocBodyStream
<< StringRef(
696 reinterpret_cast<const char *>(Entry
.Expr
.data()), Entry
.Expr
.size());
698 for (unsigned I
= 0; I
< LocList
.size();) {
699 WrittenStartxLength
= false;
700 if (emitWithBase
<DebugLocationsVector
, dwarf::LoclistEntries
,
702 LocBodyStream
, LocList
, AddrWriter
, CU
, I
,
703 dwarf::DW_LLE_base_addressx
, dwarf::DW_LLE_offset_pair
,
704 dwarf::DW_LLE_end_of_list
, writeExpression
))
707 const DebugLocationEntry
&Entry
= LocList
[I
];
708 support::endian::write(LocBodyStream
,
709 static_cast<uint8_t>(dwarf::DW_LLE_startx_length
),
710 llvm::endianness::little
);
711 const uint32_t Index
= AddrWriter
.getIndexFromAddress(Entry
.LowPC
, CU
);
712 encodeULEB128(Index
, LocBodyStream
);
713 encodeULEB128(Entry
.HighPC
- Entry
.LowPC
, LocBodyStream
);
716 WrittenStartxLength
= true;
719 if (WrittenStartxLength
)
720 support::endian::write(LocBodyStream
,
721 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list
),
722 llvm::endianness::little
);
725 void DebugLoclistWriter::addList(DIEBuilder
&DIEBldr
, DIE
&Die
,
727 DebugLocationsVector
&LocList
) {
728 if (DwarfVersion
< 5)
729 writeLegacyLocList(AttrInfo
, LocList
, DIEBldr
, Die
, *AddrWriter
, *LocBuffer
,
732 writeDWARF5LocList(NumberOfEntries
, AttrInfo
, LocList
, Die
, DIEBldr
,
733 *AddrWriter
, *LocBodyBuffer
, RelativeLocListOffsets
, CU
,
737 uint32_t DebugLoclistWriter::LoclistBaseOffset
= 0;
738 void DebugLoclistWriter::finalizeDWARF5(DIEBuilder
&DIEBldr
, DIE
&Die
) {
739 if (LocBodyBuffer
->empty()) {
740 DIEValue LocListBaseAttrInfo
=
741 Die
.findAttribute(dwarf::DW_AT_loclists_base
);
742 // Pointing to first one, because it doesn't matter. There are no uses of it
744 if (!isSplitDwarf() && LocListBaseAttrInfo
.getType())
745 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_loclists_base
,
746 LocListBaseAttrInfo
.getForm(),
747 DIEInteger(getDWARF5RngListLocListHeaderSize()));
751 std::unique_ptr
<DebugBufferVector
> LocArrayBuffer
=
752 std::make_unique
<DebugBufferVector
>();
753 std::unique_ptr
<raw_svector_ostream
> LocArrayStream
=
754 std::make_unique
<raw_svector_ostream
>(*LocArrayBuffer
);
756 const uint32_t SizeOfArraySection
= NumberOfEntries
* sizeof(uint32_t);
757 // Write out IndexArray
758 for (uint32_t RelativeOffset
: RelativeLocListOffsets
)
759 support::endian::write(
761 static_cast<uint32_t>(SizeOfArraySection
+ RelativeOffset
),
762 llvm::endianness::little
);
764 std::unique_ptr
<DebugBufferVector
> Header
= getDWARF5Header(
765 {static_cast<uint32_t>(SizeOfArraySection
+ LocBodyBuffer
.get()->size()),
766 5, 8, 0, NumberOfEntries
});
767 *LocStream
<< *Header
;
768 *LocStream
<< *LocArrayBuffer
;
769 *LocStream
<< *LocBodyBuffer
;
771 if (!isSplitDwarf()) {
772 DIEValue LocListBaseAttrInfo
=
773 Die
.findAttribute(dwarf::DW_AT_loclists_base
);
774 if (LocListBaseAttrInfo
.getType()) {
775 DIEBldr
.replaceValue(
776 &Die
, dwarf::DW_AT_loclists_base
, LocListBaseAttrInfo
.getForm(),
777 DIEInteger(LoclistBaseOffset
+ getDWARF5RngListLocListHeaderSize()));
779 DIEBldr
.addValue(&Die
, dwarf::DW_AT_loclists_base
,
780 dwarf::DW_FORM_sec_offset
,
781 DIEInteger(LoclistBaseOffset
+ Header
->size()));
783 LoclistBaseOffset
+= LocBuffer
->size();
785 clearList(RelativeLocListOffsets
);
786 clearList(*LocArrayBuffer
);
787 clearList(*LocBodyBuffer
);
790 void DebugLoclistWriter::finalize(DIEBuilder
&DIEBldr
, DIE
&Die
) {
791 if (DwarfVersion
>= 5)
792 finalizeDWARF5(DIEBldr
, Die
);
795 DebugAddrWriter
*DebugLoclistWriter::AddrWriter
= nullptr;
797 static std::string
encodeLE(size_t ByteSize
, uint64_t NewValue
) {
798 std::string
LE64(ByteSize
, 0);
799 for (size_t I
= 0; I
< ByteSize
; ++I
) {
800 LE64
[I
] = NewValue
& 0xff;
806 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset
,
807 std::string
&&NewValue
,
808 uint32_t OldValueSize
) {
809 Patches
.emplace_back(Offset
, std::move(NewValue
));
812 void SimpleBinaryPatcher::addBytePatch(uint64_t Offset
, uint8_t Value
) {
813 auto Str
= std::string(1, Value
);
814 Patches
.emplace_back(Offset
, std::move(Str
));
817 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset
, uint64_t NewValue
,
819 Patches
.emplace_back(Offset
, encodeLE(ByteSize
, NewValue
));
822 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset
, uint64_t Value
,
823 uint32_t OldValueSize
) {
825 raw_string_ostream
OS(Buff
);
826 encodeULEB128(Value
, OS
, OldValueSize
);
828 Patches
.emplace_back(Offset
, std::move(Buff
));
831 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset
, uint64_t NewValue
) {
832 addLEPatch(Offset
, NewValue
, 8);
835 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset
, uint32_t NewValue
,
836 uint32_t OldValueSize
) {
837 addLEPatch(Offset
, NewValue
, 4);
840 std::string
SimpleBinaryPatcher::patchBinary(StringRef BinaryContents
) {
841 std::string BinaryContentsStr
= std::string(BinaryContents
);
842 for (const auto &Patch
: Patches
) {
843 uint32_t Offset
= Patch
.first
;
844 const std::string
&ByteSequence
= Patch
.second
;
845 assert(Offset
+ ByteSequence
.size() <= BinaryContents
.size() &&
846 "Applied patch runs over binary size.");
847 for (uint64_t I
= 0, Size
= ByteSequence
.size(); I
< Size
; ++I
) {
848 BinaryContentsStr
[Offset
+ I
] = ByteSequence
[I
];
851 return BinaryContentsStr
;
854 void DebugStrOffsetsWriter::initialize(
855 const DWARFSection
&StrOffsetsSection
,
856 const std::optional
<StrOffsetsContributionDescriptor
> Contr
) {
860 const uint8_t DwarfOffsetByteSize
= Contr
->getDwarfOffsetByteSize();
861 assert(DwarfOffsetByteSize
== 4 &&
862 "Dwarf String Offsets Byte Size is not supported.");
864 for (uint64_t Offset
= 0; Offset
< Contr
->Size
; Offset
+= DwarfOffsetByteSize
)
865 IndexToAddressMap
[Index
++] = support::endian::read32le(
866 StrOffsetsSection
.Data
.data() + Contr
->Base
+ Offset
);
869 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index
, uint32_t Address
) {
870 assert(IndexToAddressMap
.count(Index
) > 0 && "Index is not found.");
871 IndexToAddressMap
[Index
] = Address
;
872 StrOffsetSectionWasModified
= true;
875 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit
&Unit
,
876 DIEBuilder
&DIEBldr
) {
877 if (IndexToAddressMap
.empty())
880 std::optional
<AttrInfo
> AttrVal
=
881 findAttributeInfo(Unit
.getUnitDIE(), dwarf::DW_AT_str_offsets_base
);
882 assert(AttrVal
&& "DW_AT_str_offsets_base not present.");
883 std::optional
<uint64_t> Val
= AttrVal
->V
.getAsSectionOffset();
884 assert(Val
&& "DW_AT_str_offsets_base Value not present.");
885 DIE
&Die
= *DIEBldr
.getUnitDIEbyUnit(Unit
);
886 DIEValue StrListBaseAttrInfo
=
887 Die
.findAttribute(dwarf::DW_AT_str_offsets_base
);
888 auto RetVal
= ProcessedBaseOffsets
.find(*Val
);
889 // Handling re-use of str-offsets section.
890 if (RetVal
== ProcessedBaseOffsets
.end() || StrOffsetSectionWasModified
) {
891 // Writing out the header for each section.
892 support::endian::write(*StrOffsetsStream
, CurrentSectionSize
+ 4,
893 llvm::endianness::little
);
894 support::endian::write(*StrOffsetsStream
, static_cast<uint16_t>(5),
895 llvm::endianness::little
);
896 support::endian::write(*StrOffsetsStream
, static_cast<uint16_t>(0),
897 llvm::endianness::little
);
899 uint64_t BaseOffset
= StrOffsetsBuffer
->size();
900 ProcessedBaseOffsets
[*Val
] = BaseOffset
;
901 if (StrListBaseAttrInfo
.getType())
902 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_str_offsets_base
,
903 StrListBaseAttrInfo
.getForm(),
904 DIEInteger(BaseOffset
));
905 for (const auto &Entry
: IndexToAddressMap
)
906 support::endian::write(*StrOffsetsStream
, Entry
.second
,
907 llvm::endianness::little
);
909 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_str_offsets_base
,
910 StrListBaseAttrInfo
.getForm(),
911 DIEInteger(RetVal
->second
));
914 StrOffsetSectionWasModified
= false;
915 IndexToAddressMap
.clear();
918 void DebugStrWriter::create() {
919 StrBuffer
= std::make_unique
<DebugStrBufferVector
>();
920 StrStream
= std::make_unique
<raw_svector_ostream
>(*StrBuffer
);
923 void DebugStrWriter::initialize() {
924 auto StrSection
= BC
.DwCtx
->getDWARFObj().getStrSection();
925 (*StrStream
) << StrSection
;
928 uint32_t DebugStrWriter::addString(StringRef Str
) {
929 std::lock_guard
<std::mutex
> Lock(WriterMutex
);
930 if (StrBuffer
->empty())
932 auto Offset
= StrBuffer
->size();
934 StrStream
->write_zeros(1);
938 static void emitDwarfSetLineAddrAbs(MCStreamer
&OS
,
939 MCDwarfLineTableParams Params
,
940 int64_t LineDelta
, uint64_t Address
,
942 // emit the sequence to set the address
943 OS
.emitIntValue(dwarf::DW_LNS_extended_op
, 1);
944 OS
.emitULEB128IntValue(PointerSize
+ 1);
945 OS
.emitIntValue(dwarf::DW_LNE_set_address
, 1);
946 OS
.emitIntValue(Address
, PointerSize
);
948 // emit the sequence for the LineDelta (from 1) and a zero address delta.
949 MCDwarfLineAddr::Emit(&OS
, Params
, LineDelta
, 0);
952 static inline void emitBinaryDwarfLineTable(
953 MCStreamer
*MCOS
, MCDwarfLineTableParams Params
,
954 const DWARFDebugLine::LineTable
*Table
,
955 const std::vector
<DwarfLineTable::RowSequence
> &InputSequences
) {
956 if (InputSequences
.empty())
959 constexpr uint64_t InvalidAddress
= UINT64_MAX
;
960 unsigned FileNum
= 1;
961 unsigned LastLine
= 1;
963 unsigned Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
965 unsigned Discriminator
= 0;
966 uint64_t LastAddress
= InvalidAddress
;
967 uint64_t PrevEndOfSequence
= InvalidAddress
;
968 const MCAsmInfo
*AsmInfo
= MCOS
->getContext().getAsmInfo();
970 auto emitEndOfSequence
= [&](uint64_t Address
) {
971 MCDwarfLineAddr::Emit(MCOS
, Params
, INT64_MAX
, Address
- LastAddress
);
975 Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
978 LastAddress
= InvalidAddress
;
981 for (const DwarfLineTable::RowSequence
&Sequence
: InputSequences
) {
982 const uint64_t SequenceStart
=
983 Table
->Rows
[Sequence
.FirstIndex
].Address
.Address
;
985 // Check if we need to mark the end of the sequence.
986 if (PrevEndOfSequence
!= InvalidAddress
&& LastAddress
!= InvalidAddress
&&
987 PrevEndOfSequence
!= SequenceStart
) {
988 emitEndOfSequence(PrevEndOfSequence
);
991 for (uint32_t RowIndex
= Sequence
.FirstIndex
;
992 RowIndex
<= Sequence
.LastIndex
; ++RowIndex
) {
993 const DWARFDebugLine::Row
&Row
= Table
->Rows
[RowIndex
];
994 int64_t LineDelta
= static_cast<int64_t>(Row
.Line
) - LastLine
;
995 const uint64_t Address
= Row
.Address
.Address
;
997 if (FileNum
!= Row
.File
) {
999 MCOS
->emitInt8(dwarf::DW_LNS_set_file
);
1000 MCOS
->emitULEB128IntValue(FileNum
);
1002 if (Column
!= Row
.Column
) {
1003 Column
= Row
.Column
;
1004 MCOS
->emitInt8(dwarf::DW_LNS_set_column
);
1005 MCOS
->emitULEB128IntValue(Column
);
1007 if (Discriminator
!= Row
.Discriminator
&&
1008 MCOS
->getContext().getDwarfVersion() >= 4) {
1009 Discriminator
= Row
.Discriminator
;
1010 unsigned Size
= getULEB128Size(Discriminator
);
1011 MCOS
->emitInt8(dwarf::DW_LNS_extended_op
);
1012 MCOS
->emitULEB128IntValue(Size
+ 1);
1013 MCOS
->emitInt8(dwarf::DW_LNE_set_discriminator
);
1014 MCOS
->emitULEB128IntValue(Discriminator
);
1016 if (Isa
!= Row
.Isa
) {
1018 MCOS
->emitInt8(dwarf::DW_LNS_set_isa
);
1019 MCOS
->emitULEB128IntValue(Isa
);
1021 if (Row
.IsStmt
!= Flags
) {
1023 MCOS
->emitInt8(dwarf::DW_LNS_negate_stmt
);
1026 MCOS
->emitInt8(dwarf::DW_LNS_set_basic_block
);
1027 if (Row
.PrologueEnd
)
1028 MCOS
->emitInt8(dwarf::DW_LNS_set_prologue_end
);
1029 if (Row
.EpilogueBegin
)
1030 MCOS
->emitInt8(dwarf::DW_LNS_set_epilogue_begin
);
1032 // The end of the sequence is not normal in the middle of the input
1033 // sequence, but could happen, e.g. for assembly code.
1034 if (Row
.EndSequence
) {
1035 emitEndOfSequence(Address
);
1037 if (LastAddress
== InvalidAddress
)
1038 emitDwarfSetLineAddrAbs(*MCOS
, Params
, LineDelta
, Address
,
1039 AsmInfo
->getCodePointerSize());
1041 MCDwarfLineAddr::Emit(MCOS
, Params
, LineDelta
, Address
- LastAddress
);
1043 LastAddress
= Address
;
1044 LastLine
= Row
.Line
;
1049 PrevEndOfSequence
= Sequence
.EndAddress
;
1052 // Finish with the end of the sequence.
1053 if (LastAddress
!= InvalidAddress
)
1054 emitEndOfSequence(PrevEndOfSequence
);
1057 // This function is similar to the one from MCDwarfLineTable, except it handles
1058 // end-of-sequence entries differently by utilizing line entries with
1059 // DWARF2_FLAG_END_SEQUENCE flag.
1060 static inline void emitDwarfLineTable(
1061 MCStreamer
*MCOS
, MCSection
*Section
,
1062 const MCLineSection::MCDwarfLineEntryCollection
&LineEntries
) {
1063 unsigned FileNum
= 1;
1064 unsigned LastLine
= 1;
1065 unsigned Column
= 0;
1066 unsigned Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
1068 unsigned Discriminator
= 0;
1069 MCSymbol
*LastLabel
= nullptr;
1070 const MCAsmInfo
*AsmInfo
= MCOS
->getContext().getAsmInfo();
1072 // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1073 for (const MCDwarfLineEntry
&LineEntry
: LineEntries
) {
1074 if (LineEntry
.getFlags() & DWARF2_FLAG_END_SEQUENCE
) {
1075 MCOS
->emitDwarfAdvanceLineAddr(INT64_MAX
, LastLabel
, LineEntry
.getLabel(),
1076 AsmInfo
->getCodePointerSize());
1080 Flags
= DWARF2_LINE_DEFAULT_IS_STMT
? DWARF2_FLAG_IS_STMT
: 0;
1083 LastLabel
= nullptr;
1087 int64_t LineDelta
= static_cast<int64_t>(LineEntry
.getLine()) - LastLine
;
1089 if (FileNum
!= LineEntry
.getFileNum()) {
1090 FileNum
= LineEntry
.getFileNum();
1091 MCOS
->emitInt8(dwarf::DW_LNS_set_file
);
1092 MCOS
->emitULEB128IntValue(FileNum
);
1094 if (Column
!= LineEntry
.getColumn()) {
1095 Column
= LineEntry
.getColumn();
1096 MCOS
->emitInt8(dwarf::DW_LNS_set_column
);
1097 MCOS
->emitULEB128IntValue(Column
);
1099 if (Discriminator
!= LineEntry
.getDiscriminator() &&
1100 MCOS
->getContext().getDwarfVersion() >= 2) {
1101 Discriminator
= LineEntry
.getDiscriminator();
1102 unsigned Size
= getULEB128Size(Discriminator
);
1103 MCOS
->emitInt8(dwarf::DW_LNS_extended_op
);
1104 MCOS
->emitULEB128IntValue(Size
+ 1);
1105 MCOS
->emitInt8(dwarf::DW_LNE_set_discriminator
);
1106 MCOS
->emitULEB128IntValue(Discriminator
);
1108 if (Isa
!= LineEntry
.getIsa()) {
1109 Isa
= LineEntry
.getIsa();
1110 MCOS
->emitInt8(dwarf::DW_LNS_set_isa
);
1111 MCOS
->emitULEB128IntValue(Isa
);
1113 if ((LineEntry
.getFlags() ^ Flags
) & DWARF2_FLAG_IS_STMT
) {
1114 Flags
= LineEntry
.getFlags();
1115 MCOS
->emitInt8(dwarf::DW_LNS_negate_stmt
);
1117 if (LineEntry
.getFlags() & DWARF2_FLAG_BASIC_BLOCK
)
1118 MCOS
->emitInt8(dwarf::DW_LNS_set_basic_block
);
1119 if (LineEntry
.getFlags() & DWARF2_FLAG_PROLOGUE_END
)
1120 MCOS
->emitInt8(dwarf::DW_LNS_set_prologue_end
);
1121 if (LineEntry
.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN
)
1122 MCOS
->emitInt8(dwarf::DW_LNS_set_epilogue_begin
);
1124 MCSymbol
*Label
= LineEntry
.getLabel();
1126 // At this point we want to emit/create the sequence to encode the delta
1127 // in line numbers and the increment of the address from the previous
1128 // Label and the current Label.
1129 MCOS
->emitDwarfAdvanceLineAddr(LineDelta
, LastLabel
, Label
,
1130 AsmInfo
->getCodePointerSize());
1132 LastLine
= LineEntry
.getLine();
1136 assert(LastLabel
== nullptr && "end of sequence expected");
1139 void DwarfLineTable::emitCU(MCStreamer
*MCOS
, MCDwarfLineTableParams Params
,
1140 std::optional
<MCDwarfLineStr
> &LineStr
,
1141 BinaryContext
&BC
) const {
1142 if (!RawData
.empty()) {
1143 assert(MCLineSections
.getMCLineEntries().empty() &&
1144 InputSequences
.empty() &&
1145 "cannot combine raw data with new line entries");
1146 MCOS
->emitLabel(getLabel());
1147 MCOS
->emitBytes(RawData
);
1151 MCSymbol
*LineEndSym
= Header
.Emit(MCOS
, Params
, LineStr
).second
;
1153 // Put out the line tables.
1154 for (const auto &LineSec
: MCLineSections
.getMCLineEntries())
1155 emitDwarfLineTable(MCOS
, LineSec
.first
, LineSec
.second
);
1157 // Emit line tables for the original code.
1158 emitBinaryDwarfLineTable(MCOS
, Params
, InputTable
, InputSequences
);
1160 // This is the end of the section, so set the value of the symbol at the end
1161 // of this section (that was used in a previous expression).
1162 MCOS
->emitLabel(LineEndSym
);
1165 // Helper function to parse .debug_line_str, and populate one we are using.
1166 // For functions that we do not modify we output them as raw data.
1167 // Re-constructing .debug_line_str so that offsets are correct for those
1168 // debug line tables.
1169 // Bonus is that when we output a final binary we can re-use .debug_line_str
1170 // section. So we don't have to do the SHF_ALLOC trick we did with
1172 static void parseAndPopulateDebugLineStr(BinarySection
&LineStrSection
,
1173 MCDwarfLineStr
&LineStr
,
1174 BinaryContext
&BC
) {
1175 DataExtractor
StrData(LineStrSection
.getContents(),
1176 BC
.DwCtx
->isLittleEndian(), 0);
1177 uint64_t Offset
= 0;
1178 while (StrData
.isValidOffset(Offset
)) {
1179 const uint64_t StrOffset
= Offset
;
1180 Error Err
= Error::success();
1181 const char *CStr
= StrData
.getCStr(&Offset
, &Err
);
1183 errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1186 const size_t NewOffset
= LineStr
.addString(CStr
);
1187 assert(StrOffset
== NewOffset
&&
1188 "New offset in .debug_line_str doesn't match original offset");
1194 void DwarfLineTable::emit(BinaryContext
&BC
, MCStreamer
&Streamer
) {
1195 MCAssembler
&Assembler
=
1196 static_cast<MCObjectStreamer
*>(&Streamer
)->getAssembler();
1198 MCDwarfLineTableParams Params
= Assembler
.getDWARFLinetableParams();
1200 auto &LineTables
= BC
.getDwarfLineTables();
1202 // Bail out early so we don't switch to the debug_line section needlessly and
1203 // in doing so create an unnecessary (if empty) section.
1204 if (LineTables
.empty())
1206 // In a v5 non-split line table, put the strings in a separate section.
1207 std::optional
<MCDwarfLineStr
> LineStr
;
1208 ErrorOr
<BinarySection
&> LineStrSection
=
1209 BC
.getUniqueSectionByName(".debug_line_str");
1211 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
1212 // .debug_line, so need to check if section exists.
1213 if (LineStrSection
) {
1214 LineStr
.emplace(*BC
.Ctx
);
1215 parseAndPopulateDebugLineStr(*LineStrSection
, *LineStr
, BC
);
1218 // Switch to the section where the table will be emitted into.
1219 Streamer
.switchSection(BC
.MOFI
->getDwarfLineSection());
1221 const uint16_t DwarfVersion
= BC
.Ctx
->getDwarfVersion();
1222 // Handle the rest of the Compile Units.
1223 for (auto &CUIDTablePair
: LineTables
) {
1224 Streamer
.getContext().setDwarfVersion(
1225 CUIDTablePair
.second
.getDwarfVersion());
1226 CUIDTablePair
.second
.emitCU(&Streamer
, Params
, LineStr
, BC
);
1229 // Resetting DWARF version for rest of the flow.
1230 BC
.Ctx
->setDwarfVersion(DwarfVersion
);
1232 // Still need to write the section out for the ExecutionEngine, and temp in
1233 // memory object we are constructing.
1235 LineStr
->emitSection(&Streamer
);