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"
14a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h"
15a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h"
16a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
17a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h"
18a34c753fSRafael Auler #include "llvm/MC/MCSymbol.h"
19a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
20a34c753fSRafael Auler #include "llvm/Support/EndianStream.h"
21a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
22a34c753fSRafael Auler #include <algorithm>
23a34c753fSRafael Auler #include <cassert>
24a34c753fSRafael Auler #include <cstdint>
25a34c753fSRafael Auler #include <limits>
261c2f4bbeSAlexander Yermolovich #include <unordered_map>
27a34c753fSRafael Auler 
28a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info"
29a34c753fSRafael Auler 
30a34c753fSRafael Auler namespace opts {
31a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity;
321c2f4bbeSAlexander Yermolovich } // namespace opts
33a34c753fSRafael Auler 
34a34c753fSRafael Auler namespace llvm {
35a34c753fSRafael Auler namespace bolt {
36a34c753fSRafael Auler 
37a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
38a34c753fSRafael Auler 
39a34c753fSRafael Auler namespace {
40a34c753fSRafael Auler 
411c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED
421c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) {
431c2f4bbeSAlexander Yermolovich   for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
441c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr(S[I]);
451c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr((int8_t)S[I]);
461c2f4bbeSAlexander Yermolovich   }
471c2f4bbeSAlexander Yermolovich   errs() << "\n";
481c2f4bbeSAlexander Yermolovich }
491c2f4bbeSAlexander Yermolovich 
50a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size).
51a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of
52a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address).
53a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes.
54a34c753fSRafael Auler // Returns the number of written bytes.
5540c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream,
56a34c753fSRafael Auler                             const DebugAddressRangesVector &AddressRanges,
57a34c753fSRafael Auler                             const bool WriteRelativeRanges = false) {
58a34c753fSRafael Auler   for (const DebugAddressRange &Range : AddressRanges) {
59a34c753fSRafael Auler     support::endian::write(Stream, Range.LowPC, support::little);
60a34c753fSRafael Auler     support::endian::write(
61a34c753fSRafael Auler         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
62a34c753fSRafael Auler         support::little);
63a34c753fSRafael Auler   }
64a34c753fSRafael Auler   // Finish with 0 entries.
65a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
66a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
67a34c753fSRafael Auler   return AddressRanges.size() * 16 + 16;
68a34c753fSRafael Auler }
69a34c753fSRafael Auler 
70a34c753fSRafael Auler } // namespace
71a34c753fSRafael Auler 
72a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() {
73a34c753fSRafael Auler   RangesBuffer = std::make_unique<DebugBufferVector>();
74a34c753fSRafael Auler   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
75a34c753fSRafael Auler 
76a34c753fSRafael Auler   // Add an empty range as the first entry;
77a34c753fSRafael Auler   SectionOffset +=
78a34c753fSRafael Auler       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
79a34c753fSRafael Auler }
80a34c753fSRafael Auler 
81a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges(
82a34c753fSRafael Auler     DebugAddressRangesVector &&Ranges,
83a34c753fSRafael Auler     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
84a34c753fSRafael Auler   if (Ranges.empty())
85a34c753fSRafael Auler     return getEmptyRangesOffset();
86a34c753fSRafael Auler 
87a34c753fSRafael Auler   const auto RI = CachedRanges.find(Ranges);
88a34c753fSRafael Auler   if (RI != CachedRanges.end())
89a34c753fSRafael Auler     return RI->second;
90a34c753fSRafael Auler 
91a34c753fSRafael Auler   const uint64_t EntryOffset = addRanges(Ranges);
92a34c753fSRafael Auler   CachedRanges.emplace(std::move(Ranges), EntryOffset);
93a34c753fSRafael Auler 
94a34c753fSRafael Auler   return EntryOffset;
95a34c753fSRafael Auler }
96a34c753fSRafael Auler 
97a34c753fSRafael Auler uint64_t
98a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) {
99a34c753fSRafael Auler   if (Ranges.empty())
100a34c753fSRafael Auler     return getEmptyRangesOffset();
101a34c753fSRafael Auler 
102a34c753fSRafael Auler   // Reading the SectionOffset and updating it should be atomic to guarantee
103a34c753fSRafael Auler   // unique and correct offsets in patches.
104a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
105a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
106a34c753fSRafael Auler   SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);
107a34c753fSRafael Auler 
108a34c753fSRafael Auler   return EntryOffset;
109a34c753fSRafael Auler }
110a34c753fSRafael Auler 
111a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() {
112a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
113a34c753fSRafael Auler   return SectionOffset;
114a34c753fSRafael Auler }
115a34c753fSRafael Auler 
116a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
117a34c753fSRafael Auler                                             DebugAddressRangesVector &&Ranges) {
118a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
119a34c753fSRafael Auler   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
120a34c753fSRafael Auler }
121a34c753fSRafael Auler 
122a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection(
1231c2f4bbeSAlexander Yermolovich     raw_svector_ostream &RangesStream,
1241c2f4bbeSAlexander Yermolovich     const std::unordered_map<uint32_t, uint32_t> CUMap) const {
125a34c753fSRafael Auler   // For reference on the format of the .debug_aranges section, see the DWARF4
126a34c753fSRafael Auler   // specification, section 6.1.4 Lookup by Address
127a34c753fSRafael Auler   // http://www.dwarfstd.org/doc/DWARF4.pdf
128a34c753fSRafael Auler   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
129a34c753fSRafael Auler     const uint64_t Offset = CUOffsetAddressRangesPair.first;
130a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges =
131a34c753fSRafael Auler         CUOffsetAddressRangesPair.second;
132a34c753fSRafael Auler 
133a34c753fSRafael Auler     // Emit header.
134a34c753fSRafael Auler 
135a34c753fSRafael Auler     // Size of this set: 8 (size of the header) + 4 (padding after header)
136a34c753fSRafael Auler     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
137a34c753fSRafael Auler     // pair of uint64_t's for the terminating, zero-length range.
138a34c753fSRafael Auler     // Does not include size field itself.
139a34c753fSRafael Auler     uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);
140a34c753fSRafael Auler 
141a34c753fSRafael Auler     // Header field #1: set size.
142a34c753fSRafael Auler     support::endian::write(RangesStream, Size, support::little);
143a34c753fSRafael Auler 
144a34c753fSRafael Auler     // Header field #2: version number, 2 as per the specification.
145a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint16_t>(2),
146a34c753fSRafael Auler                            support::little);
147a34c753fSRafael Auler 
1481c2f4bbeSAlexander Yermolovich     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
149a34c753fSRafael Auler     // Header field #3: debug info offset of the correspondent compile unit.
1501c2f4bbeSAlexander Yermolovich     support::endian::write(RangesStream,
1511c2f4bbeSAlexander Yermolovich                            static_cast<uint32_t>(CUMap.find(Offset)->second),
152a34c753fSRafael Auler                            support::little);
153a34c753fSRafael Auler 
154a34c753fSRafael Auler     // Header field #4: address size.
155a34c753fSRafael Auler     // 8 since we only write ELF64 binaries for now.
156a34c753fSRafael Auler     RangesStream << char(8);
157a34c753fSRafael Auler 
158a34c753fSRafael Auler     // Header field #5: segment size of target architecture.
159a34c753fSRafael Auler     RangesStream << char(0);
160a34c753fSRafael Auler 
161a34c753fSRafael Auler     // Padding before address table - 4 bytes in the 64-bit-pointer case.
162a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(0),
163a34c753fSRafael Auler                            support::little);
164a34c753fSRafael Auler 
165a34c753fSRafael Auler     writeAddressRanges(RangesStream, AddressRanges, true);
166a34c753fSRafael Auler   }
167a34c753fSRafael Auler }
168a34c753fSRafael Auler 
169a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }
170a34c753fSRafael Auler 
171a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() {
172a34c753fSRafael Auler   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
173a34c753fSRafael Auler                                           indexToAdddessEnd());
174a34c753fSRafael Auler   // Sorting address in increasing order of indices.
175a34c753fSRafael Auler   std::sort(SortedMap.begin(), SortedMap.end(),
176a34c753fSRafael Auler             [](const IndexAddressPair &A, const IndexAddressPair &B) {
177a34c753fSRafael Auler               return A.first < B.first;
178a34c753fSRafael Auler             });
179a34c753fSRafael Auler   for (auto &Pair : SortedMap)
180a34c753fSRafael Auler     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
181a34c753fSRafael Auler }
182a34c753fSRafael Auler uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address,
183a34c753fSRafael Auler                                               uint64_t DWOId) {
184e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
185a34c753fSRafael Auler   if (!AddressMaps.count(DWOId))
186a34c753fSRafael Auler     AddressMaps[DWOId] = AddressForDWOCU();
187a34c753fSRafael Auler 
188a34c753fSRafael Auler   AddressForDWOCU &Map = AddressMaps[DWOId];
189a34c753fSRafael Auler   auto Entry = Map.find(Address);
190a34c753fSRafael Auler   if (Entry == Map.end()) {
191a34c753fSRafael Auler     auto Index = Map.getNextIndex();
192a34c753fSRafael Auler     Entry = Map.insert(Address, Index).first;
193a34c753fSRafael Auler   }
194a34c753fSRafael Auler   return Entry->second;
195a34c753fSRafael Auler }
196a34c753fSRafael Auler 
197a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
198a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update
199a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
200a34c753fSRafael Auler // update AddressToIndex and IndexToAddress
201a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
202a34c753fSRafael Auler                                       uint64_t DWOId) {
203e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
204a34c753fSRafael Auler   AddressForDWOCU &Map = AddressMaps[DWOId];
205a34c753fSRafael Auler   auto Entry = Map.find(Address);
206a34c753fSRafael Auler   if (Entry != Map.end()) {
207a34c753fSRafael Auler     if (Entry->second > Index)
208a34c753fSRafael Auler       Map.updateAddressToIndex(Address, Index);
209a34c753fSRafael Auler     Map.updateIndexToAddrss(Address, Index);
2103652483cSRafael Auler   } else {
211a34c753fSRafael Auler     Map.insert(Address, Index);
212a34c753fSRafael Auler   }
2133652483cSRafael Auler }
214a34c753fSRafael Auler 
215a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() {
216a34c753fSRafael Auler   // Need to layout all sections within .debug_addr
217a34c753fSRafael Auler   // Within each section sort Address by index.
218a34c753fSRafael Auler   AddressSectionBuffer Buffer;
219a34c753fSRafael Auler   raw_svector_ostream AddressStream(Buffer);
220a34c753fSRafael Auler   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
221a34c753fSRafael Auler     Optional<uint64_t> DWOId = CU->getDWOId();
222a34c753fSRafael Auler     // Handling the case wehre debug information is a mix of Debug fission and
223a34c753fSRafael Auler     // monolitic.
224a34c753fSRafael Auler     if (!DWOId)
225a34c753fSRafael Auler       continue;
226a34c753fSRafael Auler     auto AM = AddressMaps.find(*DWOId);
227a34c753fSRafael Auler     // Adding to map even if it did not contribute to .debug_addr.
228a34c753fSRafael Auler     // The Skeleton CU will still have DW_AT_GNU_addr_base.
229a34c753fSRafael Auler     DWOIdToOffsetMap[*DWOId] = Buffer.size();
230a34c753fSRafael Auler     // If does not exist this CUs DWO section didn't contribute to .debug_addr.
231a34c753fSRafael Auler     if (AM == AddressMaps.end())
232a34c753fSRafael Auler       continue;
233a34c753fSRafael Auler     std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
234a34c753fSRafael Auler                                             AM->second.indexToAdddessEnd());
235a34c753fSRafael Auler     // Sorting address in increasing order of indices.
236a34c753fSRafael Auler     std::sort(SortedMap.begin(), SortedMap.end(),
237a34c753fSRafael Auler               [](const IndexAddressPair &A, const IndexAddressPair &B) {
238a34c753fSRafael Auler                 return A.first < B.first;
239a34c753fSRafael Auler               });
240a34c753fSRafael Auler 
241a34c753fSRafael Auler     uint8_t AddrSize = CU->getAddressByteSize();
242a34c753fSRafael Auler     uint32_t Counter = 0;
243a34c753fSRafael Auler     auto WriteAddress = [&](uint64_t Address) -> void {
244a34c753fSRafael Auler       ++Counter;
245a34c753fSRafael Auler       switch (AddrSize) {
246a34c753fSRafael Auler       default:
247a34c753fSRafael Auler         assert(false && "Address Size is invalid.");
248a34c753fSRafael Auler         break;
249a34c753fSRafael Auler       case 4:
250a34c753fSRafael Auler         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
251a34c753fSRafael Auler                                support::little);
252a34c753fSRafael Auler         break;
253a34c753fSRafael Auler       case 8:
254a34c753fSRafael Auler         support::endian::write(AddressStream, Address, support::little);
255a34c753fSRafael Auler         break;
256a34c753fSRafael Auler       }
257a34c753fSRafael Auler     };
258a34c753fSRafael Auler 
259a34c753fSRafael Auler     for (const IndexAddressPair &Val : SortedMap) {
260a34c753fSRafael Auler       while (Val.first > Counter)
261a34c753fSRafael Auler         WriteAddress(0);
262a34c753fSRafael Auler       WriteAddress(Val.second);
263a34c753fSRafael Auler     }
264a34c753fSRafael Auler   }
265a34c753fSRafael Auler 
266a34c753fSRafael Auler   return Buffer;
267a34c753fSRafael Auler }
268a34c753fSRafael Auler 
269a34c753fSRafael Auler uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
270a34c753fSRafael Auler   auto Iter = DWOIdToOffsetMap.find(DWOId);
271a34c753fSRafael Auler   assert(Iter != DWOIdToOffsetMap.end() &&
272a34c753fSRafael Auler          "Offset in to.debug_addr was not found for DWO ID.");
273a34c753fSRafael Auler   return Iter->second;
274a34c753fSRafael Auler }
275a34c753fSRafael Auler 
276a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
277a34c753fSRafael Auler   LocBuffer = std::make_unique<DebugBufferVector>();
278a34c753fSRafael Auler   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
279a34c753fSRafael Auler }
280a34c753fSRafael Auler 
281a34c753fSRafael Auler void DebugLocWriter::addList(uint64_t AttrOffset,
282a34c753fSRafael Auler                              DebugLocationsVector &&LocList) {
283a34c753fSRafael Auler   if (LocList.empty()) {
284a34c753fSRafael Auler     EmptyAttrLists.push_back(AttrOffset);
285a34c753fSRafael Auler     return;
286a34c753fSRafael Auler   }
287a34c753fSRafael Auler   // Since there is a separate DebugLocWriter for each thread,
288a34c753fSRafael Auler   // we don't need a lock to read the SectionOffset and update it.
289a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
290a34c753fSRafael Auler 
291a34c753fSRafael Auler   for (const DebugLocationEntry &Entry : LocList) {
292a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
293a34c753fSRafael Auler                            support::little);
294a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
295a34c753fSRafael Auler                            support::little);
296a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
297a34c753fSRafael Auler                            support::little);
298a34c753fSRafael Auler     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
299a34c753fSRafael Auler                             Entry.Expr.size());
300a34c753fSRafael Auler     SectionOffset += 2 * 8 + 2 + Entry.Expr.size();
301a34c753fSRafael Auler   }
302a34c753fSRafael Auler   LocStream->write_zeros(16);
303a34c753fSRafael Auler   SectionOffset += 16;
304a34c753fSRafael Auler   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
305a34c753fSRafael Auler }
306a34c753fSRafael Auler 
307a34c753fSRafael Auler void DebugLoclistWriter::addList(uint64_t AttrOffset,
308a34c753fSRafael Auler                                  DebugLocationsVector &&LocList) {
309a34c753fSRafael Auler   Patches.push_back({AttrOffset, std::move(LocList)});
310a34c753fSRafael Auler }
311a34c753fSRafael Auler 
312a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
313a34c753fSRafael Auler   return std::move(LocBuffer);
314a34c753fSRafael Auler }
315a34c753fSRafael Auler 
316a34c753fSRafael Auler // DWARF 4: 2.6.2
317a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset,
318a34c753fSRafael Auler                               SimpleBinaryPatcher &DebugInfoPatcher) {
319a34c753fSRafael Auler   for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) {
320a34c753fSRafael Auler     uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset;
321a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset,
322a34c753fSRafael Auler                                   Offset);
323a34c753fSRafael Auler   }
324a34c753fSRafael Auler 
325a34c753fSRafael Auler   for (uint64_t DebugInfoAttrOffset : EmptyAttrLists)
326a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset,
327a34c753fSRafael Auler                                   DebugLocWriter::EmptyListOffset);
328a34c753fSRafael Auler }
329a34c753fSRafael Auler 
330a34c753fSRafael Auler void DebugLoclistWriter::finalize(uint64_t SectionOffset,
331a34c753fSRafael Auler                                   SimpleBinaryPatcher &DebugInfoPatcher) {
332a34c753fSRafael Auler   for (LocPatch &Patch : Patches) {
333a34c753fSRafael Auler     if (Patch.LocList.empty()) {
334a34c753fSRafael Auler       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
335a34c753fSRafael Auler                                     DebugLocWriter::EmptyListOffset);
336a34c753fSRafael Auler       continue;
337a34c753fSRafael Auler     }
338a34c753fSRafael Auler     const uint32_t EntryOffset = LocBuffer->size();
339a34c753fSRafael Auler     for (const DebugLocationEntry &Entry : Patch.LocList) {
340a34c753fSRafael Auler       support::endian::write(*LocStream,
341a34c753fSRafael Auler                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
342a34c753fSRafael Auler                              support::little);
343a34c753fSRafael Auler       uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId);
344a34c753fSRafael Auler       encodeULEB128(Index, *LocStream);
345a34c753fSRafael Auler 
346a34c753fSRafael Auler       // TODO: Support DWARF5
347a34c753fSRafael Auler       support::endian::write(*LocStream,
348a34c753fSRafael Auler                              static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
349a34c753fSRafael Auler                              support::little);
350a34c753fSRafael Auler       support::endian::write(*LocStream,
351a34c753fSRafael Auler                              static_cast<uint16_t>(Entry.Expr.size()),
352a34c753fSRafael Auler                              support::little);
353a34c753fSRafael Auler       *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
354a34c753fSRafael Auler                               Entry.Expr.size());
355a34c753fSRafael Auler     }
356a34c753fSRafael Auler     support::endian::write(*LocStream,
357a34c753fSRafael Auler                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
358a34c753fSRafael Auler                            support::little);
359a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
360a34c753fSRafael Auler     clearList(Patch.LocList);
361a34c753fSRafael Auler   }
362a34c753fSRafael Auler   clearList(Patches);
363a34c753fSRafael Auler }
364a34c753fSRafael Auler 
365a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
366a34c753fSRafael Auler 
3671c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) {
3681c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
3691c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
370*ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset));
371a34c753fSRafael Auler }
372a34c753fSRafael Auler 
3731c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) {
3741c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
3751c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
3761c2f4bbeSAlexander Yermolovich   auto RetVal = DestinationLabels.insert(Offset);
3771c2f4bbeSAlexander Yermolovich   if (!RetVal.second)
3781c2f4bbeSAlexander Yermolovich     return;
3791c2f4bbeSAlexander Yermolovich 
380*ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DestinationReferenceLabel(Offset));
381a34c753fSRafael Auler }
382a34c753fSRafael Auler 
3831c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset,
3841c2f4bbeSAlexander Yermolovich                                                  uint32_t DestinationOffset,
3851c2f4bbeSAlexander Yermolovich                                                  uint32_t OldValueSize,
3861c2f4bbeSAlexander Yermolovich                                                  dwarf::Form Form) {
3871c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
3881c2f4bbeSAlexander Yermolovich   DestinationOffset -= DWPUnitOffset;
3891c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
390*ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(
391*ea6c8b01SAlexander Yermolovich       new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form));
3921c2f4bbeSAlexander Yermolovich }
3931c2f4bbeSAlexander Yermolovich 
3941c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue,
3951c2f4bbeSAlexander Yermolovich                                            uint32_t OldValueSize) {
3961c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
3971c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
3981c2f4bbeSAlexander Yermolovich   DebugPatches.emplace_back(
399*ea6c8b01SAlexander Yermolovich       new DebugPatchVariableSize(Offset, OldValueSize, NewValue));
4001c2f4bbeSAlexander Yermolovich }
4011c2f4bbeSAlexander Yermolovich 
4021c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
4031c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4041c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
405*ea6c8b01SAlexander Yermolovich   DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue));
4061c2f4bbeSAlexander Yermolovich }
4071c2f4bbeSAlexander Yermolovich 
4081c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
4091c2f4bbeSAlexander Yermolovich                                           uint32_t OldValueSize) {
4101c2f4bbeSAlexander Yermolovich   Offset -= DWPUnitOffset;
4111c2f4bbeSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
4121c2f4bbeSAlexander Yermolovich   if (OldValueSize == 4)
413*ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue));
4141c2f4bbeSAlexander Yermolovich   else
415*ea6c8b01SAlexander Yermolovich     DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue));
4161c2f4bbeSAlexander Yermolovich }
4171c2f4bbeSAlexander Yermolovich 
4181c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
4191c2f4bbeSAlexander Yermolovich                                          std::string &&NewValue,
4201c2f4bbeSAlexander Yermolovich                                          uint32_t OldValueSize) {
4211c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(NewValue));
4221c2f4bbeSAlexander Yermolovich }
4231c2f4bbeSAlexander Yermolovich 
4241c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
4251c2f4bbeSAlexander Yermolovich   auto Str = std::string(1, Value);
4261c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Str));
4271c2f4bbeSAlexander Yermolovich }
4281c2f4bbeSAlexander Yermolovich 
4291c2f4bbeSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
430a34c753fSRafael Auler   std::string LE64(ByteSize, 0);
431a34c753fSRafael Auler   for (size_t I = 0; I < ByteSize; ++I) {
432a34c753fSRafael Auler     LE64[I] = NewValue & 0xff;
433a34c753fSRafael Auler     NewValue >>= 8;
434a34c753fSRafael Auler   }
4351c2f4bbeSAlexander Yermolovich   return LE64;
436a34c753fSRafael Auler }
437a34c753fSRafael Auler 
4381c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
4391c2f4bbeSAlexander Yermolovich                                      size_t ByteSize) {
4401c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
4411c2f4bbeSAlexander Yermolovich }
4421c2f4bbeSAlexander Yermolovich 
4431c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
4441c2f4bbeSAlexander Yermolovich                                         uint32_t OldValueSize) {
445a34c753fSRafael Auler   std::string Buff;
446a34c753fSRafael Auler   raw_string_ostream OS(Buff);
4471c2f4bbeSAlexander Yermolovich   encodeULEB128(Value, OS, OldValueSize);
448a34c753fSRafael Auler 
4491c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Buff));
450a34c753fSRafael Auler }
451a34c753fSRafael Auler 
4521c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
453a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
454a34c753fSRafael Auler }
455a34c753fSRafael Auler 
4561c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
4571c2f4bbeSAlexander Yermolovich                                        uint32_t OldValueSize) {
458a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
459a34c753fSRafael Auler }
460a34c753fSRafael Auler 
4611c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
4621c2f4bbeSAlexander Yermolovich   std::string BinaryContentsStr = std::string(BinaryContents);
463a34c753fSRafael Auler   for (const auto &Patch : Patches) {
4641c2f4bbeSAlexander Yermolovich     uint32_t Offset = Patch.first;
465a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
466a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
467a34c753fSRafael Auler            "Applied patch runs over binary size.");
468a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
4691c2f4bbeSAlexander Yermolovich       BinaryContentsStr[Offset + I] = ByteSequence[I];
470a34c753fSRafael Auler     }
471a34c753fSRafael Auler   }
4721c2f4bbeSAlexander Yermolovich   return BinaryContentsStr;
4731c2f4bbeSAlexander Yermolovich }
4741c2f4bbeSAlexander Yermolovich 
4751c2f4bbeSAlexander Yermolovich std::unordered_map<uint32_t, uint32_t>
4761c2f4bbeSAlexander Yermolovich DebugInfoBinaryPatcher::computeNewOffsets() {
4771c2f4bbeSAlexander Yermolovich   std::unordered_map<uint32_t, uint32_t> CUMap;
478*ea6c8b01SAlexander Yermolovich   std::sort(DebugPatches.begin(), DebugPatches.end(),
479*ea6c8b01SAlexander Yermolovich             [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
4801c2f4bbeSAlexander Yermolovich               return V1.get()->Offset < V2.get()->Offset;
4811c2f4bbeSAlexander Yermolovich             });
4821c2f4bbeSAlexander Yermolovich 
4831c2f4bbeSAlexander Yermolovich   // Calculating changes in .debug_info size from Patches to build a map of old
4841c2f4bbeSAlexander Yermolovich   // to updated reference destination offsets.
485*ea6c8b01SAlexander Yermolovich   for (UniquePatchPtrType &PatchBase : DebugPatches) {
4861c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
4871c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
4881c2f4bbeSAlexander Yermolovich     default:
4891c2f4bbeSAlexander Yermolovich       continue;
4901c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
4911c2f4bbeSAlexander Yermolovich       ChangeInSize -= 4;
4921c2f4bbeSAlexander Yermolovich       break;
4931c2f4bbeSAlexander Yermolovich     }
4941c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
4951c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *DPV =
4961c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
4971c2f4bbeSAlexander Yermolovich       std::string Temp;
4981c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(Temp);
4991c2f4bbeSAlexander Yermolovich       encodeULEB128(DPV->Value, OS);
5001c2f4bbeSAlexander Yermolovich       ChangeInSize += Temp.size() - DPV->OldValueSize;
5011c2f4bbeSAlexander Yermolovich       break;
5021c2f4bbeSAlexander Yermolovich     }
5031c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DestinationReferenceLabel: {
5041c2f4bbeSAlexander Yermolovich       DestinationReferenceLabel *DRL =
5051c2f4bbeSAlexander Yermolovich           reinterpret_cast<DestinationReferenceLabel *>(P);
5061c2f4bbeSAlexander Yermolovich       OldToNewOffset[DRL->Offset] = DRL->Offset + ChangeInSize;
5071c2f4bbeSAlexander Yermolovich       break;
5081c2f4bbeSAlexander Yermolovich     }
5091c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
5101c2f4bbeSAlexander Yermolovich       // This doesn't look to be a common case, so will always encode as 4 bytes
5111c2f4bbeSAlexander Yermolovich       // to reduce algorithmic complexity.
5121c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
5131c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.IndirectRelative) {
5141c2f4bbeSAlexander Yermolovich         ChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
5151c2f4bbeSAlexander Yermolovich         assert(RDP->PatchInfo.OldValueSize <= 4 &&
5161c2f4bbeSAlexander Yermolovich                "Variable encoding reference greater than 4 bytes.");
5171c2f4bbeSAlexander Yermolovich       }
5181c2f4bbeSAlexander Yermolovich       break;
5191c2f4bbeSAlexander Yermolovich     }
5201c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
5211c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
5221c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
5231c2f4bbeSAlexander Yermolovich       uint32_t CUOffset = BaseLabel->Offset;
5241c2f4bbeSAlexander Yermolovich       uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
5251c2f4bbeSAlexander Yermolovich       CUMap[CUOffset] = CUOffsetUpdate;
5261c2f4bbeSAlexander Yermolovich     }
5271c2f4bbeSAlexander Yermolovich     }
5281c2f4bbeSAlexander Yermolovich   }
5291c2f4bbeSAlexander Yermolovich   return CUMap;
5301c2f4bbeSAlexander Yermolovich }
5311c2f4bbeSAlexander Yermolovich 
5321c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) {
5331c2f4bbeSAlexander Yermolovich   std::string NewBinaryContents;
5341c2f4bbeSAlexander Yermolovich   NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize);
5351c2f4bbeSAlexander Yermolovich   uint32_t StartOffset = 0;
5361c2f4bbeSAlexander Yermolovich   uint32_t DwarfUnitBaseOffset = 0;
5371c2f4bbeSAlexander Yermolovich   uint32_t OldValueSize = 0;
5381c2f4bbeSAlexander Yermolovich   uint32_t Offset = 0;
5391c2f4bbeSAlexander Yermolovich   std::string ByteSequence;
5401c2f4bbeSAlexander Yermolovich   std::vector<std::pair<uint32_t, uint32_t>> LengthPatches;
5411c2f4bbeSAlexander Yermolovich   // Wasting one entry to avoid checks for first.
5421c2f4bbeSAlexander Yermolovich   LengthPatches.push_back({0, 0});
5431c2f4bbeSAlexander Yermolovich 
5441c2f4bbeSAlexander Yermolovich   // Applying all the patches replacing current entry.
5451c2f4bbeSAlexander Yermolovich   // This might change the size of .debug_info section.
546*ea6c8b01SAlexander Yermolovich   for (const UniquePatchPtrType &PatchBase : DebugPatches) {
5471c2f4bbeSAlexander Yermolovich     Patch *P = PatchBase.get();
5481c2f4bbeSAlexander Yermolovich     switch (P->Kind) {
5491c2f4bbeSAlexander Yermolovich     default:
5501c2f4bbeSAlexander Yermolovich       continue;
5511c2f4bbeSAlexander Yermolovich     case DebugPatchKind::ReferencePatchValue: {
5521c2f4bbeSAlexander Yermolovich       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
5531c2f4bbeSAlexander Yermolovich       uint32_t DestinationOffset = RDP->DestinationOffset;
5541c2f4bbeSAlexander Yermolovich       assert(OldToNewOffset.count(DestinationOffset) &&
5551c2f4bbeSAlexander Yermolovich              "Destination Offset for reference not updated.");
5561c2f4bbeSAlexander Yermolovich       uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset];
5571c2f4bbeSAlexander Yermolovich       Offset = RDP->Offset;
5581c2f4bbeSAlexander Yermolovich       OldValueSize = RDP->PatchInfo.OldValueSize;
5591c2f4bbeSAlexander Yermolovich       if (RDP->PatchInfo.DirectRelative) {
5601c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
5611c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
5621c2f4bbeSAlexander Yermolovich         // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge
5631c2f4bbeSAlexander Yermolovich         // and overflow if later debug information grows.
5641c2f4bbeSAlexander Yermolovich         if (ByteSequence.size() > OldValueSize)
5651c2f4bbeSAlexander Yermolovich           errs() << "BOLT-ERROR: Relative reference of size "
5661c2f4bbeSAlexander Yermolovich                  << Twine::utohexstr(OldValueSize)
5671c2f4bbeSAlexander Yermolovich                  << " overflows with the new encoding.\n";
5681c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.DirectAbsolute) {
5691c2f4bbeSAlexander Yermolovich         ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
5701c2f4bbeSAlexander Yermolovich       } else if (RDP->PatchInfo.IndirectRelative) {
5711c2f4bbeSAlexander Yermolovich         UpdatedOffset -= DwarfUnitBaseOffset;
5721c2f4bbeSAlexander Yermolovich         ByteSequence.clear();
5731c2f4bbeSAlexander Yermolovich         raw_string_ostream OS(ByteSequence);
5741c2f4bbeSAlexander Yermolovich         encodeULEB128(UpdatedOffset, OS, 4);
5751c2f4bbeSAlexander Yermolovich       } else {
5761c2f4bbeSAlexander Yermolovich         llvm_unreachable("Invalid Reference form.");
5771c2f4bbeSAlexander Yermolovich       }
5781c2f4bbeSAlexander Yermolovich       break;
5791c2f4bbeSAlexander Yermolovich     }
5801c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue32: {
5811c2f4bbeSAlexander Yermolovich       DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P);
5821c2f4bbeSAlexander Yermolovich       Offset = P32->Offset;
5831c2f4bbeSAlexander Yermolovich       OldValueSize = 4;
5841c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P32->Value);
5851c2f4bbeSAlexander Yermolovich       break;
5861c2f4bbeSAlexander Yermolovich     }
5871c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64to32: {
5881c2f4bbeSAlexander Yermolovich       DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P);
5891c2f4bbeSAlexander Yermolovich       Offset = P64to32->Offset;
5901c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
5911c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(4, P64to32->Value);
5921c2f4bbeSAlexander Yermolovich       break;
5931c2f4bbeSAlexander Yermolovich     }
5941c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValueVariable: {
5951c2f4bbeSAlexander Yermolovich       DebugPatchVariableSize *PV =
5961c2f4bbeSAlexander Yermolovich           reinterpret_cast<DebugPatchVariableSize *>(P);
5971c2f4bbeSAlexander Yermolovich       Offset = PV->Offset;
5981c2f4bbeSAlexander Yermolovich       OldValueSize = PV->OldValueSize;
5991c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
6001c2f4bbeSAlexander Yermolovich       raw_string_ostream OS(ByteSequence);
6011c2f4bbeSAlexander Yermolovich       encodeULEB128(PV->Value, OS);
6021c2f4bbeSAlexander Yermolovich       break;
6031c2f4bbeSAlexander Yermolovich     }
6041c2f4bbeSAlexander Yermolovich     case DebugPatchKind::PatchValue64: {
6051c2f4bbeSAlexander Yermolovich       DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P);
6061c2f4bbeSAlexander Yermolovich       Offset = P64->Offset;
6071c2f4bbeSAlexander Yermolovich       OldValueSize = 8;
6081c2f4bbeSAlexander Yermolovich       ByteSequence = encodeLE(8, P64->Value);
6091c2f4bbeSAlexander Yermolovich       break;
6101c2f4bbeSAlexander Yermolovich     }
6111c2f4bbeSAlexander Yermolovich     case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
6121c2f4bbeSAlexander Yermolovich       DWARFUnitOffsetBaseLabel *BaseLabel =
6131c2f4bbeSAlexander Yermolovich           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
6141c2f4bbeSAlexander Yermolovich       Offset = BaseLabel->Offset;
6151c2f4bbeSAlexander Yermolovich       OldValueSize = 0;
6161c2f4bbeSAlexander Yermolovich       ByteSequence.clear();
6171c2f4bbeSAlexander Yermolovich       auto &Patch = LengthPatches.back();
6181c2f4bbeSAlexander Yermolovich       // Length to copy between last patch entry and next compile unit.
6191c2f4bbeSAlexander Yermolovich       uint32_t RemainingLength = Offset - StartOffset;
6201c2f4bbeSAlexander Yermolovich       uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength;
6211c2f4bbeSAlexander Yermolovich       DwarfUnitBaseOffset = NewCUOffset;
6221c2f4bbeSAlexander Yermolovich       // Length of previous CU = This CU Offset - sizeof(length) - last CU
6231c2f4bbeSAlexander Yermolovich       // Offset.
6241c2f4bbeSAlexander Yermolovich       Patch.second = NewCUOffset - 4 - Patch.first;
6251c2f4bbeSAlexander Yermolovich       LengthPatches.push_back({NewCUOffset, 0});
6261c2f4bbeSAlexander Yermolovich       break;
6271c2f4bbeSAlexander Yermolovich     }
6281c2f4bbeSAlexander Yermolovich     }
6291c2f4bbeSAlexander Yermolovich 
6301c2f4bbeSAlexander Yermolovich     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
6311c2f4bbeSAlexander Yermolovich            "Applied patch runs over binary size.");
6321c2f4bbeSAlexander Yermolovich     uint32_t Length = Offset - StartOffset;
6331c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
6341c2f4bbeSAlexander Yermolovich                              Length);
6351c2f4bbeSAlexander Yermolovich     NewBinaryContents.append(ByteSequence.data(), ByteSequence.size());
6361c2f4bbeSAlexander Yermolovich     StartOffset = Offset + OldValueSize;
6371c2f4bbeSAlexander Yermolovich   }
6381c2f4bbeSAlexander Yermolovich   uint32_t Length = BinaryContents.size() - StartOffset;
6391c2f4bbeSAlexander Yermolovich   NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
6401c2f4bbeSAlexander Yermolovich                            Length);
6411c2f4bbeSAlexander Yermolovich   DebugPatches.clear();
6421c2f4bbeSAlexander Yermolovich 
6431c2f4bbeSAlexander Yermolovich   // Patching lengths of CUs
6441c2f4bbeSAlexander Yermolovich   auto &Patch = LengthPatches.back();
6451c2f4bbeSAlexander Yermolovich   Patch.second = NewBinaryContents.size() - 4 - Patch.first;
6461c2f4bbeSAlexander Yermolovich   for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) {
6471c2f4bbeSAlexander Yermolovich     const auto &Patch = LengthPatches[J];
6481c2f4bbeSAlexander Yermolovich     ByteSequence = encodeLE(4, Patch.second);
6491c2f4bbeSAlexander Yermolovich     Offset = Patch.first;
6501c2f4bbeSAlexander Yermolovich     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I)
6511c2f4bbeSAlexander Yermolovich       NewBinaryContents[Offset + I] = ByteSequence[I];
6521c2f4bbeSAlexander Yermolovich   }
6531c2f4bbeSAlexander Yermolovich 
6541c2f4bbeSAlexander Yermolovich   return NewBinaryContents;
655a34c753fSRafael Auler }
656a34c753fSRafael Auler 
657a34c753fSRafael Auler void DebugStrWriter::create() {
658a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
659a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
660a34c753fSRafael Auler }
661a34c753fSRafael Auler 
662a34c753fSRafael Auler void DebugStrWriter::initialize() {
663a34c753fSRafael Auler   auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
664a34c753fSRafael Auler   (*StrStream) << StrSection;
665a34c753fSRafael Auler }
666a34c753fSRafael Auler 
667a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
668e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
669a34c753fSRafael Auler   if (StrBuffer->empty())
670a34c753fSRafael Auler     initialize();
671a34c753fSRafael Auler   auto Offset = StrBuffer->size();
672a34c753fSRafael Auler   (*StrStream) << Str;
673a34c753fSRafael Auler   StrStream->write_zeros(1);
674a34c753fSRafael Auler   return Offset;
675a34c753fSRafael Auler }
676a34c753fSRafael Auler 
677a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
678a34c753fSRafael Auler   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
679a34c753fSRafael Auler   if (!Abbrevs)
680a34c753fSRafael Auler     return;
681a34c753fSRafael Auler 
682a34c753fSRafael Auler   // Multiple units may share the same abbreviations. Only add abbreviations
683a34c753fSRafael Auler   // for the first unit and reuse them.
684a34c753fSRafael Auler   const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset();
68545f94abcSMaksim Panchenko   if (UnitsAbbrevData.find(AbbrevOffset) != UnitsAbbrevData.end())
686a34c753fSRafael Auler     return;
687a34c753fSRafael Auler 
68845f94abcSMaksim Panchenko   AbbrevData &UnitData = UnitsAbbrevData[AbbrevOffset];
689a34c753fSRafael Auler   UnitData.Buffer = std::make_unique<DebugBufferVector>();
690a34c753fSRafael Auler   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
691a34c753fSRafael Auler 
69245f94abcSMaksim Panchenko   const PatchesTy &UnitPatches = Patches[&Unit];
693a34c753fSRafael Auler 
694a34c753fSRafael Auler   raw_svector_ostream &OS = *UnitData.Stream.get();
695a34c753fSRafael Auler 
696a34c753fSRafael Auler   // Take a fast path if there are no patches to apply. Simply copy the original
697a34c753fSRafael Auler   // contents.
698a34c753fSRafael Auler   if (UnitPatches.empty()) {
699a34c753fSRafael Auler     StringRef AbbrevSectionContents =
700a34c753fSRafael Auler         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
701a34c753fSRafael Auler                          : Unit.getContext().getDWARFObj().getAbbrevSection();
702a34c753fSRafael Auler     StringRef AbbrevContents;
703a34c753fSRafael Auler 
704a34c753fSRafael Auler     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
705a34c753fSRafael Auler     if (!CUIndex.getRows().empty()) {
706a34c753fSRafael Auler       // Handle DWP section contribution.
707a34c753fSRafael Auler       const DWARFUnitIndex::Entry *DWOEntry =
708a34c753fSRafael Auler           CUIndex.getFromHash(*Unit.getDWOId());
709a34c753fSRafael Auler       if (!DWOEntry)
710a34c753fSRafael Auler         return;
711a34c753fSRafael Auler 
712a34c753fSRafael Auler       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
713a34c753fSRafael Auler           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
714a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
715a34c753fSRafael Auler                                                     DWOContrubution->Length);
71645f94abcSMaksim Panchenko     } else if (!Unit.isDWOUnit()) {
717a34c753fSRafael Auler       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
71845f94abcSMaksim Panchenko 
71945f94abcSMaksim Panchenko       // We know where the unit's abbreviation set starts, but not where it ends
72045f94abcSMaksim Panchenko       // as such data is not readily available. Hence, we have to build a sorted
72145f94abcSMaksim Panchenko       // list of start addresses and find the next starting address to determine
72245f94abcSMaksim Panchenko       // the set boundaries.
72345f94abcSMaksim Panchenko       //
72445f94abcSMaksim Panchenko       // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
72545f94abcSMaksim Panchenko       // we wouldn't have to build our own sorted list for the quick lookup.
72645f94abcSMaksim Panchenko       if (AbbrevSetOffsets.empty()) {
7271c2f4bbeSAlexander Yermolovich         for_each(
72845f94abcSMaksim Panchenko             *Unit.getContext().getDebugAbbrev(),
72945f94abcSMaksim Panchenko             [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
73045f94abcSMaksim Panchenko               AbbrevSetOffsets.push_back(P.first);
73145f94abcSMaksim Panchenko             });
7321c2f4bbeSAlexander Yermolovich         sort(AbbrevSetOffsets);
73345f94abcSMaksim Panchenko       }
7341c2f4bbeSAlexander Yermolovich       auto It = upper_bound(AbbrevSetOffsets, StartOffset);
73545f94abcSMaksim Panchenko       const uint64_t EndOffset =
73645f94abcSMaksim Panchenko           It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
737a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
73845f94abcSMaksim Panchenko     } else {
73945f94abcSMaksim Panchenko       // For DWO unit outside of DWP, we expect the entire section to hold
74045f94abcSMaksim Panchenko       // abbreviations for this unit only.
74145f94abcSMaksim Panchenko       AbbrevContents = AbbrevSectionContents;
742a34c753fSRafael Auler     }
743a34c753fSRafael Auler 
744a34c753fSRafael Auler     OS.reserveExtraSpace(AbbrevContents.size());
745a34c753fSRafael Auler     OS << AbbrevContents;
746a34c753fSRafael Auler 
747a34c753fSRafael Auler     return;
748a34c753fSRafael Auler   }
749a34c753fSRafael Auler 
750a34c753fSRafael Auler   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
751a34c753fSRafael Auler     const DWARFAbbreviationDeclaration &Abbrev = *I;
752a34c753fSRafael Auler     auto Patch = UnitPatches.find(&Abbrev);
753a34c753fSRafael Auler 
754a34c753fSRafael Auler     encodeULEB128(Abbrev.getCode(), OS);
755a34c753fSRafael Auler     encodeULEB128(Abbrev.getTag(), OS);
756a34c753fSRafael Auler     encodeULEB128(Abbrev.hasChildren(), OS);
757a34c753fSRafael Auler     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
758a34c753fSRafael Auler          Abbrev.attributes()) {
759a34c753fSRafael Auler       if (Patch != UnitPatches.end()) {
760a34c753fSRafael Auler         bool Patched = false;
761a34c753fSRafael Auler         // Patches added later take a precedence over earlier ones.
762a34c753fSRafael Auler         for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
763a34c753fSRafael Auler              ++I) {
764a34c753fSRafael Auler           if (I->OldAttr != AttrSpec.Attr)
765a34c753fSRafael Auler             continue;
766a34c753fSRafael Auler 
767a34c753fSRafael Auler           encodeULEB128(I->NewAttr, OS);
768a34c753fSRafael Auler           encodeULEB128(I->NewAttrForm, OS);
769a34c753fSRafael Auler           Patched = true;
770a34c753fSRafael Auler           break;
771a34c753fSRafael Auler         }
772a34c753fSRafael Auler         if (Patched)
773a34c753fSRafael Auler           continue;
774a34c753fSRafael Auler       }
775a34c753fSRafael Auler 
776a34c753fSRafael Auler       encodeULEB128(AttrSpec.Attr, OS);
777a34c753fSRafael Auler       encodeULEB128(AttrSpec.Form, OS);
778a34c753fSRafael Auler       if (AttrSpec.isImplicitConst())
779a34c753fSRafael Auler         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
780a34c753fSRafael Auler     }
781a34c753fSRafael Auler 
782a34c753fSRafael Auler     encodeULEB128(0, OS);
783a34c753fSRafael Auler     encodeULEB128(0, OS);
784a34c753fSRafael Auler   }
785a34c753fSRafael Auler   encodeULEB128(0, OS);
786a34c753fSRafael Auler }
787a34c753fSRafael Auler 
788a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
78945f94abcSMaksim Panchenko   if (DWOId) {
79045f94abcSMaksim Panchenko     // We expect abbrev_offset to always be zero for DWO units as there
79145f94abcSMaksim Panchenko     // should be one CU per DWO, and TUs should share the same abbreviation
79245f94abcSMaksim Panchenko     // set with the CU.
7931417f607SAlexander Yermolovich     // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so
7941417f607SAlexander Yermolovich     // can be none zero. Thus we are skipping the check for DWP.
79545f94abcSMaksim Panchenko     bool IsDWP = !Context.getCUIndex().getRows().empty();
7961417f607SAlexander Yermolovich     if (!IsDWP) {
79745f94abcSMaksim Panchenko       for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
79845f94abcSMaksim Panchenko         if (Unit->getAbbreviationsOffset() != 0) {
79945f94abcSMaksim Panchenko           errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
80045f94abcSMaksim Panchenko                     "Unable to update debug info.\n";
80145f94abcSMaksim Panchenko           exit(1);
80245f94abcSMaksim Panchenko         }
80345f94abcSMaksim Panchenko       }
80445f94abcSMaksim Panchenko     }
80545f94abcSMaksim Panchenko 
80645f94abcSMaksim Panchenko     // Issue abbreviations for the DWO CU only.
80745f94abcSMaksim Panchenko     addUnitAbbreviations(*Context.getDWOCompileUnitForHash(*DWOId));
80845f94abcSMaksim Panchenko   } else {
80945f94abcSMaksim Panchenko     // Add abbreviations from compile and type non-DWO units.
81045f94abcSMaksim Panchenko     for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units())
81145f94abcSMaksim Panchenko       addUnitAbbreviations(*Unit);
81245f94abcSMaksim Panchenko   }
81345f94abcSMaksim Panchenko 
814a34c753fSRafael Auler   DebugBufferVector ReturnBuffer;
815a34c753fSRafael Auler 
816a34c753fSRafael Auler   // Pre-calculate the total size of abbrev section.
817a34c753fSRafael Auler   uint64_t Size = 0;
81845f94abcSMaksim Panchenko   for (const auto &KV : UnitsAbbrevData) {
819a34c753fSRafael Auler     const AbbrevData &UnitData = KV.second;
820a34c753fSRafael Auler     Size += UnitData.Buffer->size();
821a34c753fSRafael Auler   }
822a34c753fSRafael Auler   ReturnBuffer.reserve(Size);
823a34c753fSRafael Auler 
824a34c753fSRafael Auler   uint64_t Pos = 0;
82545f94abcSMaksim Panchenko   for (auto &KV : UnitsAbbrevData) {
826a34c753fSRafael Auler     AbbrevData &UnitData = KV.second;
827a34c753fSRafael Auler     ReturnBuffer.append(*UnitData.Buffer);
828a34c753fSRafael Auler     UnitData.Offset = Pos;
829a34c753fSRafael Auler     Pos += UnitData.Buffer->size();
830a34c753fSRafael Auler 
831a34c753fSRafael Auler     UnitData.Buffer.reset();
832a34c753fSRafael Auler     UnitData.Stream.reset();
833a34c753fSRafael Auler   }
834a34c753fSRafael Auler 
835a34c753fSRafael Auler   return std::make_unique<DebugBufferVector>(ReturnBuffer);
836a34c753fSRafael Auler }
837a34c753fSRafael Auler 
838a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
839a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
840a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
841a34c753fSRafael Auler                                     int PointerSize) {
842a34c753fSRafael Auler   // emit the sequence to set the address
843a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
844a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
845a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
846a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
847a34c753fSRafael Auler 
848a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
849a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
850a34c753fSRafael Auler }
851a34c753fSRafael Auler 
852a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
853a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
854a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
855a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
856a34c753fSRafael Auler   if (InputSequences.empty())
857a34c753fSRafael Auler     return;
858a34c753fSRafael Auler 
859a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
860a34c753fSRafael Auler   unsigned FileNum = 1;
861a34c753fSRafael Auler   unsigned LastLine = 1;
862a34c753fSRafael Auler   unsigned Column = 0;
863a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
864a34c753fSRafael Auler   unsigned Isa = 0;
865a34c753fSRafael Auler   unsigned Discriminator = 0;
866a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
867a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
868a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
869a34c753fSRafael Auler 
870a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
871a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
872a34c753fSRafael Auler     FileNum = 1;
873a34c753fSRafael Auler     LastLine = 1;
874a34c753fSRafael Auler     Column = 0;
875a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
876a34c753fSRafael Auler     Isa = 0;
877a34c753fSRafael Auler     Discriminator = 0;
878a34c753fSRafael Auler     LastAddress = InvalidAddress;
879a34c753fSRafael Auler   };
880a34c753fSRafael Auler 
881a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
882a34c753fSRafael Auler     const uint64_t SequenceStart =
883a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
884a34c753fSRafael Auler 
885a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
886a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
887a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
888a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
889a34c753fSRafael Auler     }
890a34c753fSRafael Auler 
891a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
892a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
893a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
894a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
895a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
896a34c753fSRafael Auler 
897a34c753fSRafael Auler       if (FileNum != Row.File) {
898a34c753fSRafael Auler         FileNum = Row.File;
899a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
900a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
901a34c753fSRafael Auler       }
902a34c753fSRafael Auler       if (Column != Row.Column) {
903a34c753fSRafael Auler         Column = Row.Column;
904a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
905a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
906a34c753fSRafael Auler       }
907a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
908a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
909a34c753fSRafael Auler         Discriminator = Row.Discriminator;
910a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
911a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
912a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
913a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
914a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
915a34c753fSRafael Auler       }
916a34c753fSRafael Auler       if (Isa != Row.Isa) {
917a34c753fSRafael Auler         Isa = Row.Isa;
918a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
919a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
920a34c753fSRafael Auler       }
921a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
922a34c753fSRafael Auler         Flags = Row.IsStmt;
923a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
924a34c753fSRafael Auler       }
925a34c753fSRafael Auler       if (Row.BasicBlock)
926a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
927a34c753fSRafael Auler       if (Row.PrologueEnd)
928a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
929a34c753fSRafael Auler       if (Row.EpilogueBegin)
930a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
931a34c753fSRafael Auler 
932a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
933a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
934a34c753fSRafael Auler       if (Row.EndSequence) {
935a34c753fSRafael Auler         emitEndOfSequence(Address);
936a34c753fSRafael Auler       } else {
937a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
938a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
939a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
940a34c753fSRafael Auler         else
941a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
942a34c753fSRafael Auler 
943a34c753fSRafael Auler         LastAddress = Address;
944a34c753fSRafael Auler         LastLine = Row.Line;
945a34c753fSRafael Auler       }
946a34c753fSRafael Auler 
947a34c753fSRafael Auler       Discriminator = 0;
948a34c753fSRafael Auler     }
949a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
950a34c753fSRafael Auler   }
951a34c753fSRafael Auler 
952a34c753fSRafael Auler   // Finish with the end of the sequence.
953a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
954a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
955a34c753fSRafael Auler }
956a34c753fSRafael Auler 
957a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
958a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
959a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
960a34c753fSRafael Auler static inline void emitDwarfLineTable(
961a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
962a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
963a34c753fSRafael Auler   unsigned FileNum = 1;
964a34c753fSRafael Auler   unsigned LastLine = 1;
965a34c753fSRafael Auler   unsigned Column = 0;
966a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
967a34c753fSRafael Auler   unsigned Isa = 0;
968a34c753fSRafael Auler   unsigned Discriminator = 0;
969a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
970a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
971a34c753fSRafael Auler 
972a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
973a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
974a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
975a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
976a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
977a34c753fSRafael Auler       FileNum = 1;
978a34c753fSRafael Auler       LastLine = 1;
979a34c753fSRafael Auler       Column = 0;
980a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
981a34c753fSRafael Auler       Isa = 0;
982a34c753fSRafael Auler       Discriminator = 0;
983a34c753fSRafael Auler       LastLabel = nullptr;
984a34c753fSRafael Auler       continue;
985a34c753fSRafael Auler     }
986a34c753fSRafael Auler 
987a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
988a34c753fSRafael Auler 
989a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
990a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
991a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
992a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
993a34c753fSRafael Auler     }
994a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
995a34c753fSRafael Auler       Column = LineEntry.getColumn();
996a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
997a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
998a34c753fSRafael Auler     }
999a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
1000a34c753fSRafael Auler         MCOS->getContext().getDwarfVersion() >= 4) {
1001a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
1002a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
1003a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1004a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
1005a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1006a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
1007a34c753fSRafael Auler     }
1008a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
1009a34c753fSRafael Auler       Isa = LineEntry.getIsa();
1010a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1011a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
1012a34c753fSRafael Auler     }
1013a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1014a34c753fSRafael Auler       Flags = LineEntry.getFlags();
1015a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1016a34c753fSRafael Auler     }
1017a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1018a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1019a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1020a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1021a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1022a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1023a34c753fSRafael Auler 
1024a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
1025a34c753fSRafael Auler 
1026a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
1027a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
1028a34c753fSRafael Auler     // Label and the current Label.
1029a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1030a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
1031a34c753fSRafael Auler     Discriminator = 0;
1032a34c753fSRafael Auler     LastLine = LineEntry.getLine();
1033a34c753fSRafael Auler     LastLabel = Label;
1034a34c753fSRafael Auler   }
1035a34c753fSRafael Auler 
1036a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
1037a34c753fSRafael Auler }
1038a34c753fSRafael Auler 
1039a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1040b73c87bcSMaksim Panchenko                             Optional<MCDwarfLineStr> &LineStr,
1041b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
1042a34c753fSRafael Auler   if (!RawData.empty()) {
1043a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
1044a34c753fSRafael Auler            InputSequences.empty() &&
1045a34c753fSRafael Auler            "cannot combine raw data with new line entries");
1046a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
1047a34c753fSRafael Auler     MCOS->emitBytes(RawData);
1048a34c753fSRafael Auler 
1049b73c87bcSMaksim Panchenko     // Emit fake relocation for RuntimeDyld to always allocate the section.
1050b73c87bcSMaksim Panchenko     //
1051b73c87bcSMaksim Panchenko     // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
1052b73c87bcSMaksim Panchenko     //        without relocations.
1053b73c87bcSMaksim Panchenko     MCOS->emitRelocDirective(
1054b73c87bcSMaksim Panchenko         *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
1055b73c87bcSMaksim Panchenko         MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);
1056b73c87bcSMaksim Panchenko 
1057a34c753fSRafael Auler     return;
1058a34c753fSRafael Auler   }
1059a34c753fSRafael Auler 
1060a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1061a34c753fSRafael Auler 
1062a34c753fSRafael Auler   // Put out the line tables.
1063a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1064a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1065a34c753fSRafael Auler 
1066a34c753fSRafael Auler   // Emit line tables for the original code.
1067a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1068a34c753fSRafael Auler 
1069a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
1070a34c753fSRafael Auler   // of this section (that was used in a previous expression).
1071a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
1072a34c753fSRafael Auler }
1073a34c753fSRafael Auler 
1074a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1075a34c753fSRafael Auler   MCAssembler &Assembler =
1076a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1077a34c753fSRafael Auler 
1078a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1079a34c753fSRafael Auler 
1080a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
1081a34c753fSRafael Auler 
1082a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
1083a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
1084a34c753fSRafael Auler   if (LineTables.empty())
1085a34c753fSRafael Auler     return;
1086a34c753fSRafael Auler 
1087a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
1088a34c753fSRafael Auler   Optional<MCDwarfLineStr> LineStr(None);
1089a34c753fSRafael Auler   if (BC.Ctx->getDwarfVersion() >= 5)
1090a34c753fSRafael Auler     LineStr = MCDwarfLineStr(*BC.Ctx);
1091a34c753fSRafael Auler 
1092a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
1093a34c753fSRafael Auler   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
1094a34c753fSRafael Auler 
1095a34c753fSRafael Auler   // Handle the rest of the Compile Units.
1096a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
1097b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1098a34c753fSRafael Auler   }
1099a34c753fSRafael Auler }
1100a34c753fSRafael Auler 
1101a34c753fSRafael Auler } // namespace bolt
1102a34c753fSRafael Auler } // namespace llvm
1103