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