xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision a44fe31977c781b58922e6ad065c15920883dc57)
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"
15a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
16290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
17290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
1857f7c7d9Sserge-sans-paille #include "llvm/MC/MCAssembler.h"
19f8c7fb49SAmir Ayupov #include "llvm/MC/MCContext.h"
20a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h"
21a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
22a34c753fSRafael Auler #include "llvm/Support/EndianStream.h"
23a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
249f3f9d19SAlexander Yermolovich #include "llvm/Support/SHA1.h"
25a34c753fSRafael Auler #include <algorithm>
26a34c753fSRafael Auler #include <cassert>
27a34c753fSRafael Auler #include <cstdint>
28a34c753fSRafael Auler #include <limits>
291c2f4bbeSAlexander Yermolovich #include <unordered_map>
30a34c753fSRafael Auler 
31a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info"
32a34c753fSRafael Auler 
33a34c753fSRafael Auler namespace opts {
34a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity;
351c2f4bbeSAlexander Yermolovich } // namespace opts
36a34c753fSRafael Auler 
37a34c753fSRafael Auler namespace llvm {
38f8c7fb49SAmir Ayupov class MCSymbol;
39f8c7fb49SAmir Ayupov 
40a34c753fSRafael Auler namespace bolt {
41a34c753fSRafael Auler 
42bd1ebe9dSAlexander Yermolovich /// Finds attributes FormValue and Offset.
43bd1ebe9dSAlexander Yermolovich ///
44bd1ebe9dSAlexander Yermolovich /// \param DIE die to look up in.
45bd1ebe9dSAlexander Yermolovich /// \param Index the attribute index to extract.
46bd1ebe9dSAlexander Yermolovich /// \return an optional AttrInfo with DWARFFormValue and Offset.
47bd1ebe9dSAlexander Yermolovich Optional<AttrInfo>
48bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE,
49bd1ebe9dSAlexander Yermolovich                   const DWARFAbbreviationDeclaration *AbbrevDecl,
50bd1ebe9dSAlexander Yermolovich                   uint32_t Index) {
51bd1ebe9dSAlexander Yermolovich   const DWARFUnit &U = *DIE.getDwarfUnit();
52bd1ebe9dSAlexander Yermolovich   uint64_t Offset =
53bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
54bd1ebe9dSAlexander Yermolovich   Optional<DWARFFormValue> Value =
55bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
56bd1ebe9dSAlexander Yermolovich   if (!Value)
57bd1ebe9dSAlexander Yermolovich     return None;
58bd1ebe9dSAlexander Yermolovich   // AttributeSpec
59bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
60bd1ebe9dSAlexander Yermolovich       AbbrevDecl->attributes().begin() + Index;
61bd1ebe9dSAlexander Yermolovich   uint32_t ValSize = 0;
62bd1ebe9dSAlexander Yermolovich   Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
63bd1ebe9dSAlexander Yermolovich   if (ValSizeOpt) {
64bd1ebe9dSAlexander Yermolovich     ValSize = static_cast<uint32_t>(*ValSizeOpt);
65bd1ebe9dSAlexander Yermolovich   } else {
66bd1ebe9dSAlexander Yermolovich     DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
67bd1ebe9dSAlexander Yermolovich     uint64_t NewOffset = Offset;
68bd1ebe9dSAlexander Yermolovich     DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
69bd1ebe9dSAlexander Yermolovich                               U.getFormParams());
70bd1ebe9dSAlexander Yermolovich     // This includes entire size of the entry, which might not be just the
71bd1ebe9dSAlexander Yermolovich     // encoding part. For example for DW_AT_loc it will include expression
72bd1ebe9dSAlexander Yermolovich     // location.
73bd1ebe9dSAlexander Yermolovich     ValSize = NewOffset - Offset;
74bd1ebe9dSAlexander Yermolovich   }
75bd1ebe9dSAlexander Yermolovich 
76bd1ebe9dSAlexander Yermolovich   return AttrInfo{*Value, Offset, ValSize};
77bd1ebe9dSAlexander Yermolovich }
78bd1ebe9dSAlexander Yermolovich 
79a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
80a34c753fSRafael Auler 
81a34c753fSRafael Auler namespace {
82a34c753fSRafael Auler 
831c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED
841c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) {
851c2f4bbeSAlexander Yermolovich   for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
861c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr(S[I]);
871c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr((int8_t)S[I]);
881c2f4bbeSAlexander Yermolovich   }
891c2f4bbeSAlexander Yermolovich   errs() << "\n";
901c2f4bbeSAlexander Yermolovich }
911c2f4bbeSAlexander Yermolovich 
92a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size).
93a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of
94a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address).
95a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes.
96a34c753fSRafael Auler // Returns the number of written bytes.
9740c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream,
98a34c753fSRafael Auler                             const DebugAddressRangesVector &AddressRanges,
99a34c753fSRafael Auler                             const bool WriteRelativeRanges = false) {
100a34c753fSRafael Auler   for (const DebugAddressRange &Range : AddressRanges) {
101a34c753fSRafael Auler     support::endian::write(Stream, Range.LowPC, support::little);
102a34c753fSRafael Auler     support::endian::write(
103a34c753fSRafael Auler         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
104a34c753fSRafael Auler         support::little);
105a34c753fSRafael Auler   }
106a34c753fSRafael Auler   // Finish with 0 entries.
107a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
108a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
109a34c753fSRafael Auler   return AddressRanges.size() * 16 + 16;
110a34c753fSRafael Auler }
111a34c753fSRafael Auler 
112a34c753fSRafael Auler } // namespace
113a34c753fSRafael Auler 
114a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() {
115a34c753fSRafael Auler   RangesBuffer = std::make_unique<DebugBufferVector>();
116a34c753fSRafael Auler   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
117a34c753fSRafael Auler 
118a34c753fSRafael Auler   // Add an empty range as the first entry;
119a34c753fSRafael Auler   SectionOffset +=
120a34c753fSRafael Auler       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
121a34c753fSRafael Auler }
122a34c753fSRafael Auler 
123a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges(
124a34c753fSRafael Auler     DebugAddressRangesVector &&Ranges,
125a34c753fSRafael Auler     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
126a34c753fSRafael Auler   if (Ranges.empty())
127a34c753fSRafael Auler     return getEmptyRangesOffset();
128a34c753fSRafael Auler 
129a34c753fSRafael Auler   const auto RI = CachedRanges.find(Ranges);
130a34c753fSRafael Auler   if (RI != CachedRanges.end())
131a34c753fSRafael Auler     return RI->second;
132a34c753fSRafael Auler 
133a34c753fSRafael Auler   const uint64_t EntryOffset = addRanges(Ranges);
134a34c753fSRafael Auler   CachedRanges.emplace(std::move(Ranges), EntryOffset);
135a34c753fSRafael Auler 
136a34c753fSRafael Auler   return EntryOffset;
137a34c753fSRafael Auler }
138a34c753fSRafael Auler 
139a34c753fSRafael Auler uint64_t
140a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) {
141a34c753fSRafael Auler   if (Ranges.empty())
142a34c753fSRafael Auler     return getEmptyRangesOffset();
143a34c753fSRafael Auler 
144a34c753fSRafael Auler   // Reading the SectionOffset and updating it should be atomic to guarantee
145a34c753fSRafael Auler   // unique and correct offsets in patches.
146a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
147a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
148a34c753fSRafael Auler   SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);
149a34c753fSRafael Auler 
150a34c753fSRafael Auler   return EntryOffset;
151a34c753fSRafael Auler }
152a34c753fSRafael Auler 
153a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() {
154a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
155a34c753fSRafael Auler   return SectionOffset;
156a34c753fSRafael Auler }
157a34c753fSRafael Auler 
158a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
159a34c753fSRafael Auler                                             DebugAddressRangesVector &&Ranges) {
160a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
161a34c753fSRafael Auler   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
162a34c753fSRafael Auler }
163a34c753fSRafael Auler 
164a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection(
165612f0f45SAlexander Yermolovich     raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
166a34c753fSRafael Auler   // For reference on the format of the .debug_aranges section, see the DWARF4
167a34c753fSRafael Auler   // specification, section 6.1.4 Lookup by Address
168a34c753fSRafael Auler   // http://www.dwarfstd.org/doc/DWARF4.pdf
169a34c753fSRafael Auler   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
170a34c753fSRafael Auler     const uint64_t Offset = CUOffsetAddressRangesPair.first;
171a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges =
172a34c753fSRafael Auler         CUOffsetAddressRangesPair.second;
173a34c753fSRafael Auler 
174a34c753fSRafael Auler     // Emit header.
175a34c753fSRafael Auler 
176a34c753fSRafael Auler     // Size of this set: 8 (size of the header) + 4 (padding after header)
177a34c753fSRafael Auler     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
178a34c753fSRafael Auler     // pair of uint64_t's for the terminating, zero-length range.
179a34c753fSRafael Auler     // Does not include size field itself.
180a34c753fSRafael Auler     uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);
181a34c753fSRafael Auler 
182a34c753fSRafael Auler     // Header field #1: set size.
183a34c753fSRafael Auler     support::endian::write(RangesStream, Size, support::little);
184a34c753fSRafael Auler 
185a34c753fSRafael Auler     // Header field #2: version number, 2 as per the specification.
186a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint16_t>(2),
187a34c753fSRafael Auler                            support::little);
188a34c753fSRafael Auler 
1891c2f4bbeSAlexander Yermolovich     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
190a34c753fSRafael Auler     // Header field #3: debug info offset of the correspondent compile unit.
191612f0f45SAlexander Yermolovich     support::endian::write(
192612f0f45SAlexander Yermolovich         RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
193a34c753fSRafael Auler         support::little);
194a34c753fSRafael Auler 
195a34c753fSRafael Auler     // Header field #4: address size.
196a34c753fSRafael Auler     // 8 since we only write ELF64 binaries for now.
197a34c753fSRafael Auler     RangesStream << char(8);
198a34c753fSRafael Auler 
199a34c753fSRafael Auler     // Header field #5: segment size of target architecture.
200a34c753fSRafael Auler     RangesStream << char(0);
201a34c753fSRafael Auler 
202a34c753fSRafael Auler     // Padding before address table - 4 bytes in the 64-bit-pointer case.
203a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(0),
204a34c753fSRafael Auler                            support::little);
205a34c753fSRafael Auler 
206a34c753fSRafael Auler     writeAddressRanges(RangesStream, AddressRanges, true);
207a34c753fSRafael Auler   }
208a34c753fSRafael Auler }
209a34c753fSRafael Auler 
210a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }
211a34c753fSRafael Auler 
212a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() {
213a34c753fSRafael Auler   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
214a34c753fSRafael Auler                                           indexToAdddessEnd());
215a34c753fSRafael Auler   // Sorting address in increasing order of indices.
216a34c753fSRafael Auler   std::sort(SortedMap.begin(), SortedMap.end(),
217a34c753fSRafael Auler             [](const IndexAddressPair &A, const IndexAddressPair &B) {
218a34c753fSRafael Auler               return A.first < B.first;
219a34c753fSRafael Auler             });
220a34c753fSRafael Auler   for (auto &Pair : SortedMap)
221a34c753fSRafael Auler     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
222a34c753fSRafael Auler }
223a34c753fSRafael Auler uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address,
224a34c753fSRafael Auler                                               uint64_t DWOId) {
225e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
226a34c753fSRafael Auler   if (!AddressMaps.count(DWOId))
227a34c753fSRafael Auler     AddressMaps[DWOId] = AddressForDWOCU();
228a34c753fSRafael Auler 
229a34c753fSRafael Auler   AddressForDWOCU &Map = AddressMaps[DWOId];
230a34c753fSRafael Auler   auto Entry = Map.find(Address);
231a34c753fSRafael Auler   if (Entry == Map.end()) {
232a34c753fSRafael Auler     auto Index = Map.getNextIndex();
233a34c753fSRafael Auler     Entry = Map.insert(Address, Index).first;
234a34c753fSRafael Auler   }
235a34c753fSRafael Auler   return Entry->second;
236a34c753fSRafael Auler }
237a34c753fSRafael Auler 
238a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
239a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update
240a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
241a34c753fSRafael Auler // update AddressToIndex and IndexToAddress
242a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
243a34c753fSRafael Auler                                       uint64_t DWOId) {
244e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
245a34c753fSRafael Auler   AddressForDWOCU &Map = AddressMaps[DWOId];
246a34c753fSRafael Auler   auto Entry = Map.find(Address);
247a34c753fSRafael Auler   if (Entry != Map.end()) {
248a34c753fSRafael Auler     if (Entry->second > Index)
249a34c753fSRafael Auler       Map.updateAddressToIndex(Address, Index);
250a34c753fSRafael Auler     Map.updateIndexToAddrss(Address, Index);
2513652483cSRafael Auler   } else {
252a34c753fSRafael Auler     Map.insert(Address, Index);
253a34c753fSRafael Auler   }
2543652483cSRafael Auler }
255a34c753fSRafael Auler 
256a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() {
257a34c753fSRafael Auler   // Need to layout all sections within .debug_addr
258a34c753fSRafael Auler   // Within each section sort Address by index.
259a34c753fSRafael Auler   AddressSectionBuffer Buffer;
260a34c753fSRafael Auler   raw_svector_ostream AddressStream(Buffer);
261a34c753fSRafael Auler   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
262a34c753fSRafael Auler     Optional<uint64_t> DWOId = CU->getDWOId();
263a34c753fSRafael Auler     // Handling the case wehre debug information is a mix of Debug fission and
264a34c753fSRafael Auler     // monolitic.
265a34c753fSRafael Auler     if (!DWOId)
266a34c753fSRafael Auler       continue;
267a34c753fSRafael Auler     auto AM = AddressMaps.find(*DWOId);
268a34c753fSRafael Auler     // Adding to map even if it did not contribute to .debug_addr.
269a34c753fSRafael Auler     // The Skeleton CU will still have DW_AT_GNU_addr_base.
270a34c753fSRafael Auler     DWOIdToOffsetMap[*DWOId] = Buffer.size();
271a34c753fSRafael Auler     // If does not exist this CUs DWO section didn't contribute to .debug_addr.
272a34c753fSRafael Auler     if (AM == AddressMaps.end())
273a34c753fSRafael Auler       continue;
274a34c753fSRafael Auler     std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
275a34c753fSRafael Auler                                             AM->second.indexToAdddessEnd());
276a34c753fSRafael Auler     // Sorting address in increasing order of indices.
277a34c753fSRafael Auler     std::sort(SortedMap.begin(), SortedMap.end(),
278a34c753fSRafael Auler               [](const IndexAddressPair &A, const IndexAddressPair &B) {
279a34c753fSRafael Auler                 return A.first < B.first;
280a34c753fSRafael Auler               });
281a34c753fSRafael Auler 
282a34c753fSRafael Auler     uint8_t AddrSize = CU->getAddressByteSize();
283a34c753fSRafael Auler     uint32_t Counter = 0;
284a34c753fSRafael Auler     auto WriteAddress = [&](uint64_t Address) -> void {
285a34c753fSRafael Auler       ++Counter;
286a34c753fSRafael Auler       switch (AddrSize) {
287a34c753fSRafael Auler       default:
288a34c753fSRafael Auler         assert(false && "Address Size is invalid.");
289a34c753fSRafael Auler         break;
290a34c753fSRafael Auler       case 4:
291a34c753fSRafael Auler         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
292a34c753fSRafael Auler                                support::little);
293a34c753fSRafael Auler         break;
294a34c753fSRafael Auler       case 8:
295a34c753fSRafael Auler         support::endian::write(AddressStream, Address, support::little);
296a34c753fSRafael Auler         break;
297a34c753fSRafael Auler       }
298a34c753fSRafael Auler     };
299a34c753fSRafael Auler 
300a34c753fSRafael Auler     for (const IndexAddressPair &Val : SortedMap) {
301a34c753fSRafael Auler       while (Val.first > Counter)
302a34c753fSRafael Auler         WriteAddress(0);
303a34c753fSRafael Auler       WriteAddress(Val.second);
304a34c753fSRafael Auler     }
305a34c753fSRafael Auler   }
306a34c753fSRafael Auler 
307a34c753fSRafael Auler   return Buffer;
308a34c753fSRafael Auler }
309a34c753fSRafael Auler 
310a34c753fSRafael Auler uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
311a34c753fSRafael Auler   auto Iter = DWOIdToOffsetMap.find(DWOId);
312a34c753fSRafael Auler   assert(Iter != DWOIdToOffsetMap.end() &&
313a34c753fSRafael Auler          "Offset in to.debug_addr was not found for DWO ID.");
314a34c753fSRafael Auler   return Iter->second;
315a34c753fSRafael Auler }
316a34c753fSRafael Auler 
317a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
318a34c753fSRafael Auler   LocBuffer = std::make_unique<DebugBufferVector>();
319a34c753fSRafael Auler   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
320a34c753fSRafael Auler }
321a34c753fSRafael Auler 
322a34c753fSRafael Auler void DebugLocWriter::addList(uint64_t AttrOffset,
323a34c753fSRafael Auler                              DebugLocationsVector &&LocList) {
324a34c753fSRafael Auler   if (LocList.empty()) {
325a34c753fSRafael Auler     EmptyAttrLists.push_back(AttrOffset);
326a34c753fSRafael Auler     return;
327a34c753fSRafael Auler   }
328a34c753fSRafael Auler   // Since there is a separate DebugLocWriter for each thread,
329a34c753fSRafael Auler   // we don't need a lock to read the SectionOffset and update it.
330a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
331a34c753fSRafael Auler 
332a34c753fSRafael Auler   for (const DebugLocationEntry &Entry : LocList) {
333a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
334a34c753fSRafael Auler                            support::little);
335a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
336a34c753fSRafael Auler                            support::little);
337a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
338a34c753fSRafael Auler                            support::little);
339a34c753fSRafael Auler     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
340a34c753fSRafael Auler                             Entry.Expr.size());
341a34c753fSRafael Auler     SectionOffset += 2 * 8 + 2 + Entry.Expr.size();
342a34c753fSRafael Auler   }
343a34c753fSRafael Auler   LocStream->write_zeros(16);
344a34c753fSRafael Auler   SectionOffset += 16;
345a34c753fSRafael Auler   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
346a34c753fSRafael Auler }
347a34c753fSRafael Auler 
348a34c753fSRafael Auler void DebugLoclistWriter::addList(uint64_t AttrOffset,
349a34c753fSRafael Auler                                  DebugLocationsVector &&LocList) {
350a34c753fSRafael Auler   Patches.push_back({AttrOffset, std::move(LocList)});
351a34c753fSRafael Auler }
352a34c753fSRafael Auler 
353a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
354a34c753fSRafael Auler   return std::move(LocBuffer);
355a34c753fSRafael Auler }
356a34c753fSRafael Auler 
357a34c753fSRafael Auler // DWARF 4: 2.6.2
358a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset,
359a34c753fSRafael Auler                               SimpleBinaryPatcher &DebugInfoPatcher) {
360a34c753fSRafael Auler   for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) {
361a34c753fSRafael Auler     uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset;
362a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset,
363a34c753fSRafael Auler                                   Offset);
364a34c753fSRafael Auler   }
365a34c753fSRafael Auler 
366a34c753fSRafael Auler   for (uint64_t DebugInfoAttrOffset : EmptyAttrLists)
367a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset,
368a34c753fSRafael Auler                                   DebugLocWriter::EmptyListOffset);
369a34c753fSRafael Auler }
370a34c753fSRafael Auler 
371a34c753fSRafael Auler void DebugLoclistWriter::finalize(uint64_t SectionOffset,
372a34c753fSRafael Auler                                   SimpleBinaryPatcher &DebugInfoPatcher) {
373a34c753fSRafael Auler   for (LocPatch &Patch : Patches) {
374a34c753fSRafael Auler     if (Patch.LocList.empty()) {
375a34c753fSRafael Auler       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
376a34c753fSRafael Auler                                     DebugLocWriter::EmptyListOffset);
377a34c753fSRafael Auler       continue;
378a34c753fSRafael Auler     }
379a34c753fSRafael Auler     const uint32_t EntryOffset = LocBuffer->size();
380a34c753fSRafael Auler     for (const DebugLocationEntry &Entry : Patch.LocList) {
381a34c753fSRafael Auler       support::endian::write(*LocStream,
382a34c753fSRafael Auler                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
383a34c753fSRafael Auler                              support::little);
384a34c753fSRafael Auler       uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId);
385a34c753fSRafael Auler       encodeULEB128(Index, *LocStream);
386a34c753fSRafael Auler 
387a34c753fSRafael Auler       // TODO: Support DWARF5
388a34c753fSRafael Auler       support::endian::write(*LocStream,
389a34c753fSRafael Auler                              static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
390a34c753fSRafael Auler                              support::little);
391a34c753fSRafael Auler       support::endian::write(*LocStream,
392a34c753fSRafael Auler                              static_cast<uint16_t>(Entry.Expr.size()),
393a34c753fSRafael Auler                              support::little);
394a34c753fSRafael Auler       *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
395a34c753fSRafael Auler                               Entry.Expr.size());
396a34c753fSRafael Auler     }
397a34c753fSRafael Auler     support::endian::write(*LocStream,
398a34c753fSRafael Auler                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
399a34c753fSRafael Auler                            support::little);
400a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
401a34c753fSRafael Auler     clearList(Patch.LocList);
402a34c753fSRafael Auler   }
403a34c753fSRafael Auler   clearList(Patches);
404a34c753fSRafael Auler }
405a34c753fSRafael Auler 
406a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
407a34c753fSRafael Auler 
4081c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) {
4091c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4101c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
411ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset));
412a34c753fSRafael Auler }
413a34c753fSRafael Auler 
4141c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) {
4151c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4161c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
4171c2f4bbeSAlexander Yermolovich   auto RetVal = DestinationLabels.insert(Offset);
4181c2f4bbeSAlexander Yermolovich   if (!RetVal.second)
4191c2f4bbeSAlexander Yermolovich     return;
4201c2f4bbeSAlexander Yermolovich 
421ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DestinationReferenceLabel(Offset));
422a34c753fSRafael Auler }
423a34c753fSRafael Auler 
424bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
425bd1ebe9dSAlexander Yermolovich   std::string LE64(ByteSize, 0);
426bd1ebe9dSAlexander Yermolovich   for (size_t I = 0; I < ByteSize; ++I) {
427bd1ebe9dSAlexander Yermolovich     LE64[I] = NewValue & 0xff;
428bd1ebe9dSAlexander Yermolovich     NewValue >>= 8;
429bd1ebe9dSAlexander Yermolovich   }
430bd1ebe9dSAlexander Yermolovich   return LE64;
431bd1ebe9dSAlexander Yermolovich }
432bd1ebe9dSAlexander Yermolovich 
433bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
434bd1ebe9dSAlexander Yermolovich                                             uint32_t Value) {
435bd1ebe9dSAlexander Yermolovich   std::string StrValue = encodeLE(4, Value);
436bd1ebe9dSAlexander Yermolovich   insertNewEntry(DIE, std::move(StrValue));
437bd1ebe9dSAlexander Yermolovich }
438bd1ebe9dSAlexander Yermolovich 
439bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
440bd1ebe9dSAlexander Yermolovich                                             std::string &&Value) {
441bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration *AbbrevDecl =
442bd1ebe9dSAlexander Yermolovich       DIE.getAbbreviationDeclarationPtr();
443bd1ebe9dSAlexander Yermolovich 
444bd1ebe9dSAlexander Yermolovich   // In case this DIE has no attributes.
445bd1ebe9dSAlexander Yermolovich   uint32_t Offset = DIE.getOffset() + 1;
446bd1ebe9dSAlexander Yermolovich   size_t NumOfAttributes = AbbrevDecl->getNumAttributes();
447bd1ebe9dSAlexander Yermolovich   if (NumOfAttributes) {
448bd1ebe9dSAlexander Yermolovich     Optional<AttrInfo> Val =
449bd1ebe9dSAlexander Yermolovich         findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1);
450bd1ebe9dSAlexander Yermolovich     assert(Val && "Invalid Value.");
451bd1ebe9dSAlexander Yermolovich 
452bd1ebe9dSAlexander Yermolovich     Offset = Val->Offset + Val->Size - DWPUnitOffset;
453bd1ebe9dSAlexander Yermolovich   }
454bd1ebe9dSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
455bd1ebe9dSAlexander Yermolovich   DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value)));
456bd1ebe9dSAlexander Yermolovich }
457bd1ebe9dSAlexander Yermolovich 
4581c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset,
4591c2f4bbeSAlexander Yermolovich                                                  uint32_t DestinationOffset,
4601c2f4bbeSAlexander Yermolovich                                                  uint32_t OldValueSize,
4611c2f4bbeSAlexander Yermolovich                                                  dwarf::Form Form) {
4621c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4631c2f4bbeSAlexander Yermolovich   DestinationOffset -= DWPUnitOffset;
4641c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
465ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(
466ea6c8b01SAlexander Yermolovich       new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form));
4671c2f4bbeSAlexander Yermolovich }
4681c2f4bbeSAlexander Yermolovich 
4691c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue,
4701c2f4bbeSAlexander Yermolovich                                            uint32_t OldValueSize) {
4711c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4721c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
4731c2f4bbeSAlexander Yermolovich   DebugPatches.emplace_back(
474ea6c8b01SAlexander Yermolovich       new DebugPatchVariableSize(Offset, OldValueSize, NewValue));
4751c2f4bbeSAlexander Yermolovich }
4761c2f4bbeSAlexander Yermolovich 
4771c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
4781c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4791c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
480ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue));
4811c2f4bbeSAlexander Yermolovich }
4821c2f4bbeSAlexander Yermolovich 
4831c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
4841c2f4bbeSAlexander Yermolovich                                           uint32_t OldValueSize) {
4851c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4861c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
4871c2f4bbeSAlexander Yermolovich   if (OldValueSize == 4)
488ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue));
489*a44fe319SAlexander Yermolovich   else if (OldValueSize == 8)
490ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue));
491*a44fe319SAlexander Yermolovich   else
492*a44fe319SAlexander Yermolovich     DebugPatches.emplace_back(
493*a44fe319SAlexander Yermolovich         new DebugPatch32GenericSize(Offset, NewValue, OldValueSize));
4941c2f4bbeSAlexander Yermolovich }
4951c2f4bbeSAlexander Yermolovich 
4961c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
4971c2f4bbeSAlexander Yermolovich                                          std::string &&NewValue,
4981c2f4bbeSAlexander Yermolovich                                          uint32_t OldValueSize) {
4991c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(NewValue));
5001c2f4bbeSAlexander Yermolovich }
5011c2f4bbeSAlexander Yermolovich 
5021c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
5031c2f4bbeSAlexander Yermolovich   auto Str = std::string(1, Value);
5041c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Str));
5051c2f4bbeSAlexander Yermolovich }
5061c2f4bbeSAlexander Yermolovich 
5071c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
5081c2f4bbeSAlexander Yermolovich                                      size_t ByteSize) {
5091c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
5101c2f4bbeSAlexander Yermolovich }
5111c2f4bbeSAlexander Yermolovich 
5121c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
5131c2f4bbeSAlexander Yermolovich                                         uint32_t OldValueSize) {
514a34c753fSRafael Auler   std::string Buff;
515a34c753fSRafael Auler   raw_string_ostream OS(Buff);
5161c2f4bbeSAlexander Yermolovich   encodeULEB128(Value, OS, OldValueSize);
517a34c753fSRafael Auler 
5181c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Buff));
519a34c753fSRafael Auler }
520a34c753fSRafael Auler 
5211c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
522a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
523a34c753fSRafael Auler }
524a34c753fSRafael Auler 
5251c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
5261c2f4bbeSAlexander Yermolovich                                        uint32_t OldValueSize) {
527a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
528a34c753fSRafael Auler }
529a34c753fSRafael Auler 
5301c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
5311c2f4bbeSAlexander Yermolovich   std::string BinaryContentsStr = std::string(BinaryContents);
532a34c753fSRafael Auler   for (const auto &Patch : Patches) {
5331c2f4bbeSAlexander Yermolovich     uint32_t Offset = Patch.first;
534a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
535a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
536a34c753fSRafael Auler            "Applied patch runs over binary size.");
537a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
5381c2f4bbeSAlexander Yermolovich       BinaryContentsStr[Offset + I] = ByteSequence[I];
539a34c753fSRafael Auler     }
540a34c753fSRafael Auler   }
5411c2f4bbeSAlexander Yermolovich   return BinaryContentsStr;
5421c2f4bbeSAlexander Yermolovich }
5431c2f4bbeSAlexander Yermolovich 
544612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
545612f0f45SAlexander Yermolovich                                                       bool IsDWOContext) {
546612f0f45SAlexander Yermolovich   CUOffsetMap CUMap;
547ea6c8b01SAlexander Yermolovich   std::sort(DebugPatches.begin(), DebugPatches.end(),
548ea6c8b01SAlexander Yermolovich             [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
549bd1ebe9dSAlexander Yermolovich               if (V1.get()->Offset == V2.get()->Offset) {
550bd1ebe9dSAlexander Yermolovich                 if (V1->Kind == DebugPatchKind::NewDebugEntry &&
551bd1ebe9dSAlexander Yermolovich                     V2->Kind == DebugPatchKind::NewDebugEntry)
552bd1ebe9dSAlexander Yermolovich                   return reinterpret_cast<const NewDebugEntry *>(V1.get())
553bd1ebe9dSAlexander Yermolovich                              ->CurrentOrder <
554bd1ebe9dSAlexander Yermolovich                          reinterpret_cast<const NewDebugEntry *>(V2.get())
555bd1ebe9dSAlexander Yermolovich                              ->CurrentOrder;
556bd1ebe9dSAlexander Yermolovich 
557bd1ebe9dSAlexander Yermolovich                 // This is a case where we are modifying first entry of next
558bd1ebe9dSAlexander Yermolovich                 // DIE, and adding a new one.
559bd1ebe9dSAlexander Yermolovich                 return V1->Kind == DebugPatchKind::NewDebugEntry;
560bd1ebe9dSAlexander Yermolovich               }
5611c2f4bbeSAlexander Yermolovich               return V1.get()->Offset < V2.get()->Offset;
5621c2f4bbeSAlexander Yermolovich             });
5631c2f4bbeSAlexander Yermolovich 
564612f0f45SAlexander Yermolovich   DWARFUnitVector::compile_unit_range CompileUnits =
565612f0f45SAlexander Yermolovich       IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();
566612f0f45SAlexander Yermolovich 
567612f0f45SAlexander Yermolovich   for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
568612f0f45SAlexander Yermolovich     CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
569612f0f45SAlexander Yermolovich                               static_cast<uint32_t>(CU->getLength())};
570612f0f45SAlexander Yermolovich 
5711c2f4bbeSAlexander Yermolovich   // Calculating changes in .debug_info size from Patches to build a map of old
5721c2f4bbeSAlexander Yermolovich   // to updated reference destination offsets.
573612f0f45SAlexander Yermolovich   uint32_t PreviousOffset = 0;
574612f0f45SAlexander Yermolovich   int32_t PreviousChangeInSize = 0;
575ea6c8b01SAlexander Yermolovich   for (UniquePatchPtrType &PatchBase : DebugPatches) {
5761c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
5771c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
5781c2f4bbeSAlexander Yermolovich     default:
5791c2f4bbeSAlexander Yermolovich       continue;
5801c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
581612f0f45SAlexander Yermolovich       PreviousChangeInSize -= 4;
5821c2f4bbeSAlexander Yermolovich       break;
5831c2f4bbeSAlexander Yermolovich     }
584*a44fe319SAlexander Yermolovich     case DebugPatchKind::PatchValue32GenericSize: {
585*a44fe319SAlexander Yermolovich       DebugPatch32GenericSize *DPVS =
586*a44fe319SAlexander Yermolovich           reinterpret_cast<DebugPatch32GenericSize *>(P);
587*a44fe319SAlexander Yermolovich       PreviousChangeInSize += 4 - DPVS->OldValueSize;
588*a44fe319SAlexander Yermolovich       break;
589*a44fe319SAlexander Yermolovich     }
5901c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
5911c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *DPV =
5921c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
5931c2f4bbeSAlexander Yermolovich       std::string Temp;
5941c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(Temp);
5951c2f4bbeSAlexander Yermolovich       encodeULEB128(DPV->Value, OS);
596612f0f45SAlexander Yermolovich       PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
5971c2f4bbeSAlexander Yermolovich       break;
5981c2f4bbeSAlexander Yermolovich     }
5991c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DestinationReferenceLabel: {
6001c2f4bbeSAlexander Yermolovich       DestinationReferenceLabel *DRL =
6011c2f4bbeSAlexander Yermolovich           reinterpret_cast<DestinationReferenceLabel *>(P);
602612f0f45SAlexander Yermolovich       OldToNewOffset[DRL->Offset] =
603612f0f45SAlexander Yermolovich           DRL->Offset + ChangeInSize + PreviousChangeInSize;
6041c2f4bbeSAlexander Yermolovich       break;
6051c2f4bbeSAlexander Yermolovich     }
6061c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
6071c2f4bbeSAlexander Yermolovich       // This doesn't look to be a common case, so will always encode as 4 bytes
6081c2f4bbeSAlexander Yermolovich       // to reduce algorithmic complexity.
6091c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
6101c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.IndirectRelative) {
611612f0f45SAlexander Yermolovich         PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
6121c2f4bbeSAlexander Yermolovich         assert(RDP->PatchInfo.OldValueSize <= 4 &&
6131c2f4bbeSAlexander Yermolovich                "Variable encoding reference greater than 4 bytes.");
6141c2f4bbeSAlexander Yermolovich       }
6151c2f4bbeSAlexander Yermolovich       break;
6161c2f4bbeSAlexander Yermolovich     }
6171c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
6181c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
6191c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
6201c2f4bbeSAlexander Yermolovich       uint32_t CUOffset = BaseLabel->Offset;
621612f0f45SAlexander Yermolovich       ChangeInSize += PreviousChangeInSize;
6221c2f4bbeSAlexander Yermolovich       uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
623612f0f45SAlexander Yermolovich       CUMap[CUOffset].Offset = CUOffsetUpdate;
624612f0f45SAlexander Yermolovich       CUMap[PreviousOffset].Length += PreviousChangeInSize;
625612f0f45SAlexander Yermolovich       PreviousChangeInSize = 0;
626612f0f45SAlexander Yermolovich       PreviousOffset = CUOffset;
627bd1ebe9dSAlexander Yermolovich       break;
628bd1ebe9dSAlexander Yermolovich     }
629bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
630bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
631bd1ebe9dSAlexander Yermolovich       PreviousChangeInSize += NDE->Value.size();
632bd1ebe9dSAlexander Yermolovich       break;
6331c2f4bbeSAlexander Yermolovich     }
6341c2f4bbeSAlexander Yermolovich     }
6351c2f4bbeSAlexander Yermolovich   }
636612f0f45SAlexander Yermolovich   CUMap[PreviousOffset].Length += PreviousChangeInSize;
6371c2f4bbeSAlexander Yermolovich   return CUMap;
6381c2f4bbeSAlexander Yermolovich }
639bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0;
6401c2f4bbeSAlexander Yermolovich 
6411c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) {
6421c2f4bbeSAlexander Yermolovich   std::string NewBinaryContents;
6431c2f4bbeSAlexander Yermolovich   NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize);
6441c2f4bbeSAlexander Yermolovich   uint32_t StartOffset = 0;
6451c2f4bbeSAlexander Yermolovich   uint32_t DwarfUnitBaseOffset = 0;
6461c2f4bbeSAlexander Yermolovich   uint32_t OldValueSize = 0;
6471c2f4bbeSAlexander Yermolovich   uint32_t Offset = 0;
6481c2f4bbeSAlexander Yermolovich   std::string ByteSequence;
6491c2f4bbeSAlexander Yermolovich   std::vector<std::pair<uint32_t, uint32_t>> LengthPatches;
6501c2f4bbeSAlexander Yermolovich   // Wasting one entry to avoid checks for first.
6511c2f4bbeSAlexander Yermolovich   LengthPatches.push_back({0, 0});
6521c2f4bbeSAlexander Yermolovich 
6531c2f4bbeSAlexander Yermolovich   // Applying all the patches replacing current entry.
6541c2f4bbeSAlexander Yermolovich   // This might change the size of .debug_info section.
655ea6c8b01SAlexander Yermolovich   for (const UniquePatchPtrType &PatchBase : DebugPatches) {
6561c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
6571c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
6581c2f4bbeSAlexander Yermolovich     default:
6591c2f4bbeSAlexander Yermolovich       continue;
6601c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
6611c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
6621c2f4bbeSAlexander Yermolovich       uint32_t DestinationOffset = RDP->DestinationOffset;
6631c2f4bbeSAlexander Yermolovich       assert(OldToNewOffset.count(DestinationOffset) &&
6641c2f4bbeSAlexander Yermolovich              "Destination Offset for reference not updated.");
6651c2f4bbeSAlexander Yermolovich       uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset];
6661c2f4bbeSAlexander Yermolovich       Offset = RDP->Offset;
6671c2f4bbeSAlexander Yermolovich       OldValueSize = RDP->PatchInfo.OldValueSize;
6681c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.DirectRelative) {
6691c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
6701c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
6711c2f4bbeSAlexander Yermolovich         // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge
6721c2f4bbeSAlexander Yermolovich         // and overflow if later debug information grows.
6731c2f4bbeSAlexander Yermolovich         if (ByteSequence.size() > OldValueSize)
6741c2f4bbeSAlexander Yermolovich           errs() << "BOLT-ERROR: Relative reference of size "
6751c2f4bbeSAlexander Yermolovich                  << Twine::utohexstr(OldValueSize)
6761c2f4bbeSAlexander Yermolovich                  << " overflows with the new encoding.\n";
6771c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.DirectAbsolute) {
6781c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
6791c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.IndirectRelative) {
6801c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
6811c2f4bbeSAlexander Yermolovich         ByteSequence.clear();
6821c2f4bbeSAlexander Yermolovich         raw_string_ostream OS(ByteSequence);
6831c2f4bbeSAlexander Yermolovich         encodeULEB128(UpdatedOffset, OS, 4);
6841c2f4bbeSAlexander Yermolovich       } else {
6851c2f4bbeSAlexander Yermolovich         llvm_unreachable("Invalid Reference form.");
6861c2f4bbeSAlexander Yermolovich       }
6871c2f4bbeSAlexander Yermolovich       break;
6881c2f4bbeSAlexander Yermolovich     }
6891c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue32: {
6901c2f4bbeSAlexander Yermolovich       DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P);
6911c2f4bbeSAlexander Yermolovich       Offset = P32->Offset;
6921c2f4bbeSAlexander Yermolovich       OldValueSize = 4;
6931c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P32->Value);
6941c2f4bbeSAlexander Yermolovich       break;
6951c2f4bbeSAlexander Yermolovich     }
6961c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
6971c2f4bbeSAlexander Yermolovich       DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P);
6981c2f4bbeSAlexander Yermolovich       Offset = P64to32->Offset;
6991c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
7001c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P64to32->Value);
7011c2f4bbeSAlexander Yermolovich       break;
7021c2f4bbeSAlexander Yermolovich     }
703*a44fe319SAlexander Yermolovich     case DebugPatchKind::PatchValue32GenericSize: {
704*a44fe319SAlexander Yermolovich       DebugPatch32GenericSize *DPVS =
705*a44fe319SAlexander Yermolovich           reinterpret_cast<DebugPatch32GenericSize *>(P);
706*a44fe319SAlexander Yermolovich       Offset = DPVS->Offset;
707*a44fe319SAlexander Yermolovich       OldValueSize = DPVS->OldValueSize;
708*a44fe319SAlexander Yermolovich       ByteSequence = encodeLE(4, DPVS->Value);
709*a44fe319SAlexander Yermolovich       break;
710*a44fe319SAlexander Yermolovich     }
7111c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
7121c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *PV =
7131c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
7141c2f4bbeSAlexander Yermolovich       Offset = PV->Offset;
7151c2f4bbeSAlexander Yermolovich       OldValueSize = PV->OldValueSize;
7161c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
7171c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(ByteSequence);
7181c2f4bbeSAlexander Yermolovich       encodeULEB128(PV->Value, OS);
7191c2f4bbeSAlexander Yermolovich       break;
7201c2f4bbeSAlexander Yermolovich     }
7211c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64: {
7221c2f4bbeSAlexander Yermolovich       DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P);
7231c2f4bbeSAlexander Yermolovich       Offset = P64->Offset;
7241c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
7251c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(8, P64->Value);
7261c2f4bbeSAlexander Yermolovich       break;
7271c2f4bbeSAlexander Yermolovich     }
7281c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
7291c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
7301c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
7311c2f4bbeSAlexander Yermolovich       Offset = BaseLabel->Offset;
7321c2f4bbeSAlexander Yermolovich       OldValueSize = 0;
7331c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
7341c2f4bbeSAlexander Yermolovich       auto &Patch = LengthPatches.back();
7351c2f4bbeSAlexander Yermolovich       // Length to copy between last patch entry and next compile unit.
7361c2f4bbeSAlexander Yermolovich       uint32_t RemainingLength = Offset - StartOffset;
7371c2f4bbeSAlexander Yermolovich       uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength;
7381c2f4bbeSAlexander Yermolovich       DwarfUnitBaseOffset = NewCUOffset;
7391c2f4bbeSAlexander Yermolovich       // Length of previous CU = This CU Offset - sizeof(length) - last CU
7401c2f4bbeSAlexander Yermolovich       // Offset.
7411c2f4bbeSAlexander Yermolovich       Patch.second = NewCUOffset - 4 - Patch.first;
7421c2f4bbeSAlexander Yermolovich       LengthPatches.push_back({NewCUOffset, 0});
7431c2f4bbeSAlexander Yermolovich       break;
7441c2f4bbeSAlexander Yermolovich     }
745bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
746bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
747bd1ebe9dSAlexander Yermolovich       Offset = NDE->Offset;
748bd1ebe9dSAlexander Yermolovich       OldValueSize = 0;
749bd1ebe9dSAlexander Yermolovich       ByteSequence = NDE->Value;
750bd1ebe9dSAlexander Yermolovich       break;
751bd1ebe9dSAlexander Yermolovich     }
7521c2f4bbeSAlexander Yermolovich     }
7531c2f4bbeSAlexander Yermolovich 
754bd1ebe9dSAlexander Yermolovich     assert((P->Kind == DebugPatchKind::NewDebugEntry ||
755bd1ebe9dSAlexander Yermolovich             Offset + ByteSequence.size() <= BinaryContents.size()) &&
7561c2f4bbeSAlexander Yermolovich            "Applied patch runs over binary size.");
7571c2f4bbeSAlexander Yermolovich     uint32_t Length = Offset - StartOffset;
7581c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
7591c2f4bbeSAlexander Yermolovich                              Length);
7601c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(ByteSequence.data(), ByteSequence.size());
7611c2f4bbeSAlexander Yermolovich     StartOffset = Offset + OldValueSize;
7621c2f4bbeSAlexander Yermolovich   }
7631c2f4bbeSAlexander Yermolovich   uint32_t Length = BinaryContents.size() - StartOffset;
7641c2f4bbeSAlexander Yermolovich   NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
7651c2f4bbeSAlexander Yermolovich                            Length);
7661c2f4bbeSAlexander Yermolovich   DebugPatches.clear();
7671c2f4bbeSAlexander Yermolovich 
7681c2f4bbeSAlexander Yermolovich   // Patching lengths of CUs
7691c2f4bbeSAlexander Yermolovich   auto &Patch = LengthPatches.back();
7701c2f4bbeSAlexander Yermolovich   Patch.second = NewBinaryContents.size() - 4 - Patch.first;
7711c2f4bbeSAlexander Yermolovich   for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) {
7721c2f4bbeSAlexander Yermolovich     const auto &Patch = LengthPatches[J];
7731c2f4bbeSAlexander Yermolovich     ByteSequence = encodeLE(4, Patch.second);
7741c2f4bbeSAlexander Yermolovich     Offset = Patch.first;
7751c2f4bbeSAlexander Yermolovich     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I)
7761c2f4bbeSAlexander Yermolovich       NewBinaryContents[Offset + I] = ByteSequence[I];
7771c2f4bbeSAlexander Yermolovich   }
7781c2f4bbeSAlexander Yermolovich 
7791c2f4bbeSAlexander Yermolovich   return NewBinaryContents;
780a34c753fSRafael Auler }
781a34c753fSRafael Auler 
782a34c753fSRafael Auler void DebugStrWriter::create() {
783a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
784a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
785a34c753fSRafael Auler }
786a34c753fSRafael Auler 
787a34c753fSRafael Auler void DebugStrWriter::initialize() {
788a34c753fSRafael Auler   auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
789a34c753fSRafael Auler   (*StrStream) << StrSection;
790a34c753fSRafael Auler }
791a34c753fSRafael Auler 
792a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
793e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
794a34c753fSRafael Auler   if (StrBuffer->empty())
795a34c753fSRafael Auler     initialize();
796a34c753fSRafael Auler   auto Offset = StrBuffer->size();
797a34c753fSRafael Auler   (*StrStream) << Str;
798a34c753fSRafael Auler   StrStream->write_zeros(1);
799a34c753fSRafael Auler   return Offset;
800a34c753fSRafael Auler }
801a34c753fSRafael Auler 
802a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
803a34c753fSRafael Auler   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
804a34c753fSRafael Auler   if (!Abbrevs)
805a34c753fSRafael Auler     return;
806a34c753fSRafael Auler 
80745f94abcSMaksim Panchenko   const PatchesTy &UnitPatches = Patches[&Unit];
808bd1ebe9dSAlexander Yermolovich   const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit];
809a34c753fSRafael Auler 
8109f3f9d19SAlexander Yermolovich   // We are duplicating abbrev sections, to handle the case where for one CU we
8119f3f9d19SAlexander Yermolovich   // modify it, but for another we don't.
8129f3f9d19SAlexander Yermolovich   auto UnitDataPtr = std::make_unique<AbbrevData>();
8139f3f9d19SAlexander Yermolovich   AbbrevData &UnitData = *UnitDataPtr.get();
8149f3f9d19SAlexander Yermolovich   UnitData.Buffer = std::make_unique<DebugBufferVector>();
8159f3f9d19SAlexander Yermolovich   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
816bd1ebe9dSAlexander Yermolovich 
817a34c753fSRafael Auler   raw_svector_ostream &OS = *UnitData.Stream.get();
818a34c753fSRafael Auler 
8199f3f9d19SAlexander Yermolovich   // Returns true if AbbrevData is re-used, false otherwise.
8209f3f9d19SAlexander Yermolovich   auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool {
8219f3f9d19SAlexander Yermolovich     llvm::SHA1 Hasher;
8229f3f9d19SAlexander Yermolovich     Hasher.update(AbbrevData);
8239f3f9d19SAlexander Yermolovich     StringRef Key = Hasher.final();
8249f3f9d19SAlexander Yermolovich     auto Iter = AbbrevDataCache.find(Key);
8259f3f9d19SAlexander Yermolovich     if (Iter != AbbrevDataCache.end()) {
8269f3f9d19SAlexander Yermolovich       UnitsAbbrevData[&Unit] = Iter->second.get();
8279f3f9d19SAlexander Yermolovich       return true;
8289f3f9d19SAlexander Yermolovich     }
8299f3f9d19SAlexander Yermolovich     AbbrevDataCache[Key] = std::move(UnitDataPtr);
8309f3f9d19SAlexander Yermolovich     UnitsAbbrevData[&Unit] = &UnitData;
8319f3f9d19SAlexander Yermolovich     return false;
8329f3f9d19SAlexander Yermolovich   };
833a34c753fSRafael Auler   // Take a fast path if there are no patches to apply. Simply copy the original
834a34c753fSRafael Auler   // contents.
835bd1ebe9dSAlexander Yermolovich   if (UnitPatches.empty() && AbbrevEntries.empty()) {
836a34c753fSRafael Auler     StringRef AbbrevSectionContents =
837a34c753fSRafael Auler         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
838a34c753fSRafael Auler                          : Unit.getContext().getDWARFObj().getAbbrevSection();
839a34c753fSRafael Auler     StringRef AbbrevContents;
840a34c753fSRafael Auler 
841a34c753fSRafael Auler     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
842a34c753fSRafael Auler     if (!CUIndex.getRows().empty()) {
843a34c753fSRafael Auler       // Handle DWP section contribution.
844a34c753fSRafael Auler       const DWARFUnitIndex::Entry *DWOEntry =
845a34c753fSRafael Auler           CUIndex.getFromHash(*Unit.getDWOId());
846a34c753fSRafael Auler       if (!DWOEntry)
847a34c753fSRafael Auler         return;
848a34c753fSRafael Auler 
849a34c753fSRafael Auler       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
850a34c753fSRafael Auler           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
851a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
852a34c753fSRafael Auler                                                     DWOContrubution->Length);
85345f94abcSMaksim Panchenko     } else if (!Unit.isDWOUnit()) {
854a34c753fSRafael Auler       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
85545f94abcSMaksim Panchenko 
85645f94abcSMaksim Panchenko       // We know where the unit's abbreviation set starts, but not where it ends
85745f94abcSMaksim Panchenko       // as such data is not readily available. Hence, we have to build a sorted
85845f94abcSMaksim Panchenko       // list of start addresses and find the next starting address to determine
85945f94abcSMaksim Panchenko       // the set boundaries.
86045f94abcSMaksim Panchenko       //
86145f94abcSMaksim Panchenko       // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
86245f94abcSMaksim Panchenko       // we wouldn't have to build our own sorted list for the quick lookup.
86345f94abcSMaksim Panchenko       if (AbbrevSetOffsets.empty()) {
8641c2f4bbeSAlexander Yermolovich         for_each(
86545f94abcSMaksim Panchenko             *Unit.getContext().getDebugAbbrev(),
86645f94abcSMaksim Panchenko             [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
86745f94abcSMaksim Panchenko               AbbrevSetOffsets.push_back(P.first);
86845f94abcSMaksim Panchenko             });
8691c2f4bbeSAlexander Yermolovich         sort(AbbrevSetOffsets);
87045f94abcSMaksim Panchenko       }
8711c2f4bbeSAlexander Yermolovich       auto It = upper_bound(AbbrevSetOffsets, StartOffset);
87245f94abcSMaksim Panchenko       const uint64_t EndOffset =
87345f94abcSMaksim Panchenko           It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
874a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
87545f94abcSMaksim Panchenko     } else {
87645f94abcSMaksim Panchenko       // For DWO unit outside of DWP, we expect the entire section to hold
87745f94abcSMaksim Panchenko       // abbreviations for this unit only.
87845f94abcSMaksim Panchenko       AbbrevContents = AbbrevSectionContents;
879a34c753fSRafael Auler     }
880a34c753fSRafael Auler 
8819f3f9d19SAlexander Yermolovich     if (!hashAndAddAbbrev(AbbrevContents)) {
882a34c753fSRafael Auler       OS.reserveExtraSpace(AbbrevContents.size());
883a34c753fSRafael Auler       OS << AbbrevContents;
8849f3f9d19SAlexander Yermolovich     }
885a34c753fSRafael Auler     return;
886a34c753fSRafael Auler   }
887a34c753fSRafael Auler 
888a34c753fSRafael Auler   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
889a34c753fSRafael Auler     const DWARFAbbreviationDeclaration &Abbrev = *I;
890a34c753fSRafael Auler     auto Patch = UnitPatches.find(&Abbrev);
891a34c753fSRafael Auler 
892a34c753fSRafael Auler     encodeULEB128(Abbrev.getCode(), OS);
893a34c753fSRafael Auler     encodeULEB128(Abbrev.getTag(), OS);
894a34c753fSRafael Auler     encodeULEB128(Abbrev.hasChildren(), OS);
895a34c753fSRafael Auler     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
896a34c753fSRafael Auler          Abbrev.attributes()) {
897a34c753fSRafael Auler       if (Patch != UnitPatches.end()) {
898a34c753fSRafael Auler         bool Patched = false;
899a34c753fSRafael Auler         // Patches added later take a precedence over earlier ones.
900a34c753fSRafael Auler         for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
901a34c753fSRafael Auler              ++I) {
902a34c753fSRafael Auler           if (I->OldAttr != AttrSpec.Attr)
903a34c753fSRafael Auler             continue;
904a34c753fSRafael Auler 
905a34c753fSRafael Auler           encodeULEB128(I->NewAttr, OS);
906a34c753fSRafael Auler           encodeULEB128(I->NewAttrForm, OS);
907a34c753fSRafael Auler           Patched = true;
908a34c753fSRafael Auler           break;
909a34c753fSRafael Auler         }
910a34c753fSRafael Auler         if (Patched)
911a34c753fSRafael Auler           continue;
912a34c753fSRafael Auler       }
913a34c753fSRafael Auler 
914a34c753fSRafael Auler       encodeULEB128(AttrSpec.Attr, OS);
915a34c753fSRafael Auler       encodeULEB128(AttrSpec.Form, OS);
916a34c753fSRafael Auler       if (AttrSpec.isImplicitConst())
917a34c753fSRafael Auler         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
918a34c753fSRafael Auler     }
919bd1ebe9dSAlexander Yermolovich     const auto Entries = AbbrevEntries.find(&Abbrev);
920bd1ebe9dSAlexander Yermolovich     // Adding new Abbrevs for inserted entries.
921bd1ebe9dSAlexander Yermolovich     if (Entries != AbbrevEntries.end()) {
922bd1ebe9dSAlexander Yermolovich       for (const AbbrevEntry &Entry : Entries->second) {
923bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Attr, OS);
924bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Form, OS);
925bd1ebe9dSAlexander Yermolovich       }
926bd1ebe9dSAlexander Yermolovich     }
927a34c753fSRafael Auler     encodeULEB128(0, OS);
928a34c753fSRafael Auler     encodeULEB128(0, OS);
929a34c753fSRafael Auler   }
930a34c753fSRafael Auler   encodeULEB128(0, OS);
9319f3f9d19SAlexander Yermolovich 
9329f3f9d19SAlexander Yermolovich   hashAndAddAbbrev(OS.str());
933a34c753fSRafael Auler }
934a34c753fSRafael Auler 
935a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
9369f3f9d19SAlexander Yermolovich   // Used to create determinism for writing out abbrevs.
9379f3f9d19SAlexander Yermolovich   std::vector<AbbrevData *> Abbrevs;
93845f94abcSMaksim Panchenko   if (DWOId) {
93945f94abcSMaksim Panchenko     // We expect abbrev_offset to always be zero for DWO units as there
94045f94abcSMaksim Panchenko     // should be one CU per DWO, and TUs should share the same abbreviation
94145f94abcSMaksim Panchenko     // set with the CU.
9421417f607SAlexander Yermolovich     // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so
9431417f607SAlexander Yermolovich     // can be none zero. Thus we are skipping the check for DWP.
94445f94abcSMaksim Panchenko     bool IsDWP = !Context.getCUIndex().getRows().empty();
9451417f607SAlexander Yermolovich     if (!IsDWP) {
94645f94abcSMaksim Panchenko       for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
94745f94abcSMaksim Panchenko         if (Unit->getAbbreviationsOffset() != 0) {
94845f94abcSMaksim Panchenko           errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
94945f94abcSMaksim Panchenko                     "Unable to update debug info.\n";
95045f94abcSMaksim Panchenko           exit(1);
95145f94abcSMaksim Panchenko         }
95245f94abcSMaksim Panchenko       }
95345f94abcSMaksim Panchenko     }
95445f94abcSMaksim Panchenko 
9559f3f9d19SAlexander Yermolovich     DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId);
95645f94abcSMaksim Panchenko     // Issue abbreviations for the DWO CU only.
95745f94abcSMaksim Panchenko     addUnitAbbreviations(*Unit);
9589f3f9d19SAlexander Yermolovich     AbbrevData *Abbrev = UnitsAbbrevData[Unit];
9599f3f9d19SAlexander Yermolovich     Abbrevs.push_back(Abbrev);
9609f3f9d19SAlexander Yermolovich   } else {
9619f3f9d19SAlexander Yermolovich     Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits());
9629f3f9d19SAlexander Yermolovich     std::unordered_set<AbbrevData *> ProcessedAbbrevs;
9639f3f9d19SAlexander Yermolovich     // Add abbreviations from compile and type non-DWO units.
9649f3f9d19SAlexander Yermolovich     for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) {
9659f3f9d19SAlexander Yermolovich       addUnitAbbreviations(*Unit);
9669f3f9d19SAlexander Yermolovich       AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()];
9679f3f9d19SAlexander Yermolovich       if (!ProcessedAbbrevs.insert(Abbrev).second)
9689f3f9d19SAlexander Yermolovich         continue;
9699f3f9d19SAlexander Yermolovich       Abbrevs.push_back(Abbrev);
9709f3f9d19SAlexander Yermolovich     }
97145f94abcSMaksim Panchenko   }
97245f94abcSMaksim Panchenko 
973a34c753fSRafael Auler   DebugBufferVector ReturnBuffer;
974a34c753fSRafael Auler   // Pre-calculate the total size of abbrev section.
975a34c753fSRafael Auler   uint64_t Size = 0;
9769f3f9d19SAlexander Yermolovich   for (const AbbrevData *UnitData : Abbrevs)
9779f3f9d19SAlexander Yermolovich     Size += UnitData->Buffer->size();
9789f3f9d19SAlexander Yermolovich 
979a34c753fSRafael Auler   ReturnBuffer.reserve(Size);
980a34c753fSRafael Auler 
981a34c753fSRafael Auler   uint64_t Pos = 0;
9829f3f9d19SAlexander Yermolovich   for (AbbrevData *UnitData : Abbrevs) {
9839f3f9d19SAlexander Yermolovich     ReturnBuffer.append(*UnitData->Buffer);
9849f3f9d19SAlexander Yermolovich     UnitData->Offset = Pos;
9859f3f9d19SAlexander Yermolovich     Pos += UnitData->Buffer->size();
986a34c753fSRafael Auler 
9879f3f9d19SAlexander Yermolovich     UnitData->Buffer.reset();
9889f3f9d19SAlexander Yermolovich     UnitData->Stream.reset();
989a34c753fSRafael Auler   }
990a34c753fSRafael Auler 
991a34c753fSRafael Auler   return std::make_unique<DebugBufferVector>(ReturnBuffer);
992a34c753fSRafael Auler }
993a34c753fSRafael Auler 
994a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
995a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
996a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
997a34c753fSRafael Auler                                     int PointerSize) {
998a34c753fSRafael Auler   // emit the sequence to set the address
999a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
1000a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
1001a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
1002a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
1003a34c753fSRafael Auler 
1004a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
1005a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
1006a34c753fSRafael Auler }
1007a34c753fSRafael Auler 
1008a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
1009a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
1010a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
1011a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
1012a34c753fSRafael Auler   if (InputSequences.empty())
1013a34c753fSRafael Auler     return;
1014a34c753fSRafael Auler 
1015a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
1016a34c753fSRafael Auler   unsigned FileNum = 1;
1017a34c753fSRafael Auler   unsigned LastLine = 1;
1018a34c753fSRafael Auler   unsigned Column = 0;
1019a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1020a34c753fSRafael Auler   unsigned Isa = 0;
1021a34c753fSRafael Auler   unsigned Discriminator = 0;
1022a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
1023a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
1024a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1025a34c753fSRafael Auler 
1026a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
1027a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
1028a34c753fSRafael Auler     FileNum = 1;
1029a34c753fSRafael Auler     LastLine = 1;
1030a34c753fSRafael Auler     Column = 0;
1031a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1032a34c753fSRafael Auler     Isa = 0;
1033a34c753fSRafael Auler     Discriminator = 0;
1034a34c753fSRafael Auler     LastAddress = InvalidAddress;
1035a34c753fSRafael Auler   };
1036a34c753fSRafael Auler 
1037a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
1038a34c753fSRafael Auler     const uint64_t SequenceStart =
1039a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
1040a34c753fSRafael Auler 
1041a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
1042a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
1043a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
1044a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
1045a34c753fSRafael Auler     }
1046a34c753fSRafael Auler 
1047a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
1048a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
1049a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
1050a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
1051a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
1052a34c753fSRafael Auler 
1053a34c753fSRafael Auler       if (FileNum != Row.File) {
1054a34c753fSRafael Auler         FileNum = Row.File;
1055a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1056a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
1057a34c753fSRafael Auler       }
1058a34c753fSRafael Auler       if (Column != Row.Column) {
1059a34c753fSRafael Auler         Column = Row.Column;
1060a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1061a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
1062a34c753fSRafael Auler       }
1063a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
1064a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
1065a34c753fSRafael Auler         Discriminator = Row.Discriminator;
1066a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
1067a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1068a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
1069a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1070a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
1071a34c753fSRafael Auler       }
1072a34c753fSRafael Auler       if (Isa != Row.Isa) {
1073a34c753fSRafael Auler         Isa = Row.Isa;
1074a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1075a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
1076a34c753fSRafael Auler       }
1077a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
1078a34c753fSRafael Auler         Flags = Row.IsStmt;
1079a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1080a34c753fSRafael Auler       }
1081a34c753fSRafael Auler       if (Row.BasicBlock)
1082a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1083a34c753fSRafael Auler       if (Row.PrologueEnd)
1084a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1085a34c753fSRafael Auler       if (Row.EpilogueBegin)
1086a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1087a34c753fSRafael Auler 
1088a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
1089a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
1090a34c753fSRafael Auler       if (Row.EndSequence) {
1091a34c753fSRafael Auler         emitEndOfSequence(Address);
1092a34c753fSRafael Auler       } else {
1093a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
1094a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1095a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
1096a34c753fSRafael Auler         else
1097a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1098a34c753fSRafael Auler 
1099a34c753fSRafael Auler         LastAddress = Address;
1100a34c753fSRafael Auler         LastLine = Row.Line;
1101a34c753fSRafael Auler       }
1102a34c753fSRafael Auler 
1103a34c753fSRafael Auler       Discriminator = 0;
1104a34c753fSRafael Auler     }
1105a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
1106a34c753fSRafael Auler   }
1107a34c753fSRafael Auler 
1108a34c753fSRafael Auler   // Finish with the end of the sequence.
1109a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
1110a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
1111a34c753fSRafael Auler }
1112a34c753fSRafael Auler 
1113a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
1114a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
1115a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
1116a34c753fSRafael Auler static inline void emitDwarfLineTable(
1117a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
1118a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1119a34c753fSRafael Auler   unsigned FileNum = 1;
1120a34c753fSRafael Auler   unsigned LastLine = 1;
1121a34c753fSRafael Auler   unsigned Column = 0;
1122a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1123a34c753fSRafael Auler   unsigned Isa = 0;
1124a34c753fSRafael Auler   unsigned Discriminator = 0;
1125a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
1126a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1127a34c753fSRafael Auler 
1128a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1129a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1130a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1131a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1132a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
1133a34c753fSRafael Auler       FileNum = 1;
1134a34c753fSRafael Auler       LastLine = 1;
1135a34c753fSRafael Auler       Column = 0;
1136a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1137a34c753fSRafael Auler       Isa = 0;
1138a34c753fSRafael Auler       Discriminator = 0;
1139a34c753fSRafael Auler       LastLabel = nullptr;
1140a34c753fSRafael Auler       continue;
1141a34c753fSRafael Auler     }
1142a34c753fSRafael Auler 
1143a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1144a34c753fSRafael Auler 
1145a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
1146a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
1147a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1148a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
1149a34c753fSRafael Auler     }
1150a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
1151a34c753fSRafael Auler       Column = LineEntry.getColumn();
1152a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1153a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
1154a34c753fSRafael Auler     }
1155a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
1156a34c753fSRafael Auler         MCOS->getContext().getDwarfVersion() >= 4) {
1157a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
1158a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
1159a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1160a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
1161a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1162a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
1163a34c753fSRafael Auler     }
1164a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
1165a34c753fSRafael Auler       Isa = LineEntry.getIsa();
1166a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1167a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
1168a34c753fSRafael Auler     }
1169a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1170a34c753fSRafael Auler       Flags = LineEntry.getFlags();
1171a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1172a34c753fSRafael Auler     }
1173a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1174a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1175a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1176a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1177a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1178a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1179a34c753fSRafael Auler 
1180a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
1181a34c753fSRafael Auler 
1182a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
1183a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
1184a34c753fSRafael Auler     // Label and the current Label.
1185a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1186a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
1187a34c753fSRafael Auler     Discriminator = 0;
1188a34c753fSRafael Auler     LastLine = LineEntry.getLine();
1189a34c753fSRafael Auler     LastLabel = Label;
1190a34c753fSRafael Auler   }
1191a34c753fSRafael Auler 
1192a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
1193a34c753fSRafael Auler }
1194a34c753fSRafael Auler 
1195a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1196b73c87bcSMaksim Panchenko                             Optional<MCDwarfLineStr> &LineStr,
1197b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
1198a34c753fSRafael Auler   if (!RawData.empty()) {
1199a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
1200a34c753fSRafael Auler            InputSequences.empty() &&
1201a34c753fSRafael Auler            "cannot combine raw data with new line entries");
1202a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
1203a34c753fSRafael Auler     MCOS->emitBytes(RawData);
1204a34c753fSRafael Auler 
1205b73c87bcSMaksim Panchenko     // Emit fake relocation for RuntimeDyld to always allocate the section.
1206b73c87bcSMaksim Panchenko     //
1207b73c87bcSMaksim Panchenko     // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
1208b73c87bcSMaksim Panchenko     //        without relocations.
1209b73c87bcSMaksim Panchenko     MCOS->emitRelocDirective(
1210b73c87bcSMaksim Panchenko         *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
1211b73c87bcSMaksim Panchenko         MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);
1212b73c87bcSMaksim Panchenko 
1213a34c753fSRafael Auler     return;
1214a34c753fSRafael Auler   }
1215a34c753fSRafael Auler 
1216a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1217a34c753fSRafael Auler 
1218a34c753fSRafael Auler   // Put out the line tables.
1219a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1220a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1221a34c753fSRafael Auler 
1222a34c753fSRafael Auler   // Emit line tables for the original code.
1223a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1224a34c753fSRafael Auler 
1225a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
1226a34c753fSRafael Auler   // of this section (that was used in a previous expression).
1227a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
1228a34c753fSRafael Auler }
1229a34c753fSRafael Auler 
1230a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1231a34c753fSRafael Auler   MCAssembler &Assembler =
1232a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1233a34c753fSRafael Auler 
1234a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1235a34c753fSRafael Auler 
1236a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
1237a34c753fSRafael Auler 
1238a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
1239a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
1240a34c753fSRafael Auler   if (LineTables.empty())
1241a34c753fSRafael Auler     return;
1242a34c753fSRafael Auler 
1243a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
1244a34c753fSRafael Auler   Optional<MCDwarfLineStr> LineStr(None);
1245a34c753fSRafael Auler   if (BC.Ctx->getDwarfVersion() >= 5)
1246a34c753fSRafael Auler     LineStr = MCDwarfLineStr(*BC.Ctx);
1247a34c753fSRafael Auler 
1248a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
1249a34c753fSRafael Auler   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
1250a34c753fSRafael Auler 
1251a34c753fSRafael Auler   // Handle the rest of the Compile Units.
1252a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
1253b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1254a34c753fSRafael Auler   }
1255a34c753fSRafael Auler }
1256a34c753fSRafael Auler 
1257a34c753fSRafael Auler } // namespace bolt
1258a34c753fSRafael Auler } // namespace llvm
1259