xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision 124ca880aaf8513ce0e93696aa7bb26e237da872)
12f09f445SMaksim Panchenko //===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
92f09f445SMaksim Panchenko // This file implements functions and classes for handling debug info.
102f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #include "bolt/Core/DebugData.h"
14f8c7fb49SAmir Ayupov #include "bolt/Core/BinaryContext.h"
15014cd37fSAlexander Yermolovich #include "bolt/Rewrite/RewriteInstance.h"
16a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
17290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
18290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
19014cd37fSAlexander Yermolovich #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
2057f7c7d9Sserge-sans-paille #include "llvm/MC/MCAssembler.h"
21f8c7fb49SAmir Ayupov #include "llvm/MC/MCContext.h"
22a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h"
23a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
24a34c753fSRafael Auler #include "llvm/Support/EndianStream.h"
25a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
269f3f9d19SAlexander Yermolovich #include "llvm/Support/SHA1.h"
27a34c753fSRafael Auler #include <algorithm>
28a34c753fSRafael Auler #include <cassert>
29a34c753fSRafael Auler #include <cstdint>
30*124ca880SAlexander Yermolovich #include <functional>
31a34c753fSRafael Auler #include <limits>
321c2f4bbeSAlexander Yermolovich #include <unordered_map>
33ba1ac98cSAlexander Yermolovich #include <vector>
34a34c753fSRafael Auler 
35a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info"
36a34c753fSRafael Auler 
37a34c753fSRafael Auler namespace opts {
38a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity;
391c2f4bbeSAlexander Yermolovich } // namespace opts
40a34c753fSRafael Auler 
41a34c753fSRafael Auler namespace llvm {
42f8c7fb49SAmir Ayupov class MCSymbol;
43f8c7fb49SAmir Ayupov 
44a34c753fSRafael Auler namespace bolt {
45a34c753fSRafael Auler 
46370e4761SAmir Ayupov std::optional<AttrInfo>
47bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE,
48bd1ebe9dSAlexander Yermolovich                   const DWARFAbbreviationDeclaration *AbbrevDecl,
49bd1ebe9dSAlexander Yermolovich                   uint32_t Index) {
50bd1ebe9dSAlexander Yermolovich   const DWARFUnit &U = *DIE.getDwarfUnit();
51bd1ebe9dSAlexander Yermolovich   uint64_t Offset =
52bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
5389fab98eSFangrui Song   std::optional<DWARFFormValue> Value =
54bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
55bd1ebe9dSAlexander Yermolovich   if (!Value)
56e324a80fSKazu Hirata     return std::nullopt;
57bd1ebe9dSAlexander Yermolovich   // AttributeSpec
58bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
59bd1ebe9dSAlexander Yermolovich       AbbrevDecl->attributes().begin() + Index;
60bd1ebe9dSAlexander Yermolovich   uint32_t ValSize = 0;
6189fab98eSFangrui Song   std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
62bd1ebe9dSAlexander Yermolovich   if (ValSizeOpt) {
63bd1ebe9dSAlexander Yermolovich     ValSize = static_cast<uint32_t>(*ValSizeOpt);
64bd1ebe9dSAlexander Yermolovich   } else {
65bd1ebe9dSAlexander Yermolovich     DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
66bd1ebe9dSAlexander Yermolovich     uint64_t NewOffset = Offset;
67bd1ebe9dSAlexander Yermolovich     DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
68bd1ebe9dSAlexander Yermolovich                               U.getFormParams());
69bd1ebe9dSAlexander Yermolovich     // This includes entire size of the entry, which might not be just the
70bd1ebe9dSAlexander Yermolovich     // encoding part. For example for DW_AT_loc it will include expression
71bd1ebe9dSAlexander Yermolovich     // location.
72bd1ebe9dSAlexander Yermolovich     ValSize = NewOffset - Offset;
73bd1ebe9dSAlexander Yermolovich   }
741c6dc43dSAlexander Yermolovich   return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};
751c6dc43dSAlexander Yermolovich }
76bd1ebe9dSAlexander Yermolovich 
77370e4761SAmir Ayupov std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
781c6dc43dSAlexander Yermolovich                                           dwarf::Attribute Attr) {
791c6dc43dSAlexander Yermolovich   if (!DIE.isValid())
80e324a80fSKazu Hirata     return std::nullopt;
811c6dc43dSAlexander Yermolovich   const DWARFAbbreviationDeclaration *AbbrevDecl =
821c6dc43dSAlexander Yermolovich       DIE.getAbbreviationDeclarationPtr();
831c6dc43dSAlexander Yermolovich   if (!AbbrevDecl)
84e324a80fSKazu Hirata     return std::nullopt;
8589fab98eSFangrui Song   std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);
861c6dc43dSAlexander Yermolovich   if (!Index)
87e324a80fSKazu Hirata     return std::nullopt;
881c6dc43dSAlexander Yermolovich   return findAttributeInfo(DIE, AbbrevDecl, *Index);
89bd1ebe9dSAlexander Yermolovich }
90bd1ebe9dSAlexander Yermolovich 
91a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
92a34c753fSRafael Auler 
93a34c753fSRafael Auler namespace {
94a34c753fSRafael Auler 
951c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED
961c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) {
971c2f4bbeSAlexander Yermolovich   for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
981c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr(S[I]);
991c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr((int8_t)S[I]);
1001c2f4bbeSAlexander Yermolovich   }
1011c2f4bbeSAlexander Yermolovich   errs() << "\n";
1021c2f4bbeSAlexander Yermolovich }
1031c2f4bbeSAlexander Yermolovich 
104a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size).
105a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of
106a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address).
107a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes.
108a34c753fSRafael Auler // Returns the number of written bytes.
10940c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream,
110a34c753fSRafael Auler                             const DebugAddressRangesVector &AddressRanges,
111a34c753fSRafael Auler                             const bool WriteRelativeRanges = false) {
112a34c753fSRafael Auler   for (const DebugAddressRange &Range : AddressRanges) {
113a34c753fSRafael Auler     support::endian::write(Stream, Range.LowPC, support::little);
114a34c753fSRafael Auler     support::endian::write(
115a34c753fSRafael Auler         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
116a34c753fSRafael Auler         support::little);
117a34c753fSRafael Auler   }
118a34c753fSRafael Auler   // Finish with 0 entries.
119a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
120a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
121a34c753fSRafael Auler   return AddressRanges.size() * 16 + 16;
122a34c753fSRafael Auler }
123a34c753fSRafael Auler 
124a34c753fSRafael Auler } // namespace
125a34c753fSRafael Auler 
126a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() {
127a34c753fSRafael Auler   RangesBuffer = std::make_unique<DebugBufferVector>();
128a34c753fSRafael Auler   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
129a34c753fSRafael Auler 
130a34c753fSRafael Auler   // Add an empty range as the first entry;
131a34c753fSRafael Auler   SectionOffset +=
132a34c753fSRafael Auler       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
133014cd37fSAlexander Yermolovich   Kind = RangesWriterKind::DebugRangesWriter;
134a34c753fSRafael Auler }
135a34c753fSRafael Auler 
136a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges(
137a34c753fSRafael Auler     DebugAddressRangesVector &&Ranges,
138a34c753fSRafael Auler     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
139a34c753fSRafael Auler   if (Ranges.empty())
140a34c753fSRafael Auler     return getEmptyRangesOffset();
141a34c753fSRafael Auler 
142a34c753fSRafael Auler   const auto RI = CachedRanges.find(Ranges);
143a34c753fSRafael Auler   if (RI != CachedRanges.end())
144a34c753fSRafael Auler     return RI->second;
145a34c753fSRafael Auler 
146a34c753fSRafael Auler   const uint64_t EntryOffset = addRanges(Ranges);
147a34c753fSRafael Auler   CachedRanges.emplace(std::move(Ranges), EntryOffset);
148a34c753fSRafael Auler 
149a34c753fSRafael Auler   return EntryOffset;
150a34c753fSRafael Auler }
151a34c753fSRafael Auler 
152e22ff52cSAlexander Yermolovich uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
153a34c753fSRafael Auler   if (Ranges.empty())
154a34c753fSRafael Auler     return getEmptyRangesOffset();
155a34c753fSRafael Auler 
156a34c753fSRafael Auler   // Reading the SectionOffset and updating it should be atomic to guarantee
157a34c753fSRafael Auler   // unique and correct offsets in patches.
158a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
159a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
160a34c753fSRafael Auler   SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);
161a34c753fSRafael Auler 
162a34c753fSRafael Auler   return EntryOffset;
163a34c753fSRafael Auler }
164a34c753fSRafael Auler 
165a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() {
166a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
167a34c753fSRafael Auler   return SectionOffset;
168a34c753fSRafael Auler }
169a34c753fSRafael Auler 
170014cd37fSAlexander Yermolovich DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr;
171014cd37fSAlexander Yermolovich 
172014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges(
173014cd37fSAlexander Yermolovich     DebugAddressRangesVector &&Ranges,
174014cd37fSAlexander Yermolovich     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
175014cd37fSAlexander Yermolovich   return addRanges(Ranges);
176014cd37fSAlexander Yermolovich }
177014cd37fSAlexander Yermolovich 
178014cd37fSAlexander Yermolovich struct LocListsRangelistsHeader {
179014cd37fSAlexander Yermolovich   UnitLengthType UnitLength; // Size of loclist entris section, not including
180014cd37fSAlexander Yermolovich                              // size of header.
181014cd37fSAlexander Yermolovich   VersionType Version;
182014cd37fSAlexander Yermolovich   AddressSizeType AddressSize;
183014cd37fSAlexander Yermolovich   SegmentSelectorType SegmentSelector;
184014cd37fSAlexander Yermolovich   OffsetEntryCountType OffsetEntryCount;
185014cd37fSAlexander Yermolovich };
186014cd37fSAlexander Yermolovich 
187014cd37fSAlexander Yermolovich static std::unique_ptr<DebugBufferVector>
188014cd37fSAlexander Yermolovich getDWARF5Header(const LocListsRangelistsHeader &Header) {
189014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> HeaderBuffer =
190014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
191014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> HeaderStream =
192014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*HeaderBuffer);
193014cd37fSAlexander Yermolovich 
194014cd37fSAlexander Yermolovich   // 7.29 length of the set of entries for this compilation unit, not including
195014cd37fSAlexander Yermolovich   // the length field itself
196014cd37fSAlexander Yermolovich   const uint32_t HeaderSize =
197014cd37fSAlexander Yermolovich       getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);
198014cd37fSAlexander Yermolovich 
199014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,
200014cd37fSAlexander Yermolovich                          support::little);
201014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.Version, support::little);
202014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.AddressSize, support::little);
203014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.SegmentSelector,
204014cd37fSAlexander Yermolovich                          support::little);
205014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.OffsetEntryCount,
206014cd37fSAlexander Yermolovich                          support::little);
207014cd37fSAlexander Yermolovich   return HeaderBuffer;
208014cd37fSAlexander Yermolovich }
209014cd37fSAlexander Yermolovich 
210*124ca880SAlexander Yermolovich struct OffsetEntry {
211*124ca880SAlexander Yermolovich   uint32_t Index;
212*124ca880SAlexander Yermolovich   uint32_t StartOffset;
213*124ca880SAlexander Yermolovich   uint32_t EndOffset;
214*124ca880SAlexander Yermolovich };
215*124ca880SAlexander Yermolovich template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>
216*124ca880SAlexander Yermolovich static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
217e22ff52cSAlexander Yermolovich                          DebugAddrWriter &AddrWriter, DWARFUnit &CU,
218*124ca880SAlexander Yermolovich                          uint32_t &Index, const ListEntry BaseAddressx,
219*124ca880SAlexander Yermolovich                          const ListEntry OffsetPair, const ListEntry EndOfList,
220*124ca880SAlexander Yermolovich                          const std::function<void(uint32_t)> &Func) {
221*124ca880SAlexander Yermolovich   if (Entries.size() < 2)
222e22ff52cSAlexander Yermolovich     return false;
223*124ca880SAlexander Yermolovich   uint64_t Base = Entries[Index].LowPC;
224*124ca880SAlexander Yermolovich   std::vector<OffsetEntry> Offsets;
225e22ff52cSAlexander Yermolovich   uint8_t TempBuffer[64];
226*124ca880SAlexander Yermolovich   while (Index < Entries.size()) {
227*124ca880SAlexander Yermolovich     const DebugAddressEntry &Entry = Entries[Index];
228*124ca880SAlexander Yermolovich     if (Entry.LowPC == 0)
229e22ff52cSAlexander Yermolovich       break;
230*124ca880SAlexander Yermolovich     assert(Base <= Entry.LowPC && "Entry base is higher than low PC");
231*124ca880SAlexander Yermolovich     uint32_t StartOffset = Entry.LowPC - Base;
232*124ca880SAlexander Yermolovich     uint32_t EndOffset = Entry.HighPC - Base;
233e22ff52cSAlexander Yermolovich     if (encodeULEB128(EndOffset, TempBuffer) > 2)
234e22ff52cSAlexander Yermolovich       break;
235*124ca880SAlexander Yermolovich     Offsets.push_back({Index, StartOffset, EndOffset});
236e22ff52cSAlexander Yermolovich     ++Index;
237e22ff52cSAlexander Yermolovich   }
238e22ff52cSAlexander Yermolovich 
239*124ca880SAlexander Yermolovich   if (Offsets.size() < 2) {
240*124ca880SAlexander Yermolovich     Index -= Offsets.size();
241e22ff52cSAlexander Yermolovich     return false;
242e22ff52cSAlexander Yermolovich   }
243e22ff52cSAlexander Yermolovich 
244*124ca880SAlexander Yermolovich   support::endian::write(OS, static_cast<uint8_t>(BaseAddressx),
245e22ff52cSAlexander Yermolovich                          support::little);
246e22ff52cSAlexander Yermolovich   uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU);
247e22ff52cSAlexander Yermolovich   encodeULEB128(BaseIndex, OS);
248*124ca880SAlexander Yermolovich   for (auto &OffsetEntry : Offsets) {
249*124ca880SAlexander Yermolovich     support::endian::write(OS, static_cast<uint8_t>(OffsetPair),
250e22ff52cSAlexander Yermolovich                            support::little);
251*124ca880SAlexander Yermolovich     encodeULEB128(OffsetEntry.StartOffset, OS);
252*124ca880SAlexander Yermolovich     encodeULEB128(OffsetEntry.EndOffset, OS);
253*124ca880SAlexander Yermolovich     Func(OffsetEntry.Index);
254e22ff52cSAlexander Yermolovich   }
255*124ca880SAlexander Yermolovich   support::endian::write(OS, static_cast<uint8_t>(EndOfList), support::little);
256e22ff52cSAlexander Yermolovich   return true;
257e22ff52cSAlexander Yermolovich }
258e22ff52cSAlexander Yermolovich 
259e22ff52cSAlexander Yermolovich uint64_t
260e22ff52cSAlexander Yermolovich DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
261014cd37fSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
262014cd37fSAlexander Yermolovich 
263014cd37fSAlexander Yermolovich   RangeEntries.push_back(CurrentOffset);
264e22ff52cSAlexander Yermolovich   bool WrittenStartxLength = false;
265e22ff52cSAlexander Yermolovich   std::sort(
266e22ff52cSAlexander Yermolovich       Ranges.begin(), Ranges.end(),
267e22ff52cSAlexander Yermolovich       [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {
268e22ff52cSAlexander Yermolovich         return R1.LowPC < R2.LowPC;
269e22ff52cSAlexander Yermolovich       });
270e22ff52cSAlexander Yermolovich   for (unsigned I = 0; I < Ranges.size();) {
271e22ff52cSAlexander Yermolovich     WrittenStartxLength = false;
272*124ca880SAlexander Yermolovich     if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,
273*124ca880SAlexander Yermolovich                      DebugAddressRange>(
274*124ca880SAlexander Yermolovich             *CUBodyStream, Ranges, *AddrWriter, *CU, I,
275*124ca880SAlexander Yermolovich             dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
276*124ca880SAlexander Yermolovich             dwarf::DW_RLE_end_of_list, [](uint32_t Index) -> void {}))
277e22ff52cSAlexander Yermolovich       continue;
278*124ca880SAlexander Yermolovich 
279e22ff52cSAlexander Yermolovich     const DebugAddressRange &Range = Ranges[I];
280014cd37fSAlexander Yermolovich     support::endian::write(*CUBodyStream,
281014cd37fSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_RLE_startx_length),
282014cd37fSAlexander Yermolovich                            support::little);
283ba1ac98cSAlexander Yermolovich     uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU);
284014cd37fSAlexander Yermolovich     encodeULEB128(Index, *CUBodyStream);
285014cd37fSAlexander Yermolovich     encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
286e22ff52cSAlexander Yermolovich     ++I;
287e22ff52cSAlexander Yermolovich     WrittenStartxLength = true;
288014cd37fSAlexander Yermolovich   }
289e22ff52cSAlexander Yermolovich   if (WrittenStartxLength)
290014cd37fSAlexander Yermolovich     support::endian::write(*CUBodyStream,
291014cd37fSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
292014cd37fSAlexander Yermolovich                            support::little);
293014cd37fSAlexander Yermolovich   CurrentOffset = CUBodyBuffer->size();
294014cd37fSAlexander Yermolovich   return RangeEntries.size() - 1;
295014cd37fSAlexander Yermolovich }
296014cd37fSAlexander Yermolovich 
297014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::finalizeSection() {
298014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> CUArrayBuffer =
299014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
300014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> CUArrayStream =
301014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*CUArrayBuffer);
302014cd37fSAlexander Yermolovich   constexpr uint32_t SizeOfArrayEntry = 4;
303014cd37fSAlexander Yermolovich   const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;
304014cd37fSAlexander Yermolovich   for (uint32_t Offset : RangeEntries)
305014cd37fSAlexander Yermolovich     support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,
306014cd37fSAlexander Yermolovich                            support::little);
307014cd37fSAlexander Yermolovich 
308014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
309014cd37fSAlexander Yermolovich       {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()),
310014cd37fSAlexander Yermolovich        5, 8, 0, static_cast<uint32_t>(RangeEntries.size())});
311014cd37fSAlexander Yermolovich   *RangesStream << *Header;
312014cd37fSAlexander Yermolovich   *RangesStream << *CUArrayBuffer;
313014cd37fSAlexander Yermolovich   *RangesStream << *CUBodyBuffer;
314014cd37fSAlexander Yermolovich   SectionOffset = RangesBuffer->size();
315014cd37fSAlexander Yermolovich }
316014cd37fSAlexander Yermolovich 
317ba1ac98cSAlexander Yermolovich void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {
318014cd37fSAlexander Yermolovich   CUBodyBuffer = std::make_unique<DebugBufferVector>();
319014cd37fSAlexander Yermolovich   CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);
320014cd37fSAlexander Yermolovich   RangeEntries.clear();
321014cd37fSAlexander Yermolovich   CurrentOffset = 0;
322ba1ac98cSAlexander Yermolovich   CU = &Unit;
323014cd37fSAlexander Yermolovich }
324014cd37fSAlexander Yermolovich 
325a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
326a34c753fSRafael Auler                                             DebugAddressRangesVector &&Ranges) {
327a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
328a34c753fSRafael Auler   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
329a34c753fSRafael Auler }
330a34c753fSRafael Auler 
331a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection(
332612f0f45SAlexander Yermolovich     raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
333a34c753fSRafael Auler   // For reference on the format of the .debug_aranges section, see the DWARF4
334a34c753fSRafael Auler   // specification, section 6.1.4 Lookup by Address
335a34c753fSRafael Auler   // http://www.dwarfstd.org/doc/DWARF4.pdf
336a34c753fSRafael Auler   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
337a34c753fSRafael Auler     const uint64_t Offset = CUOffsetAddressRangesPair.first;
338a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges =
339a34c753fSRafael Auler         CUOffsetAddressRangesPair.second;
340a34c753fSRafael Auler 
341a34c753fSRafael Auler     // Emit header.
342a34c753fSRafael Auler 
343a34c753fSRafael Auler     // Size of this set: 8 (size of the header) + 4 (padding after header)
344a34c753fSRafael Auler     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
345a34c753fSRafael Auler     // pair of uint64_t's for the terminating, zero-length range.
346a34c753fSRafael Auler     // Does not include size field itself.
347a34c753fSRafael Auler     uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);
348a34c753fSRafael Auler 
349a34c753fSRafael Auler     // Header field #1: set size.
350a34c753fSRafael Auler     support::endian::write(RangesStream, Size, support::little);
351a34c753fSRafael Auler 
352a34c753fSRafael Auler     // Header field #2: version number, 2 as per the specification.
353a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint16_t>(2),
354a34c753fSRafael Auler                            support::little);
355a34c753fSRafael Auler 
3561c2f4bbeSAlexander Yermolovich     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
357a34c753fSRafael Auler     // Header field #3: debug info offset of the correspondent compile unit.
358612f0f45SAlexander Yermolovich     support::endian::write(
359612f0f45SAlexander Yermolovich         RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
360a34c753fSRafael Auler         support::little);
361a34c753fSRafael Auler 
362a34c753fSRafael Auler     // Header field #4: address size.
363a34c753fSRafael Auler     // 8 since we only write ELF64 binaries for now.
364a34c753fSRafael Auler     RangesStream << char(8);
365a34c753fSRafael Auler 
366a34c753fSRafael Auler     // Header field #5: segment size of target architecture.
367a34c753fSRafael Auler     RangesStream << char(0);
368a34c753fSRafael Auler 
369a34c753fSRafael Auler     // Padding before address table - 4 bytes in the 64-bit-pointer case.
370a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(0),
371a34c753fSRafael Auler                            support::little);
372a34c753fSRafael Auler 
373a34c753fSRafael Auler     writeAddressRanges(RangesStream, AddressRanges, true);
374a34c753fSRafael Auler   }
375a34c753fSRafael Auler }
376a34c753fSRafael Auler 
377a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }
378a34c753fSRafael Auler 
379a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() {
380a34c753fSRafael Auler   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
381a34c753fSRafael Auler                                           indexToAdddessEnd());
382a34c753fSRafael Auler   // Sorting address in increasing order of indices.
383c4302e4fSAmir Ayupov   llvm::sort(SortedMap, llvm::less_first());
384a34c753fSRafael Auler   for (auto &Pair : SortedMap)
385a34c753fSRafael Auler     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
386a34c753fSRafael Auler }
387ba1ac98cSAlexander Yermolovich uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {
388e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
389ba1ac98cSAlexander Yermolovich   const uint64_t CUID = getCUID(CU);
390014cd37fSAlexander Yermolovich   if (!AddressMaps.count(CUID))
391014cd37fSAlexander Yermolovich     AddressMaps[CUID] = AddressForDWOCU();
392a34c753fSRafael Auler 
393014cd37fSAlexander Yermolovich   AddressForDWOCU &Map = AddressMaps[CUID];
394a34c753fSRafael Auler   auto Entry = Map.find(Address);
395a34c753fSRafael Auler   if (Entry == Map.end()) {
396a34c753fSRafael Auler     auto Index = Map.getNextIndex();
397a34c753fSRafael Auler     Entry = Map.insert(Address, Index).first;
398a34c753fSRafael Auler   }
399a34c753fSRafael Auler   return Entry->second;
400a34c753fSRafael Auler }
401a34c753fSRafael Auler 
402a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
403a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update
404a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
405a34c753fSRafael Auler // update AddressToIndex and IndexToAddress
406a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
407ba1ac98cSAlexander Yermolovich                                       DWARFUnit &CU) {
408e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
409ba1ac98cSAlexander Yermolovich   const uint64_t CUID = getCUID(CU);
410014cd37fSAlexander Yermolovich   AddressForDWOCU &Map = AddressMaps[CUID];
411a34c753fSRafael Auler   auto Entry = Map.find(Address);
412a34c753fSRafael Auler   if (Entry != Map.end()) {
413a34c753fSRafael Auler     if (Entry->second > Index)
414a34c753fSRafael Auler       Map.updateAddressToIndex(Address, Index);
415a34c753fSRafael Auler     Map.updateIndexToAddrss(Address, Index);
4163652483cSRafael Auler   } else {
417a34c753fSRafael Auler     Map.insert(Address, Index);
418a34c753fSRafael Auler   }
4193652483cSRafael Auler }
420a34c753fSRafael Auler 
421a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() {
422a34c753fSRafael Auler   // Need to layout all sections within .debug_addr
423a34c753fSRafael Auler   // Within each section sort Address by index.
424a34c753fSRafael Auler   AddressSectionBuffer Buffer;
425a34c753fSRafael Auler   raw_svector_ostream AddressStream(Buffer);
426a34c753fSRafael Auler   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
427a34c753fSRafael Auler     // Handling the case wehre debug information is a mix of Debug fission and
428a34c753fSRafael Auler     // monolitic.
429ba1ac98cSAlexander Yermolovich     if (!CU->getDWOId())
430a34c753fSRafael Auler       continue;
431ba1ac98cSAlexander Yermolovich     const uint64_t CUID = getCUID(*CU.get());
432ba1ac98cSAlexander Yermolovich     auto AM = AddressMaps.find(CUID);
433a34c753fSRafael Auler     // Adding to map even if it did not contribute to .debug_addr.
4343abb68a6SAlexander Yermolovich     // The Skeleton CU might still have DW_AT_GNU_addr_base.
435ba1ac98cSAlexander Yermolovich     DWOIdToOffsetMap[CUID] = Buffer.size();
436a34c753fSRafael Auler     // If does not exist this CUs DWO section didn't contribute to .debug_addr.
437a34c753fSRafael Auler     if (AM == AddressMaps.end())
438a34c753fSRafael Auler       continue;
439a34c753fSRafael Auler     std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
440a34c753fSRafael Auler                                             AM->second.indexToAdddessEnd());
441a34c753fSRafael Auler     // Sorting address in increasing order of indices.
442c4302e4fSAmir Ayupov     llvm::sort(SortedMap, llvm::less_first());
443a34c753fSRafael Auler 
444a34c753fSRafael Auler     uint8_t AddrSize = CU->getAddressByteSize();
445a34c753fSRafael Auler     uint32_t Counter = 0;
446a34c753fSRafael Auler     auto WriteAddress = [&](uint64_t Address) -> void {
447a34c753fSRafael Auler       ++Counter;
448a34c753fSRafael Auler       switch (AddrSize) {
449a34c753fSRafael Auler       default:
450a34c753fSRafael Auler         assert(false && "Address Size is invalid.");
451a34c753fSRafael Auler         break;
452a34c753fSRafael Auler       case 4:
453a34c753fSRafael Auler         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
454a34c753fSRafael Auler                                support::little);
455a34c753fSRafael Auler         break;
456a34c753fSRafael Auler       case 8:
457a34c753fSRafael Auler         support::endian::write(AddressStream, Address, support::little);
458a34c753fSRafael Auler         break;
459a34c753fSRafael Auler       }
460a34c753fSRafael Auler     };
461a34c753fSRafael Auler 
462a34c753fSRafael Auler     for (const IndexAddressPair &Val : SortedMap) {
463a34c753fSRafael Auler       while (Val.first > Counter)
464a34c753fSRafael Auler         WriteAddress(0);
465a34c753fSRafael Auler       WriteAddress(Val.second);
466a34c753fSRafael Auler     }
467a34c753fSRafael Auler   }
468a34c753fSRafael Auler 
469a34c753fSRafael Auler   return Buffer;
470a34c753fSRafael Auler }
471014cd37fSAlexander Yermolovich AddressSectionBuffer DebugAddrWriterDwarf5::finalize() {
472014cd37fSAlexander Yermolovich   // Need to layout all sections within .debug_addr
473014cd37fSAlexander Yermolovich   // Within each section sort Address by index.
474014cd37fSAlexander Yermolovich   AddressSectionBuffer Buffer;
475014cd37fSAlexander Yermolovich   raw_svector_ostream AddressStream(Buffer);
476014cd37fSAlexander Yermolovich   const endianness Endian =
477014cd37fSAlexander Yermolovich       BC->DwCtx->isLittleEndian() ? support::little : support::big;
478014cd37fSAlexander Yermolovich   const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();
479014cd37fSAlexander Yermolovich   DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0);
480014cd37fSAlexander Yermolovich   DWARFDebugAddrTable AddrTable;
481014cd37fSAlexander Yermolovich   DIDumpOptions DumpOpts;
482014cd37fSAlexander Yermolovich   constexpr uint32_t HeaderSize = 8;
483014cd37fSAlexander Yermolovich   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
484ba1ac98cSAlexander Yermolovich     const uint64_t CUID = getCUID(*CU.get());
485014cd37fSAlexander Yermolovich     const uint8_t AddrSize = CU->getAddressByteSize();
486ba1ac98cSAlexander Yermolovich     auto AMIter = AddressMaps.find(CUID);
487014cd37fSAlexander Yermolovich     // A case where CU has entry in .debug_addr, but we don't modify addresses
488014cd37fSAlexander Yermolovich     // for it.
489ba1ac98cSAlexander Yermolovich     if (AMIter == AddressMaps.end()) {
490ba1ac98cSAlexander Yermolovich       AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first;
49189fab98eSFangrui Song       std::optional<uint64_t> BaseOffset = CU->getAddrOffsetSectionBase();
492014cd37fSAlexander Yermolovich       if (!BaseOffset)
493014cd37fSAlexander Yermolovich         continue;
494014cd37fSAlexander Yermolovich       // Address base offset is to the first entry.
495014cd37fSAlexander Yermolovich       // The size of header is 8 bytes.
496014cd37fSAlexander Yermolovich       uint64_t Offset = *BaseOffset - HeaderSize;
497014cd37fSAlexander Yermolovich       if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize,
498014cd37fSAlexander Yermolovich                                         DumpOpts.WarningHandler)) {
499014cd37fSAlexander Yermolovich         DumpOpts.RecoverableErrorHandler(std::move(Err));
500014cd37fSAlexander Yermolovich         continue;
501014cd37fSAlexander Yermolovich       }
502014cd37fSAlexander Yermolovich       uint32_t Index = 0;
503014cd37fSAlexander Yermolovich       for (uint64_t Addr : AddrTable.getAddressEntries())
504ba1ac98cSAlexander Yermolovich         AMIter->second.insert(Addr, Index++);
505014cd37fSAlexander Yermolovich     }
506a34c753fSRafael Auler 
507014cd37fSAlexander Yermolovich     DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize;
508014cd37fSAlexander Yermolovich 
509ba1ac98cSAlexander Yermolovich     std::vector<IndexAddressPair> SortedMap(
510ba1ac98cSAlexander Yermolovich         AMIter->second.indexToAddressBegin(),
511ba1ac98cSAlexander Yermolovich         AMIter->second.indexToAdddessEnd());
512014cd37fSAlexander Yermolovich     // Sorting address in increasing order of indices.
513c4302e4fSAmir Ayupov     llvm::sort(SortedMap, llvm::less_first());
514014cd37fSAlexander Yermolovich     // Writing out Header
515014cd37fSAlexander Yermolovich     const uint32_t Length = SortedMap.size() * AddrSize + 4;
516014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, Length, Endian);
517014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian);
518014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize),
519014cd37fSAlexander Yermolovich                            Endian);
520014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian);
521014cd37fSAlexander Yermolovich 
522014cd37fSAlexander Yermolovich     uint32_t Counter = 0;
523014cd37fSAlexander Yermolovich     auto writeAddress = [&](uint64_t Address) -> void {
524014cd37fSAlexander Yermolovich       ++Counter;
525014cd37fSAlexander Yermolovich       switch (AddrSize) {
526014cd37fSAlexander Yermolovich       default:
527014cd37fSAlexander Yermolovich         llvm_unreachable("Address Size is invalid.");
528014cd37fSAlexander Yermolovich         break;
529014cd37fSAlexander Yermolovich       case 4:
530014cd37fSAlexander Yermolovich         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
531014cd37fSAlexander Yermolovich                                Endian);
532014cd37fSAlexander Yermolovich         break;
533014cd37fSAlexander Yermolovich       case 8:
534014cd37fSAlexander Yermolovich         support::endian::write(AddressStream, Address, Endian);
535014cd37fSAlexander Yermolovich         break;
536014cd37fSAlexander Yermolovich       }
537014cd37fSAlexander Yermolovich     };
538014cd37fSAlexander Yermolovich 
539014cd37fSAlexander Yermolovich     for (const IndexAddressPair &Val : SortedMap) {
540014cd37fSAlexander Yermolovich       while (Val.first > Counter)
541014cd37fSAlexander Yermolovich         writeAddress(0);
542014cd37fSAlexander Yermolovich       writeAddress(Val.second);
543014cd37fSAlexander Yermolovich     }
544014cd37fSAlexander Yermolovich   }
545014cd37fSAlexander Yermolovich 
546014cd37fSAlexander Yermolovich   return Buffer;
547014cd37fSAlexander Yermolovich }
548014cd37fSAlexander Yermolovich 
549014cd37fSAlexander Yermolovich uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) {
550ba1ac98cSAlexander Yermolovich   const uint64_t CUID = getCUID(Unit);
551ba1ac98cSAlexander Yermolovich   assert(CUID && "Can't get offset, not a skeleton CU.");
552ba1ac98cSAlexander Yermolovich   auto Iter = DWOIdToOffsetMap.find(CUID);
553014cd37fSAlexander Yermolovich   assert(Iter != DWOIdToOffsetMap.end() &&
554014cd37fSAlexander Yermolovich          "Offset in to.debug_addr was not found for DWO ID.");
555014cd37fSAlexander Yermolovich   return Iter->second;
556014cd37fSAlexander Yermolovich }
557014cd37fSAlexander Yermolovich 
558014cd37fSAlexander Yermolovich uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) {
559ba1ac98cSAlexander Yermolovich   auto Iter = DWOIdToOffsetMap.find(getCUID(Unit));
560a34c753fSRafael Auler   assert(Iter != DWOIdToOffsetMap.end() &&
5613abb68a6SAlexander Yermolovich          "Offset in to.debug_addr was not found for CU ID.");
562a34c753fSRafael Auler   return Iter->second;
563a34c753fSRafael Auler }
564a34c753fSRafael Auler 
5651c6dc43dSAlexander Yermolovich void DebugLocWriter::init() {
566a34c753fSRafael Auler   LocBuffer = std::make_unique<DebugBufferVector>();
567a34c753fSRafael Auler   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
5681c6dc43dSAlexander Yermolovich   // Writing out empty location list to which all references to empty location
5691c6dc43dSAlexander Yermolovich   // lists will point.
5701c6dc43dSAlexander Yermolovich   if (!LocSectionOffset && DwarfVersion < 5) {
5711c6dc43dSAlexander Yermolovich     const char Zeroes[16] = {0};
5721c6dc43dSAlexander Yermolovich     *LocStream << StringRef(Zeroes, 16);
5731c6dc43dSAlexander Yermolovich     LocSectionOffset += 16;
5741c6dc43dSAlexander Yermolovich   }
575a34c753fSRafael Auler }
576a34c753fSRafael Auler 
5771c6dc43dSAlexander Yermolovich uint32_t DebugLocWriter::LocSectionOffset = 0;
5781c6dc43dSAlexander Yermolovich void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
5791c6dc43dSAlexander Yermolovich                              DebugInfoBinaryPatcher &DebugInfoPatcher,
5801c6dc43dSAlexander Yermolovich                              DebugAbbrevWriter &AbbrevWriter) {
5811c6dc43dSAlexander Yermolovich   const uint64_t AttrOffset = AttrVal.Offset;
582a34c753fSRafael Auler   if (LocList.empty()) {
5831c6dc43dSAlexander Yermolovich     DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset);
584a34c753fSRafael Auler     return;
585a34c753fSRafael Auler   }
586a34c753fSRafael Auler   // Since there is a separate DebugLocWriter for each thread,
587a34c753fSRafael Auler   // we don't need a lock to read the SectionOffset and update it.
5881c6dc43dSAlexander Yermolovich   const uint32_t EntryOffset = LocSectionOffset;
589a34c753fSRafael Auler 
590a34c753fSRafael Auler   for (const DebugLocationEntry &Entry : LocList) {
591a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
592a34c753fSRafael Auler                            support::little);
593a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
594a34c753fSRafael Auler                            support::little);
595a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
596a34c753fSRafael Auler                            support::little);
597a34c753fSRafael Auler     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
598a34c753fSRafael Auler                             Entry.Expr.size());
5991c6dc43dSAlexander Yermolovich     LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();
600a34c753fSRafael Auler   }
601a34c753fSRafael Auler   LocStream->write_zeros(16);
6021c6dc43dSAlexander Yermolovich   LocSectionOffset += 16;
603a34c753fSRafael Auler   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
6041c6dc43dSAlexander Yermolovich   DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset);
605a34c753fSRafael Auler }
606a34c753fSRafael Auler 
607a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
608a34c753fSRafael Auler   return std::move(LocBuffer);
609a34c753fSRafael Auler }
610a34c753fSRafael Auler 
611a34c753fSRafael Auler // DWARF 4: 2.6.2
6121c6dc43dSAlexander Yermolovich void DebugLocWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
6131c6dc43dSAlexander Yermolovich                               DebugAbbrevWriter &AbbrevWriter) {}
614a34c753fSRafael Auler 
615014cd37fSAlexander Yermolovich static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
616014cd37fSAlexander Yermolovich   support::endian::write(Stream, static_cast<uint32_t>(4), support::little);
617014cd37fSAlexander Yermolovich   support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),
618014cd37fSAlexander Yermolovich                          support::little);
619014cd37fSAlexander Yermolovich 
620014cd37fSAlexander Yermolovich   const char Zeroes[16] = {0};
621014cd37fSAlexander Yermolovich   Stream << StringRef(Zeroes, 16);
622014cd37fSAlexander Yermolovich   encodeULEB128(0, Stream);
623014cd37fSAlexander Yermolovich   support::endian::write(
624014cd37fSAlexander Yermolovich       Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little);
625014cd37fSAlexander Yermolovich }
626014cd37fSAlexander Yermolovich 
6271c6dc43dSAlexander Yermolovich static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
6281c6dc43dSAlexander Yermolovich                                DebugInfoBinaryPatcher &DebugInfoPatcher,
6291c6dc43dSAlexander Yermolovich                                DebugAddrWriter &AddrWriter,
6301c6dc43dSAlexander Yermolovich                                DebugBufferVector &LocBuffer, DWARFUnit &CU,
6311c6dc43dSAlexander Yermolovich                                raw_svector_ostream &LocStream) {
6321c6dc43dSAlexander Yermolovich   const uint64_t AttrOffset = AttrVal.Offset;
6331c6dc43dSAlexander Yermolovich   if (LocList.empty()) {
6341c6dc43dSAlexander Yermolovich     DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset);
6351c6dc43dSAlexander Yermolovich     return;
6361c6dc43dSAlexander Yermolovich   }
6371c6dc43dSAlexander Yermolovich 
6381c6dc43dSAlexander Yermolovich   const uint32_t EntryOffset = LocBuffer.size();
6391c6dc43dSAlexander Yermolovich   for (const DebugLocationEntry &Entry : LocList) {
6401c6dc43dSAlexander Yermolovich     support::endian::write(LocStream,
6411c6dc43dSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
6421c6dc43dSAlexander Yermolovich                            support::little);
6431c6dc43dSAlexander Yermolovich     const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
6441c6dc43dSAlexander Yermolovich     encodeULEB128(Index, LocStream);
6451c6dc43dSAlexander Yermolovich 
6461c6dc43dSAlexander Yermolovich     support::endian::write(LocStream,
6471c6dc43dSAlexander Yermolovich                            static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
6481c6dc43dSAlexander Yermolovich                            support::little);
6491c6dc43dSAlexander Yermolovich     support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()),
6501c6dc43dSAlexander Yermolovich                            support::little);
6511c6dc43dSAlexander Yermolovich     LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
6521c6dc43dSAlexander Yermolovich                            Entry.Expr.size());
6531c6dc43dSAlexander Yermolovich   }
6541c6dc43dSAlexander Yermolovich   support::endian::write(LocStream,
6551c6dc43dSAlexander Yermolovich                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
6561c6dc43dSAlexander Yermolovich                          support::little);
6571c6dc43dSAlexander Yermolovich   DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset);
6581c6dc43dSAlexander Yermolovich }
6591c6dc43dSAlexander Yermolovich 
6601c6dc43dSAlexander Yermolovich static void writeDWARF5LocList(
6611c6dc43dSAlexander Yermolovich     uint32_t &NumberOfEntries, AttrInfo &AttrVal, DebugLocationsVector &LocList,
6621c6dc43dSAlexander Yermolovich     DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter,
6631c6dc43dSAlexander Yermolovich     DebugAddrWriter &AddrWriter, DebugBufferVector &LocBodyBuffer,
6641c6dc43dSAlexander Yermolovich     std::vector<uint32_t> &RelativeLocListOffsets, DWARFUnit &CU,
6651c6dc43dSAlexander Yermolovich     raw_svector_ostream &LocBodyStream) {
6661c6dc43dSAlexander Yermolovich   if (AttrVal.V.getForm() != dwarf::DW_FORM_loclistx) {
6671c6dc43dSAlexander Yermolovich     AbbrevWriter.addAttributePatch(CU, AttrVal.AbbrevDecl,
6681c6dc43dSAlexander Yermolovich                                    dwarf::DW_AT_location, dwarf::DW_AT_location,
6691c6dc43dSAlexander Yermolovich                                    dwarf::DW_FORM_loclistx);
6701c6dc43dSAlexander Yermolovich   }
6711c6dc43dSAlexander Yermolovich   DebugInfoPatcher.addUDataPatch(AttrVal.Offset, NumberOfEntries, AttrVal.Size);
6721c6dc43dSAlexander Yermolovich   RelativeLocListOffsets.push_back(LocBodyBuffer.size());
6731c6dc43dSAlexander Yermolovich   ++NumberOfEntries;
6741c6dc43dSAlexander Yermolovich   if (LocList.empty()) {
6751c6dc43dSAlexander Yermolovich     writeEmptyListDwarf5(LocBodyStream);
6761c6dc43dSAlexander Yermolovich     return;
6771c6dc43dSAlexander Yermolovich   }
6781c6dc43dSAlexander Yermolovich 
6791c6dc43dSAlexander Yermolovich   std::vector<uint64_t> OffsetsArray;
680*124ca880SAlexander Yermolovich   bool WrittenStartxLength = false;
681*124ca880SAlexander Yermolovich   auto writeExpression = [&](uint32_t Index) -> void {
682*124ca880SAlexander Yermolovich     const DebugLocationEntry &Entry = LocList[Index];
683*124ca880SAlexander Yermolovich     encodeULEB128(Entry.Expr.size(), LocBodyStream);
684*124ca880SAlexander Yermolovich     LocBodyStream << StringRef(
685*124ca880SAlexander Yermolovich         reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
686*124ca880SAlexander Yermolovich   };
687*124ca880SAlexander Yermolovich   for (unsigned I = 0; I < LocList.size();) {
688*124ca880SAlexander Yermolovich     WrittenStartxLength = false;
689*124ca880SAlexander Yermolovich     if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,
690*124ca880SAlexander Yermolovich                      DebugLocationEntry>(
691*124ca880SAlexander Yermolovich             LocBodyStream, LocList, AddrWriter, CU, I,
692*124ca880SAlexander Yermolovich             dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair,
693*124ca880SAlexander Yermolovich             dwarf::DW_LLE_end_of_list, writeExpression))
694*124ca880SAlexander Yermolovich       continue;
695*124ca880SAlexander Yermolovich 
696*124ca880SAlexander Yermolovich     const DebugLocationEntry &Entry = LocList[I];
6971c6dc43dSAlexander Yermolovich     support::endian::write(LocBodyStream,
6981c6dc43dSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
6991c6dc43dSAlexander Yermolovich                            support::little);
7001c6dc43dSAlexander Yermolovich     const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
7011c6dc43dSAlexander Yermolovich     encodeULEB128(Index, LocBodyStream);
7021c6dc43dSAlexander Yermolovich     encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);
703*124ca880SAlexander Yermolovich     writeExpression(I);
704*124ca880SAlexander Yermolovich     ++I;
705*124ca880SAlexander Yermolovich     WrittenStartxLength = true;
7061c6dc43dSAlexander Yermolovich   }
707*124ca880SAlexander Yermolovich 
708*124ca880SAlexander Yermolovich   if (WrittenStartxLength)
7091c6dc43dSAlexander Yermolovich     support::endian::write(LocBodyStream,
7101c6dc43dSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
7111c6dc43dSAlexander Yermolovich                            support::little);
7121c6dc43dSAlexander Yermolovich }
7131c6dc43dSAlexander Yermolovich 
7141c6dc43dSAlexander Yermolovich void DebugLoclistWriter::addList(AttrInfo &AttrVal,
7151c6dc43dSAlexander Yermolovich                                  DebugLocationsVector &LocList,
7161c6dc43dSAlexander Yermolovich                                  DebugInfoBinaryPatcher &DebugInfoPatcher,
7171c6dc43dSAlexander Yermolovich                                  DebugAbbrevWriter &AbbrevWriter) {
7181c6dc43dSAlexander Yermolovich   if (DwarfVersion < 5)
7191c6dc43dSAlexander Yermolovich     writeLegacyLocList(AttrVal, LocList, DebugInfoPatcher, *AddrWriter,
7201c6dc43dSAlexander Yermolovich                        *LocBuffer, CU, *LocStream);
7211c6dc43dSAlexander Yermolovich   else
7221c6dc43dSAlexander Yermolovich     writeDWARF5LocList(NumberOfEntries, AttrVal, LocList, DebugInfoPatcher,
7231c6dc43dSAlexander Yermolovich                        AbbrevWriter, *AddrWriter, *LocBodyBuffer,
7241c6dc43dSAlexander Yermolovich                        RelativeLocListOffsets, CU, *LocBodyStream);
7251c6dc43dSAlexander Yermolovich }
7261c6dc43dSAlexander Yermolovich 
7271c6dc43dSAlexander Yermolovich uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;
7281c6dc43dSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARF5(
7291c6dc43dSAlexander Yermolovich     DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) {
7301c6dc43dSAlexander Yermolovich   if (LocBodyBuffer->empty())
7311c6dc43dSAlexander Yermolovich     return;
732014cd37fSAlexander Yermolovich 
733014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> LocArrayBuffer =
734014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
735014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> LocArrayStream =
736014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*LocArrayBuffer);
737014cd37fSAlexander Yermolovich 
7381c6dc43dSAlexander Yermolovich   const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t);
739014cd37fSAlexander Yermolovich   // Write out IndexArray
7401c6dc43dSAlexander Yermolovich   for (uint32_t RelativeOffset : RelativeLocListOffsets)
741014cd37fSAlexander Yermolovich     support::endian::write(
742014cd37fSAlexander Yermolovich         *LocArrayStream,
7431c6dc43dSAlexander Yermolovich         static_cast<uint32_t>(SizeOfArraySection + RelativeOffset),
744014cd37fSAlexander Yermolovich         support::little);
7451c6dc43dSAlexander Yermolovich 
7461c6dc43dSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
7471c6dc43dSAlexander Yermolovich       {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()),
7481c6dc43dSAlexander Yermolovich        5, 8, 0, NumberOfEntries});
749014cd37fSAlexander Yermolovich   *LocStream << *Header;
750014cd37fSAlexander Yermolovich   *LocStream << *LocArrayBuffer;
751014cd37fSAlexander Yermolovich   *LocStream << *LocBodyBuffer;
7521c6dc43dSAlexander Yermolovich 
7531c6dc43dSAlexander Yermolovich   if (!isSplitDwarf()) {
754370e4761SAmir Ayupov     if (std::optional<AttrInfo> AttrInfoVal =
7551c6dc43dSAlexander Yermolovich             findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base))
7561c6dc43dSAlexander Yermolovich       DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset,
7571c6dc43dSAlexander Yermolovich                                     LoclistBaseOffset +
7581c6dc43dSAlexander Yermolovich                                         getDWARF5RngListLocListHeaderSize());
7591c6dc43dSAlexander Yermolovich     else {
7601c6dc43dSAlexander Yermolovich       AbbrevWriter.addAttribute(
7611c6dc43dSAlexander Yermolovich           CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(),
7621c6dc43dSAlexander Yermolovich           dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset);
7631c6dc43dSAlexander Yermolovich       DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(),
7641c6dc43dSAlexander Yermolovich                                       LoclistBaseOffset + Header->size());
765014cd37fSAlexander Yermolovich     }
7661c6dc43dSAlexander Yermolovich     LoclistBaseOffset += LocBuffer->size();
7671c6dc43dSAlexander Yermolovich   }
7681c6dc43dSAlexander Yermolovich   clearList(RelativeLocListOffsets);
7691c6dc43dSAlexander Yermolovich   clearList(*LocArrayBuffer);
7701c6dc43dSAlexander Yermolovich   clearList(*LocBodyBuffer);
771014cd37fSAlexander Yermolovich }
772014cd37fSAlexander Yermolovich 
7731c6dc43dSAlexander Yermolovich void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
7741c6dc43dSAlexander Yermolovich                                   DebugAbbrevWriter &AbbrevWriter) {
7751c6dc43dSAlexander Yermolovich   if (DwarfVersion >= 5)
7761c6dc43dSAlexander Yermolovich     finalizeDWARF5(DebugInfoPatcher, AbbrevWriter);
777014cd37fSAlexander Yermolovich }
778014cd37fSAlexander Yermolovich 
779a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
780a34c753fSRafael Auler 
7811c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) {
7821c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
7831c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
784ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset));
785a34c753fSRafael Auler }
786a34c753fSRafael Auler 
7871c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) {
7881c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
7891c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
7901c2f4bbeSAlexander Yermolovich   auto RetVal = DestinationLabels.insert(Offset);
7911c2f4bbeSAlexander Yermolovich   if (!RetVal.second)
7921c2f4bbeSAlexander Yermolovich     return;
7931c2f4bbeSAlexander Yermolovich 
794ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DestinationReferenceLabel(Offset));
795a34c753fSRafael Auler }
796a34c753fSRafael Auler 
797bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
798bd1ebe9dSAlexander Yermolovich   std::string LE64(ByteSize, 0);
799bd1ebe9dSAlexander Yermolovich   for (size_t I = 0; I < ByteSize; ++I) {
800bd1ebe9dSAlexander Yermolovich     LE64[I] = NewValue & 0xff;
801bd1ebe9dSAlexander Yermolovich     NewValue >>= 8;
802bd1ebe9dSAlexander Yermolovich   }
803bd1ebe9dSAlexander Yermolovich   return LE64;
804bd1ebe9dSAlexander Yermolovich }
805bd1ebe9dSAlexander Yermolovich 
806bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
807bd1ebe9dSAlexander Yermolovich                                             uint32_t Value) {
808bd1ebe9dSAlexander Yermolovich   std::string StrValue = encodeLE(4, Value);
809bd1ebe9dSAlexander Yermolovich   insertNewEntry(DIE, std::move(StrValue));
810bd1ebe9dSAlexander Yermolovich }
811bd1ebe9dSAlexander Yermolovich 
812bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
813bd1ebe9dSAlexander Yermolovich                                             std::string &&Value) {
814bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration *AbbrevDecl =
815bd1ebe9dSAlexander Yermolovich       DIE.getAbbreviationDeclarationPtr();
816bd1ebe9dSAlexander Yermolovich 
817bd1ebe9dSAlexander Yermolovich   // In case this DIE has no attributes.
818bd1ebe9dSAlexander Yermolovich   uint32_t Offset = DIE.getOffset() + 1;
819bd1ebe9dSAlexander Yermolovich   size_t NumOfAttributes = AbbrevDecl->getNumAttributes();
820bd1ebe9dSAlexander Yermolovich   if (NumOfAttributes) {
821370e4761SAmir Ayupov     std::optional<AttrInfo> Val =
822bd1ebe9dSAlexander Yermolovich         findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1);
823bd1ebe9dSAlexander Yermolovich     assert(Val && "Invalid Value.");
824bd1ebe9dSAlexander Yermolovich 
825bd1ebe9dSAlexander Yermolovich     Offset = Val->Offset + Val->Size - DWPUnitOffset;
826bd1ebe9dSAlexander Yermolovich   }
827bd1ebe9dSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
828bd1ebe9dSAlexander Yermolovich   DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value)));
829bd1ebe9dSAlexander Yermolovich }
830bd1ebe9dSAlexander Yermolovich 
8311c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset,
8321c2f4bbeSAlexander Yermolovich                                                  uint32_t DestinationOffset,
8331c2f4bbeSAlexander Yermolovich                                                  uint32_t OldValueSize,
8341c2f4bbeSAlexander Yermolovich                                                  dwarf::Form Form) {
8351c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
8361c2f4bbeSAlexander Yermolovich   DestinationOffset -= DWPUnitOffset;
8371c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
838ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(
839ea6c8b01SAlexander Yermolovich       new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form));
8401c2f4bbeSAlexander Yermolovich }
8411c2f4bbeSAlexander Yermolovich 
8421c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue,
8431c2f4bbeSAlexander Yermolovich                                            uint32_t OldValueSize) {
8441c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
8451c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
8461c2f4bbeSAlexander Yermolovich   DebugPatches.emplace_back(
847ea6c8b01SAlexander Yermolovich       new DebugPatchVariableSize(Offset, OldValueSize, NewValue));
8481c2f4bbeSAlexander Yermolovich }
8491c2f4bbeSAlexander Yermolovich 
8501c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
8511c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
8521c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
853ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue));
8541c2f4bbeSAlexander Yermolovich }
8551c2f4bbeSAlexander Yermolovich 
8561c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
8571c2f4bbeSAlexander Yermolovich                                           uint32_t OldValueSize) {
8581c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
8591c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
8601c2f4bbeSAlexander Yermolovich   if (OldValueSize == 4)
861ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue));
862a44fe319SAlexander Yermolovich   else if (OldValueSize == 8)
863ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue));
864a44fe319SAlexander Yermolovich   else
865a44fe319SAlexander Yermolovich     DebugPatches.emplace_back(
866a44fe319SAlexander Yermolovich         new DebugPatch32GenericSize(Offset, NewValue, OldValueSize));
8671c2f4bbeSAlexander Yermolovich }
8681c2f4bbeSAlexander Yermolovich 
8691c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
8701c2f4bbeSAlexander Yermolovich                                          std::string &&NewValue,
8711c2f4bbeSAlexander Yermolovich                                          uint32_t OldValueSize) {
8721c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(NewValue));
8731c2f4bbeSAlexander Yermolovich }
8741c2f4bbeSAlexander Yermolovich 
8751c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
8761c2f4bbeSAlexander Yermolovich   auto Str = std::string(1, Value);
8771c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Str));
8781c2f4bbeSAlexander Yermolovich }
8791c2f4bbeSAlexander Yermolovich 
8801c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
8811c2f4bbeSAlexander Yermolovich                                      size_t ByteSize) {
8821c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
8831c2f4bbeSAlexander Yermolovich }
8841c2f4bbeSAlexander Yermolovich 
8851c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
8861c2f4bbeSAlexander Yermolovich                                         uint32_t OldValueSize) {
887a34c753fSRafael Auler   std::string Buff;
888a34c753fSRafael Auler   raw_string_ostream OS(Buff);
8891c2f4bbeSAlexander Yermolovich   encodeULEB128(Value, OS, OldValueSize);
890a34c753fSRafael Auler 
8911c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Buff));
892a34c753fSRafael Auler }
893a34c753fSRafael Auler 
8941c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
895a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
896a34c753fSRafael Auler }
897a34c753fSRafael Auler 
8981c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
8991c2f4bbeSAlexander Yermolovich                                        uint32_t OldValueSize) {
900a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
901a34c753fSRafael Auler }
902a34c753fSRafael Auler 
9031c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
9041c2f4bbeSAlexander Yermolovich   std::string BinaryContentsStr = std::string(BinaryContents);
905a34c753fSRafael Auler   for (const auto &Patch : Patches) {
9061c2f4bbeSAlexander Yermolovich     uint32_t Offset = Patch.first;
907a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
908a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
909a34c753fSRafael Auler            "Applied patch runs over binary size.");
910a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
9111c2f4bbeSAlexander Yermolovich       BinaryContentsStr[Offset + I] = ByteSequence[I];
912a34c753fSRafael Auler     }
913a34c753fSRafael Auler   }
9141c2f4bbeSAlexander Yermolovich   return BinaryContentsStr;
9151c2f4bbeSAlexander Yermolovich }
9161c2f4bbeSAlexander Yermolovich 
917612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
918612f0f45SAlexander Yermolovich                                                       bool IsDWOContext) {
919612f0f45SAlexander Yermolovich   CUOffsetMap CUMap;
920d2c87699SAmir Ayupov   llvm::sort(DebugPatches, [](const UniquePatchPtrType &V1,
921d2c87699SAmir Ayupov                               const UniquePatchPtrType &V2) {
922bd1ebe9dSAlexander Yermolovich     if (V1.get()->Offset == V2.get()->Offset) {
923bd1ebe9dSAlexander Yermolovich       if (V1->Kind == DebugPatchKind::NewDebugEntry &&
924bd1ebe9dSAlexander Yermolovich           V2->Kind == DebugPatchKind::NewDebugEntry)
925d2c87699SAmir Ayupov         return reinterpret_cast<const NewDebugEntry *>(V1.get())->CurrentOrder <
926d2c87699SAmir Ayupov                reinterpret_cast<const NewDebugEntry *>(V2.get())->CurrentOrder;
927bd1ebe9dSAlexander Yermolovich 
928bd1ebe9dSAlexander Yermolovich       // This is a case where we are modifying first entry of next
929bd1ebe9dSAlexander Yermolovich       // DIE, and adding a new one.
930bd1ebe9dSAlexander Yermolovich       return V1->Kind == DebugPatchKind::NewDebugEntry;
931bd1ebe9dSAlexander Yermolovich     }
9321c2f4bbeSAlexander Yermolovich     return V1.get()->Offset < V2.get()->Offset;
9331c2f4bbeSAlexander Yermolovich   });
9341c2f4bbeSAlexander Yermolovich 
935612f0f45SAlexander Yermolovich   DWARFUnitVector::compile_unit_range CompileUnits =
936612f0f45SAlexander Yermolovich       IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();
937612f0f45SAlexander Yermolovich 
938612f0f45SAlexander Yermolovich   for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
939612f0f45SAlexander Yermolovich     CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
940612f0f45SAlexander Yermolovich                               static_cast<uint32_t>(CU->getLength())};
941612f0f45SAlexander Yermolovich 
9421c2f4bbeSAlexander Yermolovich   // Calculating changes in .debug_info size from Patches to build a map of old
9431c2f4bbeSAlexander Yermolovich   // to updated reference destination offsets.
944612f0f45SAlexander Yermolovich   uint32_t PreviousOffset = 0;
945612f0f45SAlexander Yermolovich   int32_t PreviousChangeInSize = 0;
946ea6c8b01SAlexander Yermolovich   for (UniquePatchPtrType &PatchBase : DebugPatches) {
9471c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
9481c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
9491c2f4bbeSAlexander Yermolovich     default:
9501c2f4bbeSAlexander Yermolovich       continue;
9511c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
952612f0f45SAlexander Yermolovich       PreviousChangeInSize -= 4;
9531c2f4bbeSAlexander Yermolovich       break;
9541c2f4bbeSAlexander Yermolovich     }
955a44fe319SAlexander Yermolovich     case DebugPatchKind::PatchValue32GenericSize: {
956a44fe319SAlexander Yermolovich       DebugPatch32GenericSize *DPVS =
957a44fe319SAlexander Yermolovich           reinterpret_cast<DebugPatch32GenericSize *>(P);
958a44fe319SAlexander Yermolovich       PreviousChangeInSize += 4 - DPVS->OldValueSize;
959a44fe319SAlexander Yermolovich       break;
960a44fe319SAlexander Yermolovich     }
9611c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
9621c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *DPV =
9631c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
9641c2f4bbeSAlexander Yermolovich       std::string Temp;
9651c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(Temp);
9661c2f4bbeSAlexander Yermolovich       encodeULEB128(DPV->Value, OS);
967612f0f45SAlexander Yermolovich       PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
9681c2f4bbeSAlexander Yermolovich       break;
9691c2f4bbeSAlexander Yermolovich     }
9701c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DestinationReferenceLabel: {
9711c2f4bbeSAlexander Yermolovich       DestinationReferenceLabel *DRL =
9721c2f4bbeSAlexander Yermolovich           reinterpret_cast<DestinationReferenceLabel *>(P);
973612f0f45SAlexander Yermolovich       OldToNewOffset[DRL->Offset] =
974612f0f45SAlexander Yermolovich           DRL->Offset + ChangeInSize + PreviousChangeInSize;
9751c2f4bbeSAlexander Yermolovich       break;
9761c2f4bbeSAlexander Yermolovich     }
9771c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
9781c2f4bbeSAlexander Yermolovich       // This doesn't look to be a common case, so will always encode as 4 bytes
9791c2f4bbeSAlexander Yermolovich       // to reduce algorithmic complexity.
9801c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
9811c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.IndirectRelative) {
982612f0f45SAlexander Yermolovich         PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
9831c2f4bbeSAlexander Yermolovich         assert(RDP->PatchInfo.OldValueSize <= 4 &&
9841c2f4bbeSAlexander Yermolovich                "Variable encoding reference greater than 4 bytes.");
9851c2f4bbeSAlexander Yermolovich       }
9861c2f4bbeSAlexander Yermolovich       break;
9871c2f4bbeSAlexander Yermolovich     }
9881c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
9891c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
9901c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
9911c2f4bbeSAlexander Yermolovich       uint32_t CUOffset = BaseLabel->Offset;
992612f0f45SAlexander Yermolovich       ChangeInSize += PreviousChangeInSize;
9931c2f4bbeSAlexander Yermolovich       uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
994612f0f45SAlexander Yermolovich       CUMap[CUOffset].Offset = CUOffsetUpdate;
995612f0f45SAlexander Yermolovich       CUMap[PreviousOffset].Length += PreviousChangeInSize;
996612f0f45SAlexander Yermolovich       PreviousChangeInSize = 0;
997612f0f45SAlexander Yermolovich       PreviousOffset = CUOffset;
998bd1ebe9dSAlexander Yermolovich       break;
999bd1ebe9dSAlexander Yermolovich     }
1000bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
1001bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
1002bd1ebe9dSAlexander Yermolovich       PreviousChangeInSize += NDE->Value.size();
1003bd1ebe9dSAlexander Yermolovich       break;
10041c2f4bbeSAlexander Yermolovich     }
10051c2f4bbeSAlexander Yermolovich     }
10061c2f4bbeSAlexander Yermolovich   }
1007612f0f45SAlexander Yermolovich   CUMap[PreviousOffset].Length += PreviousChangeInSize;
10081c2f4bbeSAlexander Yermolovich   return CUMap;
10091c2f4bbeSAlexander Yermolovich }
1010bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0;
10111c2f4bbeSAlexander Yermolovich 
10121c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) {
10131c2f4bbeSAlexander Yermolovich   std::string NewBinaryContents;
10141c2f4bbeSAlexander Yermolovich   NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize);
10151c2f4bbeSAlexander Yermolovich   uint32_t StartOffset = 0;
10161c2f4bbeSAlexander Yermolovich   uint32_t DwarfUnitBaseOffset = 0;
10171c2f4bbeSAlexander Yermolovich   uint32_t OldValueSize = 0;
10181c2f4bbeSAlexander Yermolovich   uint32_t Offset = 0;
10191c2f4bbeSAlexander Yermolovich   std::string ByteSequence;
10201c2f4bbeSAlexander Yermolovich   std::vector<std::pair<uint32_t, uint32_t>> LengthPatches;
10211c2f4bbeSAlexander Yermolovich   // Wasting one entry to avoid checks for first.
10221c2f4bbeSAlexander Yermolovich   LengthPatches.push_back({0, 0});
10231c2f4bbeSAlexander Yermolovich 
10241c2f4bbeSAlexander Yermolovich   // Applying all the patches replacing current entry.
10251c2f4bbeSAlexander Yermolovich   // This might change the size of .debug_info section.
1026ea6c8b01SAlexander Yermolovich   for (const UniquePatchPtrType &PatchBase : DebugPatches) {
10271c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
10281c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
10291c2f4bbeSAlexander Yermolovich     default:
10301c2f4bbeSAlexander Yermolovich       continue;
10311c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
10321c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
10331c2f4bbeSAlexander Yermolovich       uint32_t DestinationOffset = RDP->DestinationOffset;
10341c2f4bbeSAlexander Yermolovich       assert(OldToNewOffset.count(DestinationOffset) &&
10351c2f4bbeSAlexander Yermolovich              "Destination Offset for reference not updated.");
10361c2f4bbeSAlexander Yermolovich       uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset];
10371c2f4bbeSAlexander Yermolovich       Offset = RDP->Offset;
10381c2f4bbeSAlexander Yermolovich       OldValueSize = RDP->PatchInfo.OldValueSize;
10391c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.DirectRelative) {
10401c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
10411c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
10421c2f4bbeSAlexander Yermolovich         // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge
10431c2f4bbeSAlexander Yermolovich         // and overflow if later debug information grows.
10441c2f4bbeSAlexander Yermolovich         if (ByteSequence.size() > OldValueSize)
10451c2f4bbeSAlexander Yermolovich           errs() << "BOLT-ERROR: Relative reference of size "
10461c2f4bbeSAlexander Yermolovich                  << Twine::utohexstr(OldValueSize)
10471c2f4bbeSAlexander Yermolovich                  << " overflows with the new encoding.\n";
10481c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.DirectAbsolute) {
10491c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
10501c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.IndirectRelative) {
10511c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
10521c2f4bbeSAlexander Yermolovich         ByteSequence.clear();
10531c2f4bbeSAlexander Yermolovich         raw_string_ostream OS(ByteSequence);
10541c2f4bbeSAlexander Yermolovich         encodeULEB128(UpdatedOffset, OS, 4);
10551c2f4bbeSAlexander Yermolovich       } else {
10561c2f4bbeSAlexander Yermolovich         llvm_unreachable("Invalid Reference form.");
10571c2f4bbeSAlexander Yermolovich       }
10581c2f4bbeSAlexander Yermolovich       break;
10591c2f4bbeSAlexander Yermolovich     }
10601c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue32: {
10611c2f4bbeSAlexander Yermolovich       DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P);
10621c2f4bbeSAlexander Yermolovich       Offset = P32->Offset;
10631c2f4bbeSAlexander Yermolovich       OldValueSize = 4;
10641c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P32->Value);
10651c2f4bbeSAlexander Yermolovich       break;
10661c2f4bbeSAlexander Yermolovich     }
10671c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
10681c2f4bbeSAlexander Yermolovich       DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P);
10691c2f4bbeSAlexander Yermolovich       Offset = P64to32->Offset;
10701c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
10711c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P64to32->Value);
10721c2f4bbeSAlexander Yermolovich       break;
10731c2f4bbeSAlexander Yermolovich     }
1074a44fe319SAlexander Yermolovich     case DebugPatchKind::PatchValue32GenericSize: {
1075a44fe319SAlexander Yermolovich       DebugPatch32GenericSize *DPVS =
1076a44fe319SAlexander Yermolovich           reinterpret_cast<DebugPatch32GenericSize *>(P);
1077a44fe319SAlexander Yermolovich       Offset = DPVS->Offset;
1078a44fe319SAlexander Yermolovich       OldValueSize = DPVS->OldValueSize;
1079a44fe319SAlexander Yermolovich       ByteSequence = encodeLE(4, DPVS->Value);
1080a44fe319SAlexander Yermolovich       break;
1081a44fe319SAlexander Yermolovich     }
10821c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
10831c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *PV =
10841c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
10851c2f4bbeSAlexander Yermolovich       Offset = PV->Offset;
10861c2f4bbeSAlexander Yermolovich       OldValueSize = PV->OldValueSize;
10871c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
10881c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(ByteSequence);
10891c2f4bbeSAlexander Yermolovich       encodeULEB128(PV->Value, OS);
10901c2f4bbeSAlexander Yermolovich       break;
10911c2f4bbeSAlexander Yermolovich     }
10921c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64: {
10931c2f4bbeSAlexander Yermolovich       DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P);
10941c2f4bbeSAlexander Yermolovich       Offset = P64->Offset;
10951c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
10961c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(8, P64->Value);
10971c2f4bbeSAlexander Yermolovich       break;
10981c2f4bbeSAlexander Yermolovich     }
10991c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
11001c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
11011c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
11021c2f4bbeSAlexander Yermolovich       Offset = BaseLabel->Offset;
11031c2f4bbeSAlexander Yermolovich       OldValueSize = 0;
11041c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
11051c2f4bbeSAlexander Yermolovich       auto &Patch = LengthPatches.back();
11061c2f4bbeSAlexander Yermolovich       // Length to copy between last patch entry and next compile unit.
11071c2f4bbeSAlexander Yermolovich       uint32_t RemainingLength = Offset - StartOffset;
11081c2f4bbeSAlexander Yermolovich       uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength;
11091c2f4bbeSAlexander Yermolovich       DwarfUnitBaseOffset = NewCUOffset;
11101c2f4bbeSAlexander Yermolovich       // Length of previous CU = This CU Offset - sizeof(length) - last CU
11111c2f4bbeSAlexander Yermolovich       // Offset.
11121c2f4bbeSAlexander Yermolovich       Patch.second = NewCUOffset - 4 - Patch.first;
11131c2f4bbeSAlexander Yermolovich       LengthPatches.push_back({NewCUOffset, 0});
11141c2f4bbeSAlexander Yermolovich       break;
11151c2f4bbeSAlexander Yermolovich     }
1116bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
1117bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
1118bd1ebe9dSAlexander Yermolovich       Offset = NDE->Offset;
1119bd1ebe9dSAlexander Yermolovich       OldValueSize = 0;
1120bd1ebe9dSAlexander Yermolovich       ByteSequence = NDE->Value;
1121bd1ebe9dSAlexander Yermolovich       break;
1122bd1ebe9dSAlexander Yermolovich     }
11231c2f4bbeSAlexander Yermolovich     }
11241c2f4bbeSAlexander Yermolovich 
1125bd1ebe9dSAlexander Yermolovich     assert((P->Kind == DebugPatchKind::NewDebugEntry ||
1126bd1ebe9dSAlexander Yermolovich             Offset + ByteSequence.size() <= BinaryContents.size()) &&
11271c2f4bbeSAlexander Yermolovich            "Applied patch runs over binary size.");
11281c2f4bbeSAlexander Yermolovich     uint32_t Length = Offset - StartOffset;
11291c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
11301c2f4bbeSAlexander Yermolovich                              Length);
11311c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(ByteSequence.data(), ByteSequence.size());
11321c2f4bbeSAlexander Yermolovich     StartOffset = Offset + OldValueSize;
11331c2f4bbeSAlexander Yermolovich   }
11341c2f4bbeSAlexander Yermolovich   uint32_t Length = BinaryContents.size() - StartOffset;
11351c2f4bbeSAlexander Yermolovich   NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
11361c2f4bbeSAlexander Yermolovich                            Length);
11371c2f4bbeSAlexander Yermolovich   DebugPatches.clear();
11381c2f4bbeSAlexander Yermolovich 
11391c2f4bbeSAlexander Yermolovich   // Patching lengths of CUs
11401c2f4bbeSAlexander Yermolovich   auto &Patch = LengthPatches.back();
11411c2f4bbeSAlexander Yermolovich   Patch.second = NewBinaryContents.size() - 4 - Patch.first;
11421c2f4bbeSAlexander Yermolovich   for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) {
11431c2f4bbeSAlexander Yermolovich     const auto &Patch = LengthPatches[J];
11441c2f4bbeSAlexander Yermolovich     ByteSequence = encodeLE(4, Patch.second);
11451c2f4bbeSAlexander Yermolovich     Offset = Patch.first;
11461c2f4bbeSAlexander Yermolovich     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I)
11471c2f4bbeSAlexander Yermolovich       NewBinaryContents[Offset + I] = ByteSequence[I];
11481c2f4bbeSAlexander Yermolovich   }
11491c2f4bbeSAlexander Yermolovich 
11501c2f4bbeSAlexander Yermolovich   return NewBinaryContents;
1151a34c753fSRafael Auler }
1152a34c753fSRafael Auler 
1153ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::initialize(
1154ba1ac98cSAlexander Yermolovich     const DWARFSection &StrOffsetsSection,
115589fab98eSFangrui Song     const std::optional<StrOffsetsContributionDescriptor> Contr) {
1156ba1ac98cSAlexander Yermolovich   if (!Contr)
1157ba1ac98cSAlexander Yermolovich     return;
1158ba1ac98cSAlexander Yermolovich 
1159ba1ac98cSAlexander Yermolovich   const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
1160ba1ac98cSAlexander Yermolovich   assert(DwarfOffsetByteSize == 4 &&
1161ba1ac98cSAlexander Yermolovich          "Dwarf String Offsets Byte Size is not supported.");
1162ba1ac98cSAlexander Yermolovich   uint32_t Index = 0;
1163ba1ac98cSAlexander Yermolovich   for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)
1164ba1ac98cSAlexander Yermolovich     IndexToAddressMap[Index++] = *reinterpret_cast<const uint32_t *>(
1165ba1ac98cSAlexander Yermolovich         StrOffsetsSection.Data.data() + Contr->Base + Offset);
1166ba1ac98cSAlexander Yermolovich }
1167ba1ac98cSAlexander Yermolovich 
1168ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) {
1169ba1ac98cSAlexander Yermolovich   assert(IndexToAddressMap.count(Index) > 0 && "Index is not found.");
1170ba1ac98cSAlexander Yermolovich   IndexToAddressMap[Index] = Address;
1171f7a21317SAlexander Yermolovich   StrOffsetSectionWasModified = true;
1172ba1ac98cSAlexander Yermolovich }
1173ba1ac98cSAlexander Yermolovich 
1174f7a21317SAlexander Yermolovich void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit) {
1175ba1ac98cSAlexander Yermolovich   if (IndexToAddressMap.empty())
1176ba1ac98cSAlexander Yermolovich     return;
1177f7a21317SAlexander Yermolovich 
1178f7a21317SAlexander Yermolovich   std::optional<AttrInfo> AttrVal =
1179f7a21317SAlexander Yermolovich       findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
1180f7a21317SAlexander Yermolovich   assert(AttrVal && "DW_AT_str_offsets_base not present.");
1181f7a21317SAlexander Yermolovich   std::optional<uint64_t> Val = AttrVal->V.getAsSectionOffset();
1182f7a21317SAlexander Yermolovich   assert(Val && "DW_AT_str_offsets_base Value not present.");
1183f7a21317SAlexander Yermolovich   auto RetVal = ProcessedBaseOffsets.insert(*Val);
1184f7a21317SAlexander Yermolovich   if (RetVal.second) {
1185ba1ac98cSAlexander Yermolovich     // Writing out the header for each section.
1186ba1ac98cSAlexander Yermolovich     support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4,
1187ba1ac98cSAlexander Yermolovich                            support::little);
1188ba1ac98cSAlexander Yermolovich     support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),
1189ba1ac98cSAlexander Yermolovich                            support::little);
1190ba1ac98cSAlexander Yermolovich     support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),
1191ba1ac98cSAlexander Yermolovich                            support::little);
1192ba1ac98cSAlexander Yermolovich     for (const auto &Entry : IndexToAddressMap)
1193ba1ac98cSAlexander Yermolovich       support::endian::write(*StrOffsetsStream, Entry.second, support::little);
1194f7a21317SAlexander Yermolovich   }
1195f7a21317SAlexander Yermolovich   // Will print error if we already processed this contribution, and now
1196f7a21317SAlexander Yermolovich   // skipping it, but it was modified.
1197f7a21317SAlexander Yermolovich   if (!RetVal.second && StrOffsetSectionWasModified)
1198f7a21317SAlexander Yermolovich     errs() << "BOLT-WARNING: skipping string offsets section for CU at offset "
1199f7a21317SAlexander Yermolovich            << Twine::utohexstr(Unit.getOffset()) << ", but it was modified\n";
1200f7a21317SAlexander Yermolovich 
1201f7a21317SAlexander Yermolovich   StrOffsetSectionWasModified = false;
1202ba1ac98cSAlexander Yermolovich   IndexToAddressMap.clear();
1203ba1ac98cSAlexander Yermolovich }
1204ba1ac98cSAlexander Yermolovich 
1205a34c753fSRafael Auler void DebugStrWriter::create() {
1206a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
1207a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
1208a34c753fSRafael Auler }
1209a34c753fSRafael Auler 
1210a34c753fSRafael Auler void DebugStrWriter::initialize() {
1211ba1ac98cSAlexander Yermolovich   auto StrSection = BC.DwCtx->getDWARFObj().getStrSection();
1212a34c753fSRafael Auler   (*StrStream) << StrSection;
1213a34c753fSRafael Auler }
1214a34c753fSRafael Auler 
1215a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
1216e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
1217a34c753fSRafael Auler   if (StrBuffer->empty())
1218a34c753fSRafael Auler     initialize();
1219a34c753fSRafael Auler   auto Offset = StrBuffer->size();
1220a34c753fSRafael Auler   (*StrStream) << Str;
1221a34c753fSRafael Auler   StrStream->write_zeros(1);
1222a34c753fSRafael Auler   return Offset;
1223a34c753fSRafael Auler }
1224a34c753fSRafael Auler 
1225a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
1226a34c753fSRafael Auler   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
1227a34c753fSRafael Auler   if (!Abbrevs)
1228a34c753fSRafael Auler     return;
1229a34c753fSRafael Auler 
123045f94abcSMaksim Panchenko   const PatchesTy &UnitPatches = Patches[&Unit];
1231bd1ebe9dSAlexander Yermolovich   const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit];
1232a34c753fSRafael Auler 
12339f3f9d19SAlexander Yermolovich   // We are duplicating abbrev sections, to handle the case where for one CU we
12349f3f9d19SAlexander Yermolovich   // modify it, but for another we don't.
12359f3f9d19SAlexander Yermolovich   auto UnitDataPtr = std::make_unique<AbbrevData>();
12369f3f9d19SAlexander Yermolovich   AbbrevData &UnitData = *UnitDataPtr.get();
12379f3f9d19SAlexander Yermolovich   UnitData.Buffer = std::make_unique<DebugBufferVector>();
12389f3f9d19SAlexander Yermolovich   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
1239bd1ebe9dSAlexander Yermolovich 
1240a34c753fSRafael Auler   raw_svector_ostream &OS = *UnitData.Stream.get();
1241a34c753fSRafael Auler 
12429f3f9d19SAlexander Yermolovich   // Returns true if AbbrevData is re-used, false otherwise.
12439f3f9d19SAlexander Yermolovich   auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool {
12449f3f9d19SAlexander Yermolovich     llvm::SHA1 Hasher;
12459f3f9d19SAlexander Yermolovich     Hasher.update(AbbrevData);
1246330268baSArgyrios Kyrtzidis     std::array<uint8_t, 20> Hash = Hasher.final();
1247330268baSArgyrios Kyrtzidis     StringRef Key((const char *)Hash.data(), Hash.size());
12489f3f9d19SAlexander Yermolovich     auto Iter = AbbrevDataCache.find(Key);
12499f3f9d19SAlexander Yermolovich     if (Iter != AbbrevDataCache.end()) {
12509f3f9d19SAlexander Yermolovich       UnitsAbbrevData[&Unit] = Iter->second.get();
12519f3f9d19SAlexander Yermolovich       return true;
12529f3f9d19SAlexander Yermolovich     }
12539f3f9d19SAlexander Yermolovich     AbbrevDataCache[Key] = std::move(UnitDataPtr);
12549f3f9d19SAlexander Yermolovich     UnitsAbbrevData[&Unit] = &UnitData;
12559f3f9d19SAlexander Yermolovich     return false;
12569f3f9d19SAlexander Yermolovich   };
1257a34c753fSRafael Auler   // Take a fast path if there are no patches to apply. Simply copy the original
1258a34c753fSRafael Auler   // contents.
1259bd1ebe9dSAlexander Yermolovich   if (UnitPatches.empty() && AbbrevEntries.empty()) {
1260a34c753fSRafael Auler     StringRef AbbrevSectionContents =
1261a34c753fSRafael Auler         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
1262a34c753fSRafael Auler                          : Unit.getContext().getDWARFObj().getAbbrevSection();
1263a34c753fSRafael Auler     StringRef AbbrevContents;
1264a34c753fSRafael Auler 
1265a34c753fSRafael Auler     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
1266a34c753fSRafael Auler     if (!CUIndex.getRows().empty()) {
1267a34c753fSRafael Auler       // Handle DWP section contribution.
1268a34c753fSRafael Auler       const DWARFUnitIndex::Entry *DWOEntry =
1269a34c753fSRafael Auler           CUIndex.getFromHash(*Unit.getDWOId());
1270a34c753fSRafael Auler       if (!DWOEntry)
1271a34c753fSRafael Auler         return;
1272a34c753fSRafael Auler 
1273a34c753fSRafael Auler       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
1274a34c753fSRafael Auler           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
12757fc79340SAlexander Yermolovich       AbbrevContents = AbbrevSectionContents.substr(
12767fc79340SAlexander Yermolovich           DWOContrubution->getOffset(), DWOContrubution->getLength());
127745f94abcSMaksim Panchenko     } else if (!Unit.isDWOUnit()) {
1278a34c753fSRafael Auler       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
127945f94abcSMaksim Panchenko 
128045f94abcSMaksim Panchenko       // We know where the unit's abbreviation set starts, but not where it ends
128145f94abcSMaksim Panchenko       // as such data is not readily available. Hence, we have to build a sorted
128245f94abcSMaksim Panchenko       // list of start addresses and find the next starting address to determine
128345f94abcSMaksim Panchenko       // the set boundaries.
128445f94abcSMaksim Panchenko       //
128545f94abcSMaksim Panchenko       // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
128645f94abcSMaksim Panchenko       // we wouldn't have to build our own sorted list for the quick lookup.
128745f94abcSMaksim Panchenko       if (AbbrevSetOffsets.empty()) {
1288a0c7ca8aSKazu Hirata         for (const std::pair<const uint64_t, DWARFAbbreviationDeclarationSet>
1289a0c7ca8aSKazu Hirata                  &P : *Unit.getContext().getDebugAbbrev())
129045f94abcSMaksim Panchenko           AbbrevSetOffsets.push_back(P.first);
12911c2f4bbeSAlexander Yermolovich         sort(AbbrevSetOffsets);
129245f94abcSMaksim Panchenko       }
12931c2f4bbeSAlexander Yermolovich       auto It = upper_bound(AbbrevSetOffsets, StartOffset);
129445f94abcSMaksim Panchenko       const uint64_t EndOffset =
129545f94abcSMaksim Panchenko           It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
1296a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
129745f94abcSMaksim Panchenko     } else {
129845f94abcSMaksim Panchenko       // For DWO unit outside of DWP, we expect the entire section to hold
129945f94abcSMaksim Panchenko       // abbreviations for this unit only.
130045f94abcSMaksim Panchenko       AbbrevContents = AbbrevSectionContents;
1301a34c753fSRafael Auler     }
1302a34c753fSRafael Auler 
13039f3f9d19SAlexander Yermolovich     if (!hashAndAddAbbrev(AbbrevContents)) {
1304a34c753fSRafael Auler       OS.reserveExtraSpace(AbbrevContents.size());
1305a34c753fSRafael Auler       OS << AbbrevContents;
13069f3f9d19SAlexander Yermolovich     }
1307a34c753fSRafael Auler     return;
1308a34c753fSRafael Auler   }
1309a34c753fSRafael Auler 
1310a34c753fSRafael Auler   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
1311a34c753fSRafael Auler     const DWARFAbbreviationDeclaration &Abbrev = *I;
1312a34c753fSRafael Auler     auto Patch = UnitPatches.find(&Abbrev);
1313a34c753fSRafael Auler 
1314a34c753fSRafael Auler     encodeULEB128(Abbrev.getCode(), OS);
1315a34c753fSRafael Auler     encodeULEB128(Abbrev.getTag(), OS);
1316a34c753fSRafael Auler     encodeULEB128(Abbrev.hasChildren(), OS);
1317a34c753fSRafael Auler     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
1318a34c753fSRafael Auler          Abbrev.attributes()) {
1319a34c753fSRafael Auler       if (Patch != UnitPatches.end()) {
1320a34c753fSRafael Auler         bool Patched = false;
1321a34c753fSRafael Auler         // Patches added later take a precedence over earlier ones.
1322f40d25ddSAmir Ayupov         for (const PatchInfo &PI : llvm::reverse(Patch->second)) {
1323f40d25ddSAmir Ayupov           if (PI.OldAttr != AttrSpec.Attr)
1324a34c753fSRafael Auler             continue;
1325a34c753fSRafael Auler 
1326f40d25ddSAmir Ayupov           encodeULEB128(PI.NewAttr, OS);
1327f40d25ddSAmir Ayupov           encodeULEB128(PI.NewAttrForm, OS);
1328a34c753fSRafael Auler           Patched = true;
1329a34c753fSRafael Auler           break;
1330a34c753fSRafael Auler         }
1331a34c753fSRafael Auler         if (Patched)
1332a34c753fSRafael Auler           continue;
1333a34c753fSRafael Auler       }
1334a34c753fSRafael Auler 
1335a34c753fSRafael Auler       encodeULEB128(AttrSpec.Attr, OS);
1336a34c753fSRafael Auler       encodeULEB128(AttrSpec.Form, OS);
1337a34c753fSRafael Auler       if (AttrSpec.isImplicitConst())
1338a34c753fSRafael Auler         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
1339a34c753fSRafael Auler     }
1340bd1ebe9dSAlexander Yermolovich     const auto Entries = AbbrevEntries.find(&Abbrev);
1341bd1ebe9dSAlexander Yermolovich     // Adding new Abbrevs for inserted entries.
1342bd1ebe9dSAlexander Yermolovich     if (Entries != AbbrevEntries.end()) {
1343bd1ebe9dSAlexander Yermolovich       for (const AbbrevEntry &Entry : Entries->second) {
1344bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Attr, OS);
1345bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Form, OS);
1346bd1ebe9dSAlexander Yermolovich       }
1347bd1ebe9dSAlexander Yermolovich     }
1348a34c753fSRafael Auler     encodeULEB128(0, OS);
1349a34c753fSRafael Auler     encodeULEB128(0, OS);
1350a34c753fSRafael Auler   }
1351a34c753fSRafael Auler   encodeULEB128(0, OS);
13529f3f9d19SAlexander Yermolovich 
13539f3f9d19SAlexander Yermolovich   hashAndAddAbbrev(OS.str());
1354a34c753fSRafael Auler }
1355a34c753fSRafael Auler 
1356a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
13579f3f9d19SAlexander Yermolovich   // Used to create determinism for writing out abbrevs.
13589f3f9d19SAlexander Yermolovich   std::vector<AbbrevData *> Abbrevs;
135945f94abcSMaksim Panchenko   if (DWOId) {
136045f94abcSMaksim Panchenko     // We expect abbrev_offset to always be zero for DWO units as there
136145f94abcSMaksim Panchenko     // should be one CU per DWO, and TUs should share the same abbreviation
136245f94abcSMaksim Panchenko     // set with the CU.
13631417f607SAlexander Yermolovich     // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so
13641417f607SAlexander Yermolovich     // can be none zero. Thus we are skipping the check for DWP.
136545f94abcSMaksim Panchenko     bool IsDWP = !Context.getCUIndex().getRows().empty();
13661417f607SAlexander Yermolovich     if (!IsDWP) {
136745f94abcSMaksim Panchenko       for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
136845f94abcSMaksim Panchenko         if (Unit->getAbbreviationsOffset() != 0) {
136945f94abcSMaksim Panchenko           errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
137045f94abcSMaksim Panchenko                     "Unable to update debug info.\n";
137145f94abcSMaksim Panchenko           exit(1);
137245f94abcSMaksim Panchenko         }
137345f94abcSMaksim Panchenko       }
137445f94abcSMaksim Panchenko     }
137545f94abcSMaksim Panchenko 
13769f3f9d19SAlexander Yermolovich     DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId);
137745f94abcSMaksim Panchenko     // Issue abbreviations for the DWO CU only.
137845f94abcSMaksim Panchenko     addUnitAbbreviations(*Unit);
13799f3f9d19SAlexander Yermolovich     AbbrevData *Abbrev = UnitsAbbrevData[Unit];
13809f3f9d19SAlexander Yermolovich     Abbrevs.push_back(Abbrev);
13819f3f9d19SAlexander Yermolovich   } else {
13829f3f9d19SAlexander Yermolovich     Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits());
13839f3f9d19SAlexander Yermolovich     std::unordered_set<AbbrevData *> ProcessedAbbrevs;
13849f3f9d19SAlexander Yermolovich     // Add abbreviations from compile and type non-DWO units.
13859f3f9d19SAlexander Yermolovich     for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) {
13869f3f9d19SAlexander Yermolovich       addUnitAbbreviations(*Unit);
13879f3f9d19SAlexander Yermolovich       AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()];
13889f3f9d19SAlexander Yermolovich       if (!ProcessedAbbrevs.insert(Abbrev).second)
13899f3f9d19SAlexander Yermolovich         continue;
13909f3f9d19SAlexander Yermolovich       Abbrevs.push_back(Abbrev);
13919f3f9d19SAlexander Yermolovich     }
139245f94abcSMaksim Panchenko   }
139345f94abcSMaksim Panchenko 
1394a34c753fSRafael Auler   DebugBufferVector ReturnBuffer;
1395a34c753fSRafael Auler   // Pre-calculate the total size of abbrev section.
1396a34c753fSRafael Auler   uint64_t Size = 0;
13979f3f9d19SAlexander Yermolovich   for (const AbbrevData *UnitData : Abbrevs)
13989f3f9d19SAlexander Yermolovich     Size += UnitData->Buffer->size();
13999f3f9d19SAlexander Yermolovich 
1400a34c753fSRafael Auler   ReturnBuffer.reserve(Size);
1401a34c753fSRafael Auler 
1402a34c753fSRafael Auler   uint64_t Pos = 0;
14039f3f9d19SAlexander Yermolovich   for (AbbrevData *UnitData : Abbrevs) {
14049f3f9d19SAlexander Yermolovich     ReturnBuffer.append(*UnitData->Buffer);
14059f3f9d19SAlexander Yermolovich     UnitData->Offset = Pos;
14069f3f9d19SAlexander Yermolovich     Pos += UnitData->Buffer->size();
1407a34c753fSRafael Auler 
14089f3f9d19SAlexander Yermolovich     UnitData->Buffer.reset();
14099f3f9d19SAlexander Yermolovich     UnitData->Stream.reset();
1410a34c753fSRafael Auler   }
1411a34c753fSRafael Auler 
1412a34c753fSRafael Auler   return std::make_unique<DebugBufferVector>(ReturnBuffer);
1413a34c753fSRafael Auler }
1414a34c753fSRafael Auler 
1415a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
1416a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
1417a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
1418a34c753fSRafael Auler                                     int PointerSize) {
1419a34c753fSRafael Auler   // emit the sequence to set the address
1420a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
1421a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
1422a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
1423a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
1424a34c753fSRafael Auler 
1425a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
1426a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
1427a34c753fSRafael Auler }
1428a34c753fSRafael Auler 
1429a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
1430a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
1431a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
1432a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
1433a34c753fSRafael Auler   if (InputSequences.empty())
1434a34c753fSRafael Auler     return;
1435a34c753fSRafael Auler 
1436a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
1437a34c753fSRafael Auler   unsigned FileNum = 1;
1438a34c753fSRafael Auler   unsigned LastLine = 1;
1439a34c753fSRafael Auler   unsigned Column = 0;
1440a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1441a34c753fSRafael Auler   unsigned Isa = 0;
1442a34c753fSRafael Auler   unsigned Discriminator = 0;
1443a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
1444a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
1445a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1446a34c753fSRafael Auler 
1447a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
1448a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
1449a34c753fSRafael Auler     FileNum = 1;
1450a34c753fSRafael Auler     LastLine = 1;
1451a34c753fSRafael Auler     Column = 0;
1452a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1453a34c753fSRafael Auler     Isa = 0;
1454a34c753fSRafael Auler     Discriminator = 0;
1455a34c753fSRafael Auler     LastAddress = InvalidAddress;
1456a34c753fSRafael Auler   };
1457a34c753fSRafael Auler 
1458a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
1459a34c753fSRafael Auler     const uint64_t SequenceStart =
1460a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
1461a34c753fSRafael Auler 
1462a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
1463a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
1464a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
1465a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
1466a34c753fSRafael Auler     }
1467a34c753fSRafael Auler 
1468a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
1469a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
1470a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
1471a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
1472a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
1473a34c753fSRafael Auler 
1474a34c753fSRafael Auler       if (FileNum != Row.File) {
1475a34c753fSRafael Auler         FileNum = Row.File;
1476a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1477a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
1478a34c753fSRafael Auler       }
1479a34c753fSRafael Auler       if (Column != Row.Column) {
1480a34c753fSRafael Auler         Column = Row.Column;
1481a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1482a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
1483a34c753fSRafael Auler       }
1484a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
1485a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
1486a34c753fSRafael Auler         Discriminator = Row.Discriminator;
1487a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
1488a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1489a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
1490a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1491a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
1492a34c753fSRafael Auler       }
1493a34c753fSRafael Auler       if (Isa != Row.Isa) {
1494a34c753fSRafael Auler         Isa = Row.Isa;
1495a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1496a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
1497a34c753fSRafael Auler       }
1498a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
1499a34c753fSRafael Auler         Flags = Row.IsStmt;
1500a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1501a34c753fSRafael Auler       }
1502a34c753fSRafael Auler       if (Row.BasicBlock)
1503a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1504a34c753fSRafael Auler       if (Row.PrologueEnd)
1505a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1506a34c753fSRafael Auler       if (Row.EpilogueBegin)
1507a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1508a34c753fSRafael Auler 
1509a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
1510a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
1511a34c753fSRafael Auler       if (Row.EndSequence) {
1512a34c753fSRafael Auler         emitEndOfSequence(Address);
1513a34c753fSRafael Auler       } else {
1514a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
1515a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1516a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
1517a34c753fSRafael Auler         else
1518a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1519a34c753fSRafael Auler 
1520a34c753fSRafael Auler         LastAddress = Address;
1521a34c753fSRafael Auler         LastLine = Row.Line;
1522a34c753fSRafael Auler       }
1523a34c753fSRafael Auler 
1524a34c753fSRafael Auler       Discriminator = 0;
1525a34c753fSRafael Auler     }
1526a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
1527a34c753fSRafael Auler   }
1528a34c753fSRafael Auler 
1529a34c753fSRafael Auler   // Finish with the end of the sequence.
1530a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
1531a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
1532a34c753fSRafael Auler }
1533a34c753fSRafael Auler 
1534a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
1535a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
1536a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
1537a34c753fSRafael Auler static inline void emitDwarfLineTable(
1538a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
1539a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1540a34c753fSRafael Auler   unsigned FileNum = 1;
1541a34c753fSRafael Auler   unsigned LastLine = 1;
1542a34c753fSRafael Auler   unsigned Column = 0;
1543a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1544a34c753fSRafael Auler   unsigned Isa = 0;
1545a34c753fSRafael Auler   unsigned Discriminator = 0;
1546a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
1547a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1548a34c753fSRafael Auler 
1549a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1550a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1551a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1552a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1553a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
1554a34c753fSRafael Auler       FileNum = 1;
1555a34c753fSRafael Auler       LastLine = 1;
1556a34c753fSRafael Auler       Column = 0;
1557a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1558a34c753fSRafael Auler       Isa = 0;
1559a34c753fSRafael Auler       Discriminator = 0;
1560a34c753fSRafael Auler       LastLabel = nullptr;
1561a34c753fSRafael Auler       continue;
1562a34c753fSRafael Auler     }
1563a34c753fSRafael Auler 
1564a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1565a34c753fSRafael Auler 
1566a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
1567a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
1568a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1569a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
1570a34c753fSRafael Auler     }
1571a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
1572a34c753fSRafael Auler       Column = LineEntry.getColumn();
1573a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1574a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
1575a34c753fSRafael Auler     }
1576a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
1577014cd37fSAlexander Yermolovich         MCOS->getContext().getDwarfVersion() >= 2) {
1578a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
1579a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
1580a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1581a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
1582a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1583a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
1584a34c753fSRafael Auler     }
1585a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
1586a34c753fSRafael Auler       Isa = LineEntry.getIsa();
1587a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1588a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
1589a34c753fSRafael Auler     }
1590a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1591a34c753fSRafael Auler       Flags = LineEntry.getFlags();
1592a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1593a34c753fSRafael Auler     }
1594a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1595a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1596a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1597a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1598a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1599a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1600a34c753fSRafael Auler 
1601a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
1602a34c753fSRafael Auler 
1603a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
1604a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
1605a34c753fSRafael Auler     // Label and the current Label.
1606a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1607a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
1608a34c753fSRafael Auler     Discriminator = 0;
1609a34c753fSRafael Auler     LastLine = LineEntry.getLine();
1610a34c753fSRafael Auler     LastLabel = Label;
1611a34c753fSRafael Auler   }
1612a34c753fSRafael Auler 
1613a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
1614a34c753fSRafael Auler }
1615a34c753fSRafael Auler 
1616a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1617f4c16c44SFangrui Song                             std::optional<MCDwarfLineStr> &LineStr,
1618b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
1619a34c753fSRafael Auler   if (!RawData.empty()) {
1620a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
1621a34c753fSRafael Auler            InputSequences.empty() &&
1622a34c753fSRafael Auler            "cannot combine raw data with new line entries");
1623a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
1624a34c753fSRafael Auler     MCOS->emitBytes(RawData);
1625a34c753fSRafael Auler 
1626b73c87bcSMaksim Panchenko     // Emit fake relocation for RuntimeDyld to always allocate the section.
1627b73c87bcSMaksim Panchenko     //
1628b73c87bcSMaksim Panchenko     // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
1629b73c87bcSMaksim Panchenko     //        without relocations.
1630b73c87bcSMaksim Panchenko     MCOS->emitRelocDirective(
1631b73c87bcSMaksim Panchenko         *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
1632b73c87bcSMaksim Panchenko         MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);
1633b73c87bcSMaksim Panchenko 
1634a34c753fSRafael Auler     return;
1635a34c753fSRafael Auler   }
1636a34c753fSRafael Auler 
1637a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1638a34c753fSRafael Auler 
1639a34c753fSRafael Auler   // Put out the line tables.
1640a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1641a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1642a34c753fSRafael Auler 
1643a34c753fSRafael Auler   // Emit line tables for the original code.
1644a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1645a34c753fSRafael Auler 
1646a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
1647a34c753fSRafael Auler   // of this section (that was used in a previous expression).
1648a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
1649a34c753fSRafael Auler }
1650a34c753fSRafael Auler 
1651014cd37fSAlexander Yermolovich // Helper function to parse .debug_line_str, and populate one we are using.
1652014cd37fSAlexander Yermolovich // For functions that we do not modify we output them as raw data.
1653014cd37fSAlexander Yermolovich // Re-constructing .debug_line_str so that offsets are correct for those
1654014cd37fSAlexander Yermolovich // debut line tables.
1655014cd37fSAlexander Yermolovich // Bonus is that when we output a final binary we can re-use .debug_line_str
1656014cd37fSAlexander Yermolovich // section. So we don't have to do the SHF_ALLOC trick we did with
1657014cd37fSAlexander Yermolovich // .debug_line.
1658014cd37fSAlexander Yermolovich static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
1659014cd37fSAlexander Yermolovich                                          MCDwarfLineStr &LineStr,
1660014cd37fSAlexander Yermolovich                                          BinaryContext &BC,
1661014cd37fSAlexander Yermolovich                                          MCStreamer &Streamer) {
1662014cd37fSAlexander Yermolovich   DataExtractor StrData(LineStrSection.getContents(),
1663014cd37fSAlexander Yermolovich                         BC.DwCtx->isLittleEndian(), 0);
1664014cd37fSAlexander Yermolovich   uint64_t Offset = 0;
1665014cd37fSAlexander Yermolovich   while (StrData.isValidOffset(Offset)) {
1666014cd37fSAlexander Yermolovich     Error Err = Error::success();
1667014cd37fSAlexander Yermolovich     const char *CStr = StrData.getCStr(&Offset, &Err);
1668014cd37fSAlexander Yermolovich     if (Err) {
1669014cd37fSAlexander Yermolovich       errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1670014cd37fSAlexander Yermolovich       continue;
1671014cd37fSAlexander Yermolovich     }
1672014cd37fSAlexander Yermolovich     LineStr.emitRef(&Streamer, CStr);
1673014cd37fSAlexander Yermolovich   }
1674014cd37fSAlexander Yermolovich }
1675014cd37fSAlexander Yermolovich 
1676a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1677a34c753fSRafael Auler   MCAssembler &Assembler =
1678a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1679a34c753fSRafael Auler 
1680a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1681a34c753fSRafael Auler 
1682a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
1683a34c753fSRafael Auler 
1684a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
1685a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
1686a34c753fSRafael Auler   if (LineTables.empty())
1687a34c753fSRafael Auler     return;
1688a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
1689f4c16c44SFangrui Song   std::optional<MCDwarfLineStr> LineStr;
1690014cd37fSAlexander Yermolovich   ErrorOr<BinarySection &> LineStrSection =
1691014cd37fSAlexander Yermolovich       BC.getUniqueSectionByName(".debug_line_str");
1692014cd37fSAlexander Yermolovich   // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
1693014cd37fSAlexander Yermolovich   // .debug_line
1694014cd37fSAlexander Yermolovich   if (LineStrSection) {
169553113515SFangrui Song     LineStr.emplace(*BC.Ctx);
1696014cd37fSAlexander Yermolovich     parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer);
1697014cd37fSAlexander Yermolovich   }
1698a34c753fSRafael Auler 
1699a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
1700adf4142fSFangrui Song   Streamer.switchSection(BC.MOFI->getDwarfLineSection());
1701a34c753fSRafael Auler 
1702014cd37fSAlexander Yermolovich   const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
1703a34c753fSRafael Auler   // Handle the rest of the Compile Units.
1704a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
1705014cd37fSAlexander Yermolovich     Streamer.getContext().setDwarfVersion(
1706014cd37fSAlexander Yermolovich         CUIDTablePair.second.getDwarfVersion());
1707b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1708a34c753fSRafael Auler   }
1709014cd37fSAlexander Yermolovich 
1710014cd37fSAlexander Yermolovich   // Resetting DWARF version for rest of the flow.
1711014cd37fSAlexander Yermolovich   BC.Ctx->setDwarfVersion(DwarfVersion);
1712014cd37fSAlexander Yermolovich 
1713014cd37fSAlexander Yermolovich   // Still need to write the section out for the ExecutionEngine, and temp in
1714014cd37fSAlexander Yermolovich   // memory object we are constructing.
1715014cd37fSAlexander Yermolovich   if (LineStr) {
1716014cd37fSAlexander Yermolovich     LineStr->emitSection(&Streamer);
1717014cd37fSAlexander Yermolovich     SmallString<0> Data = LineStr->getFinalizedData();
1718014cd37fSAlexander Yermolovich     BC.registerOrUpdateNoteSection(".debug_line_str", copyByteArray(Data.str()),
1719014cd37fSAlexander Yermolovich                                    Data.size());
1720014cd37fSAlexander Yermolovich   }
1721a34c753fSRafael Auler }
1722a34c753fSRafael Auler 
1723a34c753fSRafael Auler } // namespace bolt
1724a34c753fSRafael Auler } // namespace llvm
1725