xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision b73c87bc4ffaecbc9c0f54d4ff95659fc13d2d65)
1a34c753fSRafael Auler //===- DebugData.cpp - Representation and writing of debugging information. ==//
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 //
9a34c753fSRafael Auler //===----------------------------------------------------------------------===//
10a34c753fSRafael Auler 
11a34c753fSRafael Auler #include "bolt/Core/DebugData.h"
12a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h"
13a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h"
14a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
15a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h"
16a34c753fSRafael Auler #include "llvm/MC/MCSymbol.h"
17a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
18a34c753fSRafael Auler #include "llvm/Support/EndianStream.h"
19a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
20a34c753fSRafael Auler #include <algorithm>
21a34c753fSRafael Auler #include <cassert>
22a34c753fSRafael Auler #include <cstdint>
23a34c753fSRafael Auler #include <limits>
24a34c753fSRafael Auler 
25a34c753fSRafael Auler #undef  DEBUG_TYPE
26a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info"
27a34c753fSRafael Auler 
28a34c753fSRafael Auler namespace opts {
29a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity;
30a34c753fSRafael Auler }
31a34c753fSRafael Auler 
32a34c753fSRafael Auler namespace llvm {
33a34c753fSRafael Auler namespace bolt {
34a34c753fSRafael Auler 
35a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
36a34c753fSRafael Auler 
37a34c753fSRafael Auler namespace {
38a34c753fSRafael Auler 
39a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size).
40a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of
41a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address).
42a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes.
43a34c753fSRafael Auler // Returns the number of written bytes.
44a34c753fSRafael Auler uint64_t writeAddressRanges(
45a34c753fSRafael Auler     raw_svector_ostream &Stream,
46a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges,
47a34c753fSRafael Auler     const bool WriteRelativeRanges = false) {
48a34c753fSRafael Auler   for (const DebugAddressRange &Range : AddressRanges) {
49a34c753fSRafael Auler     support::endian::write(Stream, Range.LowPC, support::little);
50a34c753fSRafael Auler     support::endian::write(
51a34c753fSRafael Auler         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
52a34c753fSRafael Auler         support::little);
53a34c753fSRafael Auler   }
54a34c753fSRafael Auler   // Finish with 0 entries.
55a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
56a34c753fSRafael Auler   support::endian::write(Stream, 0ULL, support::little);
57a34c753fSRafael Auler   return AddressRanges.size() * 16 + 16;
58a34c753fSRafael Auler }
59a34c753fSRafael Auler 
60a34c753fSRafael Auler } // namespace
61a34c753fSRafael Auler 
62a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() {
63a34c753fSRafael Auler   RangesBuffer = std::make_unique<DebugBufferVector>();
64a34c753fSRafael Auler   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
65a34c753fSRafael Auler 
66a34c753fSRafael Auler   // Add an empty range as the first entry;
67a34c753fSRafael Auler   SectionOffset +=
68a34c753fSRafael Auler       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
69a34c753fSRafael Auler }
70a34c753fSRafael Auler 
71a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges(
72a34c753fSRafael Auler     DebugAddressRangesVector &&Ranges,
73a34c753fSRafael Auler     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
74a34c753fSRafael Auler   if (Ranges.empty())
75a34c753fSRafael Auler     return getEmptyRangesOffset();
76a34c753fSRafael Auler 
77a34c753fSRafael Auler   const auto RI = CachedRanges.find(Ranges);
78a34c753fSRafael Auler   if (RI != CachedRanges.end())
79a34c753fSRafael Auler     return RI->second;
80a34c753fSRafael Auler 
81a34c753fSRafael Auler   const uint64_t EntryOffset = addRanges(Ranges);
82a34c753fSRafael Auler   CachedRanges.emplace(std::move(Ranges), EntryOffset);
83a34c753fSRafael Auler 
84a34c753fSRafael Auler   return EntryOffset;
85a34c753fSRafael Auler }
86a34c753fSRafael Auler 
87a34c753fSRafael Auler uint64_t
88a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) {
89a34c753fSRafael Auler   if (Ranges.empty())
90a34c753fSRafael Auler     return getEmptyRangesOffset();
91a34c753fSRafael Auler 
92a34c753fSRafael Auler   // Reading the SectionOffset and updating it should be atomic to guarantee
93a34c753fSRafael Auler   // unique and correct offsets in patches.
94a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
95a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
96a34c753fSRafael Auler   SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);
97a34c753fSRafael Auler 
98a34c753fSRafael Auler   return EntryOffset;
99a34c753fSRafael Auler }
100a34c753fSRafael Auler 
101a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() {
102a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
103a34c753fSRafael Auler   return SectionOffset;
104a34c753fSRafael Auler }
105a34c753fSRafael Auler 
106a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
107a34c753fSRafael Auler                                             DebugAddressRangesVector &&Ranges) {
108a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
109a34c753fSRafael Auler   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
110a34c753fSRafael Auler }
111a34c753fSRafael Auler 
112a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection(
113a34c753fSRafael Auler     raw_svector_ostream &RangesStream) const {
114a34c753fSRafael Auler   // For reference on the format of the .debug_aranges section, see the DWARF4
115a34c753fSRafael Auler   // specification, section 6.1.4 Lookup by Address
116a34c753fSRafael Auler   // http://www.dwarfstd.org/doc/DWARF4.pdf
117a34c753fSRafael Auler   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
118a34c753fSRafael Auler     const uint64_t Offset = CUOffsetAddressRangesPair.first;
119a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges =
120a34c753fSRafael Auler         CUOffsetAddressRangesPair.second;
121a34c753fSRafael Auler 
122a34c753fSRafael Auler     // Emit header.
123a34c753fSRafael Auler 
124a34c753fSRafael Auler     // Size of this set: 8 (size of the header) + 4 (padding after header)
125a34c753fSRafael Auler     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
126a34c753fSRafael Auler     // pair of uint64_t's for the terminating, zero-length range.
127a34c753fSRafael Auler     // Does not include size field itself.
128a34c753fSRafael Auler     uint32_t Size = 8 + 4 + 2*sizeof(uint64_t) * (AddressRanges.size() + 1);
129a34c753fSRafael Auler 
130a34c753fSRafael Auler     // Header field #1: set size.
131a34c753fSRafael Auler     support::endian::write(RangesStream, Size, support::little);
132a34c753fSRafael Auler 
133a34c753fSRafael Auler     // Header field #2: version number, 2 as per the specification.
134a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint16_t>(2),
135a34c753fSRafael Auler                            support::little);
136a34c753fSRafael Auler 
137a34c753fSRafael Auler     // Header field #3: debug info offset of the correspondent compile unit.
138a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(Offset),
139a34c753fSRafael Auler                            support::little);
140a34c753fSRafael Auler 
141a34c753fSRafael Auler     // Header field #4: address size.
142a34c753fSRafael Auler     // 8 since we only write ELF64 binaries for now.
143a34c753fSRafael Auler     RangesStream << char(8);
144a34c753fSRafael Auler 
145a34c753fSRafael Auler     // Header field #5: segment size of target architecture.
146a34c753fSRafael Auler     RangesStream << char(0);
147a34c753fSRafael Auler 
148a34c753fSRafael Auler     // Padding before address table - 4 bytes in the 64-bit-pointer case.
149a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(0),
150a34c753fSRafael Auler                            support::little);
151a34c753fSRafael Auler 
152a34c753fSRafael Auler     writeAddressRanges(RangesStream, AddressRanges, true);
153a34c753fSRafael Auler   }
154a34c753fSRafael Auler }
155a34c753fSRafael Auler 
156a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }
157a34c753fSRafael Auler 
158a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() {
159a34c753fSRafael Auler   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
160a34c753fSRafael Auler                                           indexToAdddessEnd());
161a34c753fSRafael Auler   // Sorting address in increasing order of indices.
162a34c753fSRafael Auler   std::sort(SortedMap.begin(), SortedMap.end(),
163a34c753fSRafael Auler             [](const IndexAddressPair &A, const IndexAddressPair &B) {
164a34c753fSRafael Auler               return A.first < B.first;
165a34c753fSRafael Auler             });
166a34c753fSRafael Auler   for (auto &Pair : SortedMap)
167a34c753fSRafael Auler     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
168a34c753fSRafael Auler }
169a34c753fSRafael Auler uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address,
170a34c753fSRafael Auler                                               uint64_t DWOId) {
171a34c753fSRafael Auler   if (!AddressMaps.count(DWOId))
172a34c753fSRafael Auler     AddressMaps[DWOId] = AddressForDWOCU();
173a34c753fSRafael Auler 
174a34c753fSRafael Auler   AddressForDWOCU &Map = AddressMaps[DWOId];
175a34c753fSRafael Auler   auto Entry = Map.find(Address);
176a34c753fSRafael Auler   if (Entry == Map.end()) {
177a34c753fSRafael Auler     auto Index = Map.getNextIndex();
178a34c753fSRafael Auler     Entry = Map.insert(Address, Index).first;
179a34c753fSRafael Auler   }
180a34c753fSRafael Auler   return Entry->second;
181a34c753fSRafael Auler }
182a34c753fSRafael Auler 
183a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
184a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update
185a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
186a34c753fSRafael Auler // update AddressToIndex and IndexToAddress
187a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
188a34c753fSRafael Auler                                       uint64_t DWOId) {
189a34c753fSRafael Auler   AddressForDWOCU &Map = AddressMaps[DWOId];
190a34c753fSRafael Auler   auto Entry = Map.find(Address);
191a34c753fSRafael Auler   if (Entry != Map.end()) {
192a34c753fSRafael Auler     if (Entry->second > Index)
193a34c753fSRafael Auler       Map.updateAddressToIndex(Address, Index);
194a34c753fSRafael Auler     Map.updateIndexToAddrss(Address, Index);
195a34c753fSRafael Auler   } else
196a34c753fSRafael Auler     Map.insert(Address, Index);
197a34c753fSRafael Auler }
198a34c753fSRafael Auler 
199a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() {
200a34c753fSRafael Auler   // Need to layout all sections within .debug_addr
201a34c753fSRafael Auler   // Within each section sort Address by index.
202a34c753fSRafael Auler   AddressSectionBuffer Buffer;
203a34c753fSRafael Auler   raw_svector_ostream AddressStream(Buffer);
204a34c753fSRafael Auler   for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
205a34c753fSRafael Auler     Optional<uint64_t> DWOId = CU->getDWOId();
206a34c753fSRafael Auler     // Handling the case wehre debug information is a mix of Debug fission and
207a34c753fSRafael Auler     // monolitic.
208a34c753fSRafael Auler     if (!DWOId)
209a34c753fSRafael Auler       continue;
210a34c753fSRafael Auler     auto AM = AddressMaps.find(*DWOId);
211a34c753fSRafael Auler     // Adding to map even if it did not contribute to .debug_addr.
212a34c753fSRafael Auler     // The Skeleton CU will still have DW_AT_GNU_addr_base.
213a34c753fSRafael Auler     DWOIdToOffsetMap[*DWOId] = Buffer.size();
214a34c753fSRafael Auler     // If does not exist this CUs DWO section didn't contribute to .debug_addr.
215a34c753fSRafael Auler     if (AM == AddressMaps.end())
216a34c753fSRafael Auler       continue;
217a34c753fSRafael Auler     std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
218a34c753fSRafael Auler                                             AM->second.indexToAdddessEnd());
219a34c753fSRafael Auler     // Sorting address in increasing order of indices.
220a34c753fSRafael Auler     std::sort(SortedMap.begin(), SortedMap.end(),
221a34c753fSRafael Auler               [](const IndexAddressPair &A, const IndexAddressPair &B) {
222a34c753fSRafael Auler                 return A.first < B.first;
223a34c753fSRafael Auler               });
224a34c753fSRafael Auler 
225a34c753fSRafael Auler     uint8_t AddrSize = CU->getAddressByteSize();
226a34c753fSRafael Auler     uint32_t Counter = 0;
227a34c753fSRafael Auler     auto WriteAddress = [&](uint64_t Address) -> void {
228a34c753fSRafael Auler       ++Counter;
229a34c753fSRafael Auler       switch (AddrSize) {
230a34c753fSRafael Auler       default:
231a34c753fSRafael Auler         assert(false && "Address Size is invalid.");
232a34c753fSRafael Auler         break;
233a34c753fSRafael Auler       case 4:
234a34c753fSRafael Auler         support::endian::write(AddressStream, static_cast<uint32_t>(Address),
235a34c753fSRafael Auler                                support::little);
236a34c753fSRafael Auler         break;
237a34c753fSRafael Auler       case 8:
238a34c753fSRafael Auler         support::endian::write(AddressStream, Address, support::little);
239a34c753fSRafael Auler         break;
240a34c753fSRafael Auler       }
241a34c753fSRafael Auler     };
242a34c753fSRafael Auler 
243a34c753fSRafael Auler     for (const IndexAddressPair &Val : SortedMap) {
244a34c753fSRafael Auler       while (Val.first > Counter)
245a34c753fSRafael Auler         WriteAddress(0);
246a34c753fSRafael Auler       WriteAddress(Val.second);
247a34c753fSRafael Auler     }
248a34c753fSRafael Auler   }
249a34c753fSRafael Auler 
250a34c753fSRafael Auler   return Buffer;
251a34c753fSRafael Auler }
252a34c753fSRafael Auler 
253a34c753fSRafael Auler uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
254a34c753fSRafael Auler   auto Iter = DWOIdToOffsetMap.find(DWOId);
255a34c753fSRafael Auler   assert(Iter != DWOIdToOffsetMap.end() &&
256a34c753fSRafael Auler          "Offset in to.debug_addr was not found for DWO ID.");
257a34c753fSRafael Auler   return Iter->second;
258a34c753fSRafael Auler }
259a34c753fSRafael Auler 
260a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
261a34c753fSRafael Auler   LocBuffer = std::make_unique<DebugBufferVector>();
262a34c753fSRafael Auler   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
263a34c753fSRafael Auler }
264a34c753fSRafael Auler 
265a34c753fSRafael Auler void DebugLocWriter::addList(uint64_t AttrOffset,
266a34c753fSRafael Auler                              DebugLocationsVector &&LocList) {
267a34c753fSRafael Auler   if (LocList.empty()) {
268a34c753fSRafael Auler     EmptyAttrLists.push_back(AttrOffset);
269a34c753fSRafael Auler     return;
270a34c753fSRafael Auler   }
271a34c753fSRafael Auler   // Since there is a separate DebugLocWriter for each thread,
272a34c753fSRafael Auler   // we don't need a lock to read the SectionOffset and update it.
273a34c753fSRafael Auler   const uint32_t EntryOffset = SectionOffset;
274a34c753fSRafael Auler 
275a34c753fSRafael Auler   for (const DebugLocationEntry &Entry : LocList) {
276a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
277a34c753fSRafael Auler                            support::little);
278a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
279a34c753fSRafael Auler                            support::little);
280a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
281a34c753fSRafael Auler                            support::little);
282a34c753fSRafael Auler     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
283a34c753fSRafael Auler                             Entry.Expr.size());
284a34c753fSRafael Auler     SectionOffset += 2 * 8 + 2 + Entry.Expr.size();
285a34c753fSRafael Auler   }
286a34c753fSRafael Auler   LocStream->write_zeros(16);
287a34c753fSRafael Auler   SectionOffset += 16;
288a34c753fSRafael Auler   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
289a34c753fSRafael Auler }
290a34c753fSRafael Auler 
291a34c753fSRafael Auler void DebugLoclistWriter::addList(uint64_t AttrOffset,
292a34c753fSRafael Auler                                  DebugLocationsVector &&LocList) {
293a34c753fSRafael Auler   Patches.push_back({AttrOffset, std::move(LocList)});
294a34c753fSRafael Auler }
295a34c753fSRafael Auler 
296a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
297a34c753fSRafael Auler   return std::move(LocBuffer);
298a34c753fSRafael Auler }
299a34c753fSRafael Auler 
300a34c753fSRafael Auler // DWARF 4: 2.6.2
301a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset,
302a34c753fSRafael Auler                               SimpleBinaryPatcher &DebugInfoPatcher) {
303a34c753fSRafael Auler   for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) {
304a34c753fSRafael Auler     uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset;
305a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset,
306a34c753fSRafael Auler                                   Offset);
307a34c753fSRafael Auler   }
308a34c753fSRafael Auler 
309a34c753fSRafael Auler   for (uint64_t DebugInfoAttrOffset : EmptyAttrLists)
310a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset,
311a34c753fSRafael Auler                                   DebugLocWriter::EmptyListOffset);
312a34c753fSRafael Auler }
313a34c753fSRafael Auler 
314a34c753fSRafael Auler void DebugLoclistWriter::finalize(uint64_t SectionOffset,
315a34c753fSRafael Auler                                   SimpleBinaryPatcher &DebugInfoPatcher) {
316a34c753fSRafael Auler   for (LocPatch &Patch : Patches) {
317a34c753fSRafael Auler     if (Patch.LocList.empty()) {
318a34c753fSRafael Auler       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
319a34c753fSRafael Auler                                     DebugLocWriter::EmptyListOffset);
320a34c753fSRafael Auler       continue;
321a34c753fSRafael Auler     }
322a34c753fSRafael Auler     const uint32_t EntryOffset = LocBuffer->size();
323a34c753fSRafael Auler     for (const DebugLocationEntry &Entry : Patch.LocList) {
324a34c753fSRafael Auler       support::endian::write(*LocStream,
325a34c753fSRafael Auler                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
326a34c753fSRafael Auler                              support::little);
327a34c753fSRafael Auler       uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId);
328a34c753fSRafael Auler       encodeULEB128(Index, *LocStream);
329a34c753fSRafael Auler 
330a34c753fSRafael Auler       // TODO: Support DWARF5
331a34c753fSRafael Auler       support::endian::write(*LocStream,
332a34c753fSRafael Auler                              static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
333a34c753fSRafael Auler                              support::little);
334a34c753fSRafael Auler       support::endian::write(*LocStream,
335a34c753fSRafael Auler                              static_cast<uint16_t>(Entry.Expr.size()),
336a34c753fSRafael Auler                              support::little);
337a34c753fSRafael Auler       *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
338a34c753fSRafael Auler                               Entry.Expr.size());
339a34c753fSRafael Auler     }
340a34c753fSRafael Auler     support::endian::write(*LocStream,
341a34c753fSRafael Auler                            static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
342a34c753fSRafael Auler                            support::little);
343a34c753fSRafael Auler     DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
344a34c753fSRafael Auler     clearList(Patch.LocList);
345a34c753fSRafael Auler   }
346a34c753fSRafael Auler   clearList(Patches);
347a34c753fSRafael Auler }
348a34c753fSRafael Auler 
349a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
350a34c753fSRafael Auler 
351a34c753fSRafael Auler void SimpleBinaryPatcher::addBinaryPatch(uint32_t Offset,
352a34c753fSRafael Auler                                          const std::string &NewValue) {
353a34c753fSRafael Auler   Patches.emplace_back(Offset, NewValue);
354a34c753fSRafael Auler }
355a34c753fSRafael Auler 
356a34c753fSRafael Auler void SimpleBinaryPatcher::addBytePatch(uint32_t Offset, uint8_t Value) {
357a34c753fSRafael Auler   Patches.emplace_back(Offset, std::string(1, Value));
358a34c753fSRafael Auler }
359a34c753fSRafael Auler 
360a34c753fSRafael Auler void SimpleBinaryPatcher::addLEPatch(uint32_t Offset, uint64_t NewValue,
361a34c753fSRafael Auler                                      size_t ByteSize) {
362a34c753fSRafael Auler   std::string LE64(ByteSize, 0);
363a34c753fSRafael Auler   for (size_t I = 0; I < ByteSize; ++I) {
364a34c753fSRafael Auler     LE64[I] = NewValue & 0xff;
365a34c753fSRafael Auler     NewValue >>= 8;
366a34c753fSRafael Auler   }
367a34c753fSRafael Auler   Patches.emplace_back(Offset, LE64);
368a34c753fSRafael Auler }
369a34c753fSRafael Auler 
370a34c753fSRafael Auler void SimpleBinaryPatcher::addUDataPatch(uint32_t Offset, uint64_t Value, uint64_t Size) {
371a34c753fSRafael Auler   std::string Buff;
372a34c753fSRafael Auler   raw_string_ostream OS(Buff);
373a34c753fSRafael Auler   encodeULEB128(Value, OS, Size);
374a34c753fSRafael Auler 
375a34c753fSRafael Auler   Patches.emplace_back(Offset, OS.str());
376a34c753fSRafael Auler }
377a34c753fSRafael Auler 
378a34c753fSRafael Auler void SimpleBinaryPatcher::addLE64Patch(uint32_t Offset, uint64_t NewValue) {
379a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
380a34c753fSRafael Auler }
381a34c753fSRafael Auler 
382a34c753fSRafael Auler void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) {
383a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
384a34c753fSRafael Auler }
385a34c753fSRafael Auler 
386a34c753fSRafael Auler void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents,
387a34c753fSRafael Auler                                       uint32_t DWPOffset = 0) {
388a34c753fSRafael Auler   for (const auto &Patch : Patches) {
389a34c753fSRafael Auler     uint32_t Offset = Patch.first - DWPOffset;
390a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
391a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
392a34c753fSRafael Auler         "Applied patch runs over binary size.");
393a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
394a34c753fSRafael Auler       BinaryContents[Offset + I] = ByteSequence[I];
395a34c753fSRafael Auler     }
396a34c753fSRafael Auler   }
397a34c753fSRafael Auler }
398a34c753fSRafael Auler 
399a34c753fSRafael Auler void DebugStrWriter::create() {
400a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
401a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
402a34c753fSRafael Auler }
403a34c753fSRafael Auler 
404a34c753fSRafael Auler void DebugStrWriter::initialize() {
405a34c753fSRafael Auler   auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
406a34c753fSRafael Auler   (*StrStream) << StrSection;
407a34c753fSRafael Auler }
408a34c753fSRafael Auler 
409a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
410a34c753fSRafael Auler   if (StrBuffer->empty())
411a34c753fSRafael Auler     initialize();
412a34c753fSRafael Auler   auto Offset = StrBuffer->size();
413a34c753fSRafael Auler   (*StrStream) << Str;
414a34c753fSRafael Auler   StrStream->write_zeros(1);
415a34c753fSRafael Auler   return Offset;
416a34c753fSRafael Auler }
417a34c753fSRafael Auler 
418a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
419a34c753fSRafael Auler   const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
420a34c753fSRafael Auler   if (!Abbrevs)
421a34c753fSRafael Auler     return;
422a34c753fSRafael Auler 
423a34c753fSRafael Auler   // Multiple units may share the same abbreviations. Only add abbreviations
424a34c753fSRafael Auler   // for the first unit and reuse them.
425a34c753fSRafael Auler   const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset();
42645f94abcSMaksim Panchenko   if (UnitsAbbrevData.find(AbbrevOffset) != UnitsAbbrevData.end())
427a34c753fSRafael Auler     return;
428a34c753fSRafael Auler 
42945f94abcSMaksim Panchenko   AbbrevData &UnitData = UnitsAbbrevData[AbbrevOffset];
430a34c753fSRafael Auler   UnitData.Buffer = std::make_unique<DebugBufferVector>();
431a34c753fSRafael Auler   UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
432a34c753fSRafael Auler 
43345f94abcSMaksim Panchenko   const PatchesTy &UnitPatches = Patches[&Unit];
434a34c753fSRafael Auler 
435a34c753fSRafael Auler   raw_svector_ostream &OS = *UnitData.Stream.get();
436a34c753fSRafael Auler 
437a34c753fSRafael Auler   // Take a fast path if there are no patches to apply. Simply copy the original
438a34c753fSRafael Auler   // contents.
439a34c753fSRafael Auler   if (UnitPatches.empty()) {
440a34c753fSRafael Auler     StringRef AbbrevSectionContents =
441a34c753fSRafael Auler         Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
442a34c753fSRafael Auler                          : Unit.getContext().getDWARFObj().getAbbrevSection();
443a34c753fSRafael Auler     StringRef AbbrevContents;
444a34c753fSRafael Auler 
445a34c753fSRafael Auler     const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
446a34c753fSRafael Auler     if (!CUIndex.getRows().empty()) {
447a34c753fSRafael Auler       // Handle DWP section contribution.
448a34c753fSRafael Auler       const DWARFUnitIndex::Entry *DWOEntry =
449a34c753fSRafael Auler           CUIndex.getFromHash(*Unit.getDWOId());
450a34c753fSRafael Auler       if (!DWOEntry)
451a34c753fSRafael Auler         return;
452a34c753fSRafael Auler 
453a34c753fSRafael Auler       const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
454a34c753fSRafael Auler           DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
455a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
456a34c753fSRafael Auler                                                     DWOContrubution->Length);
45745f94abcSMaksim Panchenko     } else if (!Unit.isDWOUnit()) {
458a34c753fSRafael Auler       const uint64_t StartOffset = Unit.getAbbreviationsOffset();
45945f94abcSMaksim Panchenko 
46045f94abcSMaksim Panchenko       // We know where the unit's abbreviation set starts, but not where it ends
46145f94abcSMaksim Panchenko       // as such data is not readily available. Hence, we have to build a sorted
46245f94abcSMaksim Panchenko       // list of start addresses and find the next starting address to determine
46345f94abcSMaksim Panchenko       // the set boundaries.
46445f94abcSMaksim Panchenko       //
46545f94abcSMaksim Panchenko       // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
46645f94abcSMaksim Panchenko       // we wouldn't have to build our own sorted list for the quick lookup.
46745f94abcSMaksim Panchenko       if (AbbrevSetOffsets.empty()) {
46845f94abcSMaksim Panchenko         llvm::for_each(
46945f94abcSMaksim Panchenko             *Unit.getContext().getDebugAbbrev(),
47045f94abcSMaksim Panchenko             [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
47145f94abcSMaksim Panchenko               AbbrevSetOffsets.push_back(P.first);
47245f94abcSMaksim Panchenko             });
47345f94abcSMaksim Panchenko         llvm::sort(AbbrevSetOffsets);
47445f94abcSMaksim Panchenko       }
47545f94abcSMaksim Panchenko       auto It = llvm::upper_bound(AbbrevSetOffsets, StartOffset);
47645f94abcSMaksim Panchenko       const uint64_t EndOffset =
47745f94abcSMaksim Panchenko           It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
478a34c753fSRafael Auler       AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
47945f94abcSMaksim Panchenko     } else {
48045f94abcSMaksim Panchenko       // For DWO unit outside of DWP, we expect the entire section to hold
48145f94abcSMaksim Panchenko       // abbreviations for this unit only.
48245f94abcSMaksim Panchenko       AbbrevContents = AbbrevSectionContents;
483a34c753fSRafael Auler     }
484a34c753fSRafael Auler 
485a34c753fSRafael Auler     OS.reserveExtraSpace(AbbrevContents.size());
486a34c753fSRafael Auler     OS << AbbrevContents;
487a34c753fSRafael Auler 
488a34c753fSRafael Auler     return;
489a34c753fSRafael Auler   }
490a34c753fSRafael Auler 
491a34c753fSRafael Auler   for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
492a34c753fSRafael Auler     const DWARFAbbreviationDeclaration &Abbrev = *I;
493a34c753fSRafael Auler     auto Patch = UnitPatches.find(&Abbrev);
494a34c753fSRafael Auler 
495a34c753fSRafael Auler     encodeULEB128(Abbrev.getCode(), OS);
496a34c753fSRafael Auler     encodeULEB128(Abbrev.getTag(), OS);
497a34c753fSRafael Auler     encodeULEB128(Abbrev.hasChildren(), OS);
498a34c753fSRafael Auler     for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
499a34c753fSRafael Auler          Abbrev.attributes()) {
500a34c753fSRafael Auler       if (Patch != UnitPatches.end()) {
501a34c753fSRafael Auler         bool Patched = false;
502a34c753fSRafael Auler         // Patches added later take a precedence over earlier ones.
503a34c753fSRafael Auler         for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
504a34c753fSRafael Auler              ++I) {
505a34c753fSRafael Auler           if (I->OldAttr != AttrSpec.Attr)
506a34c753fSRafael Auler             continue;
507a34c753fSRafael Auler 
508a34c753fSRafael Auler           encodeULEB128(I->NewAttr, OS);
509a34c753fSRafael Auler           encodeULEB128(I->NewAttrForm, OS);
510a34c753fSRafael Auler           Patched = true;
511a34c753fSRafael Auler           break;
512a34c753fSRafael Auler         }
513a34c753fSRafael Auler         if (Patched)
514a34c753fSRafael Auler           continue;
515a34c753fSRafael Auler       }
516a34c753fSRafael Auler 
517a34c753fSRafael Auler       encodeULEB128(AttrSpec.Attr, OS);
518a34c753fSRafael Auler       encodeULEB128(AttrSpec.Form, OS);
519a34c753fSRafael Auler       if (AttrSpec.isImplicitConst())
520a34c753fSRafael Auler         encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
521a34c753fSRafael Auler     }
522a34c753fSRafael Auler 
523a34c753fSRafael Auler     encodeULEB128(0, OS);
524a34c753fSRafael Auler     encodeULEB128(0, OS);
525a34c753fSRafael Auler   }
526a34c753fSRafael Auler   encodeULEB128(0, OS);
527a34c753fSRafael Auler }
528a34c753fSRafael Auler 
529a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
53045f94abcSMaksim Panchenko   if (DWOId) {
53145f94abcSMaksim Panchenko     // We expect abbrev_offset to always be zero for DWO units as there
53245f94abcSMaksim Panchenko     // should be one CU per DWO, and TUs should share the same abbreviation
53345f94abcSMaksim Panchenko     // set with the CU.
53445f94abcSMaksim Panchenko     // NOTE: this check could be expensive for DWPs as it iterates over
53545f94abcSMaksim Panchenko     //       all units and we invoke it for every unit. Hence only run
53645f94abcSMaksim Panchenko     //       it once per DWP.
53745f94abcSMaksim Panchenko     bool IsDWP = !Context.getCUIndex().getRows().empty();
53845f94abcSMaksim Panchenko     static bool CheckedDWP = false;
53945f94abcSMaksim Panchenko     if (!IsDWP || !CheckedDWP) {
54045f94abcSMaksim Panchenko       for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
54145f94abcSMaksim Panchenko         if (Unit->getAbbreviationsOffset() != 0) {
54245f94abcSMaksim Panchenko           errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
54345f94abcSMaksim Panchenko                     "Unable to update debug info.\n";
54445f94abcSMaksim Panchenko           exit(1);
54545f94abcSMaksim Panchenko         }
54645f94abcSMaksim Panchenko       }
54745f94abcSMaksim Panchenko       if (IsDWP)
54845f94abcSMaksim Panchenko         CheckedDWP = true;
54945f94abcSMaksim Panchenko     }
55045f94abcSMaksim Panchenko 
55145f94abcSMaksim Panchenko     // Issue abbreviations for the DWO CU only.
55245f94abcSMaksim Panchenko     addUnitAbbreviations(*Context.getDWOCompileUnitForHash(*DWOId));
55345f94abcSMaksim Panchenko   } else {
55445f94abcSMaksim Panchenko     // Add abbreviations from compile and type non-DWO units.
55545f94abcSMaksim Panchenko     for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units())
55645f94abcSMaksim Panchenko       addUnitAbbreviations(*Unit);
55745f94abcSMaksim Panchenko   }
55845f94abcSMaksim Panchenko 
559a34c753fSRafael Auler   DebugBufferVector ReturnBuffer;
560a34c753fSRafael Auler 
561a34c753fSRafael Auler   // Pre-calculate the total size of abbrev section.
562a34c753fSRafael Auler   uint64_t Size = 0;
56345f94abcSMaksim Panchenko   for (const auto &KV : UnitsAbbrevData) {
564a34c753fSRafael Auler     const AbbrevData &UnitData = KV.second;
565a34c753fSRafael Auler     Size += UnitData.Buffer->size();
566a34c753fSRafael Auler   }
567a34c753fSRafael Auler   ReturnBuffer.reserve(Size);
568a34c753fSRafael Auler 
569a34c753fSRafael Auler   uint64_t Pos = 0;
57045f94abcSMaksim Panchenko   for (auto &KV : UnitsAbbrevData) {
571a34c753fSRafael Auler     AbbrevData &UnitData = KV.second;
572a34c753fSRafael Auler     ReturnBuffer.append(*UnitData.Buffer);
573a34c753fSRafael Auler     UnitData.Offset = Pos;
574a34c753fSRafael Auler     Pos += UnitData.Buffer->size();
575a34c753fSRafael Auler 
576a34c753fSRafael Auler     UnitData.Buffer.reset();
577a34c753fSRafael Auler     UnitData.Stream.reset();
578a34c753fSRafael Auler   }
579a34c753fSRafael Auler 
580a34c753fSRafael Auler   return std::make_unique<DebugBufferVector>(ReturnBuffer);
581a34c753fSRafael Auler }
582a34c753fSRafael Auler 
583a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
584a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
585a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
586a34c753fSRafael Auler                                     int PointerSize) {
587a34c753fSRafael Auler   // emit the sequence to set the address
588a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
589a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
590a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
591a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
592a34c753fSRafael Auler 
593a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
594a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
595a34c753fSRafael Auler }
596a34c753fSRafael Auler 
597a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
598a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
599a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
600a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
601a34c753fSRafael Auler   if (InputSequences.empty())
602a34c753fSRafael Auler     return;
603a34c753fSRafael Auler 
604a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
605a34c753fSRafael Auler   unsigned FileNum = 1;
606a34c753fSRafael Auler   unsigned LastLine = 1;
607a34c753fSRafael Auler   unsigned Column = 0;
608a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
609a34c753fSRafael Auler   unsigned Isa = 0;
610a34c753fSRafael Auler   unsigned Discriminator = 0;
611a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
612a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
613a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
614a34c753fSRafael Auler 
615a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
616a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
617a34c753fSRafael Auler     FileNum = 1;
618a34c753fSRafael Auler     LastLine = 1;
619a34c753fSRafael Auler     Column = 0;
620a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
621a34c753fSRafael Auler     Isa = 0;
622a34c753fSRafael Auler     Discriminator = 0;
623a34c753fSRafael Auler     LastAddress = InvalidAddress;
624a34c753fSRafael Auler   };
625a34c753fSRafael Auler 
626a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
627a34c753fSRafael Auler     const uint64_t SequenceStart =
628a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
629a34c753fSRafael Auler 
630a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
631a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
632a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
633a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
634a34c753fSRafael Auler     }
635a34c753fSRafael Auler 
636a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
637a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
638a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
639a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
640a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
641a34c753fSRafael Auler 
642a34c753fSRafael Auler       if (FileNum != Row.File) {
643a34c753fSRafael Auler         FileNum = Row.File;
644a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
645a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
646a34c753fSRafael Auler       }
647a34c753fSRafael Auler       if (Column != Row.Column) {
648a34c753fSRafael Auler         Column = Row.Column;
649a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
650a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
651a34c753fSRafael Auler       }
652a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
653a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
654a34c753fSRafael Auler         Discriminator = Row.Discriminator;
655a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
656a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
657a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
658a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
659a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
660a34c753fSRafael Auler       }
661a34c753fSRafael Auler       if (Isa != Row.Isa) {
662a34c753fSRafael Auler         Isa = Row.Isa;
663a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
664a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
665a34c753fSRafael Auler       }
666a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
667a34c753fSRafael Auler         Flags = Row.IsStmt;
668a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
669a34c753fSRafael Auler       }
670a34c753fSRafael Auler       if (Row.BasicBlock)
671a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
672a34c753fSRafael Auler       if (Row.PrologueEnd)
673a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
674a34c753fSRafael Auler       if (Row.EpilogueBegin)
675a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
676a34c753fSRafael Auler 
677a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
678a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
679a34c753fSRafael Auler       if (Row.EndSequence) {
680a34c753fSRafael Auler         emitEndOfSequence(Address);
681a34c753fSRafael Auler       } else {
682a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
683a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
684a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
685a34c753fSRafael Auler         else
686a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
687a34c753fSRafael Auler 
688a34c753fSRafael Auler         LastAddress = Address;
689a34c753fSRafael Auler         LastLine = Row.Line;
690a34c753fSRafael Auler       }
691a34c753fSRafael Auler 
692a34c753fSRafael Auler       Discriminator = 0;
693a34c753fSRafael Auler     }
694a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
695a34c753fSRafael Auler   }
696a34c753fSRafael Auler 
697a34c753fSRafael Auler   // Finish with the end of the sequence.
698a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
699a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
700a34c753fSRafael Auler }
701a34c753fSRafael Auler 
702a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
703a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
704a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
705a34c753fSRafael Auler static inline void emitDwarfLineTable(
706a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
707a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
708a34c753fSRafael Auler   unsigned FileNum = 1;
709a34c753fSRafael Auler   unsigned LastLine = 1;
710a34c753fSRafael Auler   unsigned Column = 0;
711a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
712a34c753fSRafael Auler   unsigned Isa = 0;
713a34c753fSRafael Auler   unsigned Discriminator = 0;
714a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
715a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
716a34c753fSRafael Auler 
717a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
718a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
719a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
720a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
721a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
722a34c753fSRafael Auler       FileNum = 1;
723a34c753fSRafael Auler       LastLine = 1;
724a34c753fSRafael Auler       Column = 0;
725a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
726a34c753fSRafael Auler       Isa = 0;
727a34c753fSRafael Auler       Discriminator = 0;
728a34c753fSRafael Auler       LastLabel = nullptr;
729a34c753fSRafael Auler       continue;
730a34c753fSRafael Auler     }
731a34c753fSRafael Auler 
732a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
733a34c753fSRafael Auler 
734a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
735a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
736a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
737a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
738a34c753fSRafael Auler     }
739a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
740a34c753fSRafael Auler       Column = LineEntry.getColumn();
741a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
742a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
743a34c753fSRafael Auler     }
744a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
745a34c753fSRafael Auler         MCOS->getContext().getDwarfVersion() >= 4) {
746a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
747a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
748a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
749a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
750a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
751a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
752a34c753fSRafael Auler     }
753a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
754a34c753fSRafael Auler       Isa = LineEntry.getIsa();
755a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
756a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
757a34c753fSRafael Auler     }
758a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
759a34c753fSRafael Auler       Flags = LineEntry.getFlags();
760a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
761a34c753fSRafael Auler     }
762a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
763a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
764a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
765a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
766a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
767a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
768a34c753fSRafael Auler 
769a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
770a34c753fSRafael Auler 
771a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
772a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
773a34c753fSRafael Auler     // Label and the current Label.
774a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
775a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
776a34c753fSRafael Auler     Discriminator = 0;
777a34c753fSRafael Auler     LastLine = LineEntry.getLine();
778a34c753fSRafael Auler     LastLabel = Label;
779a34c753fSRafael Auler   }
780a34c753fSRafael Auler 
781a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
782a34c753fSRafael Auler }
783a34c753fSRafael Auler 
784a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
785*b73c87bcSMaksim Panchenko                             Optional<MCDwarfLineStr> &LineStr,
786*b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
787a34c753fSRafael Auler   if (!RawData.empty()) {
788a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
789a34c753fSRafael Auler            InputSequences.empty() &&
790a34c753fSRafael Auler            "cannot combine raw data with new line entries");
791a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
792a34c753fSRafael Auler     MCOS->emitBytes(RawData);
793a34c753fSRafael Auler 
794*b73c87bcSMaksim Panchenko     // Emit fake relocation for RuntimeDyld to always allocate the section.
795*b73c87bcSMaksim Panchenko     //
796*b73c87bcSMaksim Panchenko     // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
797*b73c87bcSMaksim Panchenko     //        without relocations.
798*b73c87bcSMaksim Panchenko     MCOS->emitRelocDirective(
799*b73c87bcSMaksim Panchenko         *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
800*b73c87bcSMaksim Panchenko         MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);
801*b73c87bcSMaksim Panchenko 
802a34c753fSRafael Auler     return;
803a34c753fSRafael Auler   }
804a34c753fSRafael Auler 
805a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
806a34c753fSRafael Auler 
807a34c753fSRafael Auler   // Put out the line tables.
808a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
809a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
810a34c753fSRafael Auler 
811a34c753fSRafael Auler   // Emit line tables for the original code.
812a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
813a34c753fSRafael Auler 
814a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
815a34c753fSRafael Auler   // of this section (that was used in a previous expression).
816a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
817a34c753fSRafael Auler }
818a34c753fSRafael Auler 
819a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
820a34c753fSRafael Auler   MCAssembler &Assembler =
821a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
822a34c753fSRafael Auler 
823a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
824a34c753fSRafael Auler 
825a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
826a34c753fSRafael Auler 
827a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
828a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
829a34c753fSRafael Auler   if (LineTables.empty())
830a34c753fSRafael Auler     return;
831a34c753fSRafael Auler 
832a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
833a34c753fSRafael Auler   Optional<MCDwarfLineStr> LineStr(None);
834a34c753fSRafael Auler   if (BC.Ctx->getDwarfVersion() >= 5)
835a34c753fSRafael Auler     LineStr = MCDwarfLineStr(*BC.Ctx);
836a34c753fSRafael Auler 
837a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
838a34c753fSRafael Auler   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
839a34c753fSRafael Auler 
840a34c753fSRafael Auler   // Handle the rest of the Compile Units.
841a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
842*b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
843a34c753fSRafael Auler   }
844a34c753fSRafael Auler }
845a34c753fSRafael Auler 
846a34c753fSRafael Auler } // namespace bolt
847a34c753fSRafael Auler } // namespace llvm
848