xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision bd1ebe9d047b71b229cb79fe01e2b69fcbc1b9f3)
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 
42*bd1ebe9dSAlexander Yermolovich /// Finds attributes FormValue and Offset.
43*bd1ebe9dSAlexander Yermolovich ///
44*bd1ebe9dSAlexander Yermolovich /// \param DIE die to look up in.
45*bd1ebe9dSAlexander Yermolovich /// \param Index the attribute index to extract.
46*bd1ebe9dSAlexander Yermolovich /// \return an optional AttrInfo with DWARFFormValue and Offset.
47*bd1ebe9dSAlexander Yermolovich Optional<AttrInfo>
48*bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE,
49*bd1ebe9dSAlexander Yermolovich                   const DWARFAbbreviationDeclaration *AbbrevDecl,
50*bd1ebe9dSAlexander Yermolovich                   uint32_t Index) {
51*bd1ebe9dSAlexander Yermolovich   const DWARFUnit &U = *DIE.getDwarfUnit();
52*bd1ebe9dSAlexander Yermolovich   uint64_t Offset =
53*bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
54*bd1ebe9dSAlexander Yermolovich   Optional<DWARFFormValue> Value =
55*bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
56*bd1ebe9dSAlexander Yermolovich   if (!Value)
57*bd1ebe9dSAlexander Yermolovich     return None;
58*bd1ebe9dSAlexander Yermolovich   // AttributeSpec
59*bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
60*bd1ebe9dSAlexander Yermolovich       AbbrevDecl->attributes().begin() + Index;
61*bd1ebe9dSAlexander Yermolovich   uint32_t ValSize = 0;
62*bd1ebe9dSAlexander Yermolovich   Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
63*bd1ebe9dSAlexander Yermolovich   if (ValSizeOpt) {
64*bd1ebe9dSAlexander Yermolovich     ValSize = static_cast<uint32_t>(*ValSizeOpt);
65*bd1ebe9dSAlexander Yermolovich   } else {
66*bd1ebe9dSAlexander Yermolovich     DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
67*bd1ebe9dSAlexander Yermolovich     uint64_t NewOffset = Offset;
68*bd1ebe9dSAlexander Yermolovich     DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
69*bd1ebe9dSAlexander Yermolovich                               U.getFormParams());
70*bd1ebe9dSAlexander Yermolovich     // This includes entire size of the entry, which might not be just the
71*bd1ebe9dSAlexander Yermolovich     // encoding part. For example for DW_AT_loc it will include expression
72*bd1ebe9dSAlexander Yermolovich     // location.
73*bd1ebe9dSAlexander Yermolovich     ValSize = NewOffset - Offset;
74*bd1ebe9dSAlexander Yermolovich   }
75*bd1ebe9dSAlexander Yermolovich 
76*bd1ebe9dSAlexander Yermolovich   return AttrInfo{*Value, Offset, ValSize};
77*bd1ebe9dSAlexander Yermolovich }
78*bd1ebe9dSAlexander 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 
424*bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
425*bd1ebe9dSAlexander Yermolovich   std::string LE64(ByteSize, 0);
426*bd1ebe9dSAlexander Yermolovich   for (size_t I = 0; I < ByteSize; ++I) {
427*bd1ebe9dSAlexander Yermolovich     LE64[I] = NewValue & 0xff;
428*bd1ebe9dSAlexander Yermolovich     NewValue >>= 8;
429*bd1ebe9dSAlexander Yermolovich   }
430*bd1ebe9dSAlexander Yermolovich   return LE64;
431*bd1ebe9dSAlexander Yermolovich }
432*bd1ebe9dSAlexander Yermolovich 
433*bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
434*bd1ebe9dSAlexander Yermolovich                                             uint32_t Value) {
435*bd1ebe9dSAlexander Yermolovich   std::string StrValue = encodeLE(4, Value);
436*bd1ebe9dSAlexander Yermolovich   insertNewEntry(DIE, std::move(StrValue));
437*bd1ebe9dSAlexander Yermolovich }
438*bd1ebe9dSAlexander Yermolovich 
439*bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE,
440*bd1ebe9dSAlexander Yermolovich                                             std::string &&Value) {
441*bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration *AbbrevDecl =
442*bd1ebe9dSAlexander Yermolovich       DIE.getAbbreviationDeclarationPtr();
443*bd1ebe9dSAlexander Yermolovich 
444*bd1ebe9dSAlexander Yermolovich   // In case this DIE has no attributes.
445*bd1ebe9dSAlexander Yermolovich   uint32_t Offset = DIE.getOffset() + 1;
446*bd1ebe9dSAlexander Yermolovich   size_t NumOfAttributes = AbbrevDecl->getNumAttributes();
447*bd1ebe9dSAlexander Yermolovich   if (NumOfAttributes) {
448*bd1ebe9dSAlexander Yermolovich     Optional<AttrInfo> Val =
449*bd1ebe9dSAlexander Yermolovich         findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1);
450*bd1ebe9dSAlexander Yermolovich     assert(Val && "Invalid Value.");
451*bd1ebe9dSAlexander Yermolovich 
452*bd1ebe9dSAlexander Yermolovich     Offset = Val->Offset + Val->Size - DWPUnitOffset;
453*bd1ebe9dSAlexander Yermolovich   }
454*bd1ebe9dSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
455*bd1ebe9dSAlexander Yermolovich   DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value)));
456*bd1ebe9dSAlexander Yermolovich }
457*bd1ebe9dSAlexander 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));
4891c2f4bbeSAlexander Yermolovich   else
490ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue));
4911c2f4bbeSAlexander Yermolovich }
4921c2f4bbeSAlexander Yermolovich 
4931c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
4941c2f4bbeSAlexander Yermolovich                                          std::string &&NewValue,
4951c2f4bbeSAlexander Yermolovich                                          uint32_t OldValueSize) {
4961c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(NewValue));
4971c2f4bbeSAlexander Yermolovich }
4981c2f4bbeSAlexander Yermolovich 
4991c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
5001c2f4bbeSAlexander Yermolovich   auto Str = std::string(1, Value);
5011c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Str));
5021c2f4bbeSAlexander Yermolovich }
5031c2f4bbeSAlexander Yermolovich 
5041c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
5051c2f4bbeSAlexander Yermolovich                                      size_t ByteSize) {
5061c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
5071c2f4bbeSAlexander Yermolovich }
5081c2f4bbeSAlexander Yermolovich 
5091c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
5101c2f4bbeSAlexander Yermolovich                                         uint32_t OldValueSize) {
511a34c753fSRafael Auler   std::string Buff;
512a34c753fSRafael Auler   raw_string_ostream OS(Buff);
5131c2f4bbeSAlexander Yermolovich   encodeULEB128(Value, OS, OldValueSize);
514a34c753fSRafael Auler 
5151c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Buff));
516a34c753fSRafael Auler }
517a34c753fSRafael Auler 
5181c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
519a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
520a34c753fSRafael Auler }
521a34c753fSRafael Auler 
5221c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
5231c2f4bbeSAlexander Yermolovich                                        uint32_t OldValueSize) {
524a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
525a34c753fSRafael Auler }
526a34c753fSRafael Auler 
5271c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
5281c2f4bbeSAlexander Yermolovich   std::string BinaryContentsStr = std::string(BinaryContents);
529a34c753fSRafael Auler   for (const auto &Patch : Patches) {
5301c2f4bbeSAlexander Yermolovich     uint32_t Offset = Patch.first;
531a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
532a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
533a34c753fSRafael Auler            "Applied patch runs over binary size.");
534a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
5351c2f4bbeSAlexander Yermolovich       BinaryContentsStr[Offset + I] = ByteSequence[I];
536a34c753fSRafael Auler     }
537a34c753fSRafael Auler   }
5381c2f4bbeSAlexander Yermolovich   return BinaryContentsStr;
5391c2f4bbeSAlexander Yermolovich }
5401c2f4bbeSAlexander Yermolovich 
541612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
542612f0f45SAlexander Yermolovich                                                       bool IsDWOContext) {
543612f0f45SAlexander Yermolovich   CUOffsetMap CUMap;
544ea6c8b01SAlexander Yermolovich   std::sort(DebugPatches.begin(), DebugPatches.end(),
545ea6c8b01SAlexander Yermolovich             [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
546*bd1ebe9dSAlexander Yermolovich               if (V1.get()->Offset == V2.get()->Offset) {
547*bd1ebe9dSAlexander Yermolovich                 if (V1->Kind == DebugPatchKind::NewDebugEntry &&
548*bd1ebe9dSAlexander Yermolovich                     V2->Kind == DebugPatchKind::NewDebugEntry)
549*bd1ebe9dSAlexander Yermolovich                   return reinterpret_cast<const NewDebugEntry *>(V1.get())
550*bd1ebe9dSAlexander Yermolovich                              ->CurrentOrder <
551*bd1ebe9dSAlexander Yermolovich                          reinterpret_cast<const NewDebugEntry *>(V2.get())
552*bd1ebe9dSAlexander Yermolovich                              ->CurrentOrder;
553*bd1ebe9dSAlexander Yermolovich 
554*bd1ebe9dSAlexander Yermolovich                 // This is a case where we are modifying first entry of next
555*bd1ebe9dSAlexander Yermolovich                 // DIE, and adding a new one.
556*bd1ebe9dSAlexander Yermolovich                 return V1->Kind == DebugPatchKind::NewDebugEntry;
557*bd1ebe9dSAlexander Yermolovich               }
5581c2f4bbeSAlexander Yermolovich               return V1.get()->Offset < V2.get()->Offset;
5591c2f4bbeSAlexander Yermolovich             });
5601c2f4bbeSAlexander Yermolovich 
561612f0f45SAlexander Yermolovich   DWARFUnitVector::compile_unit_range CompileUnits =
562612f0f45SAlexander Yermolovich       IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();
563612f0f45SAlexander Yermolovich 
564612f0f45SAlexander Yermolovich   for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
565612f0f45SAlexander Yermolovich     CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
566612f0f45SAlexander Yermolovich                               static_cast<uint32_t>(CU->getLength())};
567612f0f45SAlexander Yermolovich 
5681c2f4bbeSAlexander Yermolovich   // Calculating changes in .debug_info size from Patches to build a map of old
5691c2f4bbeSAlexander Yermolovich   // to updated reference destination offsets.
570612f0f45SAlexander Yermolovich   uint32_t PreviousOffset = 0;
571612f0f45SAlexander Yermolovich   int32_t PreviousChangeInSize = 0;
572ea6c8b01SAlexander Yermolovich   for (UniquePatchPtrType &PatchBase : DebugPatches) {
5731c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
5741c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
5751c2f4bbeSAlexander Yermolovich     default:
5761c2f4bbeSAlexander Yermolovich       continue;
5771c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
578612f0f45SAlexander Yermolovich       PreviousChangeInSize -= 4;
5791c2f4bbeSAlexander Yermolovich       break;
5801c2f4bbeSAlexander Yermolovich     }
5811c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
5821c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *DPV =
5831c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
5841c2f4bbeSAlexander Yermolovich       std::string Temp;
5851c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(Temp);
5861c2f4bbeSAlexander Yermolovich       encodeULEB128(DPV->Value, OS);
587612f0f45SAlexander Yermolovich       PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
5881c2f4bbeSAlexander Yermolovich       break;
5891c2f4bbeSAlexander Yermolovich     }
5901c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DestinationReferenceLabel: {
5911c2f4bbeSAlexander Yermolovich       DestinationReferenceLabel *DRL =
5921c2f4bbeSAlexander Yermolovich           reinterpret_cast<DestinationReferenceLabel *>(P);
593612f0f45SAlexander Yermolovich       OldToNewOffset[DRL->Offset] =
594612f0f45SAlexander Yermolovich           DRL->Offset + ChangeInSize + PreviousChangeInSize;
5951c2f4bbeSAlexander Yermolovich       break;
5961c2f4bbeSAlexander Yermolovich     }
5971c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
5981c2f4bbeSAlexander Yermolovich       // This doesn't look to be a common case, so will always encode as 4 bytes
5991c2f4bbeSAlexander Yermolovich       // to reduce algorithmic complexity.
6001c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
6011c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.IndirectRelative) {
602612f0f45SAlexander Yermolovich         PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
6031c2f4bbeSAlexander Yermolovich         assert(RDP->PatchInfo.OldValueSize <= 4 &&
6041c2f4bbeSAlexander Yermolovich                "Variable encoding reference greater than 4 bytes.");
6051c2f4bbeSAlexander Yermolovich       }
6061c2f4bbeSAlexander Yermolovich       break;
6071c2f4bbeSAlexander Yermolovich     }
6081c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
6091c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
6101c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
6111c2f4bbeSAlexander Yermolovich       uint32_t CUOffset = BaseLabel->Offset;
612612f0f45SAlexander Yermolovich       ChangeInSize += PreviousChangeInSize;
6131c2f4bbeSAlexander Yermolovich       uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
614612f0f45SAlexander Yermolovich       CUMap[CUOffset].Offset = CUOffsetUpdate;
615612f0f45SAlexander Yermolovich       CUMap[PreviousOffset].Length += PreviousChangeInSize;
616612f0f45SAlexander Yermolovich       PreviousChangeInSize = 0;
617612f0f45SAlexander Yermolovich       PreviousOffset = CUOffset;
618*bd1ebe9dSAlexander Yermolovich       break;
619*bd1ebe9dSAlexander Yermolovich     }
620*bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
621*bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
622*bd1ebe9dSAlexander Yermolovich       PreviousChangeInSize += NDE->Value.size();
623*bd1ebe9dSAlexander Yermolovich       break;
6241c2f4bbeSAlexander Yermolovich     }
6251c2f4bbeSAlexander Yermolovich     }
6261c2f4bbeSAlexander Yermolovich   }
627612f0f45SAlexander Yermolovich   CUMap[PreviousOffset].Length += PreviousChangeInSize;
6281c2f4bbeSAlexander Yermolovich   return CUMap;
6291c2f4bbeSAlexander Yermolovich }
630*bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0;
6311c2f4bbeSAlexander Yermolovich 
6321c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) {
6331c2f4bbeSAlexander Yermolovich   std::string NewBinaryContents;
6341c2f4bbeSAlexander Yermolovich   NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize);
6351c2f4bbeSAlexander Yermolovich   uint32_t StartOffset = 0;
6361c2f4bbeSAlexander Yermolovich   uint32_t DwarfUnitBaseOffset = 0;
6371c2f4bbeSAlexander Yermolovich   uint32_t OldValueSize = 0;
6381c2f4bbeSAlexander Yermolovich   uint32_t Offset = 0;
6391c2f4bbeSAlexander Yermolovich   std::string ByteSequence;
6401c2f4bbeSAlexander Yermolovich   std::vector<std::pair<uint32_t, uint32_t>> LengthPatches;
6411c2f4bbeSAlexander Yermolovich   // Wasting one entry to avoid checks for first.
6421c2f4bbeSAlexander Yermolovich   LengthPatches.push_back({0, 0});
6431c2f4bbeSAlexander Yermolovich 
6441c2f4bbeSAlexander Yermolovich   // Applying all the patches replacing current entry.
6451c2f4bbeSAlexander Yermolovich   // This might change the size of .debug_info section.
646ea6c8b01SAlexander Yermolovich   for (const UniquePatchPtrType &PatchBase : DebugPatches) {
6471c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
6481c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
6491c2f4bbeSAlexander Yermolovich     default:
6501c2f4bbeSAlexander Yermolovich       continue;
6511c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
6521c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
6531c2f4bbeSAlexander Yermolovich       uint32_t DestinationOffset = RDP->DestinationOffset;
6541c2f4bbeSAlexander Yermolovich       assert(OldToNewOffset.count(DestinationOffset) &&
6551c2f4bbeSAlexander Yermolovich              "Destination Offset for reference not updated.");
6561c2f4bbeSAlexander Yermolovich       uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset];
6571c2f4bbeSAlexander Yermolovich       Offset = RDP->Offset;
6581c2f4bbeSAlexander Yermolovich       OldValueSize = RDP->PatchInfo.OldValueSize;
6591c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.DirectRelative) {
6601c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
6611c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
6621c2f4bbeSAlexander Yermolovich         // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge
6631c2f4bbeSAlexander Yermolovich         // and overflow if later debug information grows.
6641c2f4bbeSAlexander Yermolovich         if (ByteSequence.size() > OldValueSize)
6651c2f4bbeSAlexander Yermolovich           errs() << "BOLT-ERROR: Relative reference of size "
6661c2f4bbeSAlexander Yermolovich                  << Twine::utohexstr(OldValueSize)
6671c2f4bbeSAlexander Yermolovich                  << " overflows with the new encoding.\n";
6681c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.DirectAbsolute) {
6691c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
6701c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.IndirectRelative) {
6711c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
6721c2f4bbeSAlexander Yermolovich         ByteSequence.clear();
6731c2f4bbeSAlexander Yermolovich         raw_string_ostream OS(ByteSequence);
6741c2f4bbeSAlexander Yermolovich         encodeULEB128(UpdatedOffset, OS, 4);
6751c2f4bbeSAlexander Yermolovich       } else {
6761c2f4bbeSAlexander Yermolovich         llvm_unreachable("Invalid Reference form.");
6771c2f4bbeSAlexander Yermolovich       }
6781c2f4bbeSAlexander Yermolovich       break;
6791c2f4bbeSAlexander Yermolovich     }
6801c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue32: {
6811c2f4bbeSAlexander Yermolovich       DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P);
6821c2f4bbeSAlexander Yermolovich       Offset = P32->Offset;
6831c2f4bbeSAlexander Yermolovich       OldValueSize = 4;
6841c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P32->Value);
6851c2f4bbeSAlexander Yermolovich       break;
6861c2f4bbeSAlexander Yermolovich     }
6871c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
6881c2f4bbeSAlexander Yermolovich       DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P);
6891c2f4bbeSAlexander Yermolovich       Offset = P64to32->Offset;
6901c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
6911c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P64to32->Value);
6921c2f4bbeSAlexander Yermolovich       break;
6931c2f4bbeSAlexander Yermolovich     }
6941c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
6951c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *PV =
6961c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
6971c2f4bbeSAlexander Yermolovich       Offset = PV->Offset;
6981c2f4bbeSAlexander Yermolovich       OldValueSize = PV->OldValueSize;
6991c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
7001c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(ByteSequence);
7011c2f4bbeSAlexander Yermolovich       encodeULEB128(PV->Value, OS);
7021c2f4bbeSAlexander Yermolovich       break;
7031c2f4bbeSAlexander Yermolovich     }
7041c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64: {
7051c2f4bbeSAlexander Yermolovich       DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P);
7061c2f4bbeSAlexander Yermolovich       Offset = P64->Offset;
7071c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
7081c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(8, P64->Value);
7091c2f4bbeSAlexander Yermolovich       break;
7101c2f4bbeSAlexander Yermolovich     }
7111c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
7121c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
7131c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
7141c2f4bbeSAlexander Yermolovich       Offset = BaseLabel->Offset;
7151c2f4bbeSAlexander Yermolovich       OldValueSize = 0;
7161c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
7171c2f4bbeSAlexander Yermolovich       auto &Patch = LengthPatches.back();
7181c2f4bbeSAlexander Yermolovich       // Length to copy between last patch entry and next compile unit.
7191c2f4bbeSAlexander Yermolovich       uint32_t RemainingLength = Offset - StartOffset;
7201c2f4bbeSAlexander Yermolovich       uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength;
7211c2f4bbeSAlexander Yermolovich       DwarfUnitBaseOffset = NewCUOffset;
7221c2f4bbeSAlexander Yermolovich       // Length of previous CU = This CU Offset - sizeof(length) - last CU
7231c2f4bbeSAlexander Yermolovich       // Offset.
7241c2f4bbeSAlexander Yermolovich       Patch.second = NewCUOffset - 4 - Patch.first;
7251c2f4bbeSAlexander Yermolovich       LengthPatches.push_back({NewCUOffset, 0});
7261c2f4bbeSAlexander Yermolovich       break;
7271c2f4bbeSAlexander Yermolovich     }
728*bd1ebe9dSAlexander Yermolovich     case DebugPatchKind::NewDebugEntry: {
729*bd1ebe9dSAlexander Yermolovich       NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P);
730*bd1ebe9dSAlexander Yermolovich       Offset = NDE->Offset;
731*bd1ebe9dSAlexander Yermolovich       OldValueSize = 0;
732*bd1ebe9dSAlexander Yermolovich       ByteSequence = NDE->Value;
733*bd1ebe9dSAlexander Yermolovich       break;
734*bd1ebe9dSAlexander Yermolovich     }
7351c2f4bbeSAlexander Yermolovich     }
7361c2f4bbeSAlexander Yermolovich 
737*bd1ebe9dSAlexander Yermolovich     assert((P->Kind == DebugPatchKind::NewDebugEntry ||
738*bd1ebe9dSAlexander Yermolovich             Offset + ByteSequence.size() <= BinaryContents.size()) &&
7391c2f4bbeSAlexander Yermolovich            "Applied patch runs over binary size.");
7401c2f4bbeSAlexander Yermolovich     uint32_t Length = Offset - StartOffset;
7411c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
7421c2f4bbeSAlexander Yermolovich                              Length);
7431c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(ByteSequence.data(), ByteSequence.size());
7441c2f4bbeSAlexander Yermolovich     StartOffset = Offset + OldValueSize;
7451c2f4bbeSAlexander Yermolovich   }
7461c2f4bbeSAlexander Yermolovich   uint32_t Length = BinaryContents.size() - StartOffset;
7471c2f4bbeSAlexander Yermolovich   NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
7481c2f4bbeSAlexander Yermolovich                            Length);
7491c2f4bbeSAlexander Yermolovich   DebugPatches.clear();
7501c2f4bbeSAlexander Yermolovich 
7511c2f4bbeSAlexander Yermolovich   // Patching lengths of CUs
7521c2f4bbeSAlexander Yermolovich   auto &Patch = LengthPatches.back();
7531c2f4bbeSAlexander Yermolovich   Patch.second = NewBinaryContents.size() - 4 - Patch.first;
7541c2f4bbeSAlexander Yermolovich   for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) {
7551c2f4bbeSAlexander Yermolovich     const auto &Patch = LengthPatches[J];
7561c2f4bbeSAlexander Yermolovich     ByteSequence = encodeLE(4, Patch.second);
7571c2f4bbeSAlexander Yermolovich     Offset = Patch.first;
7581c2f4bbeSAlexander Yermolovich     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I)
7591c2f4bbeSAlexander Yermolovich       NewBinaryContents[Offset + I] = ByteSequence[I];
7601c2f4bbeSAlexander Yermolovich   }
7611c2f4bbeSAlexander Yermolovich 
7621c2f4bbeSAlexander Yermolovich   return NewBinaryContents;
763a34c753fSRafael Auler }
764a34c753fSRafael Auler 
765a34c753fSRafael Auler void DebugStrWriter::create() {
766a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
767a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
768a34c753fSRafael Auler }
769a34c753fSRafael Auler 
770a34c753fSRafael Auler void DebugStrWriter::initialize() {
771a34c753fSRafael Auler   auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
772a34c753fSRafael Auler   (*StrStream) << StrSection;
773a34c753fSRafael Auler }
774a34c753fSRafael Auler 
775a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
776e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
777a34c753fSRafael Auler   if (StrBuffer->empty())
778a34c753fSRafael Auler     initialize();
779a34c753fSRafael Auler   auto Offset = StrBuffer->size();
780a34c753fSRafael Auler   (*StrStream) << Str;
781a34c753fSRafael Auler   StrStream->write_zeros(1);
782a34c753fSRafael Auler   return Offset;
783a34c753fSRafael Auler }
784a34c753fSRafael Auler 
785a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
786a34c753fSRafael Auler   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
787a34c753fSRafael Auler   if (!Abbrevs)
788a34c753fSRafael Auler     return;
789a34c753fSRafael Auler 
79045f94abcSMaksim Panchenko   const PatchesTy &UnitPatches = Patches[&Unit];
791*bd1ebe9dSAlexander Yermolovich   const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit];
792a34c753fSRafael Auler 
7939f3f9d19SAlexander Yermolovich   // We are duplicating abbrev sections, to handle the case where for one CU we
7949f3f9d19SAlexander Yermolovich   // modify it, but for another we don't.
7959f3f9d19SAlexander Yermolovich   auto UnitDataPtr = std::make_unique<AbbrevData>();
7969f3f9d19SAlexander Yermolovich   AbbrevData &UnitData = *UnitDataPtr.get();
7979f3f9d19SAlexander Yermolovich   UnitData.Buffer = std::make_unique<DebugBufferVector>();
7989f3f9d19SAlexander Yermolovich   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
799*bd1ebe9dSAlexander Yermolovich 
800a34c753fSRafael Auler   raw_svector_ostream &OS = *UnitData.Stream.get();
801a34c753fSRafael Auler 
8029f3f9d19SAlexander Yermolovich   // Returns true if AbbrevData is re-used, false otherwise.
8039f3f9d19SAlexander Yermolovich   auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool {
8049f3f9d19SAlexander Yermolovich     llvm::SHA1 Hasher;
8059f3f9d19SAlexander Yermolovich     Hasher.update(AbbrevData);
8069f3f9d19SAlexander Yermolovich     StringRef Key = Hasher.final();
8079f3f9d19SAlexander Yermolovich     auto Iter = AbbrevDataCache.find(Key);
8089f3f9d19SAlexander Yermolovich     if (Iter != AbbrevDataCache.end()) {
8099f3f9d19SAlexander Yermolovich       UnitsAbbrevData[&Unit] = Iter->second.get();
8109f3f9d19SAlexander Yermolovich       return true;
8119f3f9d19SAlexander Yermolovich     }
8129f3f9d19SAlexander Yermolovich     AbbrevDataCache[Key] = std::move(UnitDataPtr);
8139f3f9d19SAlexander Yermolovich     UnitsAbbrevData[&Unit] = &UnitData;
8149f3f9d19SAlexander Yermolovich     return false;
8159f3f9d19SAlexander Yermolovich   };
816a34c753fSRafael Auler   // Take a fast path if there are no patches to apply. Simply copy the original
817a34c753fSRafael Auler   // contents.
818*bd1ebe9dSAlexander Yermolovich   if (UnitPatches.empty() && AbbrevEntries.empty()) {
819a34c753fSRafael Auler     StringRef AbbrevSectionContents =
820a34c753fSRafael Auler         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
821a34c753fSRafael Auler                          : Unit.getContext().getDWARFObj().getAbbrevSection();
822a34c753fSRafael Auler     StringRef AbbrevContents;
823a34c753fSRafael Auler 
824a34c753fSRafael Auler     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
825a34c753fSRafael Auler     if (!CUIndex.getRows().empty()) {
826a34c753fSRafael Auler       // Handle DWP section contribution.
827a34c753fSRafael Auler       const DWARFUnitIndex::Entry *DWOEntry =
828a34c753fSRafael Auler           CUIndex.getFromHash(*Unit.getDWOId());
829a34c753fSRafael Auler       if (!DWOEntry)
830a34c753fSRafael Auler         return;
831a34c753fSRafael Auler 
832a34c753fSRafael Auler       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
833a34c753fSRafael Auler           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
834a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
835a34c753fSRafael Auler                                                     DWOContrubution->Length);
83645f94abcSMaksim Panchenko     } else if (!Unit.isDWOUnit()) {
837a34c753fSRafael Auler       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
83845f94abcSMaksim Panchenko 
83945f94abcSMaksim Panchenko       // We know where the unit's abbreviation set starts, but not where it ends
84045f94abcSMaksim Panchenko       // as such data is not readily available. Hence, we have to build a sorted
84145f94abcSMaksim Panchenko       // list of start addresses and find the next starting address to determine
84245f94abcSMaksim Panchenko       // the set boundaries.
84345f94abcSMaksim Panchenko       //
84445f94abcSMaksim Panchenko       // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
84545f94abcSMaksim Panchenko       // we wouldn't have to build our own sorted list for the quick lookup.
84645f94abcSMaksim Panchenko       if (AbbrevSetOffsets.empty()) {
8471c2f4bbeSAlexander Yermolovich         for_each(
84845f94abcSMaksim Panchenko             *Unit.getContext().getDebugAbbrev(),
84945f94abcSMaksim Panchenko             [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
85045f94abcSMaksim Panchenko               AbbrevSetOffsets.push_back(P.first);
85145f94abcSMaksim Panchenko             });
8521c2f4bbeSAlexander Yermolovich         sort(AbbrevSetOffsets);
85345f94abcSMaksim Panchenko       }
8541c2f4bbeSAlexander Yermolovich       auto It = upper_bound(AbbrevSetOffsets, StartOffset);
85545f94abcSMaksim Panchenko       const uint64_t EndOffset =
85645f94abcSMaksim Panchenko           It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
857a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
85845f94abcSMaksim Panchenko     } else {
85945f94abcSMaksim Panchenko       // For DWO unit outside of DWP, we expect the entire section to hold
86045f94abcSMaksim Panchenko       // abbreviations for this unit only.
86145f94abcSMaksim Panchenko       AbbrevContents = AbbrevSectionContents;
862a34c753fSRafael Auler     }
863a34c753fSRafael Auler 
8649f3f9d19SAlexander Yermolovich     if (!hashAndAddAbbrev(AbbrevContents)) {
865a34c753fSRafael Auler       OS.reserveExtraSpace(AbbrevContents.size());
866a34c753fSRafael Auler       OS << AbbrevContents;
8679f3f9d19SAlexander Yermolovich     }
868a34c753fSRafael Auler     return;
869a34c753fSRafael Auler   }
870a34c753fSRafael Auler 
871a34c753fSRafael Auler   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
872a34c753fSRafael Auler     const DWARFAbbreviationDeclaration &Abbrev = *I;
873a34c753fSRafael Auler     auto Patch = UnitPatches.find(&Abbrev);
874a34c753fSRafael Auler 
875a34c753fSRafael Auler     encodeULEB128(Abbrev.getCode(), OS);
876a34c753fSRafael Auler     encodeULEB128(Abbrev.getTag(), OS);
877a34c753fSRafael Auler     encodeULEB128(Abbrev.hasChildren(), OS);
878a34c753fSRafael Auler     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
879a34c753fSRafael Auler          Abbrev.attributes()) {
880a34c753fSRafael Auler       if (Patch != UnitPatches.end()) {
881a34c753fSRafael Auler         bool Patched = false;
882a34c753fSRafael Auler         // Patches added later take a precedence over earlier ones.
883a34c753fSRafael Auler         for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
884a34c753fSRafael Auler              ++I) {
885a34c753fSRafael Auler           if (I->OldAttr != AttrSpec.Attr)
886a34c753fSRafael Auler             continue;
887a34c753fSRafael Auler 
888a34c753fSRafael Auler           encodeULEB128(I->NewAttr, OS);
889a34c753fSRafael Auler           encodeULEB128(I->NewAttrForm, OS);
890a34c753fSRafael Auler           Patched = true;
891a34c753fSRafael Auler           break;
892a34c753fSRafael Auler         }
893a34c753fSRafael Auler         if (Patched)
894a34c753fSRafael Auler           continue;
895a34c753fSRafael Auler       }
896a34c753fSRafael Auler 
897a34c753fSRafael Auler       encodeULEB128(AttrSpec.Attr, OS);
898a34c753fSRafael Auler       encodeULEB128(AttrSpec.Form, OS);
899a34c753fSRafael Auler       if (AttrSpec.isImplicitConst())
900a34c753fSRafael Auler         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
901a34c753fSRafael Auler     }
902*bd1ebe9dSAlexander Yermolovich     const auto Entries = AbbrevEntries.find(&Abbrev);
903*bd1ebe9dSAlexander Yermolovich     // Adding new Abbrevs for inserted entries.
904*bd1ebe9dSAlexander Yermolovich     if (Entries != AbbrevEntries.end()) {
905*bd1ebe9dSAlexander Yermolovich       for (const AbbrevEntry &Entry : Entries->second) {
906*bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Attr, OS);
907*bd1ebe9dSAlexander Yermolovich         encodeULEB128(Entry.Form, OS);
908*bd1ebe9dSAlexander Yermolovich       }
909*bd1ebe9dSAlexander Yermolovich     }
910a34c753fSRafael Auler     encodeULEB128(0, OS);
911a34c753fSRafael Auler     encodeULEB128(0, OS);
912a34c753fSRafael Auler   }
913a34c753fSRafael Auler   encodeULEB128(0, OS);
9149f3f9d19SAlexander Yermolovich 
9159f3f9d19SAlexander Yermolovich   hashAndAddAbbrev(OS.str());
916a34c753fSRafael Auler }
917a34c753fSRafael Auler 
918a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
9199f3f9d19SAlexander Yermolovich   // Used to create determinism for writing out abbrevs.
9209f3f9d19SAlexander Yermolovich   std::vector<AbbrevData *> Abbrevs;
92145f94abcSMaksim Panchenko   if (DWOId) {
92245f94abcSMaksim Panchenko     // We expect abbrev_offset to always be zero for DWO units as there
92345f94abcSMaksim Panchenko     // should be one CU per DWO, and TUs should share the same abbreviation
92445f94abcSMaksim Panchenko     // set with the CU.
9251417f607SAlexander Yermolovich     // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so
9261417f607SAlexander Yermolovich     // can be none zero. Thus we are skipping the check for DWP.
92745f94abcSMaksim Panchenko     bool IsDWP = !Context.getCUIndex().getRows().empty();
9281417f607SAlexander Yermolovich     if (!IsDWP) {
92945f94abcSMaksim Panchenko       for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
93045f94abcSMaksim Panchenko         if (Unit->getAbbreviationsOffset() != 0) {
93145f94abcSMaksim Panchenko           errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
93245f94abcSMaksim Panchenko                     "Unable to update debug info.\n";
93345f94abcSMaksim Panchenko           exit(1);
93445f94abcSMaksim Panchenko         }
93545f94abcSMaksim Panchenko       }
93645f94abcSMaksim Panchenko     }
93745f94abcSMaksim Panchenko 
9389f3f9d19SAlexander Yermolovich     DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId);
93945f94abcSMaksim Panchenko     // Issue abbreviations for the DWO CU only.
94045f94abcSMaksim Panchenko     addUnitAbbreviations(*Unit);
9419f3f9d19SAlexander Yermolovich     AbbrevData *Abbrev = UnitsAbbrevData[Unit];
9429f3f9d19SAlexander Yermolovich     Abbrevs.push_back(Abbrev);
9439f3f9d19SAlexander Yermolovich   } else {
9449f3f9d19SAlexander Yermolovich     Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits());
9459f3f9d19SAlexander Yermolovich     std::unordered_set<AbbrevData *> ProcessedAbbrevs;
9469f3f9d19SAlexander Yermolovich     // Add abbreviations from compile and type non-DWO units.
9479f3f9d19SAlexander Yermolovich     for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) {
9489f3f9d19SAlexander Yermolovich       addUnitAbbreviations(*Unit);
9499f3f9d19SAlexander Yermolovich       AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()];
9509f3f9d19SAlexander Yermolovich       if (!ProcessedAbbrevs.insert(Abbrev).second)
9519f3f9d19SAlexander Yermolovich         continue;
9529f3f9d19SAlexander Yermolovich       Abbrevs.push_back(Abbrev);
9539f3f9d19SAlexander Yermolovich     }
95445f94abcSMaksim Panchenko   }
95545f94abcSMaksim Panchenko 
956a34c753fSRafael Auler   DebugBufferVector ReturnBuffer;
957a34c753fSRafael Auler   // Pre-calculate the total size of abbrev section.
958a34c753fSRafael Auler   uint64_t Size = 0;
9599f3f9d19SAlexander Yermolovich   for (const AbbrevData *UnitData : Abbrevs)
9609f3f9d19SAlexander Yermolovich     Size += UnitData->Buffer->size();
9619f3f9d19SAlexander Yermolovich 
962a34c753fSRafael Auler   ReturnBuffer.reserve(Size);
963a34c753fSRafael Auler 
964a34c753fSRafael Auler   uint64_t Pos = 0;
9659f3f9d19SAlexander Yermolovich   for (AbbrevData *UnitData : Abbrevs) {
9669f3f9d19SAlexander Yermolovich     ReturnBuffer.append(*UnitData->Buffer);
9679f3f9d19SAlexander Yermolovich     UnitData->Offset = Pos;
9689f3f9d19SAlexander Yermolovich     Pos += UnitData->Buffer->size();
969a34c753fSRafael Auler 
9709f3f9d19SAlexander Yermolovich     UnitData->Buffer.reset();
9719f3f9d19SAlexander Yermolovich     UnitData->Stream.reset();
972a34c753fSRafael Auler   }
973a34c753fSRafael Auler 
974a34c753fSRafael Auler   return std::make_unique<DebugBufferVector>(ReturnBuffer);
975a34c753fSRafael Auler }
976a34c753fSRafael Auler 
977a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
978a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
979a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
980a34c753fSRafael Auler                                     int PointerSize) {
981a34c753fSRafael Auler   // emit the sequence to set the address
982a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
983a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
984a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
985a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
986a34c753fSRafael Auler 
987a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
988a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
989a34c753fSRafael Auler }
990a34c753fSRafael Auler 
991a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
992a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
993a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
994a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
995a34c753fSRafael Auler   if (InputSequences.empty())
996a34c753fSRafael Auler     return;
997a34c753fSRafael Auler 
998a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
999a34c753fSRafael Auler   unsigned FileNum = 1;
1000a34c753fSRafael Auler   unsigned LastLine = 1;
1001a34c753fSRafael Auler   unsigned Column = 0;
1002a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1003a34c753fSRafael Auler   unsigned Isa = 0;
1004a34c753fSRafael Auler   unsigned Discriminator = 0;
1005a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
1006a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
1007a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1008a34c753fSRafael Auler 
1009a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
1010a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
1011a34c753fSRafael Auler     FileNum = 1;
1012a34c753fSRafael Auler     LastLine = 1;
1013a34c753fSRafael Auler     Column = 0;
1014a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1015a34c753fSRafael Auler     Isa = 0;
1016a34c753fSRafael Auler     Discriminator = 0;
1017a34c753fSRafael Auler     LastAddress = InvalidAddress;
1018a34c753fSRafael Auler   };
1019a34c753fSRafael Auler 
1020a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
1021a34c753fSRafael Auler     const uint64_t SequenceStart =
1022a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
1023a34c753fSRafael Auler 
1024a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
1025a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
1026a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
1027a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
1028a34c753fSRafael Auler     }
1029a34c753fSRafael Auler 
1030a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
1031a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
1032a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
1033a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
1034a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
1035a34c753fSRafael Auler 
1036a34c753fSRafael Auler       if (FileNum != Row.File) {
1037a34c753fSRafael Auler         FileNum = Row.File;
1038a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1039a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
1040a34c753fSRafael Auler       }
1041a34c753fSRafael Auler       if (Column != Row.Column) {
1042a34c753fSRafael Auler         Column = Row.Column;
1043a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1044a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
1045a34c753fSRafael Auler       }
1046a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
1047a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
1048a34c753fSRafael Auler         Discriminator = Row.Discriminator;
1049a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
1050a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1051a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
1052a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1053a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
1054a34c753fSRafael Auler       }
1055a34c753fSRafael Auler       if (Isa != Row.Isa) {
1056a34c753fSRafael Auler         Isa = Row.Isa;
1057a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1058a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
1059a34c753fSRafael Auler       }
1060a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
1061a34c753fSRafael Auler         Flags = Row.IsStmt;
1062a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1063a34c753fSRafael Auler       }
1064a34c753fSRafael Auler       if (Row.BasicBlock)
1065a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1066a34c753fSRafael Auler       if (Row.PrologueEnd)
1067a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1068a34c753fSRafael Auler       if (Row.EpilogueBegin)
1069a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1070a34c753fSRafael Auler 
1071a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
1072a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
1073a34c753fSRafael Auler       if (Row.EndSequence) {
1074a34c753fSRafael Auler         emitEndOfSequence(Address);
1075a34c753fSRafael Auler       } else {
1076a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
1077a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1078a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
1079a34c753fSRafael Auler         else
1080a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1081a34c753fSRafael Auler 
1082a34c753fSRafael Auler         LastAddress = Address;
1083a34c753fSRafael Auler         LastLine = Row.Line;
1084a34c753fSRafael Auler       }
1085a34c753fSRafael Auler 
1086a34c753fSRafael Auler       Discriminator = 0;
1087a34c753fSRafael Auler     }
1088a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
1089a34c753fSRafael Auler   }
1090a34c753fSRafael Auler 
1091a34c753fSRafael Auler   // Finish with the end of the sequence.
1092a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
1093a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
1094a34c753fSRafael Auler }
1095a34c753fSRafael Auler 
1096a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
1097a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
1098a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
1099a34c753fSRafael Auler static inline void emitDwarfLineTable(
1100a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
1101a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1102a34c753fSRafael Auler   unsigned FileNum = 1;
1103a34c753fSRafael Auler   unsigned LastLine = 1;
1104a34c753fSRafael Auler   unsigned Column = 0;
1105a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1106a34c753fSRafael Auler   unsigned Isa = 0;
1107a34c753fSRafael Auler   unsigned Discriminator = 0;
1108a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
1109a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1110a34c753fSRafael Auler 
1111a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1112a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1113a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1114a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1115a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
1116a34c753fSRafael Auler       FileNum = 1;
1117a34c753fSRafael Auler       LastLine = 1;
1118a34c753fSRafael Auler       Column = 0;
1119a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1120a34c753fSRafael Auler       Isa = 0;
1121a34c753fSRafael Auler       Discriminator = 0;
1122a34c753fSRafael Auler       LastLabel = nullptr;
1123a34c753fSRafael Auler       continue;
1124a34c753fSRafael Auler     }
1125a34c753fSRafael Auler 
1126a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1127a34c753fSRafael Auler 
1128a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
1129a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
1130a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1131a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
1132a34c753fSRafael Auler     }
1133a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
1134a34c753fSRafael Auler       Column = LineEntry.getColumn();
1135a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1136a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
1137a34c753fSRafael Auler     }
1138a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
1139a34c753fSRafael Auler         MCOS->getContext().getDwarfVersion() >= 4) {
1140a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
1141a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
1142a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1143a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
1144a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1145a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
1146a34c753fSRafael Auler     }
1147a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
1148a34c753fSRafael Auler       Isa = LineEntry.getIsa();
1149a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1150a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
1151a34c753fSRafael Auler     }
1152a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1153a34c753fSRafael Auler       Flags = LineEntry.getFlags();
1154a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1155a34c753fSRafael Auler     }
1156a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1157a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1158a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1159a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1160a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1161a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1162a34c753fSRafael Auler 
1163a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
1164a34c753fSRafael Auler 
1165a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
1166a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
1167a34c753fSRafael Auler     // Label and the current Label.
1168a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1169a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
1170a34c753fSRafael Auler     Discriminator = 0;
1171a34c753fSRafael Auler     LastLine = LineEntry.getLine();
1172a34c753fSRafael Auler     LastLabel = Label;
1173a34c753fSRafael Auler   }
1174a34c753fSRafael Auler 
1175a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
1176a34c753fSRafael Auler }
1177a34c753fSRafael Auler 
1178a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1179b73c87bcSMaksim Panchenko                             Optional<MCDwarfLineStr> &LineStr,
1180b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
1181a34c753fSRafael Auler   if (!RawData.empty()) {
1182a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
1183a34c753fSRafael Auler            InputSequences.empty() &&
1184a34c753fSRafael Auler            "cannot combine raw data with new line entries");
1185a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
1186a34c753fSRafael Auler     MCOS->emitBytes(RawData);
1187a34c753fSRafael Auler 
1188b73c87bcSMaksim Panchenko     // Emit fake relocation for RuntimeDyld to always allocate the section.
1189b73c87bcSMaksim Panchenko     //
1190b73c87bcSMaksim Panchenko     // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
1191b73c87bcSMaksim Panchenko     //        without relocations.
1192b73c87bcSMaksim Panchenko     MCOS->emitRelocDirective(
1193b73c87bcSMaksim Panchenko         *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
1194b73c87bcSMaksim Panchenko         MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);
1195b73c87bcSMaksim Panchenko 
1196a34c753fSRafael Auler     return;
1197a34c753fSRafael Auler   }
1198a34c753fSRafael Auler 
1199a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1200a34c753fSRafael Auler 
1201a34c753fSRafael Auler   // Put out the line tables.
1202a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1203a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1204a34c753fSRafael Auler 
1205a34c753fSRafael Auler   // Emit line tables for the original code.
1206a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1207a34c753fSRafael Auler 
1208a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
1209a34c753fSRafael Auler   // of this section (that was used in a previous expression).
1210a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
1211a34c753fSRafael Auler }
1212a34c753fSRafael Auler 
1213a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1214a34c753fSRafael Auler   MCAssembler &Assembler =
1215a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1216a34c753fSRafael Auler 
1217a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1218a34c753fSRafael Auler 
1219a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
1220a34c753fSRafael Auler 
1221a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
1222a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
1223a34c753fSRafael Auler   if (LineTables.empty())
1224a34c753fSRafael Auler     return;
1225a34c753fSRafael Auler 
1226a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
1227a34c753fSRafael Auler   Optional<MCDwarfLineStr> LineStr(None);
1228a34c753fSRafael Auler   if (BC.Ctx->getDwarfVersion() >= 5)
1229a34c753fSRafael Auler     LineStr = MCDwarfLineStr(*BC.Ctx);
1230a34c753fSRafael Auler 
1231a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
1232a34c753fSRafael Auler   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
1233a34c753fSRafael Auler 
1234a34c753fSRafael Auler   // Handle the rest of the Compile Units.
1235a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
1236b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1237a34c753fSRafael Auler   }
1238a34c753fSRafael Auler }
1239a34c753fSRafael Auler 
1240a34c753fSRafael Auler } // namespace bolt
1241a34c753fSRafael Auler } // namespace llvm
1242