[mlir] minor documentation fix in GPUTransformOps.td (#121157)
[llvm-project.git] / bolt / lib / Core / DebugData.cpp
blobbd8aa807f1aaedd06254fa606838225ed75697d9
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/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"
29 #include <algorithm>
30 #include <cassert>
31 #include <cstdint>
32 #include <functional>
33 #include <memory>
34 #include <optional>
35 #include <unordered_map>
36 #include <vector>
38 #define DEBUG_TYPE "bolt-debug-info"
40 namespace opts {
41 extern llvm::cl::opt<unsigned> Verbosity;
42 } // namespace opts
44 namespace llvm {
45 class MCSymbol;
47 namespace bolt {
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,
53 DIELocList(NewVal));
54 else
55 DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
56 DIEInteger(NewVal));
59 std::optional<AttrInfo>
60 findAttributeInfo(const DWARFDie DIE,
61 const DWARFAbbreviationDeclaration *AbbrevDecl,
62 uint32_t Index) {
63 const DWARFUnit &U = *DIE.getDwarfUnit();
64 uint64_t Offset =
65 AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
66 std::optional<DWARFFormValue> Value =
67 AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
68 if (!Value)
69 return std::nullopt;
70 // AttributeSpec
71 const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
72 AbbrevDecl->attributes().begin() + Index;
73 uint32_t ValSize = 0;
74 std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
75 if (ValSizeOpt) {
76 ValSize = static_cast<uint32_t>(*ValSizeOpt);
77 } else {
78 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
79 uint64_t NewOffset = Offset;
80 DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
81 U.getFormParams());
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
84 // location.
85 ValSize = NewOffset - Offset;
87 return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};
90 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
91 dwarf::Attribute Attr) {
92 if (!DIE.isValid())
93 return std::nullopt;
94 const DWARFAbbreviationDeclaration *AbbrevDecl =
95 DIE.getAbbreviationDeclarationPtr();
96 if (!AbbrevDecl)
97 return std::nullopt;
98 std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);
99 if (!Index)
100 return std::nullopt;
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]);
112 errs() << "\n";
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.
120 static uint64_t
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) {
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 = RangesBuffer->size();
172 writeAddressRanges(*RangesStream.get(), Ranges);
174 return EntryOffset;
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
195 // size of header.
196 VersionType Version;
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);
224 return HeaderBuffer;
227 struct OffsetEntry {
228 uint32_t Index;
229 uint32_t StartOffset;
230 uint32_t EndOffset;
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)
239 return false;
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)
246 break;
247 // In case rnglists or loclists are not sorted.
248 if (Base > Entry.LowPC)
249 break;
250 uint32_t StartOffset = Entry.LowPC - Base;
251 uint32_t EndOffset = Entry.HighPC - Base;
252 if (encodeULEB128(EndOffset, TempBuffer) > 2)
253 break;
254 Offsets.push_back({Index, StartOffset, EndOffset});
255 ++Index;
258 if (Offsets.size() < 2) {
259 Index -= Offsets.size();
260 return false;
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);
274 return true;
277 uint64_t
278 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
279 std::lock_guard<std::mutex> Lock(WriterMutex);
281 RangeEntries.push_back(CurrentOffset);
282 std::sort(
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 {}))
293 continue;
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);
302 ++I;
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();
335 CurrentOffset = 0;
336 CU = &Unit;
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;
355 // Emit header.
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)
425 return;
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
441 // now using it.
442 DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,
443 DIEInteger(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())
454 return std::nullopt;
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 {
462 ++Counter;
463 switch (AddressByteSize) {
464 default:
465 assert(false && "Address Size is invalid.");
466 break;
467 case 4:
468 support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
469 llvm::endianness::little);
470 break;
471 case 8:
472 support::endian::write(*AddressStream, Address, llvm::endianness::little);
473 break;
477 for (const IndexAddressPair &Val : SortedMap) {
478 while (Val.first > Counter)
479 WriteAddress(0);
480 WriteAddress(Val.second);
482 return std::nullopt;
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
506 // for it.
507 if (Map.begin() == Map.end()) {
508 if (!AddrOffsetSectionBase)
509 return std::nullopt;
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())
515 return Iter->second;
516 UnmodifiedAddressOffsets[Offset] = BufferSize;
517 if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize,
518 DumpOpts.WarningHandler)) {
519 DumpOpts.RecoverableErrorHandler(std::move(Err));
520 return std::nullopt;
522 uint32_t Index = 0;
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),
536 Endian);
537 support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);
539 uint32_t Counter = 0;
540 auto writeAddress = [&](uint64_t Address) -> void {
541 ++Counter;
542 switch (AddressByteSize) {
543 default:
544 llvm_unreachable("Address Size is invalid.");
545 break;
546 case 4:
547 support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
548 Endian);
549 break;
550 case 8:
551 support::endian::write(*AddressStream, Address, Endian);
552 break;
556 for (const IndexAddressPair &Val : SortedMap) {
557 while (Val.first > Counter)
558 writeAddress(0);
559 writeAddress(Val.second);
561 return std::nullopt;
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
568 // lists will point.
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);
582 return;
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()),
596 Entry.Expr.size());
597 LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();
599 LocStream->write_zeros(16);
600 LocSectionOffset += 16;
601 LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen
602 // use
603 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
606 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
607 return std::move(LocBuffer);
610 // DWARF 4: 2.6.2
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);
636 return;
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()),
653 Entry.Expr.size());
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,
666 DWARFUnit &CU,
667 raw_svector_ostream &LocBodyStream) {
669 replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
670 NumberOfEntries);
672 RelativeLocListOffsets.push_back(LocBodyBuffer.size());
673 ++NumberOfEntries;
674 if (LocList.empty()) {
675 writeEmptyListDwarf5(LocBodyStream);
676 return;
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,
691 writeExpression))
692 continue;
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);
701 writeExpression(I);
702 ++I;
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,
711 DIEValue &AttrInfo,
712 DebugLocationsVector &LocList) {
713 if (DwarfVersion < 5)
714 writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer,
715 CU, *LocStream);
716 else
717 writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
718 AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
719 *LocBodyStream);
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
728 // in this CU.
729 if (!isSplitDwarf() && LocListBaseAttrInfo.getType())
730 DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
731 LocListBaseAttrInfo.getForm(),
732 DIEInteger(getDWARF5RngListLocListHeaderSize()));
733 return;
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(
745 *LocArrayStream,
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()));
763 } else {
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;
784 NewValue >>= 8;
786 return LE64;
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,
801 size_t ByteSize) {
802 Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
805 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
806 uint32_t OldValueSize) {
807 std::string Buff;
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)
839 return;
840 const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
841 const std::optional<StrOffsetsContributionDescriptor> &Contr =
842 Unit.getStringOffsetsTableContribution();
843 if (!Contr)
844 return;
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())
868 return;
869 std::optional<uint64_t> Val = std::nullopt;
870 if (AttrVal) {
871 Val = AttrVal->V.getAsSectionOffset();
872 } else {
873 if (!Unit.isDWOUnit())
874 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
875 "DW_AT_str_offsets_base Value not present\n";
876 Val = 0;
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) {
884 initialize(Unit);
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);
906 } else {
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.");
915 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 StringRef StrSection;
925 if (IsDWO)
926 StrSection = DwCtx.getDWARFObj().getStrDWOSection();
927 else
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())
935 initialize();
936 auto Offset = StrBuffer->size();
937 (*StrStream) << Str;
938 StrStream->write_zeros(1);
939 return Offset;
942 static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
943 MCDwarfLineTableParams Params,
944 int64_t LineDelta, uint64_t Address,
945 int PointerSize) {
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())
961 return;
963 constexpr uint64_t InvalidAddress = UINT64_MAX;
964 unsigned FileNum = 1;
965 unsigned LastLine = 1;
966 unsigned Column = 0;
967 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
968 unsigned Isa = 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);
976 FileNum = 1;
977 LastLine = 1;
978 Column = 0;
979 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
980 Isa = 0;
981 Discriminator = 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) {
1002 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) {
1021 Isa = Row.Isa;
1022 MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1023 MCOS->emitULEB128IntValue(Isa);
1025 if (Row.IsStmt != Flags) {
1026 Flags = Row.IsStmt;
1027 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1029 if (Row.BasicBlock)
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);
1040 } else {
1041 if (LastAddress == InvalidAddress)
1042 emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1043 AsmInfo->getCodePointerSize());
1044 else
1045 MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1047 LastAddress = Address;
1048 LastLine = Row.Line;
1051 Discriminator = 0;
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;
1071 unsigned Isa = 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());
1081 FileNum = 1;
1082 LastLine = 1;
1083 Column = 0;
1084 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1085 Isa = 0;
1086 Discriminator = 0;
1087 LastLabel = nullptr;
1088 continue;
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());
1135 Discriminator = 0;
1136 LastLine = LineEntry.getLine();
1137 LastLabel = Label;
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);
1152 return;
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
1175 // .debug_line.
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);
1186 if (Err) {
1187 BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1188 continue;
1190 const size_t NewOffset = LineStr.addString(CStr);
1191 assert(StrOffset == NewOffset &&
1192 "New offset in .debug_line_str doesn't match original offset");
1193 (void)StrOffset;
1194 (void)NewOffset;
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())
1209 return;
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.
1238 if (LineStr)
1239 LineStr->emitSection(&Streamer);
1242 } // namespace bolt
1243 } // namespace llvm