xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision f137be30a4b6f49b86bfde6b5ee59463884916fc)
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   // Add an empty range as the first entry;
141   writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
142   Kind = RangesWriterKind::DebugRangesWriter;
143 }
144 
145 uint64_t DebugRangesSectionWriter::addRanges(
146     DebugAddressRangesVector &&Ranges,
147     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
148   if (Ranges.empty())
149     return getEmptyRangesOffset();
150 
151   const auto RI = CachedRanges.find(Ranges);
152   if (RI != CachedRanges.end())
153     return RI->second;
154 
155   const uint64_t EntryOffset = addRanges(Ranges);
156   CachedRanges.emplace(std::move(Ranges), EntryOffset);
157 
158   return EntryOffset;
159 }
160 
161 uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
162   if (Ranges.empty())
163     return getEmptyRangesOffset();
164 
165   // Reading the SectionOffset and updating it should be atomic to guarantee
166   // unique and correct offsets in patches.
167   std::lock_guard<std::mutex> Lock(WriterMutex);
168   const uint32_t EntryOffset = RangesBuffer->size();
169   writeAddressRanges(*RangesStream.get(), Ranges);
170 
171   return EntryOffset;
172 }
173 
174 uint64_t DebugRangesSectionWriter::getSectionOffset() {
175   std::lock_guard<std::mutex> Lock(WriterMutex);
176   return RangesBuffer->size();
177 }
178 
179 void DebugRangesSectionWriter::appendToRangeBuffer(
180     const DebugBufferVector &CUBuffer) {
181   *RangesStream << CUBuffer;
182 }
183 
184 DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr;
185 
186 uint64_t DebugRangeListsSectionWriter::addRanges(
187     DebugAddressRangesVector &&Ranges,
188     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
189   return addRanges(Ranges);
190 }
191 
192 struct LocListsRangelistsHeader {
193   UnitLengthType UnitLength; // Size of loclist entries section, not including
194                              // size of header.
195   VersionType Version;
196   AddressSizeType AddressSize;
197   SegmentSelectorType SegmentSelector;
198   OffsetEntryCountType OffsetEntryCount;
199 };
200 
201 static std::unique_ptr<DebugBufferVector>
202 getDWARF5Header(const LocListsRangelistsHeader &Header) {
203   std::unique_ptr<DebugBufferVector> HeaderBuffer =
204       std::make_unique<DebugBufferVector>();
205   std::unique_ptr<raw_svector_ostream> HeaderStream =
206       std::make_unique<raw_svector_ostream>(*HeaderBuffer);
207 
208   // 7.29 length of the set of entries for this compilation unit, not including
209   // the length field itself
210   const uint32_t HeaderSize =
211       getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);
212 
213   support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,
214                          llvm::endianness::little);
215   support::endian::write(*HeaderStream, Header.Version,
216                          llvm::endianness::little);
217   support::endian::write(*HeaderStream, Header.AddressSize,
218                          llvm::endianness::little);
219   support::endian::write(*HeaderStream, Header.SegmentSelector,
220                          llvm::endianness::little);
221   support::endian::write(*HeaderStream, Header.OffsetEntryCount,
222                          llvm::endianness::little);
223   return HeaderBuffer;
224 }
225 
226 struct OffsetEntry {
227   uint32_t Index;
228   uint32_t StartOffset;
229   uint32_t EndOffset;
230 };
231 template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>
232 static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
233                          DebugAddrWriter &AddrWriter, DWARFUnit &CU,
234                          uint32_t &Index, const ListEntry BaseAddressx,
235                          const ListEntry OffsetPair,
236                          const std::function<void(uint32_t)> &Func) {
237   if (Entries.size() < 2)
238     return false;
239   uint64_t Base = Entries[Index].LowPC;
240   std::vector<OffsetEntry> Offsets;
241   uint8_t TempBuffer[64];
242   while (Index < Entries.size()) {
243     const DebugAddressEntry &Entry = Entries[Index];
244     if (Entry.LowPC == 0)
245       break;
246     // In case rnglists or loclists are not sorted.
247     if (Base > Entry.LowPC)
248       break;
249     uint32_t StartOffset = Entry.LowPC - Base;
250     uint32_t EndOffset = Entry.HighPC - Base;
251     if (encodeULEB128(EndOffset, TempBuffer) > 2)
252       break;
253     Offsets.push_back({Index, StartOffset, EndOffset});
254     ++Index;
255   }
256 
257   if (Offsets.size() < 2) {
258     Index -= Offsets.size();
259     return false;
260   }
261 
262   support::endian::write(OS, static_cast<uint8_t>(BaseAddressx),
263                          llvm::endianness::little);
264   uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU);
265   encodeULEB128(BaseIndex, OS);
266   for (auto &OffsetEntry : Offsets) {
267     support::endian::write(OS, static_cast<uint8_t>(OffsetPair),
268                            llvm::endianness::little);
269     encodeULEB128(OffsetEntry.StartOffset, OS);
270     encodeULEB128(OffsetEntry.EndOffset, OS);
271     Func(OffsetEntry.Index);
272   }
273   return true;
274 }
275 
276 uint64_t
277 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
278   std::lock_guard<std::mutex> Lock(WriterMutex);
279 
280   RangeEntries.push_back(CurrentOffset);
281   std::sort(
282       Ranges.begin(), Ranges.end(),
283       [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {
284         return R1.LowPC < R2.LowPC;
285       });
286   for (unsigned I = 0; I < Ranges.size();) {
287     if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,
288                      DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU,
289                                         I, dwarf::DW_RLE_base_addressx,
290                                         dwarf::DW_RLE_offset_pair,
291                                         [](uint32_t Index) -> void {}))
292       continue;
293 
294     const DebugAddressRange &Range = Ranges[I];
295     support::endian::write(*CUBodyStream,
296                            static_cast<uint8_t>(dwarf::DW_RLE_startx_length),
297                            llvm::endianness::little);
298     uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU);
299     encodeULEB128(Index, *CUBodyStream);
300     encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
301     ++I;
302   }
303 
304   support::endian::write(*CUBodyStream,
305                          static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
306                          llvm::endianness::little);
307   CurrentOffset = CUBodyBuffer->size();
308   return RangeEntries.size() - 1;
309 }
310 
311 void DebugRangeListsSectionWriter::finalizeSection() {
312   std::unique_ptr<DebugBufferVector> CUArrayBuffer =
313       std::make_unique<DebugBufferVector>();
314   std::unique_ptr<raw_svector_ostream> CUArrayStream =
315       std::make_unique<raw_svector_ostream>(*CUArrayBuffer);
316   constexpr uint32_t SizeOfArrayEntry = 4;
317   const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;
318   for (uint32_t Offset : RangeEntries)
319     support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,
320                            llvm::endianness::little);
321 
322   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
323       {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()),
324        5, 8, 0, static_cast<uint32_t>(RangeEntries.size())});
325   *RangesStream << *Header;
326   *RangesStream << *CUArrayBuffer;
327   *RangesStream << *CUBodyBuffer;
328 }
329 
330 void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {
331   CUBodyBuffer = std::make_unique<DebugBufferVector>();
332   CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);
333   RangeEntries.clear();
334   CurrentOffset = 0;
335   CU = &Unit;
336 }
337 
338 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
339                                             DebugAddressRangesVector &&Ranges) {
340   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
341   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
342 }
343 
344 void DebugARangesSectionWriter::writeARangesSection(
345     raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
346   // For reference on the format of the .debug_aranges section, see the DWARF4
347   // specification, section 6.1.4 Lookup by Address
348   // http://www.dwarfstd.org/doc/DWARF4.pdf
349   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
350     const uint64_t Offset = CUOffsetAddressRangesPair.first;
351     const DebugAddressRangesVector &AddressRanges =
352         CUOffsetAddressRangesPair.second;
353 
354     // Emit header.
355 
356     // Size of this set: 8 (size of the header) + 4 (padding after header)
357     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
358     // pair of uint64_t's for the terminating, zero-length range.
359     // Does not include size field itself.
360     uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);
361 
362     // Header field #1: set size.
363     support::endian::write(RangesStream, Size, llvm::endianness::little);
364 
365     // Header field #2: version number, 2 as per the specification.
366     support::endian::write(RangesStream, static_cast<uint16_t>(2),
367                            llvm::endianness::little);
368 
369     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
370     // Header field #3: debug info offset of the correspondent compile unit.
371     support::endian::write(
372         RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
373         llvm::endianness::little);
374 
375     // Header field #4: address size.
376     // 8 since we only write ELF64 binaries for now.
377     RangesStream << char(8);
378 
379     // Header field #5: segment size of target architecture.
380     RangesStream << char(0);
381 
382     // Padding before address table - 4 bytes in the 64-bit-pointer case.
383     support::endian::write(RangesStream, static_cast<uint32_t>(0),
384                            llvm::endianness::little);
385 
386     writeAddressRanges(RangesStream, AddressRanges, true);
387   }
388 }
389 
390 DebugAddrWriter::DebugAddrWriter(BinaryContext *BC) : BC(BC) {
391   Buffer = std::make_unique<AddressSectionBuffer>();
392   AddressStream = std::make_unique<raw_svector_ostream>(*Buffer);
393 }
394 
395 void DebugAddrWriter::AddressForDWOCU::dump() {
396   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
397                                           indexToAdddessEnd());
398   // Sorting address in increasing order of indices.
399   llvm::sort(SortedMap, llvm::less_first());
400   for (auto &Pair : SortedMap)
401     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
402 }
403 uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {
404   std::lock_guard<std::mutex> Lock(WriterMutex);
405   const uint64_t CUID = getCUID(CU);
406   if (!AddressMaps.count(CUID))
407     AddressMaps[CUID] = AddressForDWOCU();
408 
409   AddressForDWOCU &Map = AddressMaps[CUID];
410   auto Entry = Map.find(Address);
411   if (Entry == Map.end()) {
412     auto Index = Map.getNextIndex();
413     Entry = Map.insert(Address, Index).first;
414   }
415   return Entry->second;
416 }
417 
418 static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter,
419                               DWARFUnit &CU, const uint64_t Offset) {
420   DIE *Die = DIEBlder.getUnitDIEbyUnit(CU);
421   DIEValue GnuAddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_GNU_addr_base);
422   DIEValue AddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_addr_base);
423   dwarf::Form BaseAttrForm;
424   dwarf::Attribute BaseAttr;
425   // For cases where Skeleton CU does not have DW_AT_GNU_addr_base
426   if (!GnuAddrBaseAttrInfo && CU.getVersion() < 5)
427     return;
428 
429   if (GnuAddrBaseAttrInfo) {
430     BaseAttrForm = GnuAddrBaseAttrInfo.getForm();
431     BaseAttr = GnuAddrBaseAttrInfo.getAttribute();
432   }
433 
434   if (AddrBaseAttrInfo) {
435     BaseAttrForm = AddrBaseAttrInfo.getForm();
436     BaseAttr = AddrBaseAttrInfo.getAttribute();
437   }
438 
439   if (GnuAddrBaseAttrInfo || AddrBaseAttrInfo) {
440     DIEBlder.replaceValue(Die, BaseAttr, BaseAttrForm, DIEInteger(Offset));
441   } else if (CU.getVersion() >= 5) {
442     // A case where we were not using .debug_addr section, but after update
443     // now using it.
444     DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,
445                       DIEInteger(Offset));
446   }
447 }
448 
449 void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
450   // Handling the case where debug information is a mix of Debug fission and
451   // monolithic.
452   if (!CU.getDWOId())
453     return;
454   const uint64_t CUID = getCUID(CU);
455   auto AM = AddressMaps.find(CUID);
456   // Adding to map even if it did not contribute to .debug_addr.
457   // The Skeleton CU might still have DW_AT_GNU_addr_base.
458   uint64_t Offset = Buffer->size();
459   // If does not exist this CUs DWO section didn't contribute to .debug_addr.
460   if (AM == AddressMaps.end())
461     return;
462   std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
463                                           AM->second.indexToAdddessEnd());
464   // Sorting address in increasing order of indices.
465   llvm::sort(SortedMap, llvm::less_first());
466 
467   uint8_t AddrSize = CU.getAddressByteSize();
468   uint32_t Counter = 0;
469   auto WriteAddress = [&](uint64_t Address) -> void {
470     ++Counter;
471     switch (AddrSize) {
472     default:
473       assert(false && "Address Size is invalid.");
474       break;
475     case 4:
476       support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
477                              llvm::endianness::little);
478       break;
479     case 8:
480       support::endian::write(*AddressStream, Address, llvm::endianness::little);
481       break;
482     }
483   };
484 
485   for (const IndexAddressPair &Val : SortedMap) {
486     while (Val.first > Counter)
487       WriteAddress(0);
488     WriteAddress(Val.second);
489   }
490   updateAddressBase(DIEBlder, *this, CU, Offset);
491 }
492 
493 void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
494   // Need to layout all sections within .debug_addr
495   // Within each section sort Address by index.
496   const endianness Endian = BC->DwCtx->isLittleEndian()
497                                 ? llvm::endianness::little
498                                 : llvm::endianness::big;
499   const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();
500   DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec,
501                               Endian == llvm::endianness::little, 0);
502   DWARFDebugAddrTable AddrTable;
503   DIDumpOptions DumpOpts;
504   constexpr uint32_t HeaderSize = 8;
505   const uint64_t CUID = getCUID(CU);
506   const uint8_t AddrSize = CU.getAddressByteSize();
507   auto AMIter = AddressMaps.find(CUID);
508   // A case where CU has entry in .debug_addr, but we don't modify addresses
509   // for it.
510   if (AMIter == AddressMaps.end()) {
511     AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first;
512     std::optional<uint64_t> BaseOffset = CU.getAddrOffsetSectionBase();
513     if (!BaseOffset)
514       return;
515     // Address base offset is to the first entry.
516     // The size of header is 8 bytes.
517     uint64_t Offset = *BaseOffset - HeaderSize;
518     auto Iter = UnmodifiedAddressOffsets.find(Offset);
519     if (Iter != UnmodifiedAddressOffsets.end()) {
520       updateAddressBase(DIEBlder, *this, CU, Iter->getSecond());
521       return;
522     }
523     UnmodifiedAddressOffsets[Offset] = Buffer->size() + HeaderSize;
524     if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize,
525                                       DumpOpts.WarningHandler)) {
526       DumpOpts.RecoverableErrorHandler(std::move(Err));
527       return;
528     }
529 
530     uint32_t Index = 0;
531     for (uint64_t Addr : AddrTable.getAddressEntries())
532       AMIter->second.insert(Addr, Index++);
533   }
534 
535   updateAddressBase(DIEBlder, *this, CU, Buffer->size() + HeaderSize);
536 
537   std::vector<IndexAddressPair> SortedMap(AMIter->second.indexToAddressBegin(),
538                                           AMIter->second.indexToAdddessEnd());
539   // Sorting address in increasing order of indices.
540   llvm::sort(SortedMap, llvm::less_first());
541   // Writing out Header
542   const uint32_t Length = SortedMap.size() * AddrSize + 4;
543   support::endian::write(*AddressStream, Length, Endian);
544   support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);
545   support::endian::write(*AddressStream, static_cast<uint8_t>(AddrSize),
546                          Endian);
547   support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);
548 
549   uint32_t Counter = 0;
550   auto writeAddress = [&](uint64_t Address) -> void {
551     ++Counter;
552     switch (AddrSize) {
553     default:
554       llvm_unreachable("Address Size is invalid.");
555       break;
556     case 4:
557       support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
558                              Endian);
559       break;
560     case 8:
561       support::endian::write(*AddressStream, Address, Endian);
562       break;
563     }
564   };
565 
566   for (const IndexAddressPair &Val : SortedMap) {
567     while (Val.first > Counter)
568       writeAddress(0);
569     writeAddress(Val.second);
570   }
571 }
572 
573 void DebugLocWriter::init() {
574   LocBuffer = std::make_unique<DebugBufferVector>();
575   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
576   // Writing out empty location list to which all references to empty location
577   // lists will point.
578   if (!LocSectionOffset && DwarfVersion < 5) {
579     const char Zeroes[16] = {0};
580     *LocStream << StringRef(Zeroes, 16);
581     LocSectionOffset += 16;
582   }
583 }
584 
585 uint32_t DebugLocWriter::LocSectionOffset = 0;
586 void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
587                              DebugLocationsVector &LocList) {
588   if (LocList.empty()) {
589     replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
590                         DebugLocWriter::EmptyListOffset);
591     return;
592   }
593   // Since there is a separate DebugLocWriter for each thread,
594   // we don't need a lock to read the SectionOffset and update it.
595   const uint32_t EntryOffset = LocSectionOffset;
596 
597   for (const DebugLocationEntry &Entry : LocList) {
598     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
599                            llvm::endianness::little);
600     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
601                            llvm::endianness::little);
602     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
603                            llvm::endianness::little);
604     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
605                             Entry.Expr.size());
606     LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();
607   }
608   LocStream->write_zeros(16);
609   LocSectionOffset += 16;
610   LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen
611                                                                 // use
612   replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
613 }
614 
615 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
616   return std::move(LocBuffer);
617 }
618 
619 // DWARF 4: 2.6.2
620 void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}
621 
622 static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
623   support::endian::write(Stream, static_cast<uint32_t>(4),
624                          llvm::endianness::little);
625   support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),
626                          llvm::endianness::little);
627 
628   const char Zeroes[16] = {0};
629   Stream << StringRef(Zeroes, 16);
630   encodeULEB128(0, Stream);
631   support::endian::write(Stream,
632                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
633                          llvm::endianness::little);
634 }
635 
636 static void writeLegacyLocList(DIEValue &AttrInfo,
637                                DebugLocationsVector &LocList,
638                                DIEBuilder &DIEBldr, DIE &Die,
639                                DebugAddrWriter &AddrWriter,
640                                DebugBufferVector &LocBuffer, DWARFUnit &CU,
641                                raw_svector_ostream &LocStream) {
642   if (LocList.empty()) {
643     replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
644                         DebugLocWriter::EmptyListOffset);
645     return;
646   }
647 
648   const uint32_t EntryOffset = LocBuffer.size();
649   for (const DebugLocationEntry &Entry : LocList) {
650     support::endian::write(LocStream,
651                            static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
652                            llvm::endianness::little);
653     const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
654     encodeULEB128(Index, LocStream);
655 
656     support::endian::write(LocStream,
657                            static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
658                            llvm::endianness::little);
659     support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()),
660                            llvm::endianness::little);
661     LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
662                            Entry.Expr.size());
663   }
664   support::endian::write(LocStream,
665                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
666                          llvm::endianness::little);
667   replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
668 }
669 
670 static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,
671                                DebugLocationsVector &LocList, DIE &Die,
672                                DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter,
673                                DebugBufferVector &LocBodyBuffer,
674                                std::vector<uint32_t> &RelativeLocListOffsets,
675                                DWARFUnit &CU,
676                                raw_svector_ostream &LocBodyStream) {
677 
678   replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
679                       NumberOfEntries);
680 
681   RelativeLocListOffsets.push_back(LocBodyBuffer.size());
682   ++NumberOfEntries;
683   if (LocList.empty()) {
684     writeEmptyListDwarf5(LocBodyStream);
685     return;
686   }
687 
688   std::vector<uint64_t> OffsetsArray;
689   auto writeExpression = [&](uint32_t Index) -> void {
690     const DebugLocationEntry &Entry = LocList[Index];
691     encodeULEB128(Entry.Expr.size(), LocBodyStream);
692     LocBodyStream << StringRef(
693         reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
694   };
695   for (unsigned I = 0; I < LocList.size();) {
696     if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,
697                      DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU,
698                                          I, dwarf::DW_LLE_base_addressx,
699                                          dwarf::DW_LLE_offset_pair,
700                                          writeExpression))
701       continue;
702 
703     const DebugLocationEntry &Entry = LocList[I];
704     support::endian::write(LocBodyStream,
705                            static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
706                            llvm::endianness::little);
707     const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
708     encodeULEB128(Index, LocBodyStream);
709     encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);
710     writeExpression(I);
711     ++I;
712   }
713 
714   support::endian::write(LocBodyStream,
715                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
716                          llvm::endianness::little);
717 }
718 
719 void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,
720                                  DIEValue &AttrInfo,
721                                  DebugLocationsVector &LocList) {
722   if (DwarfVersion < 5)
723     writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, *AddrWriter, *LocBuffer,
724                        CU, *LocStream);
725   else
726     writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
727                        *AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
728                        *LocBodyStream);
729 }
730 
731 uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;
732 void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) {
733   if (LocBodyBuffer->empty()) {
734     DIEValue LocListBaseAttrInfo =
735         Die.findAttribute(dwarf::DW_AT_loclists_base);
736     // Pointing to first one, because it doesn't matter. There are no uses of it
737     // in this CU.
738     if (!isSplitDwarf() && LocListBaseAttrInfo.getType())
739       DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
740                            LocListBaseAttrInfo.getForm(),
741                            DIEInteger(getDWARF5RngListLocListHeaderSize()));
742     return;
743   }
744 
745   std::unique_ptr<DebugBufferVector> LocArrayBuffer =
746       std::make_unique<DebugBufferVector>();
747   std::unique_ptr<raw_svector_ostream> LocArrayStream =
748       std::make_unique<raw_svector_ostream>(*LocArrayBuffer);
749 
750   const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t);
751   // Write out IndexArray
752   for (uint32_t RelativeOffset : RelativeLocListOffsets)
753     support::endian::write(
754         *LocArrayStream,
755         static_cast<uint32_t>(SizeOfArraySection + RelativeOffset),
756         llvm::endianness::little);
757 
758   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
759       {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()),
760        5, 8, 0, NumberOfEntries});
761   *LocStream << *Header;
762   *LocStream << *LocArrayBuffer;
763   *LocStream << *LocBodyBuffer;
764 
765   if (!isSplitDwarf()) {
766     DIEValue LocListBaseAttrInfo =
767         Die.findAttribute(dwarf::DW_AT_loclists_base);
768     if (LocListBaseAttrInfo.getType()) {
769       DIEBldr.replaceValue(
770           &Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(),
771           DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize()));
772     } else {
773       DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,
774                        dwarf::DW_FORM_sec_offset,
775                        DIEInteger(LoclistBaseOffset + Header->size()));
776     }
777     LoclistBaseOffset += LocBuffer->size();
778   }
779   clearList(RelativeLocListOffsets);
780   clearList(*LocArrayBuffer);
781   clearList(*LocBodyBuffer);
782 }
783 
784 void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {
785   if (DwarfVersion >= 5)
786     finalizeDWARF5(DIEBldr, Die);
787 }
788 
789 DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
790 
791 static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
792   std::string LE64(ByteSize, 0);
793   for (size_t I = 0; I < ByteSize; ++I) {
794     LE64[I] = NewValue & 0xff;
795     NewValue >>= 8;
796   }
797   return LE64;
798 }
799 
800 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
801                                          std::string &&NewValue,
802                                          uint32_t OldValueSize) {
803   Patches.emplace_back(Offset, std::move(NewValue));
804 }
805 
806 void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
807   auto Str = std::string(1, Value);
808   Patches.emplace_back(Offset, std::move(Str));
809 }
810 
811 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
812                                      size_t ByteSize) {
813   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
814 }
815 
816 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
817                                         uint32_t OldValueSize) {
818   std::string Buff;
819   raw_string_ostream OS(Buff);
820   encodeULEB128(Value, OS, OldValueSize);
821 
822   Patches.emplace_back(Offset, std::move(Buff));
823 }
824 
825 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
826   addLEPatch(Offset, NewValue, 8);
827 }
828 
829 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
830                                        uint32_t OldValueSize) {
831   addLEPatch(Offset, NewValue, 4);
832 }
833 
834 std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
835   std::string BinaryContentsStr = std::string(BinaryContents);
836   for (const auto &Patch : Patches) {
837     uint32_t Offset = Patch.first;
838     const std::string &ByteSequence = Patch.second;
839     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
840            "Applied patch runs over binary size.");
841     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
842       BinaryContentsStr[Offset + I] = ByteSequence[I];
843     }
844   }
845   return BinaryContentsStr;
846 }
847 
848 void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) {
849   if (Unit.getVersion() < 5)
850     return;
851   const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
852   const std::optional<StrOffsetsContributionDescriptor> &Contr =
853       Unit.getStringOffsetsTableContribution();
854   if (!Contr)
855     return;
856   const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
857   assert(DwarfOffsetByteSize == 4 &&
858          "Dwarf String Offsets Byte Size is not supported.");
859   StrOffsets.reserve(Contr->Size);
860   for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)
861     StrOffsets.push_back(support::endian::read32le(
862         StrOffsetsSection.Data.data() + Contr->Base + Offset));
863 }
864 
865 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) {
866   IndexToAddressMap[Index] = Address;
867   StrOffsetSectionWasModified = true;
868 }
869 
870 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
871                                             DIEBuilder &DIEBldr) {
872   std::optional<AttrInfo> AttrVal =
873       findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
874   if (!AttrVal && !Unit.isDWOUnit())
875     return;
876   std::optional<uint64_t> Val = std::nullopt;
877   if (AttrVal) {
878     Val = AttrVal->V.getAsSectionOffset();
879   } else {
880     if (!Unit.isDWOUnit())
881       BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
882                    "DW_AT_str_offsets_base Value not present\n";
883     Val = 0;
884   }
885   DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
886   DIEValue StrListBaseAttrInfo =
887       Die.findAttribute(dwarf::DW_AT_str_offsets_base);
888   auto RetVal = ProcessedBaseOffsets.find(*Val);
889   // Handling re-use of str-offsets section.
890   if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {
891     initialize(Unit);
892     // Update String Offsets that were modified.
893     for (const auto &Entry : IndexToAddressMap)
894       StrOffsets[Entry.first] = Entry.second;
895     // Writing out the header for each section.
896     support::endian::write(*StrOffsetsStream,
897                            static_cast<uint32_t>(StrOffsets.size() * 4 + 4),
898                            llvm::endianness::little);
899     support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),
900                            llvm::endianness::little);
901     support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),
902                            llvm::endianness::little);
903 
904     uint64_t BaseOffset = StrOffsetsBuffer->size();
905     ProcessedBaseOffsets[*Val] = BaseOffset;
906     if (StrListBaseAttrInfo.getType())
907       DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
908                            StrListBaseAttrInfo.getForm(),
909                            DIEInteger(BaseOffset));
910     for (const uint32_t Offset : StrOffsets)
911       support::endian::write(*StrOffsetsStream, Offset,
912                              llvm::endianness::little);
913   } else {
914     DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
915                          StrListBaseAttrInfo.getForm(),
916                          DIEInteger(RetVal->second));
917   }
918 
919   StrOffsetSectionWasModified = false;
920   clear();
921 }
922 
923 void DebugStrWriter::create() {
924   StrBuffer = std::make_unique<DebugStrBufferVector>();
925   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
926 }
927 
928 void DebugStrWriter::initialize() {
929   StringRef StrSection;
930   if (IsDWO)
931     StrSection = DwCtx.getDWARFObj().getStrDWOSection();
932   else
933     StrSection = DwCtx.getDWARFObj().getStrSection();
934   (*StrStream) << StrSection;
935 }
936 
937 uint32_t DebugStrWriter::addString(StringRef Str) {
938   std::lock_guard<std::mutex> Lock(WriterMutex);
939   if (StrBuffer->empty())
940     initialize();
941   auto Offset = StrBuffer->size();
942   (*StrStream) << Str;
943   StrStream->write_zeros(1);
944   return Offset;
945 }
946 
947 static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
948                                     MCDwarfLineTableParams Params,
949                                     int64_t LineDelta, uint64_t Address,
950                                     int PointerSize) {
951   // emit the sequence to set the address
952   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
953   OS.emitULEB128IntValue(PointerSize + 1);
954   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
955   OS.emitIntValue(Address, PointerSize);
956 
957   // emit the sequence for the LineDelta (from 1) and a zero address delta.
958   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
959 }
960 
961 static inline void emitBinaryDwarfLineTable(
962     MCStreamer *MCOS, MCDwarfLineTableParams Params,
963     const DWARFDebugLine::LineTable *Table,
964     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
965   if (InputSequences.empty())
966     return;
967 
968   constexpr uint64_t InvalidAddress = UINT64_MAX;
969   unsigned FileNum = 1;
970   unsigned LastLine = 1;
971   unsigned Column = 0;
972   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
973   unsigned Isa = 0;
974   unsigned Discriminator = 0;
975   uint64_t LastAddress = InvalidAddress;
976   uint64_t PrevEndOfSequence = InvalidAddress;
977   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
978 
979   auto emitEndOfSequence = [&](uint64_t Address) {
980     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
981     FileNum = 1;
982     LastLine = 1;
983     Column = 0;
984     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
985     Isa = 0;
986     Discriminator = 0;
987     LastAddress = InvalidAddress;
988   };
989 
990   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
991     const uint64_t SequenceStart =
992         Table->Rows[Sequence.FirstIndex].Address.Address;
993 
994     // Check if we need to mark the end of the sequence.
995     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
996         PrevEndOfSequence != SequenceStart) {
997       emitEndOfSequence(PrevEndOfSequence);
998     }
999 
1000     for (uint32_t RowIndex = Sequence.FirstIndex;
1001          RowIndex <= Sequence.LastIndex; ++RowIndex) {
1002       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
1003       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
1004       const uint64_t Address = Row.Address.Address;
1005 
1006       if (FileNum != Row.File) {
1007         FileNum = Row.File;
1008         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1009         MCOS->emitULEB128IntValue(FileNum);
1010       }
1011       if (Column != Row.Column) {
1012         Column = Row.Column;
1013         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1014         MCOS->emitULEB128IntValue(Column);
1015       }
1016       if (Discriminator != Row.Discriminator &&
1017           MCOS->getContext().getDwarfVersion() >= 4) {
1018         Discriminator = Row.Discriminator;
1019         unsigned Size = getULEB128Size(Discriminator);
1020         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1021         MCOS->emitULEB128IntValue(Size + 1);
1022         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1023         MCOS->emitULEB128IntValue(Discriminator);
1024       }
1025       if (Isa != Row.Isa) {
1026         Isa = Row.Isa;
1027         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1028         MCOS->emitULEB128IntValue(Isa);
1029       }
1030       if (Row.IsStmt != Flags) {
1031         Flags = Row.IsStmt;
1032         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1033       }
1034       if (Row.BasicBlock)
1035         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1036       if (Row.PrologueEnd)
1037         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1038       if (Row.EpilogueBegin)
1039         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1040 
1041       // The end of the sequence is not normal in the middle of the input
1042       // sequence, but could happen, e.g. for assembly code.
1043       if (Row.EndSequence) {
1044         emitEndOfSequence(Address);
1045       } else {
1046         if (LastAddress == InvalidAddress)
1047           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1048                                   AsmInfo->getCodePointerSize());
1049         else
1050           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1051 
1052         LastAddress = Address;
1053         LastLine = Row.Line;
1054       }
1055 
1056       Discriminator = 0;
1057     }
1058     PrevEndOfSequence = Sequence.EndAddress;
1059   }
1060 
1061   // Finish with the end of the sequence.
1062   if (LastAddress != InvalidAddress)
1063     emitEndOfSequence(PrevEndOfSequence);
1064 }
1065 
1066 // This function is similar to the one from MCDwarfLineTable, except it handles
1067 // end-of-sequence entries differently by utilizing line entries with
1068 // DWARF2_FLAG_END_SEQUENCE flag.
1069 static inline void emitDwarfLineTable(
1070     MCStreamer *MCOS, MCSection *Section,
1071     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1072   unsigned FileNum = 1;
1073   unsigned LastLine = 1;
1074   unsigned Column = 0;
1075   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1076   unsigned Isa = 0;
1077   unsigned Discriminator = 0;
1078   MCSymbol *LastLabel = nullptr;
1079   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1080 
1081   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1082   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1083     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1084       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1085                                      AsmInfo->getCodePointerSize());
1086       FileNum = 1;
1087       LastLine = 1;
1088       Column = 0;
1089       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1090       Isa = 0;
1091       Discriminator = 0;
1092       LastLabel = nullptr;
1093       continue;
1094     }
1095 
1096     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1097 
1098     if (FileNum != LineEntry.getFileNum()) {
1099       FileNum = LineEntry.getFileNum();
1100       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1101       MCOS->emitULEB128IntValue(FileNum);
1102     }
1103     if (Column != LineEntry.getColumn()) {
1104       Column = LineEntry.getColumn();
1105       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1106       MCOS->emitULEB128IntValue(Column);
1107     }
1108     if (Discriminator != LineEntry.getDiscriminator() &&
1109         MCOS->getContext().getDwarfVersion() >= 2) {
1110       Discriminator = LineEntry.getDiscriminator();
1111       unsigned Size = getULEB128Size(Discriminator);
1112       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1113       MCOS->emitULEB128IntValue(Size + 1);
1114       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1115       MCOS->emitULEB128IntValue(Discriminator);
1116     }
1117     if (Isa != LineEntry.getIsa()) {
1118       Isa = LineEntry.getIsa();
1119       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1120       MCOS->emitULEB128IntValue(Isa);
1121     }
1122     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1123       Flags = LineEntry.getFlags();
1124       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1125     }
1126     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1127       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1128     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1129       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1130     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1131       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1132 
1133     MCSymbol *Label = LineEntry.getLabel();
1134 
1135     // At this point we want to emit/create the sequence to encode the delta
1136     // in line numbers and the increment of the address from the previous
1137     // Label and the current Label.
1138     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1139                                    AsmInfo->getCodePointerSize());
1140     Discriminator = 0;
1141     LastLine = LineEntry.getLine();
1142     LastLabel = Label;
1143   }
1144 
1145   assert(LastLabel == nullptr && "end of sequence expected");
1146 }
1147 
1148 void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1149                             std::optional<MCDwarfLineStr> &LineStr,
1150                             BinaryContext &BC) const {
1151   if (!RawData.empty()) {
1152     assert(MCLineSections.getMCLineEntries().empty() &&
1153            InputSequences.empty() &&
1154            "cannot combine raw data with new line entries");
1155     MCOS->emitLabel(getLabel());
1156     MCOS->emitBytes(RawData);
1157     return;
1158   }
1159 
1160   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1161 
1162   // Put out the line tables.
1163   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1164     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1165 
1166   // Emit line tables for the original code.
1167   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1168 
1169   // This is the end of the section, so set the value of the symbol at the end
1170   // of this section (that was used in a previous expression).
1171   MCOS->emitLabel(LineEndSym);
1172 }
1173 
1174 // Helper function to parse .debug_line_str, and populate one we are using.
1175 // For functions that we do not modify we output them as raw data.
1176 // Re-constructing .debug_line_str so that offsets are correct for those
1177 // debug line tables.
1178 // Bonus is that when we output a final binary we can re-use .debug_line_str
1179 // section. So we don't have to do the SHF_ALLOC trick we did with
1180 // .debug_line.
1181 static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
1182                                          MCDwarfLineStr &LineStr,
1183                                          BinaryContext &BC) {
1184   DataExtractor StrData(LineStrSection.getContents(),
1185                         BC.DwCtx->isLittleEndian(), 0);
1186   uint64_t Offset = 0;
1187   while (StrData.isValidOffset(Offset)) {
1188     const uint64_t StrOffset = Offset;
1189     Error Err = Error::success();
1190     const char *CStr = StrData.getCStr(&Offset, &Err);
1191     if (Err) {
1192       BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1193       continue;
1194     }
1195     const size_t NewOffset = LineStr.addString(CStr);
1196     assert(StrOffset == NewOffset &&
1197            "New offset in .debug_line_str doesn't match original offset");
1198     (void)StrOffset;
1199     (void)NewOffset;
1200   }
1201 }
1202 
1203 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1204   MCAssembler &Assembler =
1205       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1206 
1207   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1208 
1209   auto &LineTables = BC.getDwarfLineTables();
1210 
1211   // Bail out early so we don't switch to the debug_line section needlessly and
1212   // in doing so create an unnecessary (if empty) section.
1213   if (LineTables.empty())
1214     return;
1215   // In a v5 non-split line table, put the strings in a separate section.
1216   std::optional<MCDwarfLineStr> LineStr;
1217   ErrorOr<BinarySection &> LineStrSection =
1218       BC.getUniqueSectionByName(".debug_line_str");
1219 
1220   // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
1221   // .debug_line, so need to check if section exists.
1222   if (LineStrSection) {
1223     LineStr.emplace(*BC.Ctx);
1224     parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC);
1225   }
1226 
1227   // Switch to the section where the table will be emitted into.
1228   Streamer.switchSection(BC.MOFI->getDwarfLineSection());
1229 
1230   const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
1231   // Handle the rest of the Compile Units.
1232   for (auto &CUIDTablePair : LineTables) {
1233     Streamer.getContext().setDwarfVersion(
1234         CUIDTablePair.second.getDwarfVersion());
1235     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1236   }
1237 
1238   // Resetting DWARF version for rest of the flow.
1239   BC.Ctx->setDwarfVersion(DwarfVersion);
1240 
1241   // Still need to write the section out for the ExecutionEngine, and temp in
1242   // memory object we are constructing.
1243   if (LineStr)
1244     LineStr->emitSection(&Streamer);
1245 }
1246 
1247 } // namespace bolt
1248 } // namespace llvm
1249