[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / bolt / lib / Core / DebugData.cpp
blob415b0310b6bac84c2daee8a26faea78ad850ae91
1 //===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
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"
31 #include <algorithm>
32 #include <cassert>
33 #include <cstdint>
34 #include <functional>
35 #include <limits>
36 #include <memory>
37 #include <unordered_map>
38 #include <vector>
40 #define DEBUG_TYPE "bolt-debug-info"
42 namespace opts {
43 extern llvm::cl::opt<unsigned> Verbosity;
44 } // namespace opts
46 namespace llvm {
47 class MCSymbol;
49 namespace bolt {
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,
55 DIELocList(NewVal));
56 else
57 DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
58 DIEInteger(NewVal));
61 std::optional<AttrInfo>
62 findAttributeInfo(const DWARFDie DIE,
63 const DWARFAbbreviationDeclaration *AbbrevDecl,
64 uint32_t Index) {
65 const DWARFUnit &U = *DIE.getDwarfUnit();
66 uint64_t Offset =
67 AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
68 std::optional<DWARFFormValue> Value =
69 AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
70 if (!Value)
71 return std::nullopt;
72 // AttributeSpec
73 const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
74 AbbrevDecl->attributes().begin() + Index;
75 uint32_t ValSize = 0;
76 std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
77 if (ValSizeOpt) {
78 ValSize = static_cast<uint32_t>(*ValSizeOpt);
79 } else {
80 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
81 uint64_t NewOffset = Offset;
82 DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
83 U.getFormParams());
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
86 // location.
87 ValSize = NewOffset - Offset;
89 return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};
92 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
93 dwarf::Attribute Attr) {
94 if (!DIE.isValid())
95 return std::nullopt;
96 const DWARFAbbreviationDeclaration *AbbrevDecl =
97 DIE.getAbbreviationDeclarationPtr();
98 if (!AbbrevDecl)
99 return std::nullopt;
100 std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);
101 if (!Index)
102 return std::nullopt;
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]);
114 errs() << "\n";
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.
122 static uint64_t
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;
143 SectionOffset +=
144 writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
145 Kind = RangesWriterKind::DebugRangesWriter;
148 uint64_t DebugRangesSectionWriter::addRanges(
149 DebugAddressRangesVector &&Ranges,
150 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
151 if (Ranges.empty())
152 return getEmptyRangesOffset();
154 const auto RI = CachedRanges.find(Ranges);
155 if (RI != CachedRanges.end())
156 return RI->second;
158 const uint64_t EntryOffset = addRanges(Ranges);
159 CachedRanges.emplace(std::move(Ranges), EntryOffset);
161 return EntryOffset;
164 uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
165 if (Ranges.empty())
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);
174 return EntryOffset;
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 entries section, not including
192 // size of header.
193 VersionType Version;
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);
221 return HeaderBuffer;
224 struct OffsetEntry {
225 uint32_t Index;
226 uint32_t StartOffset;
227 uint32_t EndOffset;
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)
236 return false;
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)
243 break;
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)
248 break;
249 Offsets.push_back({Index, StartOffset, EndOffset});
250 ++Index;
253 if (Offsets.size() < 2) {
254 Index -= Offsets.size();
255 return false;
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);
271 return true;
274 uint64_t
275 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
276 std::lock_guard<std::mutex> Lock(WriterMutex);
278 RangeEntries.push_back(CurrentOffset);
279 bool WrittenStartxLength = false;
280 std::sort(
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,
288 DebugAddressRange>(
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 {}))
292 continue;
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);
301 ++I;
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();
336 CurrentOffset = 0;
337 CU = &Unit;
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;
356 // Emit header.
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)
429 return;
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
445 // now using it.
446 DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,
447 DIEInteger(Offset));
451 void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
452 // Handling the case where debug information is a mix of Debug fission and
453 // monolithic.
454 if (!CU.getDWOId())
455 return;
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())
463 return;
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 {
472 ++Counter;
473 switch (AddrSize) {
474 default:
475 assert(false && "Address Size is invalid.");
476 break;
477 case 4:
478 support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
479 llvm::endianness::little);
480 break;
481 case 8:
482 support::endian::write(*AddressStream, Address, llvm::endianness::little);
483 break;
487 for (const IndexAddressPair &Val : SortedMap) {
488 while (Val.first > Counter)
489 WriteAddress(0);
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
511 // for it.
512 if (AMIter == AddressMaps.end()) {
513 AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first;
514 std::optional<uint64_t> BaseOffset = CU.getAddrOffsetSectionBase();
515 if (!BaseOffset)
516 return;
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());
523 return;
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));
529 return;
532 uint32_t Index = 0;
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),
548 Endian);
549 support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);
551 uint32_t Counter = 0;
552 auto writeAddress = [&](uint64_t Address) -> void {
553 ++Counter;
554 switch (AddrSize) {
555 default:
556 llvm_unreachable("Address Size is invalid.");
557 break;
558 case 4:
559 support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
560 Endian);
561 break;
562 case 8:
563 support::endian::write(*AddressStream, Address, Endian);
564 break;
568 for (const IndexAddressPair &Val : SortedMap) {
569 while (Val.first > Counter)
570 writeAddress(0);
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
579 // lists will point.
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);
593 return;
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()),
607 Entry.Expr.size());
608 LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();
610 LocStream->write_zeros(16);
611 LocSectionOffset += 16;
612 LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen
613 // use
614 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
617 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
618 return std::move(LocBuffer);
621 // DWARF 4: 2.6.2
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);
647 return;
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()),
664 Entry.Expr.size());
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,
677 DWARFUnit &CU,
678 raw_svector_ostream &LocBodyStream) {
680 replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
681 NumberOfEntries);
683 RelativeLocListOffsets.push_back(LocBodyBuffer.size());
684 ++NumberOfEntries;
685 if (LocList.empty()) {
686 writeEmptyListDwarf5(LocBodyStream);
687 return;
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,
701 DebugLocationEntry>(
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))
705 continue;
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);
714 writeExpression(I);
715 ++I;
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,
726 DIEValue &AttrInfo,
727 DebugLocationsVector &LocList) {
728 if (DwarfVersion < 5)
729 writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, *AddrWriter, *LocBuffer,
730 CU, *LocStream);
731 else
732 writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
733 *AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
734 *LocBodyStream);
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
743 // in this CU.
744 if (!isSplitDwarf() && LocListBaseAttrInfo.getType())
745 DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
746 LocListBaseAttrInfo.getForm(),
747 DIEInteger(getDWARF5RngListLocListHeaderSize()));
748 return;
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(
760 *LocArrayStream,
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()));
778 } else {
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;
801 NewValue >>= 8;
803 return LE64;
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,
818 size_t ByteSize) {
819 Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
822 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
823 uint32_t OldValueSize) {
824 std::string Buff;
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(DWARFUnit &Unit) {
855 if (Unit.getVersion() < 5)
856 return;
857 const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
858 const std::optional<StrOffsetsContributionDescriptor> &Contr =
859 Unit.getStringOffsetsTableContribution();
860 if (!Contr)
861 return;
862 const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
863 assert(DwarfOffsetByteSize == 4 &&
864 "Dwarf String Offsets Byte Size is not supported.");
865 StrOffsets.reserve(Contr->Size);
866 for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)
867 StrOffsets.push_back(support::endian::read32le(
868 StrOffsetsSection.Data.data() + Contr->Base + Offset));
871 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) {
872 IndexToAddressMap[Index] = Address;
873 StrOffsetSectionWasModified = true;
876 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
877 DIEBuilder &DIEBldr) {
878 std::optional<AttrInfo> AttrVal =
879 findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
880 if (!AttrVal)
881 return;
882 std::optional<uint64_t> Val = AttrVal->V.getAsSectionOffset();
883 assert(Val && "DW_AT_str_offsets_base Value not present.");
884 DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
885 DIEValue StrListBaseAttrInfo =
886 Die.findAttribute(dwarf::DW_AT_str_offsets_base);
887 auto RetVal = ProcessedBaseOffsets.find(*Val);
888 // Handling re-use of str-offsets section.
889 if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {
890 initialize(Unit);
891 // Update String Offsets that were modified.
892 for (const auto &Entry : IndexToAddressMap)
893 StrOffsets[Entry.first] = Entry.second;
894 // Writing out the header for each section.
895 support::endian::write(*StrOffsetsStream,
896 static_cast<uint32_t>(StrOffsets.size() * 4 + 4),
897 llvm::endianness::little);
898 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),
899 llvm::endianness::little);
900 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),
901 llvm::endianness::little);
903 uint64_t BaseOffset = StrOffsetsBuffer->size();
904 ProcessedBaseOffsets[*Val] = BaseOffset;
905 if (StrListBaseAttrInfo.getType())
906 DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
907 StrListBaseAttrInfo.getForm(),
908 DIEInteger(BaseOffset));
909 for (const uint32_t Offset : StrOffsets)
910 support::endian::write(*StrOffsetsStream, Offset,
911 llvm::endianness::little);
912 } else {
913 DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
914 StrListBaseAttrInfo.getForm(),
915 DIEInteger(RetVal->second));
918 StrOffsetSectionWasModified = false;
919 IndexToAddressMap.clear();
920 StrOffsets.clear();
923 void DebugStrWriter::create() {
924 StrBuffer = std::make_unique<DebugStrBufferVector>();
925 StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
928 void DebugStrWriter::initialize() {
929 auto StrSection = BC.DwCtx->getDWARFObj().getStrSection();
930 (*StrStream) << StrSection;
933 uint32_t DebugStrWriter::addString(StringRef Str) {
934 std::lock_guard<std::mutex> Lock(WriterMutex);
935 if (StrBuffer->empty())
936 initialize();
937 auto Offset = StrBuffer->size();
938 (*StrStream) << Str;
939 StrStream->write_zeros(1);
940 return Offset;
943 static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
944 MCDwarfLineTableParams Params,
945 int64_t LineDelta, uint64_t Address,
946 int PointerSize) {
947 // emit the sequence to set the address
948 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
949 OS.emitULEB128IntValue(PointerSize + 1);
950 OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
951 OS.emitIntValue(Address, PointerSize);
953 // emit the sequence for the LineDelta (from 1) and a zero address delta.
954 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
957 static inline void emitBinaryDwarfLineTable(
958 MCStreamer *MCOS, MCDwarfLineTableParams Params,
959 const DWARFDebugLine::LineTable *Table,
960 const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
961 if (InputSequences.empty())
962 return;
964 constexpr uint64_t InvalidAddress = UINT64_MAX;
965 unsigned FileNum = 1;
966 unsigned LastLine = 1;
967 unsigned Column = 0;
968 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
969 unsigned Isa = 0;
970 unsigned Discriminator = 0;
971 uint64_t LastAddress = InvalidAddress;
972 uint64_t PrevEndOfSequence = InvalidAddress;
973 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
975 auto emitEndOfSequence = [&](uint64_t Address) {
976 MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
977 FileNum = 1;
978 LastLine = 1;
979 Column = 0;
980 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
981 Isa = 0;
982 Discriminator = 0;
983 LastAddress = InvalidAddress;
986 for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
987 const uint64_t SequenceStart =
988 Table->Rows[Sequence.FirstIndex].Address.Address;
990 // Check if we need to mark the end of the sequence.
991 if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
992 PrevEndOfSequence != SequenceStart) {
993 emitEndOfSequence(PrevEndOfSequence);
996 for (uint32_t RowIndex = Sequence.FirstIndex;
997 RowIndex <= Sequence.LastIndex; ++RowIndex) {
998 const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
999 int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
1000 const uint64_t Address = Row.Address.Address;
1002 if (FileNum != Row.File) {
1003 FileNum = Row.File;
1004 MCOS->emitInt8(dwarf::DW_LNS_set_file);
1005 MCOS->emitULEB128IntValue(FileNum);
1007 if (Column != Row.Column) {
1008 Column = Row.Column;
1009 MCOS->emitInt8(dwarf::DW_LNS_set_column);
1010 MCOS->emitULEB128IntValue(Column);
1012 if (Discriminator != Row.Discriminator &&
1013 MCOS->getContext().getDwarfVersion() >= 4) {
1014 Discriminator = Row.Discriminator;
1015 unsigned Size = getULEB128Size(Discriminator);
1016 MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1017 MCOS->emitULEB128IntValue(Size + 1);
1018 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1019 MCOS->emitULEB128IntValue(Discriminator);
1021 if (Isa != Row.Isa) {
1022 Isa = Row.Isa;
1023 MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1024 MCOS->emitULEB128IntValue(Isa);
1026 if (Row.IsStmt != Flags) {
1027 Flags = Row.IsStmt;
1028 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1030 if (Row.BasicBlock)
1031 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1032 if (Row.PrologueEnd)
1033 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1034 if (Row.EpilogueBegin)
1035 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1037 // The end of the sequence is not normal in the middle of the input
1038 // sequence, but could happen, e.g. for assembly code.
1039 if (Row.EndSequence) {
1040 emitEndOfSequence(Address);
1041 } else {
1042 if (LastAddress == InvalidAddress)
1043 emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1044 AsmInfo->getCodePointerSize());
1045 else
1046 MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1048 LastAddress = Address;
1049 LastLine = Row.Line;
1052 Discriminator = 0;
1054 PrevEndOfSequence = Sequence.EndAddress;
1057 // Finish with the end of the sequence.
1058 if (LastAddress != InvalidAddress)
1059 emitEndOfSequence(PrevEndOfSequence);
1062 // This function is similar to the one from MCDwarfLineTable, except it handles
1063 // end-of-sequence entries differently by utilizing line entries with
1064 // DWARF2_FLAG_END_SEQUENCE flag.
1065 static inline void emitDwarfLineTable(
1066 MCStreamer *MCOS, MCSection *Section,
1067 const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1068 unsigned FileNum = 1;
1069 unsigned LastLine = 1;
1070 unsigned Column = 0;
1071 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1072 unsigned Isa = 0;
1073 unsigned Discriminator = 0;
1074 MCSymbol *LastLabel = nullptr;
1075 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1077 // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1078 for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1079 if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1080 MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1081 AsmInfo->getCodePointerSize());
1082 FileNum = 1;
1083 LastLine = 1;
1084 Column = 0;
1085 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1086 Isa = 0;
1087 Discriminator = 0;
1088 LastLabel = nullptr;
1089 continue;
1092 int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1094 if (FileNum != LineEntry.getFileNum()) {
1095 FileNum = LineEntry.getFileNum();
1096 MCOS->emitInt8(dwarf::DW_LNS_set_file);
1097 MCOS->emitULEB128IntValue(FileNum);
1099 if (Column != LineEntry.getColumn()) {
1100 Column = LineEntry.getColumn();
1101 MCOS->emitInt8(dwarf::DW_LNS_set_column);
1102 MCOS->emitULEB128IntValue(Column);
1104 if (Discriminator != LineEntry.getDiscriminator() &&
1105 MCOS->getContext().getDwarfVersion() >= 2) {
1106 Discriminator = LineEntry.getDiscriminator();
1107 unsigned Size = getULEB128Size(Discriminator);
1108 MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1109 MCOS->emitULEB128IntValue(Size + 1);
1110 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1111 MCOS->emitULEB128IntValue(Discriminator);
1113 if (Isa != LineEntry.getIsa()) {
1114 Isa = LineEntry.getIsa();
1115 MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1116 MCOS->emitULEB128IntValue(Isa);
1118 if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1119 Flags = LineEntry.getFlags();
1120 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1122 if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1123 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1124 if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1125 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1126 if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1127 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1129 MCSymbol *Label = LineEntry.getLabel();
1131 // At this point we want to emit/create the sequence to encode the delta
1132 // in line numbers and the increment of the address from the previous
1133 // Label and the current Label.
1134 MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1135 AsmInfo->getCodePointerSize());
1136 Discriminator = 0;
1137 LastLine = LineEntry.getLine();
1138 LastLabel = Label;
1141 assert(LastLabel == nullptr && "end of sequence expected");
1144 void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1145 std::optional<MCDwarfLineStr> &LineStr,
1146 BinaryContext &BC) const {
1147 if (!RawData.empty()) {
1148 assert(MCLineSections.getMCLineEntries().empty() &&
1149 InputSequences.empty() &&
1150 "cannot combine raw data with new line entries");
1151 MCOS->emitLabel(getLabel());
1152 MCOS->emitBytes(RawData);
1153 return;
1156 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1158 // Put out the line tables.
1159 for (const auto &LineSec : MCLineSections.getMCLineEntries())
1160 emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1162 // Emit line tables for the original code.
1163 emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1165 // This is the end of the section, so set the value of the symbol at the end
1166 // of this section (that was used in a previous expression).
1167 MCOS->emitLabel(LineEndSym);
1170 // Helper function to parse .debug_line_str, and populate one we are using.
1171 // For functions that we do not modify we output them as raw data.
1172 // Re-constructing .debug_line_str so that offsets are correct for those
1173 // debug line tables.
1174 // Bonus is that when we output a final binary we can re-use .debug_line_str
1175 // section. So we don't have to do the SHF_ALLOC trick we did with
1176 // .debug_line.
1177 static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
1178 MCDwarfLineStr &LineStr,
1179 BinaryContext &BC) {
1180 DataExtractor StrData(LineStrSection.getContents(),
1181 BC.DwCtx->isLittleEndian(), 0);
1182 uint64_t Offset = 0;
1183 while (StrData.isValidOffset(Offset)) {
1184 const uint64_t StrOffset = Offset;
1185 Error Err = Error::success();
1186 const char *CStr = StrData.getCStr(&Offset, &Err);
1187 if (Err) {
1188 errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1189 continue;
1191 const size_t NewOffset = LineStr.addString(CStr);
1192 assert(StrOffset == NewOffset &&
1193 "New offset in .debug_line_str doesn't match original offset");
1194 (void)StrOffset;
1195 (void)NewOffset;
1199 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1200 MCAssembler &Assembler =
1201 static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1203 MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1205 auto &LineTables = BC.getDwarfLineTables();
1207 // Bail out early so we don't switch to the debug_line section needlessly and
1208 // in doing so create an unnecessary (if empty) section.
1209 if (LineTables.empty())
1210 return;
1211 // In a v5 non-split line table, put the strings in a separate section.
1212 std::optional<MCDwarfLineStr> LineStr;
1213 ErrorOr<BinarySection &> LineStrSection =
1214 BC.getUniqueSectionByName(".debug_line_str");
1216 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
1217 // .debug_line, so need to check if section exists.
1218 if (LineStrSection) {
1219 LineStr.emplace(*BC.Ctx);
1220 parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC);
1223 // Switch to the section where the table will be emitted into.
1224 Streamer.switchSection(BC.MOFI->getDwarfLineSection());
1226 const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
1227 // Handle the rest of the Compile Units.
1228 for (auto &CUIDTablePair : LineTables) {
1229 Streamer.getContext().setDwarfVersion(
1230 CUIDTablePair.second.getDwarfVersion());
1231 CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1234 // Resetting DWARF version for rest of the flow.
1235 BC.Ctx->setDwarfVersion(DwarfVersion);
1237 // Still need to write the section out for the ExecutionEngine, and temp in
1238 // memory object we are constructing.
1239 if (LineStr)
1240 LineStr->emitSection(&Streamer);
1243 } // namespace bolt
1244 } // namespace llvm