xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision 9a3e66e314e698ffb08dba151bc098b6b8867c61)
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.
10 //
11 //===----------------------------------------------------------------------===//
12 
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>
37 
38 #define DEBUG_TYPE "bolt-debug-info"
39 
40 namespace opts {
41 extern llvm::cl::opt<unsigned> Verbosity;
42 } // namespace opts
43 
44 namespace llvm {
45 class MCSymbol;
46 
47 namespace bolt {
48 
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));
57 }
58 
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;
86   }
87   return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};
88 }
89 
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);
102 }
103 
104 const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
105 
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]);
111   }
112   errs() << "\n";
113 }
114 
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);
129   }
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;
134 }
135 
136 DebugRangesSectionWriter::DebugRangesSectionWriter() {
137   RangesBuffer = std::make_unique<DebugBufferVector>();
138   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
139 
140   Kind = RangesWriterKind::DebugRangesWriter;
141 }
142 
143 void DebugRangesSectionWriter::initSection() {
144   // Adds an empty range to the buffer.
145   writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
146 }
147 
148 uint64_t DebugRangesSectionWriter::addRanges(
149     DebugAddressRangesVector &&Ranges,
150     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
151   if (Ranges.empty())
152     return getEmptyRangesOffset();
153 
154   const auto RI = CachedRanges.find(Ranges);
155   if (RI != CachedRanges.end())
156     return RI->second;
157 
158   const uint64_t EntryOffset = addRanges(Ranges);
159   CachedRanges.emplace(std::move(Ranges), EntryOffset);
160 
161   return EntryOffset;
162 }
163 
164 uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
165   if (Ranges.empty())
166     return getEmptyRangesOffset();
167 
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);
173 
174   return EntryOffset;
175 }
176 
177 uint64_t DebugRangesSectionWriter::getSectionOffset() {
178   std::lock_guard<std::mutex> Lock(WriterMutex);
179   return RangesBuffer->size();
180 }
181 
182 void DebugRangesSectionWriter::appendToRangeBuffer(
183     const DebugBufferVector &CUBuffer) {
184   *RangesStream << CUBuffer;
185 }
186 
187 uint64_t DebugRangeListsSectionWriter::addRanges(
188     DebugAddressRangesVector &&Ranges,
189     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
190   return addRanges(Ranges);
191 }
192 
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;
200 };
201 
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);
208 
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);
213 
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;
225 }
226 
227 struct OffsetEntry {
228   uint32_t Index;
229   uint32_t StartOffset;
230   uint32_t EndOffset;
231 };
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;
256   }
257 
258   if (Offsets.size() < 2) {
259     Index -= Offsets.size();
260     return false;
261   }
262 
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);
273   }
274   return true;
275 }
276 
277 uint64_t
278 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
279   std::lock_guard<std::mutex> Lock(WriterMutex);
280 
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;
286       });
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;
294 
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;
303   }
304 
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;
310 }
311 
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);
322 
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 }
330 
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;
337 }
338 
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));
343 }
344 
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;
354 
355     // Emit header.
356 
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);
362 
363     // Header field #1: set size.
364     support::endian::write(RangesStream, Size, llvm::endianness::little);
365 
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);
369 
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);
375 
376     // Header field #4: address size.
377     // 8 since we only write ELF64 binaries for now.
378     RangesStream << char(8);
379 
380     // Header field #5: segment size of target architecture.
381     RangesStream << char(0);
382 
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);
386 
387     writeAddressRanges(RangesStream, AddressRanges, true);
388   }
389 }
390 
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);
396 }
397 
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";
405 }
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;
412   }
413   return Entry->second;
414 }
415 
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;
426 
427   if (GnuAddrBaseAttrInfo) {
428     BaseAttrForm = GnuAddrBaseAttrInfo.getForm();
429     BaseAttr = GnuAddrBaseAttrInfo.getAttribute();
430   }
431 
432   if (AddrBaseAttrInfo) {
433     BaseAttrForm = AddrBaseAttrInfo.getForm();
434     BaseAttr = AddrBaseAttrInfo.getAttribute();
435   }
436 
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));
444   }
445 }
446 
447 void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
448                                      const uint64_t Offset) {
449   updateAddressBase(DIEBlder, *this, CU, Offset);
450 }
451 
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());
459 
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;
474     }
475   };
476 
477   for (const IndexAddressPair &Val : SortedMap) {
478     while (Val.first > Counter)
479       WriteAddress(0);
480     WriteAddress(Val.second);
481   }
482   return std::nullopt;
483 }
484 
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);
489 }
490 
491 DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets;
492 
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;
521     }
522     uint32_t Index = 0;
523     for (uint64_t Addr : AddrTable.getAddressEntries())
524       Map.insert(Addr, Index++);
525   }
526 
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);
538 
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;
553     }
554   };
555 
556   for (const IndexAddressPair &Val : SortedMap) {
557     while (Val.first > Counter)
558       writeAddress(0);
559     writeAddress(Val.second);
560   }
561   return std::nullopt;
562 }
563 
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;
573   }
574 }
575 
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;
583   }
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;
587 
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();
598   }
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);
604 }
605 
606 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
607   return std::move(LocBuffer);
608 }
609 
610 // DWARF 4: 2.6.2
611 void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}
612 
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);
618 
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);
625 }
626 
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;
637   }
638 
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);
646 
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());
654   }
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);
659 }
660 
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) {
668 
669   replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
670                       NumberOfEntries);
671 
672   RelativeLocListOffsets.push_back(LocBodyBuffer.size());
673   ++NumberOfEntries;
674   if (LocList.empty()) {
675     writeEmptyListDwarf5(LocBodyStream);
676     return;
677   }
678 
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());
685   };
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;
693 
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;
703   }
704 
705   support::endian::write(LocBodyStream,
706                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
707                          llvm::endianness::little);
708 }
709 
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);
720 }
721 
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;
734   }
735 
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);
740 
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);
748 
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;
755 
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()));
767     }
768     LoclistBaseOffset += LocBuffer->size();
769   }
770   clearList(RelativeLocListOffsets);
771   clearList(*LocArrayBuffer);
772   clearList(*LocBodyBuffer);
773 }
774 
775 void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {
776   if (DwarfVersion >= 5)
777     finalizeDWARF5(DIEBldr, Die);
778 }
779 
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;
785   }
786   return LE64;
787 }
788 
789 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
790                                          std::string &&NewValue,
791                                          uint32_t OldValueSize) {
792   Patches.emplace_back(Offset, std::move(NewValue));
793 }
794 
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));
798 }
799 
800 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
801                                      size_t ByteSize) {
802   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
803 }
804 
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);
810 
811   Patches.emplace_back(Offset, std::move(Buff));
812 }
813 
814 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
815   addLEPatch(Offset, NewValue, 8);
816 }
817 
818 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
819                                        uint32_t OldValueSize) {
820   addLEPatch(Offset, NewValue, 4);
821 }
822 
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];
832     }
833   }
834   return BinaryContentsStr;
835 }
836 
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));
852 }
853 
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;
861 }
862 
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;
877   }
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);
896 
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));
910   }
911 
912   StrOffsetSectionWasModified = false;
913   assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second &&
914          "debug_str_offsets was already finalized for this CU.");
915   clear();
916 }
917 
918 void DebugStrWriter::create() {
919   StrBuffer = std::make_unique<DebugStrBufferVector>();
920   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
921 }
922 
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;
930 }
931 
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;
940 }
941 
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);
951 
952   // emit the sequence for the LineDelta (from 1) and a zero address delta.
953   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
954 }
955 
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;
962 
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();
973 
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;
983   };
984 
985   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
986     const uint64_t SequenceStart =
987         Table->Rows[Sequence.FirstIndex].Address.Address;
988 
989     // Check if we need to mark the end of the sequence.
990     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
991         PrevEndOfSequence != SequenceStart) {
992       emitEndOfSequence(PrevEndOfSequence);
993     }
994 
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;
1000 
1001       if (FileNum != Row.File) {
1002         FileNum = Row.File;
1003         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1004         MCOS->emitULEB128IntValue(FileNum);
1005       }
1006       if (Column != Row.Column) {
1007         Column = Row.Column;
1008         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1009         MCOS->emitULEB128IntValue(Column);
1010       }
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);
1019       }
1020       if (Isa != Row.Isa) {
1021         Isa = Row.Isa;
1022         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1023         MCOS->emitULEB128IntValue(Isa);
1024       }
1025       if (Row.IsStmt != Flags) {
1026         Flags = Row.IsStmt;
1027         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1028       }
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);
1035 
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);
1046 
1047         LastAddress = Address;
1048         LastLine = Row.Line;
1049       }
1050 
1051       Discriminator = 0;
1052     }
1053     PrevEndOfSequence = Sequence.EndAddress;
1054   }
1055 
1056   // Finish with the end of the sequence.
1057   if (LastAddress != InvalidAddress)
1058     emitEndOfSequence(PrevEndOfSequence);
1059 }
1060 
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();
1075 
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;
1089     }
1090 
1091     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1092 
1093     if (FileNum != LineEntry.getFileNum()) {
1094       FileNum = LineEntry.getFileNum();
1095       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1096       MCOS->emitULEB128IntValue(FileNum);
1097     }
1098     if (Column != LineEntry.getColumn()) {
1099       Column = LineEntry.getColumn();
1100       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1101       MCOS->emitULEB128IntValue(Column);
1102     }
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);
1111     }
1112     if (Isa != LineEntry.getIsa()) {
1113       Isa = LineEntry.getIsa();
1114       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1115       MCOS->emitULEB128IntValue(Isa);
1116     }
1117     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1118       Flags = LineEntry.getFlags();
1119       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1120     }
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);
1127 
1128     MCSymbol *Label = LineEntry.getLabel();
1129 
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;
1138   }
1139 
1140   assert(LastLabel == nullptr && "end of sequence expected");
1141 }
1142 
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;
1153   }
1154 
1155   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1156 
1157   // Put out the line tables.
1158   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1159     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1160 
1161   // Emit line tables for the original code.
1162   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1163 
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);
1167 }
1168 
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;
1189     }
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;
1195   }
1196 }
1197 
1198 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1199   MCAssembler &Assembler =
1200       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1201 
1202   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1203 
1204   auto &LineTables = BC.getDwarfLineTables();
1205 
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");
1214 
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);
1220   }
1221 
1222   // Switch to the section where the table will be emitted into.
1223   Streamer.switchSection(BC.MOFI->getDwarfLineSection());
1224 
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);
1231   }
1232 
1233   // Resetting DWARF version for rest of the flow.
1234   BC.Ctx->setDwarfVersion(DwarfVersion);
1235 
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);
1240 }
1241 
1242 } // namespace bolt
1243 } // namespace llvm
1244