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"
15*014cd37fSAlexander 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"
19*014cd37fSAlexander 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>
30a34c753fSRafael Auler #include <limits>
311c2f4bbeSAlexander Yermolovich #include <unordered_map>
32a34c753fSRafael Auler 
33a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info"
34a34c753fSRafael Auler 
35a34c753fSRafael Auler namespace opts {
36a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity;
371c2f4bbeSAlexander Yermolovich } // namespace opts
38a34c753fSRafael Auler 
39a34c753fSRafael Auler namespace llvm {
40f8c7fb49SAmir Ayupov class MCSymbol;
41f8c7fb49SAmir Ayupov 
42a34c753fSRafael Auler namespace bolt {
43a34c753fSRafael Auler 
44bd1ebe9dSAlexander Yermolovich /// Finds attributes FormValue and Offset.
45bd1ebe9dSAlexander Yermolovich ///
46bd1ebe9dSAlexander Yermolovich /// \param DIE die to look up in.
47bd1ebe9dSAlexander Yermolovich /// \param Index the attribute index to extract.
48bd1ebe9dSAlexander Yermolovich /// \return an optional AttrInfo with DWARFFormValue and Offset.
49bd1ebe9dSAlexander Yermolovich Optional<AttrInfo>
50bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE,
51bd1ebe9dSAlexander Yermolovich                   const DWARFAbbreviationDeclaration *AbbrevDecl,
52bd1ebe9dSAlexander Yermolovich                   uint32_t Index) {
53bd1ebe9dSAlexander Yermolovich   const DWARFUnit &U = *DIE.getDwarfUnit();
54bd1ebe9dSAlexander Yermolovich   uint64_t Offset =
55bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
56bd1ebe9dSAlexander Yermolovich   Optional<DWARFFormValue> Value =
57bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
58bd1ebe9dSAlexander Yermolovich   if (!Value)
59bd1ebe9dSAlexander Yermolovich     return None;
60bd1ebe9dSAlexander Yermolovich   // AttributeSpec
61bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
62bd1ebe9dSAlexander Yermolovich       AbbrevDecl->attributes().begin() + Index;
63bd1ebe9dSAlexander Yermolovich   uint32_t ValSize = 0;
64bd1ebe9dSAlexander Yermolovich   Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
65bd1ebe9dSAlexander Yermolovich   if (ValSizeOpt) {
66bd1ebe9dSAlexander Yermolovich     ValSize = static_cast<uint32_t>(*ValSizeOpt);
67bd1ebe9dSAlexander Yermolovich   } else {
68bd1ebe9dSAlexander Yermolovich     DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
69bd1ebe9dSAlexander Yermolovich     uint64_t NewOffset = Offset;
70bd1ebe9dSAlexander Yermolovich     DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
71bd1ebe9dSAlexander Yermolovich                               U.getFormParams());
72bd1ebe9dSAlexander Yermolovich     // This includes entire size of the entry, which might not be just the
73bd1ebe9dSAlexander Yermolovich     // encoding part. For example for DW_AT_loc it will include expression
74bd1ebe9dSAlexander Yermolovich     // location.
75bd1ebe9dSAlexander Yermolovich     ValSize = NewOffset - Offset;
76bd1ebe9dSAlexander Yermolovich   }
77bd1ebe9dSAlexander Yermolovich 
78bd1ebe9dSAlexander Yermolovich   return AttrInfo{*Value, Offset, ValSize};
79bd1ebe9dSAlexander Yermolovich }
80bd1ebe9dSAlexander Yermolovich 
81a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
82a34c753fSRafael Auler 
83a34c753fSRafael Auler namespace {
84a34c753fSRafael Auler 
851c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED
861c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) {
871c2f4bbeSAlexander Yermolovich   for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
881c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr(S[I]);
891c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr((int8_t)S[I]);
901c2f4bbeSAlexander Yermolovich   }
911c2f4bbeSAlexander Yermolovich   errs() << "\n";
921c2f4bbeSAlexander Yermolovich }
931c2f4bbeSAlexander Yermolovich 
94a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size).
95a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of
96a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address).
97a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes.
98a34c753fSRafael Auler // Returns the number of written bytes.
9940c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream,
100a34c753fSRafael Auler                             const DebugAddressRangesVector &AddressRanges,
101a34c753fSRafael Auler                             const bool WriteRelativeRanges = false) {
102a34c753fSRafael Auler   for (const DebugAddressRange &Range : AddressRanges) {
103a34c753fSRafael Auler     support::endian::write(Stream, Range.LowPC, support::little);
104a34c753fSRafael Auler     support::endian::write(
105a34c753fSRafael Auler         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
106a34c753fSRafael Auler         support::little);
107a34c753fSRafael Auler   }
108a34c753fSRafael Auler   // Finish with 0 entries.
109a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
110a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
111a34c753fSRafael Auler   return AddressRanges.size() * 16 + 16;
112a34c753fSRafael Auler }
113a34c753fSRafael Auler 
114a34c753fSRafael Auler } // namespace
115a34c753fSRafael Auler 
116a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() {
117a34c753fSRafael Auler   RangesBuffer = std::make_unique<DebugBufferVector>();
118a34c753fSRafael Auler   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
119a34c753fSRafael Auler 
120a34c753fSRafael Auler   // Add an empty range as the first entry;
121a34c753fSRafael Auler   SectionOffset +=
122a34c753fSRafael Auler       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
123*014cd37fSAlexander Yermolovich   Kind = RangesWriterKind::DebugRangesWriter;
124a34c753fSRafael Auler }
125a34c753fSRafael Auler 
126a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges(
127a34c753fSRafael Auler     DebugAddressRangesVector &&Ranges,
128a34c753fSRafael Auler     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
129a34c753fSRafael Auler   if (Ranges.empty())
130a34c753fSRafael Auler     return getEmptyRangesOffset();
131a34c753fSRafael Auler 
132a34c753fSRafael Auler   const auto RI = CachedRanges.find(Ranges);
133a34c753fSRafael Auler   if (RI != CachedRanges.end())
134a34c753fSRafael Auler     return RI->second;
135a34c753fSRafael Auler 
136a34c753fSRafael Auler   const uint64_t EntryOffset = addRanges(Ranges);
137a34c753fSRafael Auler   CachedRanges.emplace(std::move(Ranges), EntryOffset);
138a34c753fSRafael Auler 
139a34c753fSRafael Auler   return EntryOffset;
140a34c753fSRafael Auler }
141a34c753fSRafael Auler 
142a34c753fSRafael Auler uint64_t
143a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) {
144a34c753fSRafael Auler   if (Ranges.empty())
145a34c753fSRafael Auler     return getEmptyRangesOffset();
146a34c753fSRafael Auler 
147a34c753fSRafael Auler   // Reading the SectionOffset and updating it should be atomic to guarantee
148a34c753fSRafael Auler   // unique and correct offsets in patches.
149a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
150a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
151a34c753fSRafael Auler   SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);
152a34c753fSRafael Auler 
153a34c753fSRafael Auler   return EntryOffset;
154a34c753fSRafael Auler }
155a34c753fSRafael Auler 
156a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() {
157a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
158a34c753fSRafael Auler   return SectionOffset;
159a34c753fSRafael Auler }
160a34c753fSRafael Auler 
161*014cd37fSAlexander Yermolovich DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr;
162*014cd37fSAlexander Yermolovich 
163*014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges(
164*014cd37fSAlexander Yermolovich     DebugAddressRangesVector &&Ranges,
165*014cd37fSAlexander Yermolovich     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
166*014cd37fSAlexander Yermolovich   return addRanges(Ranges);
167*014cd37fSAlexander Yermolovich }
168*014cd37fSAlexander Yermolovich 
169*014cd37fSAlexander Yermolovich struct LocListsRangelistsHeader {
170*014cd37fSAlexander Yermolovich   UnitLengthType UnitLength; // Size of loclist entris section, not including
171*014cd37fSAlexander Yermolovich                              // size of header.
172*014cd37fSAlexander Yermolovich   VersionType Version;
173*014cd37fSAlexander Yermolovich   AddressSizeType AddressSize;
174*014cd37fSAlexander Yermolovich   SegmentSelectorType SegmentSelector;
175*014cd37fSAlexander Yermolovich   OffsetEntryCountType OffsetEntryCount;
176*014cd37fSAlexander Yermolovich };
177*014cd37fSAlexander Yermolovich 
178*014cd37fSAlexander Yermolovich static std::unique_ptr<DebugBufferVector>
179*014cd37fSAlexander Yermolovich getDWARF5Header(const LocListsRangelistsHeader &Header) {
180*014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> HeaderBuffer =
181*014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
182*014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> HeaderStream =
183*014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*HeaderBuffer);
184*014cd37fSAlexander Yermolovich 
185*014cd37fSAlexander Yermolovich   // 7.29 length of the set of entries for this compilation unit, not including
186*014cd37fSAlexander Yermolovich   // the length field itself
187*014cd37fSAlexander Yermolovich   const uint32_t HeaderSize =
188*014cd37fSAlexander Yermolovich       getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);
189*014cd37fSAlexander Yermolovich 
190*014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,
191*014cd37fSAlexander Yermolovich                          support::little);
192*014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.Version, support::little);
193*014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.AddressSize, support::little);
194*014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.SegmentSelector,
195*014cd37fSAlexander Yermolovich                          support::little);
196*014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.OffsetEntryCount,
197*014cd37fSAlexander Yermolovich                          support::little);
198*014cd37fSAlexander Yermolovich   return HeaderBuffer;
199*014cd37fSAlexander Yermolovich }
200*014cd37fSAlexander Yermolovich 
201*014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges(
202*014cd37fSAlexander Yermolovich     const DebugAddressRangesVector &Ranges) {
203*014cd37fSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
204*014cd37fSAlexander Yermolovich 
205*014cd37fSAlexander Yermolovich   RangeEntries.push_back(CurrentOffset);
206*014cd37fSAlexander Yermolovich   for (const DebugAddressRange &Range : Ranges) {
207*014cd37fSAlexander Yermolovich     support::endian::write(*CUBodyStream,
208*014cd37fSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_RLE_startx_length),
209*014cd37fSAlexander Yermolovich                            support::little);
210*014cd37fSAlexander Yermolovich     const uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, CUID);
211*014cd37fSAlexander Yermolovich     encodeULEB128(Index, *CUBodyStream);
212*014cd37fSAlexander Yermolovich     encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
213*014cd37fSAlexander Yermolovich   }
214*014cd37fSAlexander Yermolovich   support::endian::write(*CUBodyStream,
215*014cd37fSAlexander Yermolovich                          static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
216*014cd37fSAlexander Yermolovich                          support::little);
217*014cd37fSAlexander Yermolovich   CurrentOffset = CUBodyBuffer->size();
218*014cd37fSAlexander Yermolovich   return RangeEntries.size() - 1;
219*014cd37fSAlexander Yermolovich }
220*014cd37fSAlexander Yermolovich 
221*014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::finalizeSection() {
222*014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> CUArrayBuffer =
223*014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
224*014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> CUArrayStream =
225*014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*CUArrayBuffer);
226*014cd37fSAlexander Yermolovich   constexpr uint32_t SizeOfArrayEntry = 4;
227*014cd37fSAlexander Yermolovich   const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;
228*014cd37fSAlexander Yermolovich   for (uint32_t Offset : RangeEntries)
229*014cd37fSAlexander Yermolovich     support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,
230*014cd37fSAlexander Yermolovich                            support::little);
231*014cd37fSAlexander Yermolovich 
232*014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
233*014cd37fSAlexander Yermolovich       {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()),
234*014cd37fSAlexander Yermolovich        5, 8, 0, static_cast<uint32_t>(RangeEntries.size())});
235*014cd37fSAlexander Yermolovich   *RangesStream << *Header;
236*014cd37fSAlexander Yermolovich   *RangesStream << *CUArrayBuffer;
237*014cd37fSAlexander Yermolovich   *RangesStream << *CUBodyBuffer;
238*014cd37fSAlexander Yermolovich   SectionOffset = RangesBuffer->size();
239*014cd37fSAlexander Yermolovich }
240*014cd37fSAlexander Yermolovich 
241*014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::initSection(uint64_t CUId_) {
242*014cd37fSAlexander Yermolovich   CUBodyBuffer = std::make_unique<DebugBufferVector>();
243*014cd37fSAlexander Yermolovich   CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);
244*014cd37fSAlexander Yermolovich   RangeEntries.clear();
245*014cd37fSAlexander Yermolovich   CurrentOffset = 0;
246*014cd37fSAlexander Yermolovich   CUID = CUId_;
247*014cd37fSAlexander Yermolovich }
248*014cd37fSAlexander Yermolovich 
249a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
250a34c753fSRafael Auler                                             DebugAddressRangesVector &&Ranges) {
251a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
252a34c753fSRafael Auler   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
253a34c753fSRafael Auler }
254a34c753fSRafael Auler 
255a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection(
256612f0f45SAlexander Yermolovich     raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
257a34c753fSRafael Auler   // For reference on the format of the .debug_aranges section, see the DWARF4
258a34c753fSRafael Auler   // specification, section 6.1.4 Lookup by Address
259a34c753fSRafael Auler   // http://www.dwarfstd.org/doc/DWARF4.pdf
260a34c753fSRafael Auler   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
261a34c753fSRafael Auler     const uint64_t Offset = CUOffsetAddressRangesPair.first;
262a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges =
263a34c753fSRafael Auler         CUOffsetAddressRangesPair.second;
264a34c753fSRafael Auler 
265a34c753fSRafael Auler     // Emit header.
266a34c753fSRafael Auler 
267a34c753fSRafael Auler     // Size of this set: 8 (size of the header) + 4 (padding after header)
268a34c753fSRafael Auler     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
269a34c753fSRafael Auler     // pair of uint64_t's for the terminating, zero-length range.
270a34c753fSRafael Auler     // Does not include size field itself.
271a34c753fSRafael Auler     uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);
272a34c753fSRafael Auler 
273a34c753fSRafael Auler     // Header field #1: set size.
274a34c753fSRafael Auler     support::endian::write(RangesStream, Size, support::little);
275a34c753fSRafael Auler 
276a34c753fSRafael Auler     // Header field #2: version number, 2 as per the specification.
277a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint16_t>(2),
278a34c753fSRafael Auler                            support::little);
279a34c753fSRafael Auler 
2801c2f4bbeSAlexander Yermolovich     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
281a34c753fSRafael Auler     // Header field #3: debug info offset of the correspondent compile unit.
282612f0f45SAlexander Yermolovich     support::endian::write(
283612f0f45SAlexander Yermolovich         RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
284a34c753fSRafael Auler         support::little);
285a34c753fSRafael Auler 
286a34c753fSRafael Auler     // Header field #4: address size.
287a34c753fSRafael Auler     // 8 since we only write ELF64 binaries for now.
288a34c753fSRafael Auler     RangesStream << char(8);
289a34c753fSRafael Auler 
290a34c753fSRafael Auler     // Header field #5: segment size of target architecture.
291a34c753fSRafael Auler     RangesStream << char(0);
292a34c753fSRafael Auler 
293a34c753fSRafael Auler     // Padding before address table - 4 bytes in the 64-bit-pointer case.
294a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(0),
295a34c753fSRafael Auler                            support::little);
296a34c753fSRafael Auler 
297a34c753fSRafael Auler     writeAddressRanges(RangesStream, AddressRanges, true);
298a34c753fSRafael Auler   }
299a34c753fSRafael Auler }
300a34c753fSRafael Auler 
301a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }
302a34c753fSRafael Auler 
303a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() {
304a34c753fSRafael Auler   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
305a34c753fSRafael Auler                                           indexToAdddessEnd());
306a34c753fSRafael Auler   // Sorting address in increasing order of indices.
307a34c753fSRafael Auler   std::sort(SortedMap.begin(), SortedMap.end(),
308a34c753fSRafael Auler             [](const IndexAddressPair &A, const IndexAddressPair &B) {
309a34c753fSRafael Auler               return A.first < B.first;
310a34c753fSRafael Auler             });
311a34c753fSRafael Auler   for (auto &Pair : SortedMap)
312a34c753fSRafael Auler     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
313a34c753fSRafael Auler }
314*014cd37fSAlexander Yermolovich uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, uint64_t CUID) {
315e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
316*014cd37fSAlexander Yermolovich   if (!AddressMaps.count(CUID))
317*014cd37fSAlexander Yermolovich     AddressMaps[CUID] = AddressForDWOCU();
318a34c753fSRafael Auler 
319*014cd37fSAlexander Yermolovich   AddressForDWOCU &Map = AddressMaps[CUID];
320a34c753fSRafael Auler   auto Entry = Map.find(Address);
321a34c753fSRafael Auler   if (Entry == Map.end()) {
322a34c753fSRafael Auler     auto Index = Map.getNextIndex();
323a34c753fSRafael Auler     Entry = Map.insert(Address, Index).first;
324a34c753fSRafael Auler   }
325a34c753fSRafael Auler   return Entry->second;
326a34c753fSRafael Auler }
327a34c753fSRafael Auler 
328a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
329a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update
330a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
331a34c753fSRafael Auler // update AddressToIndex and IndexToAddress
332a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
333*014cd37fSAlexander Yermolovich                                       uint64_t CUID) {
334e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
335*014cd37fSAlexander Yermolovich   AddressForDWOCU &Map = AddressMaps[CUID];
336a34c753fSRafael Auler   auto Entry = Map.find(Address);
337a34c753fSRafael Auler   if (Entry != Map.end()) {
338a34c753fSRafael Auler     if (Entry->second > Index)
339a34c753fSRafael Auler       Map.updateAddressToIndex(Address, Index);
340a34c753fSRafael Auler     Map.updateIndexToAddrss(Address, Index);
3413652483cSRafael Auler   } else {
342a34c753fSRafael Auler     Map.insert(Address, Index);
343a34c753fSRafael Auler   }
3443652483cSRafael Auler }
345a34c753fSRafael Auler 
346a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() {
347a34c753fSRafael Auler   // Need to layout all sections within .debug_addr
348a34c753fSRafael Auler   // Within each section sort Address by index.
349a34c753fSRafael Auler   AddressSectionBuffer Buffer;
350a34c753fSRafael Auler   raw_svector_ostream AddressStream(Buffer);
351a34c753fSRafael Auler   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
352a34c753fSRafael Auler     Optional<uint64_t> DWOId = CU->getDWOId();
353a34c753fSRafael Auler     // Handling the case wehre debug information is a mix of Debug fission and
354a34c753fSRafael Auler     // monolitic.
355a34c753fSRafael Auler     if (!DWOId)
356a34c753fSRafael Auler       continue;
357a34c753fSRafael Auler     auto AM = AddressMaps.find(*DWOId);
358*014cd37fSAlexander Yermolovich     assert(AM != AddressMaps.end() && "Address Map not found.");
359a34c753fSRafael Auler     // Adding to map even if it did not contribute to .debug_addr.
360a34c753fSRafael Auler     // The Skeleton CU will still have DW_AT_GNU_addr_base.
361a34c753fSRafael Auler     DWOIdToOffsetMap[*DWOId] = Buffer.size();
362a34c753fSRafael Auler     // If does not exist this CUs DWO section didn't contribute to .debug_addr.
363a34c753fSRafael Auler     if (AM == AddressMaps.end())
364a34c753fSRafael Auler       continue;
365a34c753fSRafael Auler     std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
366a34c753fSRafael Auler                                             AM->second.indexToAdddessEnd());
367a34c753fSRafael Auler     // Sorting address in increasing order of indices.
368a34c753fSRafael Auler     std::sort(SortedMap.begin(), SortedMap.end(),
369a34c753fSRafael Auler               [](const IndexAddressPair &A, const IndexAddressPair &B) {
370a34c753fSRafael Auler                 return A.first < B.first;
371a34c753fSRafael Auler               });
372a34c753fSRafael Auler 
373a34c753fSRafael Auler     uint8_t AddrSize = CU->getAddressByteSize();
374a34c753fSRafael Auler     uint32_t Counter = 0;
375a34c753fSRafael Auler     auto WriteAddress = [&](uint64_t Address) -> void {
376a34c753fSRafael Auler       ++Counter;
377a34c753fSRafael Auler       switch (AddrSize) {
378a34c753fSRafael Auler       default:
379a34c753fSRafael Auler         assert(false && "Address Size is invalid.");
380a34c753fSRafael Auler         break;
381a34c753fSRafael Auler       case 4:
382a34c753fSRafael Auler         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
383a34c753fSRafael Auler                                support::little);
384a34c753fSRafael Auler         break;
385a34c753fSRafael Auler       case 8:
386a34c753fSRafael Auler         support::endian::write(AddressStream, Address, support::little);
387a34c753fSRafael Auler         break;
388a34c753fSRafael Auler       }
389a34c753fSRafael Auler     };
390a34c753fSRafael Auler 
391a34c753fSRafael Auler     for (const IndexAddressPair &Val : SortedMap) {
392a34c753fSRafael Auler       while (Val.first > Counter)
393a34c753fSRafael Auler         WriteAddress(0);
394a34c753fSRafael Auler       WriteAddress(Val.second);
395a34c753fSRafael Auler     }
396a34c753fSRafael Auler   }
397a34c753fSRafael Auler 
398a34c753fSRafael Auler   return Buffer;
399a34c753fSRafael Auler }
400*014cd37fSAlexander Yermolovich AddressSectionBuffer DebugAddrWriterDwarf5::finalize() {
401*014cd37fSAlexander Yermolovich   // Need to layout all sections within .debug_addr
402*014cd37fSAlexander Yermolovich   // Within each section sort Address by index.
403*014cd37fSAlexander Yermolovich   AddressSectionBuffer Buffer;
404*014cd37fSAlexander Yermolovich   raw_svector_ostream AddressStream(Buffer);
405*014cd37fSAlexander Yermolovich   const endianness Endian =
406*014cd37fSAlexander Yermolovich       BC->DwCtx->isLittleEndian() ? support::little : support::big;
407*014cd37fSAlexander Yermolovich   const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();
408*014cd37fSAlexander Yermolovich   DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0);
409*014cd37fSAlexander Yermolovich   DWARFDebugAddrTable AddrTable;
410*014cd37fSAlexander Yermolovich   DIDumpOptions DumpOpts;
411*014cd37fSAlexander Yermolovich   constexpr uint32_t HeaderSize = 8;
412*014cd37fSAlexander Yermolovich   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
413*014cd37fSAlexander Yermolovich     const uint64_t CUID = CU->getOffset();
414*014cd37fSAlexander Yermolovich     const uint8_t AddrSize = CU->getAddressByteSize();
415*014cd37fSAlexander Yermolovich     auto Iter = AddressMaps.find(CUID);
416*014cd37fSAlexander Yermolovich     // A case where CU has entry in .debug_addr, but we don't modify addresses
417*014cd37fSAlexander Yermolovich     // for it.
418*014cd37fSAlexander Yermolovich     if (Iter == AddressMaps.end()) {
419*014cd37fSAlexander Yermolovich       Iter = AddressMaps.insert({CUID, AddressForDWOCU()}).first;
420*014cd37fSAlexander Yermolovich       Optional<uint64_t> BaseOffset = CU->getAddrOffsetSectionBase();
421*014cd37fSAlexander Yermolovich       if (!BaseOffset)
422*014cd37fSAlexander Yermolovich         continue;
423*014cd37fSAlexander Yermolovich       // Address base offset is to the first entry.
424*014cd37fSAlexander Yermolovich       // The size of header is 8 bytes.
425*014cd37fSAlexander Yermolovich       uint64_t Offset = *BaseOffset - HeaderSize;
426*014cd37fSAlexander Yermolovich       if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize,
427*014cd37fSAlexander Yermolovich                                         DumpOpts.WarningHandler)) {
428*014cd37fSAlexander Yermolovich         DumpOpts.RecoverableErrorHandler(std::move(Err));
429*014cd37fSAlexander Yermolovich         continue;
430*014cd37fSAlexander Yermolovich       }
431*014cd37fSAlexander Yermolovich       uint32_t Index = 0;
432*014cd37fSAlexander Yermolovich       for (uint64_t Addr : AddrTable.getAddressEntries())
433*014cd37fSAlexander Yermolovich         Iter->second.insert(Addr, Index++);
434*014cd37fSAlexander Yermolovich     }
435a34c753fSRafael Auler 
436*014cd37fSAlexander Yermolovich     DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize;
437*014cd37fSAlexander Yermolovich 
438*014cd37fSAlexander Yermolovich     std::vector<IndexAddressPair> SortedMap(Iter->second.indexToAddressBegin(),
439*014cd37fSAlexander Yermolovich                                             Iter->second.indexToAdddessEnd());
440*014cd37fSAlexander Yermolovich     // Sorting address in increasing order of indices.
441*014cd37fSAlexander Yermolovich     std::sort(SortedMap.begin(), SortedMap.end(),
442*014cd37fSAlexander Yermolovich               [](const IndexAddressPair &A, const IndexAddressPair &B) {
443*014cd37fSAlexander Yermolovich                 return A.first < B.first;
444*014cd37fSAlexander Yermolovich               });
445*014cd37fSAlexander Yermolovich     // Writing out Header
446*014cd37fSAlexander Yermolovich     const uint32_t Length = SortedMap.size() * AddrSize + 4;
447*014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, Length, Endian);
448*014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian);
449*014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize),
450*014cd37fSAlexander Yermolovich                            Endian);
451*014cd37fSAlexander Yermolovich     support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian);
452*014cd37fSAlexander Yermolovich 
453*014cd37fSAlexander Yermolovich     uint32_t Counter = 0;
454*014cd37fSAlexander Yermolovich     auto writeAddress = [&](uint64_t Address) -> void {
455*014cd37fSAlexander Yermolovich       ++Counter;
456*014cd37fSAlexander Yermolovich       switch (AddrSize) {
457*014cd37fSAlexander Yermolovich       default:
458*014cd37fSAlexander Yermolovich         llvm_unreachable("Address Size is invalid.");
459*014cd37fSAlexander Yermolovich         break;
460*014cd37fSAlexander Yermolovich       case 4:
461*014cd37fSAlexander Yermolovich         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
462*014cd37fSAlexander Yermolovich                                Endian);
463*014cd37fSAlexander Yermolovich         break;
464*014cd37fSAlexander Yermolovich       case 8:
465*014cd37fSAlexander Yermolovich         support::endian::write(AddressStream, Address, Endian);
466*014cd37fSAlexander Yermolovich         break;
467*014cd37fSAlexander Yermolovich       }
468*014cd37fSAlexander Yermolovich     };
469*014cd37fSAlexander Yermolovich 
470*014cd37fSAlexander Yermolovich     for (const IndexAddressPair &Val : SortedMap) {
471*014cd37fSAlexander Yermolovich       while (Val.first > Counter)
472*014cd37fSAlexander Yermolovich         writeAddress(0);
473*014cd37fSAlexander Yermolovich       writeAddress(Val.second);
474*014cd37fSAlexander Yermolovich     }
475*014cd37fSAlexander Yermolovich   }
476*014cd37fSAlexander Yermolovich 
477*014cd37fSAlexander Yermolovich   return Buffer;
478*014cd37fSAlexander Yermolovich }
479*014cd37fSAlexander Yermolovich 
480*014cd37fSAlexander Yermolovich uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) {
481*014cd37fSAlexander Yermolovich   Optional<uint64_t> DWOId = Unit.getDWOId();
482*014cd37fSAlexander Yermolovich   assert(DWOId && "Can't get offset, not a skeleton CU.");
483*014cd37fSAlexander Yermolovich   auto Iter = DWOIdToOffsetMap.find(*DWOId);
484*014cd37fSAlexander Yermolovich   assert(Iter != DWOIdToOffsetMap.end() &&
485*014cd37fSAlexander Yermolovich          "Offset in to.debug_addr was not found for DWO ID.");
486*014cd37fSAlexander Yermolovich   return Iter->second;
487*014cd37fSAlexander Yermolovich }
488*014cd37fSAlexander Yermolovich 
489*014cd37fSAlexander Yermolovich uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) {
490*014cd37fSAlexander Yermolovich   auto Iter = DWOIdToOffsetMap.find(Unit.getOffset());
491a34c753fSRafael Auler   assert(Iter != DWOIdToOffsetMap.end() &&
492a34c753fSRafael Auler          "Offset in to.debug_addr was not found for DWO ID.");
493a34c753fSRafael Auler   return Iter->second;
494a34c753fSRafael Auler }
495a34c753fSRafael Auler 
496a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
497a34c753fSRafael Auler   LocBuffer = std::make_unique<DebugBufferVector>();
498a34c753fSRafael Auler   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
499a34c753fSRafael Auler }
500a34c753fSRafael Auler 
501*014cd37fSAlexander Yermolovich void DebugLocWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex,
502a34c753fSRafael Auler                              DebugLocationsVector &&LocList) {
503a34c753fSRafael Auler   if (LocList.empty()) {
504a34c753fSRafael Auler     EmptyAttrLists.push_back(AttrOffset);
505a34c753fSRafael Auler     return;
506a34c753fSRafael Auler   }
507a34c753fSRafael Auler   // Since there is a separate DebugLocWriter for each thread,
508a34c753fSRafael Auler   // we don't need a lock to read the SectionOffset and update it.
509a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
510a34c753fSRafael Auler 
511a34c753fSRafael Auler   for (const DebugLocationEntry &Entry : LocList) {
512a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
513a34c753fSRafael Auler                            support::little);
514a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
515a34c753fSRafael Auler                            support::little);
516a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
517a34c753fSRafael Auler                            support::little);
518a34c753fSRafael Auler     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
519a34c753fSRafael Auler                             Entry.Expr.size());
520a34c753fSRafael Auler     SectionOffset += 2 * 8 + 2 + Entry.Expr.size();
521a34c753fSRafael Auler   }
522a34c753fSRafael Auler   LocStream->write_zeros(16);
523a34c753fSRafael Auler   SectionOffset += 16;
524a34c753fSRafael Auler   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
525a34c753fSRafael Auler }
526a34c753fSRafael Auler 
527*014cd37fSAlexander Yermolovich void DebugLoclistWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex,
528a34c753fSRafael Auler                                  DebugLocationsVector &&LocList) {
529*014cd37fSAlexander Yermolovich   Patches.push_back({AttrOffset, LocListIndex, std::move(LocList)});
530a34c753fSRafael Auler }
531a34c753fSRafael Auler 
532a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
533a34c753fSRafael Auler   return std::move(LocBuffer);
534a34c753fSRafael Auler }
535a34c753fSRafael Auler 
536a34c753fSRafael Auler // DWARF 4: 2.6.2
537a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset,
538a34c753fSRafael Auler                               SimpleBinaryPatcher &DebugInfoPatcher) {
539a34c753fSRafael Auler   for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) {
540a34c753fSRafael Auler     uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset;
541a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset,
542a34c753fSRafael Auler                                   Offset);
543a34c753fSRafael Auler   }
544a34c753fSRafael Auler 
545a34c753fSRafael Auler   for (uint64_t DebugInfoAttrOffset : EmptyAttrLists)
546a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset,
547a34c753fSRafael Auler                                   DebugLocWriter::EmptyListOffset);
548a34c753fSRafael Auler }
549a34c753fSRafael Auler 
550*014cd37fSAlexander Yermolovich static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
551*014cd37fSAlexander Yermolovich   support::endian::write(Stream, static_cast<uint32_t>(4), support::little);
552*014cd37fSAlexander Yermolovich   support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),
553*014cd37fSAlexander Yermolovich                          support::little);
554*014cd37fSAlexander Yermolovich 
555*014cd37fSAlexander Yermolovich   const char Zeroes[16] = {0};
556*014cd37fSAlexander Yermolovich   Stream << StringRef(Zeroes, 16);
557*014cd37fSAlexander Yermolovich   encodeULEB128(0, Stream);
558*014cd37fSAlexander Yermolovich   support::endian::write(
559*014cd37fSAlexander Yermolovich       Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little);
560*014cd37fSAlexander Yermolovich }
561*014cd37fSAlexander Yermolovich 
562*014cd37fSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARF5(uint64_t SectionOffset,
563a34c753fSRafael Auler                                         SimpleBinaryPatcher &DebugInfoPatcher) {
564*014cd37fSAlexander Yermolovich 
565*014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> LocArrayBuffer =
566*014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
567*014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> LocArrayStream =
568*014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*LocArrayBuffer);
569*014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> LocBodyBuffer =
570*014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
571*014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> LocBodyStream =
572*014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*LocBodyBuffer);
573*014cd37fSAlexander Yermolovich 
574*014cd37fSAlexander Yermolovich   const uint32_t SizeOfArraySection = Patches.size() * sizeof(uint32_t);
575*014cd37fSAlexander Yermolovich   std::sort(Patches.begin(), Patches.end(),
576*014cd37fSAlexander Yermolovich             [](const LocPatch &P1, const LocPatch &P2) -> bool {
577*014cd37fSAlexander Yermolovich               return P1.Index < P2.Index;
578*014cd37fSAlexander Yermolovich             });
579*014cd37fSAlexander Yermolovich 
580*014cd37fSAlexander Yermolovich   if (LocListsBaseAttrOffset != InvalidLocListsBaseAttrOffset)
581*014cd37fSAlexander Yermolovich     DebugInfoPatcher.addLE32Patch(LocListsBaseAttrOffset,
582*014cd37fSAlexander Yermolovich                                   SectionOffset +
583*014cd37fSAlexander Yermolovich                                       getDWARF5RngListLocListHeaderSize());
584*014cd37fSAlexander Yermolovich 
585*014cd37fSAlexander Yermolovich   uint32_t Index{0};
586*014cd37fSAlexander Yermolovich   for (LocPatch &Patch : Patches) {
587*014cd37fSAlexander Yermolovich     const uint32_t EntryOffset = LocBodyBuffer->size();
588*014cd37fSAlexander Yermolovich     if (Patch.LocList.empty()) {
589*014cd37fSAlexander Yermolovich       if (Patch.Index == DebugLoclistWriter::InvalidIndex)
590*014cd37fSAlexander Yermolovich         DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
591*014cd37fSAlexander Yermolovich 
592*014cd37fSAlexander Yermolovich       writeEmptyListDwarf5(*LocBodyStream);
593*014cd37fSAlexander Yermolovich       continue;
594*014cd37fSAlexander Yermolovich     }
595*014cd37fSAlexander Yermolovich 
596*014cd37fSAlexander Yermolovich     assert(Patch.Index == DebugLoclistWriter::InvalidIndex ||
597*014cd37fSAlexander Yermolovich            Patch.Index == Index++ && "Gap in LocList Index Array.");
598*014cd37fSAlexander Yermolovich 
599*014cd37fSAlexander Yermolovich     std::vector<uint64_t> OffsetsArray;
600*014cd37fSAlexander Yermolovich     for (const DebugLocationEntry &Entry : Patch.LocList) {
601*014cd37fSAlexander Yermolovich       support::endian::write(*LocBodyStream,
602*014cd37fSAlexander Yermolovich                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
603*014cd37fSAlexander Yermolovich                              support::little);
604*014cd37fSAlexander Yermolovich       const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUID);
605*014cd37fSAlexander Yermolovich       encodeULEB128(Index, *LocBodyStream);
606*014cd37fSAlexander Yermolovich       encodeULEB128(Entry.HighPC - Entry.LowPC, *LocBodyStream);
607*014cd37fSAlexander Yermolovich       encodeULEB128(Entry.Expr.size(), *LocBodyStream);
608*014cd37fSAlexander Yermolovich       *LocBodyStream << StringRef(
609*014cd37fSAlexander Yermolovich           reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
610*014cd37fSAlexander Yermolovich     }
611*014cd37fSAlexander Yermolovich     support::endian::write(*LocBodyStream,
612*014cd37fSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
613*014cd37fSAlexander Yermolovich                            support::little);
614*014cd37fSAlexander Yermolovich 
615*014cd37fSAlexander Yermolovich     // Write out IndexArray
616*014cd37fSAlexander Yermolovich     support::endian::write(
617*014cd37fSAlexander Yermolovich         *LocArrayStream,
618*014cd37fSAlexander Yermolovich         static_cast<uint32_t>(SizeOfArraySection + EntryOffset),
619*014cd37fSAlexander Yermolovich         support::little);
620*014cd37fSAlexander Yermolovich     // Don't need to patch Index since we are re-using them.
621*014cd37fSAlexander Yermolovich     if (Patch.Index == DebugLoclistWriter::InvalidIndex)
622*014cd37fSAlexander Yermolovich       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
623*014cd37fSAlexander Yermolovich     clearList(Patch.LocList);
624*014cd37fSAlexander Yermolovich   }
625*014cd37fSAlexander Yermolovich   if (!Patches.empty()) {
626*014cd37fSAlexander Yermolovich     std::unique_ptr<DebugBufferVector> Header =
627*014cd37fSAlexander Yermolovich         getDWARF5Header({static_cast<uint32_t>(SizeOfArraySection +
628*014cd37fSAlexander Yermolovich                                                LocBodyBuffer.get()->size()),
629*014cd37fSAlexander Yermolovich                          5, 8, 0, static_cast<uint32_t>(Patches.size())});
630*014cd37fSAlexander Yermolovich     *LocStream << *Header;
631*014cd37fSAlexander Yermolovich     *LocStream << *LocArrayBuffer;
632*014cd37fSAlexander Yermolovich     *LocStream << *LocBodyBuffer;
633*014cd37fSAlexander Yermolovich   }
634*014cd37fSAlexander Yermolovich   clearList(Patches);
635*014cd37fSAlexander Yermolovich }
636*014cd37fSAlexander Yermolovich 
637*014cd37fSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARFLegacy(
638*014cd37fSAlexander Yermolovich     uint64_t SectionOffset, SimpleBinaryPatcher &DebugInfoPatcher) {
639a34c753fSRafael Auler   for (LocPatch &Patch : Patches) {
640a34c753fSRafael Auler     if (Patch.LocList.empty()) {
641a34c753fSRafael Auler       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
642a34c753fSRafael Auler                                     DebugLocWriter::EmptyListOffset);
643a34c753fSRafael Auler       continue;
644a34c753fSRafael Auler     }
645a34c753fSRafael Auler     const uint32_t EntryOffset = LocBuffer->size();
646a34c753fSRafael Auler     for (const DebugLocationEntry &Entry : Patch.LocList) {
647a34c753fSRafael Auler       support::endian::write(*LocStream,
648a34c753fSRafael Auler                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
649a34c753fSRafael Auler                              support::little);
650*014cd37fSAlexander Yermolovich       const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUID);
651a34c753fSRafael Auler       encodeULEB128(Index, *LocStream);
652a34c753fSRafael Auler 
653a34c753fSRafael Auler       // TODO: Support DWARF5
654a34c753fSRafael Auler       support::endian::write(*LocStream,
655a34c753fSRafael Auler                              static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
656a34c753fSRafael Auler                              support::little);
657a34c753fSRafael Auler       support::endian::write(*LocStream,
658a34c753fSRafael Auler                              static_cast<uint16_t>(Entry.Expr.size()),
659a34c753fSRafael Auler                              support::little);
660a34c753fSRafael Auler       *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
661a34c753fSRafael Auler                               Entry.Expr.size());
662a34c753fSRafael Auler     }
663a34c753fSRafael Auler     support::endian::write(*LocStream,
664a34c753fSRafael Auler                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
665a34c753fSRafael Auler                            support::little);
666a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
667a34c753fSRafael Auler     clearList(Patch.LocList);
668a34c753fSRafael Auler   }
669a34c753fSRafael Auler   clearList(Patches);
670a34c753fSRafael Auler }
671a34c753fSRafael Auler 
672*014cd37fSAlexander Yermolovich void DebugLoclistWriter::finalize(uint64_t SectionOffset,
673*014cd37fSAlexander Yermolovich                                   SimpleBinaryPatcher &DebugInfoPatcher) {
674*014cd37fSAlexander Yermolovich   if (DwarfVersion < 5)
675*014cd37fSAlexander Yermolovich     finalizeDWARFLegacy(SectionOffset, DebugInfoPatcher);
676*014cd37fSAlexander Yermolovich   else
677*014cd37fSAlexander Yermolovich     finalizeDWARF5(SectionOffset, DebugInfoPatcher);
678*014cd37fSAlexander Yermolovich }
679*014cd37fSAlexander Yermolovich 
680a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
681a34c753fSRafael Auler 
6821c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) {
6831c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
6841c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
685ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset));
686a34c753fSRafael Auler }
687a34c753fSRafael Auler 
6881c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) {
6891c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
6901c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
6911c2f4bbeSAlexander Yermolovich   auto RetVal = DestinationLabels.insert(Offset);
6921c2f4bbeSAlexander Yermolovich   if (!RetVal.second)
6931c2f4bbeSAlexander Yermolovich     return;
6941c2f4bbeSAlexander Yermolovich 
695ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DestinationReferenceLabel(Offset));
696a34c753fSRafael Auler }
697a34c753fSRafael Auler 
698bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
699bd1ebe9dSAlexander Yermolovich   std::string LE64(ByteSize, 0);
700bd1ebe9dSAlexander Yermolovich   for (size_t I = 0; I < ByteSize; ++I) {
701bd1ebe9dSAlexander Yermolovich     LE64[I] = NewValue & 0xff;
702bd1ebe9dSAlexander Yermolovich     NewValue >>= 8;
703bd1ebe9dSAlexander Yermolovich   }
704bd1ebe9dSAlexander Yermolovich   return LE64;
705bd1ebe9dSAlexander Yermolovich }
706bd1ebe9dSAlexander Yermolovich 
707bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
708bd1ebe9dSAlexander Yermolovich                                             uint32_t Value) {
709bd1ebe9dSAlexander Yermolovich   std::string StrValue = encodeLE(4, Value);
710bd1ebe9dSAlexander Yermolovich   insertNewEntry(DIE, std::move(StrValue));
711bd1ebe9dSAlexander Yermolovich }
712bd1ebe9dSAlexander Yermolovich 
713bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
714bd1ebe9dSAlexander Yermolovich                                             std::string &&Value) {
715bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration *AbbrevDecl =
716bd1ebe9dSAlexander Yermolovich       DIE.getAbbreviationDeclarationPtr();
717bd1ebe9dSAlexander Yermolovich 
718bd1ebe9dSAlexander Yermolovich   // In case this DIE has no attributes.
719bd1ebe9dSAlexander Yermolovich   uint32_t Offset = DIE.getOffset() + 1;
720bd1ebe9dSAlexander Yermolovich   size_t NumOfAttributes = AbbrevDecl->getNumAttributes();
721bd1ebe9dSAlexander Yermolovich   if (NumOfAttributes) {
722bd1ebe9dSAlexander Yermolovich     Optional<AttrInfo> Val =
723bd1ebe9dSAlexander Yermolovich         findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1);
724bd1ebe9dSAlexander Yermolovich     assert(Val && "Invalid Value.");
725bd1ebe9dSAlexander Yermolovich 
726bd1ebe9dSAlexander Yermolovich     Offset = Val->Offset + Val->Size - DWPUnitOffset;
727bd1ebe9dSAlexander Yermolovich   }
728bd1ebe9dSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
729bd1ebe9dSAlexander Yermolovich   DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value)));
730bd1ebe9dSAlexander Yermolovich }
731bd1ebe9dSAlexander Yermolovich 
7321c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset,
7331c2f4bbeSAlexander Yermolovich                                                  uint32_t DestinationOffset,
7341c2f4bbeSAlexander Yermolovich                                                  uint32_t OldValueSize,
7351c2f4bbeSAlexander Yermolovich                                                  dwarf::Form Form) {
7361c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
7371c2f4bbeSAlexander Yermolovich   DestinationOffset -= DWPUnitOffset;
7381c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
739ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(
740ea6c8b01SAlexander Yermolovich       new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form));
7411c2f4bbeSAlexander Yermolovich }
7421c2f4bbeSAlexander Yermolovich 
7431c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue,
7441c2f4bbeSAlexander Yermolovich                                            uint32_t OldValueSize) {
7451c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
7461c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
7471c2f4bbeSAlexander Yermolovich   DebugPatches.emplace_back(
748ea6c8b01SAlexander Yermolovich       new DebugPatchVariableSize(Offset, OldValueSize, NewValue));
7491c2f4bbeSAlexander Yermolovich }
7501c2f4bbeSAlexander Yermolovich 
7511c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
7521c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
7531c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
754ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue));
7551c2f4bbeSAlexander Yermolovich }
7561c2f4bbeSAlexander Yermolovich 
7571c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
7581c2f4bbeSAlexander Yermolovich                                           uint32_t OldValueSize) {
7591c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
7601c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
7611c2f4bbeSAlexander Yermolovich   if (OldValueSize == 4)
762ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue));
763a44fe319SAlexander Yermolovich   else if (OldValueSize == 8)
764ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue));
765a44fe319SAlexander Yermolovich   else
766a44fe319SAlexander Yermolovich     DebugPatches.emplace_back(
767a44fe319SAlexander Yermolovich         new DebugPatch32GenericSize(Offset, NewValue, OldValueSize));
7681c2f4bbeSAlexander Yermolovich }
7691c2f4bbeSAlexander Yermolovich 
7701c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
7711c2f4bbeSAlexander Yermolovich                                          std::string &&NewValue,
7721c2f4bbeSAlexander Yermolovich                                          uint32_t OldValueSize) {
7731c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(NewValue));
7741c2f4bbeSAlexander Yermolovich }
7751c2f4bbeSAlexander Yermolovich 
7761c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
7771c2f4bbeSAlexander Yermolovich   auto Str = std::string(1, Value);
7781c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Str));
7791c2f4bbeSAlexander Yermolovich }
7801c2f4bbeSAlexander Yermolovich 
7811c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
7821c2f4bbeSAlexander Yermolovich                                      size_t ByteSize) {
7831c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
7841c2f4bbeSAlexander Yermolovich }
7851c2f4bbeSAlexander Yermolovich 
7861c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
7871c2f4bbeSAlexander Yermolovich                                         uint32_t OldValueSize) {
788a34c753fSRafael Auler   std::string Buff;
789a34c753fSRafael Auler   raw_string_ostream OS(Buff);
7901c2f4bbeSAlexander Yermolovich   encodeULEB128(Value, OS, OldValueSize);
791a34c753fSRafael Auler 
7921c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Buff));
793a34c753fSRafael Auler }
794a34c753fSRafael Auler 
7951c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
796a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
797a34c753fSRafael Auler }
798a34c753fSRafael Auler 
7991c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
8001c2f4bbeSAlexander Yermolovich                                        uint32_t OldValueSize) {
801a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
802a34c753fSRafael Auler }
803a34c753fSRafael Auler 
8041c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
8051c2f4bbeSAlexander Yermolovich   std::string BinaryContentsStr = std::string(BinaryContents);
806a34c753fSRafael Auler   for (const auto &Patch : Patches) {
8071c2f4bbeSAlexander Yermolovich     uint32_t Offset = Patch.first;
808a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
809a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
810a34c753fSRafael Auler            "Applied patch runs over binary size.");
811a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
8121c2f4bbeSAlexander Yermolovich       BinaryContentsStr[Offset + I] = ByteSequence[I];
813a34c753fSRafael Auler     }
814a34c753fSRafael Auler   }
8151c2f4bbeSAlexander Yermolovich   return BinaryContentsStr;
8161c2f4bbeSAlexander Yermolovich }
8171c2f4bbeSAlexander Yermolovich 
818612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
819612f0f45SAlexander Yermolovich                                                       bool IsDWOContext) {
820612f0f45SAlexander Yermolovich   CUOffsetMap CUMap;
821ea6c8b01SAlexander Yermolovich   std::sort(DebugPatches.begin(), DebugPatches.end(),
822ea6c8b01SAlexander Yermolovich             [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
823bd1ebe9dSAlexander Yermolovich               if (V1.get()->Offset == V2.get()->Offset) {
824bd1ebe9dSAlexander Yermolovich                 if (V1->Kind == DebugPatchKind::NewDebugEntry &&
825bd1ebe9dSAlexander Yermolovich                     V2->Kind == DebugPatchKind::NewDebugEntry)
826bd1ebe9dSAlexander Yermolovich                   return reinterpret_cast<const NewDebugEntry *>(V1.get())
827bd1ebe9dSAlexander Yermolovich                              ->CurrentOrder <
828bd1ebe9dSAlexander Yermolovich                          reinterpret_cast<const NewDebugEntry *>(V2.get())
829bd1ebe9dSAlexander Yermolovich                              ->CurrentOrder;
830bd1ebe9dSAlexander Yermolovich 
831bd1ebe9dSAlexander Yermolovich                 // This is a case where we are modifying first entry of next
832bd1ebe9dSAlexander Yermolovich                 // DIE, and adding a new one.
833bd1ebe9dSAlexander Yermolovich                 return V1->Kind == DebugPatchKind::NewDebugEntry;
834bd1ebe9dSAlexander Yermolovich               }
8351c2f4bbeSAlexander Yermolovich               return V1.get()->Offset < V2.get()->Offset;
8361c2f4bbeSAlexander Yermolovich             });
8371c2f4bbeSAlexander Yermolovich 
838612f0f45SAlexander Yermolovich   DWARFUnitVector::compile_unit_range CompileUnits =
839612f0f45SAlexander Yermolovich       IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();
840612f0f45SAlexander Yermolovich 
841612f0f45SAlexander Yermolovich   for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
842612f0f45SAlexander Yermolovich     CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
843612f0f45SAlexander Yermolovich                               static_cast<uint32_t>(CU->getLength())};
844612f0f45SAlexander Yermolovich 
8451c2f4bbeSAlexander Yermolovich   // Calculating changes in .debug_info size from Patches to build a map of old
8461c2f4bbeSAlexander Yermolovich   // to updated reference destination offsets.
847612f0f45SAlexander Yermolovich   uint32_t PreviousOffset = 0;
848612f0f45SAlexander Yermolovich   int32_t PreviousChangeInSize = 0;
849ea6c8b01SAlexander Yermolovich   for (UniquePatchPtrType &PatchBase : DebugPatches) {
8501c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
8511c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
8521c2f4bbeSAlexander Yermolovich     default:
8531c2f4bbeSAlexander Yermolovich       continue;
8541c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
855612f0f45SAlexander Yermolovich       PreviousChangeInSize -= 4;
8561c2f4bbeSAlexander Yermolovich       break;
8571c2f4bbeSAlexander Yermolovich     }
858a44fe319SAlexander Yermolovich     case DebugPatchKind::PatchValue32GenericSize: {
859a44fe319SAlexander Yermolovich       DebugPatch32GenericSize *DPVS =
860a44fe319SAlexander Yermolovich           reinterpret_cast<DebugPatch32GenericSize *>(P);
861a44fe319SAlexander Yermolovich       PreviousChangeInSize += 4 - DPVS->OldValueSize;
862a44fe319SAlexander Yermolovich       break;
863a44fe319SAlexander Yermolovich     }
8641c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
8651c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *DPV =
8661c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
8671c2f4bbeSAlexander Yermolovich       std::string Temp;
8681c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(Temp);
8691c2f4bbeSAlexander Yermolovich       encodeULEB128(DPV->Value, OS);
870612f0f45SAlexander Yermolovich       PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
8711c2f4bbeSAlexander Yermolovich       break;
8721c2f4bbeSAlexander Yermolovich     }
8731c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DestinationReferenceLabel: {
8741c2f4bbeSAlexander Yermolovich       DestinationReferenceLabel *DRL =
8751c2f4bbeSAlexander Yermolovich           reinterpret_cast<DestinationReferenceLabel *>(P);
876612f0f45SAlexander Yermolovich       OldToNewOffset[DRL->Offset] =
877612f0f45SAlexander Yermolovich           DRL->Offset + ChangeInSize + PreviousChangeInSize;
8781c2f4bbeSAlexander Yermolovich       break;
8791c2f4bbeSAlexander Yermolovich     }
8801c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
8811c2f4bbeSAlexander Yermolovich       // This doesn't look to be a common case, so will always encode as 4 bytes
8821c2f4bbeSAlexander Yermolovich       // to reduce algorithmic complexity.
8831c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
8841c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.IndirectRelative) {
885612f0f45SAlexander Yermolovich         PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
8861c2f4bbeSAlexander Yermolovich         assert(RDP->PatchInfo.OldValueSize <= 4 &&
8871c2f4bbeSAlexander Yermolovich                "Variable encoding reference greater than 4 bytes.");
8881c2f4bbeSAlexander Yermolovich       }
8891c2f4bbeSAlexander Yermolovich       break;
8901c2f4bbeSAlexander Yermolovich     }
8911c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
8921c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
8931c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
8941c2f4bbeSAlexander Yermolovich       uint32_t CUOffset = BaseLabel->Offset;
895612f0f45SAlexander Yermolovich       ChangeInSize += PreviousChangeInSize;
8961c2f4bbeSAlexander Yermolovich       uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
897612f0f45SAlexander Yermolovich       CUMap[CUOffset].Offset = CUOffsetUpdate;
898612f0f45SAlexander Yermolovich       CUMap[PreviousOffset].Length += PreviousChangeInSize;
899612f0f45SAlexander Yermolovich       PreviousChangeInSize = 0;
900612f0f45SAlexander Yermolovich       PreviousOffset = CUOffset;
901bd1ebe9dSAlexander Yermolovich       break;
902bd1ebe9dSAlexander Yermolovich     }
903bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
904bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
905bd1ebe9dSAlexander Yermolovich       PreviousChangeInSize += NDE->Value.size();
906bd1ebe9dSAlexander Yermolovich       break;
9071c2f4bbeSAlexander Yermolovich     }
9081c2f4bbeSAlexander Yermolovich     }
9091c2f4bbeSAlexander Yermolovich   }
910612f0f45SAlexander Yermolovich   CUMap[PreviousOffset].Length += PreviousChangeInSize;
9111c2f4bbeSAlexander Yermolovich   return CUMap;
9121c2f4bbeSAlexander Yermolovich }
913bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0;
9141c2f4bbeSAlexander Yermolovich 
9151c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) {
9161c2f4bbeSAlexander Yermolovich   std::string NewBinaryContents;
9171c2f4bbeSAlexander Yermolovich   NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize);
9181c2f4bbeSAlexander Yermolovich   uint32_t StartOffset = 0;
9191c2f4bbeSAlexander Yermolovich   uint32_t DwarfUnitBaseOffset = 0;
9201c2f4bbeSAlexander Yermolovich   uint32_t OldValueSize = 0;
9211c2f4bbeSAlexander Yermolovich   uint32_t Offset = 0;
9221c2f4bbeSAlexander Yermolovich   std::string ByteSequence;
9231c2f4bbeSAlexander Yermolovich   std::vector<std::pair<uint32_t, uint32_t>> LengthPatches;
9241c2f4bbeSAlexander Yermolovich   // Wasting one entry to avoid checks for first.
9251c2f4bbeSAlexander Yermolovich   LengthPatches.push_back({0, 0});
9261c2f4bbeSAlexander Yermolovich 
9271c2f4bbeSAlexander Yermolovich   // Applying all the patches replacing current entry.
9281c2f4bbeSAlexander Yermolovich   // This might change the size of .debug_info section.
929ea6c8b01SAlexander Yermolovich   for (const UniquePatchPtrType &PatchBase : DebugPatches) {
9301c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
9311c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
9321c2f4bbeSAlexander Yermolovich     default:
9331c2f4bbeSAlexander Yermolovich       continue;
9341c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
9351c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
9361c2f4bbeSAlexander Yermolovich       uint32_t DestinationOffset = RDP->DestinationOffset;
9371c2f4bbeSAlexander Yermolovich       assert(OldToNewOffset.count(DestinationOffset) &&
9381c2f4bbeSAlexander Yermolovich              "Destination Offset for reference not updated.");
9391c2f4bbeSAlexander Yermolovich       uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset];
9401c2f4bbeSAlexander Yermolovich       Offset = RDP->Offset;
9411c2f4bbeSAlexander Yermolovich       OldValueSize = RDP->PatchInfo.OldValueSize;
9421c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.DirectRelative) {
9431c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
9441c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
9451c2f4bbeSAlexander Yermolovich         // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge
9461c2f4bbeSAlexander Yermolovich         // and overflow if later debug information grows.
9471c2f4bbeSAlexander Yermolovich         if (ByteSequence.size() > OldValueSize)
9481c2f4bbeSAlexander Yermolovich           errs() << "BOLT-ERROR: Relative reference of size "
9491c2f4bbeSAlexander Yermolovich                  << Twine::utohexstr(OldValueSize)
9501c2f4bbeSAlexander Yermolovich                  << " overflows with the new encoding.\n";
9511c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.DirectAbsolute) {
9521c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
9531c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.IndirectRelative) {
9541c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
9551c2f4bbeSAlexander Yermolovich         ByteSequence.clear();
9561c2f4bbeSAlexander Yermolovich         raw_string_ostream OS(ByteSequence);
9571c2f4bbeSAlexander Yermolovich         encodeULEB128(UpdatedOffset, OS, 4);
9581c2f4bbeSAlexander Yermolovich       } else {
9591c2f4bbeSAlexander Yermolovich         llvm_unreachable("Invalid Reference form.");
9601c2f4bbeSAlexander Yermolovich       }
9611c2f4bbeSAlexander Yermolovich       break;
9621c2f4bbeSAlexander Yermolovich     }
9631c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue32: {
9641c2f4bbeSAlexander Yermolovich       DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P);
9651c2f4bbeSAlexander Yermolovich       Offset = P32->Offset;
9661c2f4bbeSAlexander Yermolovich       OldValueSize = 4;
9671c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P32->Value);
9681c2f4bbeSAlexander Yermolovich       break;
9691c2f4bbeSAlexander Yermolovich     }
9701c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
9711c2f4bbeSAlexander Yermolovich       DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P);
9721c2f4bbeSAlexander Yermolovich       Offset = P64to32->Offset;
9731c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
9741c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P64to32->Value);
9751c2f4bbeSAlexander Yermolovich       break;
9761c2f4bbeSAlexander Yermolovich     }
977a44fe319SAlexander Yermolovich     case DebugPatchKind::PatchValue32GenericSize: {
978a44fe319SAlexander Yermolovich       DebugPatch32GenericSize *DPVS =
979a44fe319SAlexander Yermolovich           reinterpret_cast<DebugPatch32GenericSize *>(P);
980a44fe319SAlexander Yermolovich       Offset = DPVS->Offset;
981a44fe319SAlexander Yermolovich       OldValueSize = DPVS->OldValueSize;
982a44fe319SAlexander Yermolovich       ByteSequence = encodeLE(4, DPVS->Value);
983a44fe319SAlexander Yermolovich       break;
984a44fe319SAlexander Yermolovich     }
9851c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
9861c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *PV =
9871c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
9881c2f4bbeSAlexander Yermolovich       Offset = PV->Offset;
9891c2f4bbeSAlexander Yermolovich       OldValueSize = PV->OldValueSize;
9901c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
9911c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(ByteSequence);
9921c2f4bbeSAlexander Yermolovich       encodeULEB128(PV->Value, OS);
9931c2f4bbeSAlexander Yermolovich       break;
9941c2f4bbeSAlexander Yermolovich     }
9951c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64: {
9961c2f4bbeSAlexander Yermolovich       DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P);
9971c2f4bbeSAlexander Yermolovich       Offset = P64->Offset;
9981c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
9991c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(8, P64->Value);
10001c2f4bbeSAlexander Yermolovich       break;
10011c2f4bbeSAlexander Yermolovich     }
10021c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
10031c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
10041c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
10051c2f4bbeSAlexander Yermolovich       Offset = BaseLabel->Offset;
10061c2f4bbeSAlexander Yermolovich       OldValueSize = 0;
10071c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
10081c2f4bbeSAlexander Yermolovich       auto &Patch = LengthPatches.back();
10091c2f4bbeSAlexander Yermolovich       // Length to copy between last patch entry and next compile unit.
10101c2f4bbeSAlexander Yermolovich       uint32_t RemainingLength = Offset - StartOffset;
10111c2f4bbeSAlexander Yermolovich       uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength;
10121c2f4bbeSAlexander Yermolovich       DwarfUnitBaseOffset = NewCUOffset;
10131c2f4bbeSAlexander Yermolovich       // Length of previous CU = This CU Offset - sizeof(length) - last CU
10141c2f4bbeSAlexander Yermolovich       // Offset.
10151c2f4bbeSAlexander Yermolovich       Patch.second = NewCUOffset - 4 - Patch.first;
10161c2f4bbeSAlexander Yermolovich       LengthPatches.push_back({NewCUOffset, 0});
10171c2f4bbeSAlexander Yermolovich       break;
10181c2f4bbeSAlexander Yermolovich     }
1019bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
1020bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
1021bd1ebe9dSAlexander Yermolovich       Offset = NDE->Offset;
1022bd1ebe9dSAlexander Yermolovich       OldValueSize = 0;
1023bd1ebe9dSAlexander Yermolovich       ByteSequence = NDE->Value;
1024bd1ebe9dSAlexander Yermolovich       break;
1025bd1ebe9dSAlexander Yermolovich     }
10261c2f4bbeSAlexander Yermolovich     }
10271c2f4bbeSAlexander Yermolovich 
1028bd1ebe9dSAlexander Yermolovich     assert((P->Kind == DebugPatchKind::NewDebugEntry ||
1029bd1ebe9dSAlexander Yermolovich             Offset + ByteSequence.size() <= BinaryContents.size()) &&
10301c2f4bbeSAlexander Yermolovich            "Applied patch runs over binary size.");
10311c2f4bbeSAlexander Yermolovich     uint32_t Length = Offset - StartOffset;
10321c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
10331c2f4bbeSAlexander Yermolovich                              Length);
10341c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(ByteSequence.data(), ByteSequence.size());
10351c2f4bbeSAlexander Yermolovich     StartOffset = Offset + OldValueSize;
10361c2f4bbeSAlexander Yermolovich   }
10371c2f4bbeSAlexander Yermolovich   uint32_t Length = BinaryContents.size() - StartOffset;
10381c2f4bbeSAlexander Yermolovich   NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
10391c2f4bbeSAlexander Yermolovich                            Length);
10401c2f4bbeSAlexander Yermolovich   DebugPatches.clear();
10411c2f4bbeSAlexander Yermolovich 
10421c2f4bbeSAlexander Yermolovich   // Patching lengths of CUs
10431c2f4bbeSAlexander Yermolovich   auto &Patch = LengthPatches.back();
10441c2f4bbeSAlexander Yermolovich   Patch.second = NewBinaryContents.size() - 4 - Patch.first;
10451c2f4bbeSAlexander Yermolovich   for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) {
10461c2f4bbeSAlexander Yermolovich     const auto &Patch = LengthPatches[J];
10471c2f4bbeSAlexander Yermolovich     ByteSequence = encodeLE(4, Patch.second);
10481c2f4bbeSAlexander Yermolovich     Offset = Patch.first;
10491c2f4bbeSAlexander Yermolovich     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I)
10501c2f4bbeSAlexander Yermolovich       NewBinaryContents[Offset + I] = ByteSequence[I];
10511c2f4bbeSAlexander Yermolovich   }
10521c2f4bbeSAlexander Yermolovich 
10531c2f4bbeSAlexander Yermolovich   return NewBinaryContents;
1054a34c753fSRafael Auler }
1055a34c753fSRafael Auler 
1056a34c753fSRafael Auler void DebugStrWriter::create() {
1057a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
1058a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
1059a34c753fSRafael Auler }
1060a34c753fSRafael Auler 
1061a34c753fSRafael Auler void DebugStrWriter::initialize() {
1062a34c753fSRafael Auler   auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
1063a34c753fSRafael Auler   (*StrStream) << StrSection;
1064a34c753fSRafael Auler }
1065a34c753fSRafael Auler 
1066a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
1067e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
1068a34c753fSRafael Auler   if (StrBuffer->empty())
1069a34c753fSRafael Auler     initialize();
1070a34c753fSRafael Auler   auto Offset = StrBuffer->size();
1071a34c753fSRafael Auler   (*StrStream) << Str;
1072a34c753fSRafael Auler   StrStream->write_zeros(1);
1073a34c753fSRafael Auler   return Offset;
1074a34c753fSRafael Auler }
1075a34c753fSRafael Auler 
1076a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
1077a34c753fSRafael Auler   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
1078a34c753fSRafael Auler   if (!Abbrevs)
1079a34c753fSRafael Auler     return;
1080a34c753fSRafael Auler 
108145f94abcSMaksim Panchenko   const PatchesTy &UnitPatches = Patches[&Unit];
1082bd1ebe9dSAlexander Yermolovich   const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit];
1083a34c753fSRafael Auler 
10849f3f9d19SAlexander Yermolovich   // We are duplicating abbrev sections, to handle the case where for one CU we
10859f3f9d19SAlexander Yermolovich   // modify it, but for another we don't.
10869f3f9d19SAlexander Yermolovich   auto UnitDataPtr = std::make_unique<AbbrevData>();
10879f3f9d19SAlexander Yermolovich   AbbrevData &UnitData = *UnitDataPtr.get();
10889f3f9d19SAlexander Yermolovich   UnitData.Buffer = std::make_unique<DebugBufferVector>();
10899f3f9d19SAlexander Yermolovich   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
1090bd1ebe9dSAlexander Yermolovich 
1091a34c753fSRafael Auler   raw_svector_ostream &OS = *UnitData.Stream.get();
1092a34c753fSRafael Auler 
10939f3f9d19SAlexander Yermolovich   // Returns true if AbbrevData is re-used, false otherwise.
10949f3f9d19SAlexander Yermolovich   auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool {
10959f3f9d19SAlexander Yermolovich     llvm::SHA1 Hasher;
10969f3f9d19SAlexander Yermolovich     Hasher.update(AbbrevData);
1097330268baSArgyrios Kyrtzidis     std::array<uint8_t, 20> Hash = Hasher.final();
1098330268baSArgyrios Kyrtzidis     StringRef Key((const char *)Hash.data(), Hash.size());
10999f3f9d19SAlexander Yermolovich     auto Iter = AbbrevDataCache.find(Key);
11009f3f9d19SAlexander Yermolovich     if (Iter != AbbrevDataCache.end()) {
11019f3f9d19SAlexander Yermolovich       UnitsAbbrevData[&Unit] = Iter->second.get();
11029f3f9d19SAlexander Yermolovich       return true;
11039f3f9d19SAlexander Yermolovich     }
11049f3f9d19SAlexander Yermolovich     AbbrevDataCache[Key] = std::move(UnitDataPtr);
11059f3f9d19SAlexander Yermolovich     UnitsAbbrevData[&Unit] = &UnitData;
11069f3f9d19SAlexander Yermolovich     return false;
11079f3f9d19SAlexander Yermolovich   };
1108a34c753fSRafael Auler   // Take a fast path if there are no patches to apply. Simply copy the original
1109a34c753fSRafael Auler   // contents.
1110bd1ebe9dSAlexander Yermolovich   if (UnitPatches.empty() && AbbrevEntries.empty()) {
1111a34c753fSRafael Auler     StringRef AbbrevSectionContents =
1112a34c753fSRafael Auler         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
1113a34c753fSRafael Auler                          : Unit.getContext().getDWARFObj().getAbbrevSection();
1114a34c753fSRafael Auler     StringRef AbbrevContents;
1115a34c753fSRafael Auler 
1116a34c753fSRafael Auler     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
1117a34c753fSRafael Auler     if (!CUIndex.getRows().empty()) {
1118a34c753fSRafael Auler       // Handle DWP section contribution.
1119a34c753fSRafael Auler       const DWARFUnitIndex::Entry *DWOEntry =
1120a34c753fSRafael Auler           CUIndex.getFromHash(*Unit.getDWOId());
1121a34c753fSRafael Auler       if (!DWOEntry)
1122a34c753fSRafael Auler         return;
1123a34c753fSRafael Auler 
1124a34c753fSRafael Auler       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
1125a34c753fSRafael Auler           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
1126a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
1127a34c753fSRafael Auler                                                     DWOContrubution->Length);
112845f94abcSMaksim Panchenko     } else if (!Unit.isDWOUnit()) {
1129a34c753fSRafael Auler       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
113045f94abcSMaksim Panchenko 
113145f94abcSMaksim Panchenko       // We know where the unit's abbreviation set starts, but not where it ends
113245f94abcSMaksim Panchenko       // as such data is not readily available. Hence, we have to build a sorted
113345f94abcSMaksim Panchenko       // list of start addresses and find the next starting address to determine
113445f94abcSMaksim Panchenko       // the set boundaries.
113545f94abcSMaksim Panchenko       //
113645f94abcSMaksim Panchenko       // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
113745f94abcSMaksim Panchenko       // we wouldn't have to build our own sorted list for the quick lookup.
113845f94abcSMaksim Panchenko       if (AbbrevSetOffsets.empty()) {
11391c2f4bbeSAlexander Yermolovich         for_each(
114045f94abcSMaksim Panchenko             *Unit.getContext().getDebugAbbrev(),
114145f94abcSMaksim Panchenko             [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
114245f94abcSMaksim Panchenko               AbbrevSetOffsets.push_back(P.first);
114345f94abcSMaksim Panchenko             });
11441c2f4bbeSAlexander Yermolovich         sort(AbbrevSetOffsets);
114545f94abcSMaksim Panchenko       }
11461c2f4bbeSAlexander Yermolovich       auto It = upper_bound(AbbrevSetOffsets, StartOffset);
114745f94abcSMaksim Panchenko       const uint64_t EndOffset =
114845f94abcSMaksim Panchenko           It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
1149a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
115045f94abcSMaksim Panchenko     } else {
115145f94abcSMaksim Panchenko       // For DWO unit outside of DWP, we expect the entire section to hold
115245f94abcSMaksim Panchenko       // abbreviations for this unit only.
115345f94abcSMaksim Panchenko       AbbrevContents = AbbrevSectionContents;
1154a34c753fSRafael Auler     }
1155a34c753fSRafael Auler 
11569f3f9d19SAlexander Yermolovich     if (!hashAndAddAbbrev(AbbrevContents)) {
1157a34c753fSRafael Auler       OS.reserveExtraSpace(AbbrevContents.size());
1158a34c753fSRafael Auler       OS << AbbrevContents;
11599f3f9d19SAlexander Yermolovich     }
1160a34c753fSRafael Auler     return;
1161a34c753fSRafael Auler   }
1162a34c753fSRafael Auler 
1163a34c753fSRafael Auler   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
1164a34c753fSRafael Auler     const DWARFAbbreviationDeclaration &Abbrev = *I;
1165a34c753fSRafael Auler     auto Patch = UnitPatches.find(&Abbrev);
1166a34c753fSRafael Auler 
1167a34c753fSRafael Auler     encodeULEB128(Abbrev.getCode(), OS);
1168a34c753fSRafael Auler     encodeULEB128(Abbrev.getTag(), OS);
1169a34c753fSRafael Auler     encodeULEB128(Abbrev.hasChildren(), OS);
1170a34c753fSRafael Auler     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
1171a34c753fSRafael Auler          Abbrev.attributes()) {
1172a34c753fSRafael Auler       if (Patch != UnitPatches.end()) {
1173a34c753fSRafael Auler         bool Patched = false;
1174a34c753fSRafael Auler         // Patches added later take a precedence over earlier ones.
1175a34c753fSRafael Auler         for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
1176a34c753fSRafael Auler              ++I) {
1177a34c753fSRafael Auler           if (I->OldAttr != AttrSpec.Attr)
1178a34c753fSRafael Auler             continue;
1179a34c753fSRafael Auler 
1180a34c753fSRafael Auler           encodeULEB128(I->NewAttr, OS);
1181a34c753fSRafael Auler           encodeULEB128(I->NewAttrForm, OS);
1182a34c753fSRafael Auler           Patched = true;
1183a34c753fSRafael Auler           break;
1184a34c753fSRafael Auler         }
1185a34c753fSRafael Auler         if (Patched)
1186a34c753fSRafael Auler           continue;
1187a34c753fSRafael Auler       }
1188a34c753fSRafael Auler 
1189a34c753fSRafael Auler       encodeULEB128(AttrSpec.Attr, OS);
1190a34c753fSRafael Auler       encodeULEB128(AttrSpec.Form, OS);
1191a34c753fSRafael Auler       if (AttrSpec.isImplicitConst())
1192a34c753fSRafael Auler         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
1193a34c753fSRafael Auler     }
1194bd1ebe9dSAlexander Yermolovich     const auto Entries = AbbrevEntries.find(&Abbrev);
1195bd1ebe9dSAlexander Yermolovich     // Adding new Abbrevs for inserted entries.
1196bd1ebe9dSAlexander Yermolovich     if (Entries != AbbrevEntries.end()) {
1197bd1ebe9dSAlexander Yermolovich       for (const AbbrevEntry &Entry : Entries->second) {
1198bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Attr, OS);
1199bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Form, OS);
1200bd1ebe9dSAlexander Yermolovich       }
1201bd1ebe9dSAlexander Yermolovich     }
1202a34c753fSRafael Auler     encodeULEB128(0, OS);
1203a34c753fSRafael Auler     encodeULEB128(0, OS);
1204a34c753fSRafael Auler   }
1205a34c753fSRafael Auler   encodeULEB128(0, OS);
12069f3f9d19SAlexander Yermolovich 
12079f3f9d19SAlexander Yermolovich   hashAndAddAbbrev(OS.str());
1208a34c753fSRafael Auler }
1209a34c753fSRafael Auler 
1210a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
12119f3f9d19SAlexander Yermolovich   // Used to create determinism for writing out abbrevs.
12129f3f9d19SAlexander Yermolovich   std::vector<AbbrevData *> Abbrevs;
121345f94abcSMaksim Panchenko   if (DWOId) {
121445f94abcSMaksim Panchenko     // We expect abbrev_offset to always be zero for DWO units as there
121545f94abcSMaksim Panchenko     // should be one CU per DWO, and TUs should share the same abbreviation
121645f94abcSMaksim Panchenko     // set with the CU.
12171417f607SAlexander Yermolovich     // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so
12181417f607SAlexander Yermolovich     // can be none zero. Thus we are skipping the check for DWP.
121945f94abcSMaksim Panchenko     bool IsDWP = !Context.getCUIndex().getRows().empty();
12201417f607SAlexander Yermolovich     if (!IsDWP) {
122145f94abcSMaksim Panchenko       for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
122245f94abcSMaksim Panchenko         if (Unit->getAbbreviationsOffset() != 0) {
122345f94abcSMaksim Panchenko           errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
122445f94abcSMaksim Panchenko                     "Unable to update debug info.\n";
122545f94abcSMaksim Panchenko           exit(1);
122645f94abcSMaksim Panchenko         }
122745f94abcSMaksim Panchenko       }
122845f94abcSMaksim Panchenko     }
122945f94abcSMaksim Panchenko 
12309f3f9d19SAlexander Yermolovich     DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId);
123145f94abcSMaksim Panchenko     // Issue abbreviations for the DWO CU only.
123245f94abcSMaksim Panchenko     addUnitAbbreviations(*Unit);
12339f3f9d19SAlexander Yermolovich     AbbrevData *Abbrev = UnitsAbbrevData[Unit];
12349f3f9d19SAlexander Yermolovich     Abbrevs.push_back(Abbrev);
12359f3f9d19SAlexander Yermolovich   } else {
12369f3f9d19SAlexander Yermolovich     Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits());
12379f3f9d19SAlexander Yermolovich     std::unordered_set<AbbrevData *> ProcessedAbbrevs;
12389f3f9d19SAlexander Yermolovich     // Add abbreviations from compile and type non-DWO units.
12399f3f9d19SAlexander Yermolovich     for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) {
12409f3f9d19SAlexander Yermolovich       addUnitAbbreviations(*Unit);
12419f3f9d19SAlexander Yermolovich       AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()];
12429f3f9d19SAlexander Yermolovich       if (!ProcessedAbbrevs.insert(Abbrev).second)
12439f3f9d19SAlexander Yermolovich         continue;
12449f3f9d19SAlexander Yermolovich       Abbrevs.push_back(Abbrev);
12459f3f9d19SAlexander Yermolovich     }
124645f94abcSMaksim Panchenko   }
124745f94abcSMaksim Panchenko 
1248a34c753fSRafael Auler   DebugBufferVector ReturnBuffer;
1249a34c753fSRafael Auler   // Pre-calculate the total size of abbrev section.
1250a34c753fSRafael Auler   uint64_t Size = 0;
12519f3f9d19SAlexander Yermolovich   for (const AbbrevData *UnitData : Abbrevs)
12529f3f9d19SAlexander Yermolovich     Size += UnitData->Buffer->size();
12539f3f9d19SAlexander Yermolovich 
1254a34c753fSRafael Auler   ReturnBuffer.reserve(Size);
1255a34c753fSRafael Auler 
1256a34c753fSRafael Auler   uint64_t Pos = 0;
12579f3f9d19SAlexander Yermolovich   for (AbbrevData *UnitData : Abbrevs) {
12589f3f9d19SAlexander Yermolovich     ReturnBuffer.append(*UnitData->Buffer);
12599f3f9d19SAlexander Yermolovich     UnitData->Offset = Pos;
12609f3f9d19SAlexander Yermolovich     Pos += UnitData->Buffer->size();
1261a34c753fSRafael Auler 
12629f3f9d19SAlexander Yermolovich     UnitData->Buffer.reset();
12639f3f9d19SAlexander Yermolovich     UnitData->Stream.reset();
1264a34c753fSRafael Auler   }
1265a34c753fSRafael Auler 
1266a34c753fSRafael Auler   return std::make_unique<DebugBufferVector>(ReturnBuffer);
1267a34c753fSRafael Auler }
1268a34c753fSRafael Auler 
1269a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
1270a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
1271a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
1272a34c753fSRafael Auler                                     int PointerSize) {
1273a34c753fSRafael Auler   // emit the sequence to set the address
1274a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
1275a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
1276a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
1277a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
1278a34c753fSRafael Auler 
1279a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
1280a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
1281a34c753fSRafael Auler }
1282a34c753fSRafael Auler 
1283a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
1284a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
1285a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
1286a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
1287a34c753fSRafael Auler   if (InputSequences.empty())
1288a34c753fSRafael Auler     return;
1289a34c753fSRafael Auler 
1290a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
1291a34c753fSRafael Auler   unsigned FileNum = 1;
1292a34c753fSRafael Auler   unsigned LastLine = 1;
1293a34c753fSRafael Auler   unsigned Column = 0;
1294a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1295a34c753fSRafael Auler   unsigned Isa = 0;
1296a34c753fSRafael Auler   unsigned Discriminator = 0;
1297a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
1298a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
1299a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1300a34c753fSRafael Auler 
1301a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
1302a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
1303a34c753fSRafael Auler     FileNum = 1;
1304a34c753fSRafael Auler     LastLine = 1;
1305a34c753fSRafael Auler     Column = 0;
1306a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1307a34c753fSRafael Auler     Isa = 0;
1308a34c753fSRafael Auler     Discriminator = 0;
1309a34c753fSRafael Auler     LastAddress = InvalidAddress;
1310a34c753fSRafael Auler   };
1311a34c753fSRafael Auler 
1312a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
1313a34c753fSRafael Auler     const uint64_t SequenceStart =
1314a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
1315a34c753fSRafael Auler 
1316a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
1317a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
1318a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
1319a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
1320a34c753fSRafael Auler     }
1321a34c753fSRafael Auler 
1322a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
1323a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
1324a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
1325a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
1326a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
1327a34c753fSRafael Auler 
1328a34c753fSRafael Auler       if (FileNum != Row.File) {
1329a34c753fSRafael Auler         FileNum = Row.File;
1330a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1331a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
1332a34c753fSRafael Auler       }
1333a34c753fSRafael Auler       if (Column != Row.Column) {
1334a34c753fSRafael Auler         Column = Row.Column;
1335a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1336a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
1337a34c753fSRafael Auler       }
1338a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
1339a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
1340a34c753fSRafael Auler         Discriminator = Row.Discriminator;
1341a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
1342a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1343a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
1344a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1345a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
1346a34c753fSRafael Auler       }
1347a34c753fSRafael Auler       if (Isa != Row.Isa) {
1348a34c753fSRafael Auler         Isa = Row.Isa;
1349a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1350a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
1351a34c753fSRafael Auler       }
1352a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
1353a34c753fSRafael Auler         Flags = Row.IsStmt;
1354a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1355a34c753fSRafael Auler       }
1356a34c753fSRafael Auler       if (Row.BasicBlock)
1357a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1358a34c753fSRafael Auler       if (Row.PrologueEnd)
1359a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1360a34c753fSRafael Auler       if (Row.EpilogueBegin)
1361a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1362a34c753fSRafael Auler 
1363a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
1364a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
1365a34c753fSRafael Auler       if (Row.EndSequence) {
1366a34c753fSRafael Auler         emitEndOfSequence(Address);
1367a34c753fSRafael Auler       } else {
1368a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
1369a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1370a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
1371a34c753fSRafael Auler         else
1372a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1373a34c753fSRafael Auler 
1374a34c753fSRafael Auler         LastAddress = Address;
1375a34c753fSRafael Auler         LastLine = Row.Line;
1376a34c753fSRafael Auler       }
1377a34c753fSRafael Auler 
1378a34c753fSRafael Auler       Discriminator = 0;
1379a34c753fSRafael Auler     }
1380a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
1381a34c753fSRafael Auler   }
1382a34c753fSRafael Auler 
1383a34c753fSRafael Auler   // Finish with the end of the sequence.
1384a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
1385a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
1386a34c753fSRafael Auler }
1387a34c753fSRafael Auler 
1388a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
1389a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
1390a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
1391a34c753fSRafael Auler static inline void emitDwarfLineTable(
1392a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
1393a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1394a34c753fSRafael Auler   unsigned FileNum = 1;
1395a34c753fSRafael Auler   unsigned LastLine = 1;
1396a34c753fSRafael Auler   unsigned Column = 0;
1397a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1398a34c753fSRafael Auler   unsigned Isa = 0;
1399a34c753fSRafael Auler   unsigned Discriminator = 0;
1400a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
1401a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1402a34c753fSRafael Auler 
1403a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1404a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1405a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1406a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1407a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
1408a34c753fSRafael Auler       FileNum = 1;
1409a34c753fSRafael Auler       LastLine = 1;
1410a34c753fSRafael Auler       Column = 0;
1411a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1412a34c753fSRafael Auler       Isa = 0;
1413a34c753fSRafael Auler       Discriminator = 0;
1414a34c753fSRafael Auler       LastLabel = nullptr;
1415a34c753fSRafael Auler       continue;
1416a34c753fSRafael Auler     }
1417a34c753fSRafael Auler 
1418a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1419a34c753fSRafael Auler 
1420a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
1421a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
1422a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1423a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
1424a34c753fSRafael Auler     }
1425a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
1426a34c753fSRafael Auler       Column = LineEntry.getColumn();
1427a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1428a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
1429a34c753fSRafael Auler     }
1430a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
1431*014cd37fSAlexander Yermolovich         MCOS->getContext().getDwarfVersion() >= 2) {
1432a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
1433a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
1434a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1435a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
1436a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1437a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
1438a34c753fSRafael Auler     }
1439a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
1440a34c753fSRafael Auler       Isa = LineEntry.getIsa();
1441a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1442a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
1443a34c753fSRafael Auler     }
1444a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1445a34c753fSRafael Auler       Flags = LineEntry.getFlags();
1446a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1447a34c753fSRafael Auler     }
1448a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1449a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1450a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1451a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1452a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1453a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1454a34c753fSRafael Auler 
1455a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
1456a34c753fSRafael Auler 
1457a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
1458a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
1459a34c753fSRafael Auler     // Label and the current Label.
1460a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1461a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
1462a34c753fSRafael Auler     Discriminator = 0;
1463a34c753fSRafael Auler     LastLine = LineEntry.getLine();
1464a34c753fSRafael Auler     LastLabel = Label;
1465a34c753fSRafael Auler   }
1466a34c753fSRafael Auler 
1467a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
1468a34c753fSRafael Auler }
1469a34c753fSRafael Auler 
1470a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1471b73c87bcSMaksim Panchenko                             Optional<MCDwarfLineStr> &LineStr,
1472b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
1473a34c753fSRafael Auler   if (!RawData.empty()) {
1474a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
1475a34c753fSRafael Auler            InputSequences.empty() &&
1476a34c753fSRafael Auler            "cannot combine raw data with new line entries");
1477a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
1478a34c753fSRafael Auler     MCOS->emitBytes(RawData);
1479a34c753fSRafael Auler 
1480b73c87bcSMaksim Panchenko     // Emit fake relocation for RuntimeDyld to always allocate the section.
1481b73c87bcSMaksim Panchenko     //
1482b73c87bcSMaksim Panchenko     // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
1483b73c87bcSMaksim Panchenko     //        without relocations.
1484b73c87bcSMaksim Panchenko     MCOS->emitRelocDirective(
1485b73c87bcSMaksim Panchenko         *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
1486b73c87bcSMaksim Panchenko         MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);
1487b73c87bcSMaksim Panchenko 
1488a34c753fSRafael Auler     return;
1489a34c753fSRafael Auler   }
1490a34c753fSRafael Auler 
1491a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1492a34c753fSRafael Auler 
1493a34c753fSRafael Auler   // Put out the line tables.
1494a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1495a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1496a34c753fSRafael Auler 
1497a34c753fSRafael Auler   // Emit line tables for the original code.
1498a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1499a34c753fSRafael Auler 
1500a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
1501a34c753fSRafael Auler   // of this section (that was used in a previous expression).
1502a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
1503a34c753fSRafael Auler }
1504a34c753fSRafael Auler 
1505*014cd37fSAlexander Yermolovich // Helper function to parse .debug_line_str, and populate one we are using.
1506*014cd37fSAlexander Yermolovich // For functions that we do not modify we output them as raw data.
1507*014cd37fSAlexander Yermolovich // Re-constructing .debug_line_str so that offsets are correct for those
1508*014cd37fSAlexander Yermolovich // debut line tables.
1509*014cd37fSAlexander Yermolovich // Bonus is that when we output a final binary we can re-use .debug_line_str
1510*014cd37fSAlexander Yermolovich // section. So we don't have to do the SHF_ALLOC trick we did with
1511*014cd37fSAlexander Yermolovich // .debug_line.
1512*014cd37fSAlexander Yermolovich static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
1513*014cd37fSAlexander Yermolovich                                          MCDwarfLineStr &LineStr,
1514*014cd37fSAlexander Yermolovich                                          BinaryContext &BC,
1515*014cd37fSAlexander Yermolovich                                          MCStreamer &Streamer) {
1516*014cd37fSAlexander Yermolovich   DataExtractor StrData(LineStrSection.getContents(),
1517*014cd37fSAlexander Yermolovich                         BC.DwCtx->isLittleEndian(), 0);
1518*014cd37fSAlexander Yermolovich   uint64_t Offset = 0;
1519*014cd37fSAlexander Yermolovich   while (StrData.isValidOffset(Offset)) {
1520*014cd37fSAlexander Yermolovich     Error Err = Error::success();
1521*014cd37fSAlexander Yermolovich     const char *CStr = StrData.getCStr(&Offset, &Err);
1522*014cd37fSAlexander Yermolovich     if (Err) {
1523*014cd37fSAlexander Yermolovich       errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1524*014cd37fSAlexander Yermolovich       continue;
1525*014cd37fSAlexander Yermolovich     }
1526*014cd37fSAlexander Yermolovich     LineStr.emitRef(&Streamer, CStr);
1527*014cd37fSAlexander Yermolovich   }
1528*014cd37fSAlexander Yermolovich }
1529*014cd37fSAlexander Yermolovich 
1530a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1531a34c753fSRafael Auler   MCAssembler &Assembler =
1532a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1533a34c753fSRafael Auler 
1534a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1535a34c753fSRafael Auler 
1536a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
1537a34c753fSRafael Auler 
1538a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
1539a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
1540a34c753fSRafael Auler   if (LineTables.empty())
1541a34c753fSRafael Auler     return;
1542a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
1543a34c753fSRafael Auler   Optional<MCDwarfLineStr> LineStr(None);
1544*014cd37fSAlexander Yermolovich   ErrorOr<BinarySection &> LineStrSection =
1545*014cd37fSAlexander Yermolovich       BC.getUniqueSectionByName(".debug_line_str");
1546*014cd37fSAlexander Yermolovich   // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
1547*014cd37fSAlexander Yermolovich   // .debug_line
1548*014cd37fSAlexander Yermolovich   if (LineStrSection) {
1549a34c753fSRafael Auler     LineStr = MCDwarfLineStr(*BC.Ctx);
1550*014cd37fSAlexander Yermolovich     parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer);
1551*014cd37fSAlexander Yermolovich   }
1552a34c753fSRafael Auler 
1553a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
1554a34c753fSRafael Auler   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
1555a34c753fSRafael Auler 
1556*014cd37fSAlexander Yermolovich   const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
1557a34c753fSRafael Auler   // Handle the rest of the Compile Units.
1558a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
1559*014cd37fSAlexander Yermolovich     Streamer.getContext().setDwarfVersion(
1560*014cd37fSAlexander Yermolovich         CUIDTablePair.second.getDwarfVersion());
1561b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1562a34c753fSRafael Auler   }
1563*014cd37fSAlexander Yermolovich 
1564*014cd37fSAlexander Yermolovich   // Resetting DWARF version for rest of the flow.
1565*014cd37fSAlexander Yermolovich   BC.Ctx->setDwarfVersion(DwarfVersion);
1566*014cd37fSAlexander Yermolovich 
1567*014cd37fSAlexander Yermolovich   // Still need to write the section out for the ExecutionEngine, and temp in
1568*014cd37fSAlexander Yermolovich   // memory object we are constructing.
1569*014cd37fSAlexander Yermolovich   if (LineStr) {
1570*014cd37fSAlexander Yermolovich     LineStr->emitSection(&Streamer);
1571*014cd37fSAlexander Yermolovich     SmallString<0> Data = LineStr->getFinalizedData();
1572*014cd37fSAlexander Yermolovich     BC.registerOrUpdateNoteSection(".debug_line_str", copyByteArray(Data.str()),
1573*014cd37fSAlexander Yermolovich                                    Data.size());
1574*014cd37fSAlexander Yermolovich   }
1575a34c753fSRafael Auler }
1576a34c753fSRafael Auler 
1577a34c753fSRafael Auler } // namespace bolt
1578a34c753fSRafael Auler } // namespace llvm
1579