xref: /llvm-project/bolt/lib/Core/DebugData.cpp (revision 9a3e66e314e698ffb08dba151bc098b6b8867c61)
12f09f445SMaksim Panchenko //===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
92f09f445SMaksim Panchenko // This file implements functions and classes for handling debug info.
102f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #include "bolt/Core/DebugData.h"
14f8c7fb49SAmir Ayupov #include "bolt/Core/BinaryContext.h"
1587fb0ea2SRui Zhong #include "bolt/Core/DIEBuilder.h"
16a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
1787fb0ea2SRui Zhong #include "llvm/BinaryFormat/Dwarf.h"
1887fb0ea2SRui Zhong #include "llvm/CodeGen/DIE.h"
19290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
20290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
21014cd37fSAlexander Yermolovich #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
2257f7c7d9Sserge-sans-paille #include "llvm/MC/MCAssembler.h"
23f8c7fb49SAmir Ayupov #include "llvm/MC/MCContext.h"
24a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h"
25a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
26a34c753fSRafael Auler #include "llvm/Support/EndianStream.h"
27a34c753fSRafael Auler #include "llvm/Support/LEB128.h"
289f3f9d19SAlexander Yermolovich #include "llvm/Support/SHA1.h"
29a34c753fSRafael Auler #include <algorithm>
30a34c753fSRafael Auler #include <cassert>
31a34c753fSRafael Auler #include <cstdint>
32124ca880SAlexander Yermolovich #include <functional>
33dcfa2ab5SAlexander Yermolovich #include <memory>
3499fad7ebSAlexander Yermolovich #include <optional>
351c2f4bbeSAlexander Yermolovich #include <unordered_map>
36ba1ac98cSAlexander Yermolovich #include <vector>
37a34c753fSRafael Auler 
38a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info"
39a34c753fSRafael Auler 
40a34c753fSRafael Auler namespace opts {
41a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity;
421c2f4bbeSAlexander Yermolovich } // namespace opts
43a34c753fSRafael Auler 
44a34c753fSRafael Auler namespace llvm {
45f8c7fb49SAmir Ayupov class MCSymbol;
46f8c7fb49SAmir Ayupov 
47a34c753fSRafael Auler namespace bolt {
48a34c753fSRafael Auler 
4987fb0ea2SRui Zhong static void replaceLocValbyForm(DIEBuilder &DIEBldr, DIE &Die, DIEValue DIEVal,
5087fb0ea2SRui Zhong                                 dwarf::Form Format, uint64_t NewVal) {
5187fb0ea2SRui Zhong   if (Format == dwarf::DW_FORM_loclistx)
5287fb0ea2SRui Zhong     DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
5387fb0ea2SRui Zhong                          DIELocList(NewVal));
5487fb0ea2SRui Zhong   else
5587fb0ea2SRui Zhong     DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
5687fb0ea2SRui Zhong                          DIEInteger(NewVal));
5787fb0ea2SRui Zhong }
5887fb0ea2SRui Zhong 
59370e4761SAmir Ayupov std::optional<AttrInfo>
60bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE,
61bd1ebe9dSAlexander Yermolovich                   const DWARFAbbreviationDeclaration *AbbrevDecl,
62bd1ebe9dSAlexander Yermolovich                   uint32_t Index) {
63bd1ebe9dSAlexander Yermolovich   const DWARFUnit &U = *DIE.getDwarfUnit();
64bd1ebe9dSAlexander Yermolovich   uint64_t Offset =
65bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
6689fab98eSFangrui Song   std::optional<DWARFFormValue> Value =
67bd1ebe9dSAlexander Yermolovich       AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
68bd1ebe9dSAlexander Yermolovich   if (!Value)
69e324a80fSKazu Hirata     return std::nullopt;
70bd1ebe9dSAlexander Yermolovich   // AttributeSpec
71bd1ebe9dSAlexander Yermolovich   const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
72bd1ebe9dSAlexander Yermolovich       AbbrevDecl->attributes().begin() + Index;
73bd1ebe9dSAlexander Yermolovich   uint32_t ValSize = 0;
7489fab98eSFangrui Song   std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
75bd1ebe9dSAlexander Yermolovich   if (ValSizeOpt) {
76bd1ebe9dSAlexander Yermolovich     ValSize = static_cast<uint32_t>(*ValSizeOpt);
77bd1ebe9dSAlexander Yermolovich   } else {
78bd1ebe9dSAlexander Yermolovich     DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
79bd1ebe9dSAlexander Yermolovich     uint64_t NewOffset = Offset;
80bd1ebe9dSAlexander Yermolovich     DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
81bd1ebe9dSAlexander Yermolovich                               U.getFormParams());
82bd1ebe9dSAlexander Yermolovich     // This includes entire size of the entry, which might not be just the
83bd1ebe9dSAlexander Yermolovich     // encoding part. For example for DW_AT_loc it will include expression
84bd1ebe9dSAlexander Yermolovich     // location.
85bd1ebe9dSAlexander Yermolovich     ValSize = NewOffset - Offset;
86bd1ebe9dSAlexander Yermolovich   }
871c6dc43dSAlexander Yermolovich   return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};
881c6dc43dSAlexander Yermolovich }
89bd1ebe9dSAlexander Yermolovich 
90370e4761SAmir Ayupov std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
911c6dc43dSAlexander Yermolovich                                           dwarf::Attribute Attr) {
921c6dc43dSAlexander Yermolovich   if (!DIE.isValid())
93e324a80fSKazu Hirata     return std::nullopt;
941c6dc43dSAlexander Yermolovich   const DWARFAbbreviationDeclaration *AbbrevDecl =
951c6dc43dSAlexander Yermolovich       DIE.getAbbreviationDeclarationPtr();
961c6dc43dSAlexander Yermolovich   if (!AbbrevDecl)
97e324a80fSKazu Hirata     return std::nullopt;
9889fab98eSFangrui Song   std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);
991c6dc43dSAlexander Yermolovich   if (!Index)
100e324a80fSKazu Hirata     return std::nullopt;
1011c6dc43dSAlexander Yermolovich   return findAttributeInfo(DIE, AbbrevDecl, *Index);
102bd1ebe9dSAlexander Yermolovich }
103bd1ebe9dSAlexander Yermolovich 
104a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
105a34c753fSRafael Auler 
1061c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED
1071c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) {
1081c2f4bbeSAlexander Yermolovich   for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
1091c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr(S[I]);
1101c2f4bbeSAlexander Yermolovich     errs() << Twine::utohexstr((int8_t)S[I]);
1111c2f4bbeSAlexander Yermolovich   }
1121c2f4bbeSAlexander Yermolovich   errs() << "\n";
1131c2f4bbeSAlexander Yermolovich }
1141c2f4bbeSAlexander Yermolovich 
115a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size).
116a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of
117a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address).
118a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes.
119a34c753fSRafael Auler // Returns the number of written bytes.
120be2f67c4SAmir Ayupov static uint64_t
121be2f67c4SAmir Ayupov writeAddressRanges(raw_svector_ostream &Stream,
122a34c753fSRafael Auler                    const DebugAddressRangesVector &AddressRanges,
123a34c753fSRafael Auler                    const bool WriteRelativeRanges = false) {
124a34c753fSRafael Auler   for (const DebugAddressRange &Range : AddressRanges) {
1254a0ccfa8SKazu Hirata     support::endian::write(Stream, Range.LowPC, llvm::endianness::little);
126a34c753fSRafael Auler     support::endian::write(
127a34c753fSRafael Auler         Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
1284a0ccfa8SKazu Hirata         llvm::endianness::little);
129a34c753fSRafael Auler   }
130a34c753fSRafael Auler   // Finish with 0 entries.
1314a0ccfa8SKazu Hirata   support::endian::write(Stream, 0ULL, llvm::endianness::little);
1324a0ccfa8SKazu Hirata   support::endian::write(Stream, 0ULL, llvm::endianness::little);
133a34c753fSRafael Auler   return AddressRanges.size() * 16 + 16;
134a34c753fSRafael Auler }
135a34c753fSRafael Auler 
136a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() {
137a34c753fSRafael Auler   RangesBuffer = std::make_unique<DebugBufferVector>();
138a34c753fSRafael Auler   RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
139a34c753fSRafael Auler 
140014cd37fSAlexander Yermolovich   Kind = RangesWriterKind::DebugRangesWriter;
141a34c753fSRafael Auler }
142a34c753fSRafael Auler 
1437e10ad99SSayhaan Siddiqui void DebugRangesSectionWriter::initSection() {
1447e10ad99SSayhaan Siddiqui   // Adds an empty range to the buffer.
1457e10ad99SSayhaan Siddiqui   writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
1467e10ad99SSayhaan Siddiqui }
1477e10ad99SSayhaan Siddiqui 
148a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges(
149a34c753fSRafael Auler     DebugAddressRangesVector &&Ranges,
150a34c753fSRafael Auler     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
151a34c753fSRafael Auler   if (Ranges.empty())
152a34c753fSRafael Auler     return getEmptyRangesOffset();
153a34c753fSRafael Auler 
154a34c753fSRafael Auler   const auto RI = CachedRanges.find(Ranges);
155a34c753fSRafael Auler   if (RI != CachedRanges.end())
156a34c753fSRafael Auler     return RI->second;
157a34c753fSRafael Auler 
158a34c753fSRafael Auler   const uint64_t EntryOffset = addRanges(Ranges);
159a34c753fSRafael Auler   CachedRanges.emplace(std::move(Ranges), EntryOffset);
160a34c753fSRafael Auler 
161a34c753fSRafael Auler   return EntryOffset;
162a34c753fSRafael Auler }
163a34c753fSRafael Auler 
164e22ff52cSAlexander Yermolovich uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
165a34c753fSRafael Auler   if (Ranges.empty())
166a34c753fSRafael Auler     return getEmptyRangesOffset();
167a34c753fSRafael Auler 
168a34c753fSRafael Auler   // Reading the SectionOffset and updating it should be atomic to guarantee
169a34c753fSRafael Auler   // unique and correct offsets in patches.
170a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
171f137be30SSayhaan Siddiqui   const uint32_t EntryOffset = RangesBuffer->size();
172f137be30SSayhaan Siddiqui   writeAddressRanges(*RangesStream.get(), Ranges);
173a34c753fSRafael Auler 
174a34c753fSRafael Auler   return EntryOffset;
175a34c753fSRafael Auler }
176a34c753fSRafael Auler 
177a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() {
178a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(WriterMutex);
179f137be30SSayhaan Siddiqui   return RangesBuffer->size();
180a34c753fSRafael Auler }
181a34c753fSRafael Auler 
1825828b04bSSayhaan Siddiqui void DebugRangesSectionWriter::appendToRangeBuffer(
1835828b04bSSayhaan Siddiqui     const DebugBufferVector &CUBuffer) {
1845828b04bSSayhaan Siddiqui   *RangesStream << CUBuffer;
1855828b04bSSayhaan Siddiqui }
1865828b04bSSayhaan Siddiqui 
187014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges(
188014cd37fSAlexander Yermolovich     DebugAddressRangesVector &&Ranges,
189014cd37fSAlexander Yermolovich     std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
190014cd37fSAlexander Yermolovich   return addRanges(Ranges);
191014cd37fSAlexander Yermolovich }
192014cd37fSAlexander Yermolovich 
193014cd37fSAlexander Yermolovich struct LocListsRangelistsHeader {
1941a2f8336Sspaette   UnitLengthType UnitLength; // Size of loclist entries section, not including
195014cd37fSAlexander Yermolovich                              // size of header.
196014cd37fSAlexander Yermolovich   VersionType Version;
197014cd37fSAlexander Yermolovich   AddressSizeType AddressSize;
198014cd37fSAlexander Yermolovich   SegmentSelectorType SegmentSelector;
199014cd37fSAlexander Yermolovich   OffsetEntryCountType OffsetEntryCount;
200014cd37fSAlexander Yermolovich };
201014cd37fSAlexander Yermolovich 
202014cd37fSAlexander Yermolovich static std::unique_ptr<DebugBufferVector>
203014cd37fSAlexander Yermolovich getDWARF5Header(const LocListsRangelistsHeader &Header) {
204014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> HeaderBuffer =
205014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
206014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> HeaderStream =
207014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*HeaderBuffer);
208014cd37fSAlexander Yermolovich 
209014cd37fSAlexander Yermolovich   // 7.29 length of the set of entries for this compilation unit, not including
210014cd37fSAlexander Yermolovich   // the length field itself
211014cd37fSAlexander Yermolovich   const uint32_t HeaderSize =
212014cd37fSAlexander Yermolovich       getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);
213014cd37fSAlexander Yermolovich 
214014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,
2154a0ccfa8SKazu Hirata                          llvm::endianness::little);
2164a0ccfa8SKazu Hirata   support::endian::write(*HeaderStream, Header.Version,
2174a0ccfa8SKazu Hirata                          llvm::endianness::little);
2184a0ccfa8SKazu Hirata   support::endian::write(*HeaderStream, Header.AddressSize,
2194a0ccfa8SKazu Hirata                          llvm::endianness::little);
220014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.SegmentSelector,
2214a0ccfa8SKazu Hirata                          llvm::endianness::little);
222014cd37fSAlexander Yermolovich   support::endian::write(*HeaderStream, Header.OffsetEntryCount,
2234a0ccfa8SKazu Hirata                          llvm::endianness::little);
224014cd37fSAlexander Yermolovich   return HeaderBuffer;
225014cd37fSAlexander Yermolovich }
226014cd37fSAlexander Yermolovich 
227124ca880SAlexander Yermolovich struct OffsetEntry {
228124ca880SAlexander Yermolovich   uint32_t Index;
229124ca880SAlexander Yermolovich   uint32_t StartOffset;
230124ca880SAlexander Yermolovich   uint32_t EndOffset;
231124ca880SAlexander Yermolovich };
232124ca880SAlexander Yermolovich template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>
233124ca880SAlexander Yermolovich static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
234e22ff52cSAlexander Yermolovich                          DebugAddrWriter &AddrWriter, DWARFUnit &CU,
235124ca880SAlexander Yermolovich                          uint32_t &Index, const ListEntry BaseAddressx,
236c9e8e91aSAlexander Yermolovich                          const ListEntry OffsetPair,
237124ca880SAlexander Yermolovich                          const std::function<void(uint32_t)> &Func) {
238124ca880SAlexander Yermolovich   if (Entries.size() < 2)
239e22ff52cSAlexander Yermolovich     return false;
240124ca880SAlexander Yermolovich   uint64_t Base = Entries[Index].LowPC;
241124ca880SAlexander Yermolovich   std::vector<OffsetEntry> Offsets;
242e22ff52cSAlexander Yermolovich   uint8_t TempBuffer[64];
243124ca880SAlexander Yermolovich   while (Index < Entries.size()) {
244124ca880SAlexander Yermolovich     const DebugAddressEntry &Entry = Entries[Index];
245124ca880SAlexander Yermolovich     if (Entry.LowPC == 0)
246e22ff52cSAlexander Yermolovich       break;
247c9e8e91aSAlexander Yermolovich     // In case rnglists or loclists are not sorted.
248c9e8e91aSAlexander Yermolovich     if (Base > Entry.LowPC)
249c9e8e91aSAlexander Yermolovich       break;
250124ca880SAlexander Yermolovich     uint32_t StartOffset = Entry.LowPC - Base;
251124ca880SAlexander Yermolovich     uint32_t EndOffset = Entry.HighPC - Base;
252e22ff52cSAlexander Yermolovich     if (encodeULEB128(EndOffset, TempBuffer) > 2)
253e22ff52cSAlexander Yermolovich       break;
254124ca880SAlexander Yermolovich     Offsets.push_back({Index, StartOffset, EndOffset});
255e22ff52cSAlexander Yermolovich     ++Index;
256e22ff52cSAlexander Yermolovich   }
257e22ff52cSAlexander Yermolovich 
258124ca880SAlexander Yermolovich   if (Offsets.size() < 2) {
259124ca880SAlexander Yermolovich     Index -= Offsets.size();
260e22ff52cSAlexander Yermolovich     return false;
261e22ff52cSAlexander Yermolovich   }
262e22ff52cSAlexander Yermolovich 
263124ca880SAlexander Yermolovich   support::endian::write(OS, static_cast<uint8_t>(BaseAddressx),
2644a0ccfa8SKazu Hirata                          llvm::endianness::little);
265e22ff52cSAlexander Yermolovich   uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU);
266e22ff52cSAlexander Yermolovich   encodeULEB128(BaseIndex, OS);
267124ca880SAlexander Yermolovich   for (auto &OffsetEntry : Offsets) {
268124ca880SAlexander Yermolovich     support::endian::write(OS, static_cast<uint8_t>(OffsetPair),
2694a0ccfa8SKazu Hirata                            llvm::endianness::little);
270124ca880SAlexander Yermolovich     encodeULEB128(OffsetEntry.StartOffset, OS);
271124ca880SAlexander Yermolovich     encodeULEB128(OffsetEntry.EndOffset, OS);
272124ca880SAlexander Yermolovich     Func(OffsetEntry.Index);
273e22ff52cSAlexander Yermolovich   }
274e22ff52cSAlexander Yermolovich   return true;
275e22ff52cSAlexander Yermolovich }
276e22ff52cSAlexander Yermolovich 
277e22ff52cSAlexander Yermolovich uint64_t
278e22ff52cSAlexander Yermolovich DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
279014cd37fSAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
280014cd37fSAlexander Yermolovich 
281014cd37fSAlexander Yermolovich   RangeEntries.push_back(CurrentOffset);
282e22ff52cSAlexander Yermolovich   std::sort(
283e22ff52cSAlexander Yermolovich       Ranges.begin(), Ranges.end(),
284e22ff52cSAlexander Yermolovich       [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {
285e22ff52cSAlexander Yermolovich         return R1.LowPC < R2.LowPC;
286e22ff52cSAlexander Yermolovich       });
287e22ff52cSAlexander Yermolovich   for (unsigned I = 0; I < Ranges.size();) {
288124ca880SAlexander Yermolovich     if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,
289c9e8e91aSAlexander Yermolovich                      DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU,
290c9e8e91aSAlexander Yermolovich                                         I, dwarf::DW_RLE_base_addressx,
291c9e8e91aSAlexander Yermolovich                                         dwarf::DW_RLE_offset_pair,
292c9e8e91aSAlexander Yermolovich                                         [](uint32_t Index) -> void {}))
293e22ff52cSAlexander Yermolovich       continue;
294124ca880SAlexander Yermolovich 
295e22ff52cSAlexander Yermolovich     const DebugAddressRange &Range = Ranges[I];
296014cd37fSAlexander Yermolovich     support::endian::write(*CUBodyStream,
297014cd37fSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_RLE_startx_length),
2984a0ccfa8SKazu Hirata                            llvm::endianness::little);
299ba1ac98cSAlexander Yermolovich     uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU);
300014cd37fSAlexander Yermolovich     encodeULEB128(Index, *CUBodyStream);
301014cd37fSAlexander Yermolovich     encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
302e22ff52cSAlexander Yermolovich     ++I;
303014cd37fSAlexander Yermolovich   }
304c9e8e91aSAlexander Yermolovich 
305014cd37fSAlexander Yermolovich   support::endian::write(*CUBodyStream,
306014cd37fSAlexander Yermolovich                          static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
3074a0ccfa8SKazu Hirata                          llvm::endianness::little);
308014cd37fSAlexander Yermolovich   CurrentOffset = CUBodyBuffer->size();
309014cd37fSAlexander Yermolovich   return RangeEntries.size() - 1;
310014cd37fSAlexander Yermolovich }
311014cd37fSAlexander Yermolovich 
312014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::finalizeSection() {
313014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> CUArrayBuffer =
314014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
315014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> CUArrayStream =
316014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*CUArrayBuffer);
317014cd37fSAlexander Yermolovich   constexpr uint32_t SizeOfArrayEntry = 4;
318014cd37fSAlexander Yermolovich   const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;
319014cd37fSAlexander Yermolovich   for (uint32_t Offset : RangeEntries)
320014cd37fSAlexander Yermolovich     support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,
3214a0ccfa8SKazu Hirata                            llvm::endianness::little);
322014cd37fSAlexander Yermolovich 
323014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
324014cd37fSAlexander Yermolovich       {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()),
325014cd37fSAlexander Yermolovich        5, 8, 0, static_cast<uint32_t>(RangeEntries.size())});
326014cd37fSAlexander Yermolovich   *RangesStream << *Header;
327014cd37fSAlexander Yermolovich   *RangesStream << *CUArrayBuffer;
328014cd37fSAlexander Yermolovich   *RangesStream << *CUBodyBuffer;
329014cd37fSAlexander Yermolovich }
330014cd37fSAlexander Yermolovich 
331ba1ac98cSAlexander Yermolovich void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {
332014cd37fSAlexander Yermolovich   CUBodyBuffer = std::make_unique<DebugBufferVector>();
333014cd37fSAlexander Yermolovich   CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);
334014cd37fSAlexander Yermolovich   RangeEntries.clear();
335014cd37fSAlexander Yermolovich   CurrentOffset = 0;
336ba1ac98cSAlexander Yermolovich   CU = &Unit;
337014cd37fSAlexander Yermolovich }
338014cd37fSAlexander Yermolovich 
339a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
340a34c753fSRafael Auler                                             DebugAddressRangesVector &&Ranges) {
341a34c753fSRafael Auler   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
342a34c753fSRafael Auler   CUAddressRanges.emplace(CUOffset, std::move(Ranges));
343a34c753fSRafael Auler }
344a34c753fSRafael Auler 
345a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection(
346612f0f45SAlexander Yermolovich     raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
347a34c753fSRafael Auler   // For reference on the format of the .debug_aranges section, see the DWARF4
348a34c753fSRafael Auler   // specification, section 6.1.4 Lookup by Address
349a34c753fSRafael Auler   // http://www.dwarfstd.org/doc/DWARF4.pdf
350a34c753fSRafael Auler   for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
351a34c753fSRafael Auler     const uint64_t Offset = CUOffsetAddressRangesPair.first;
352a34c753fSRafael Auler     const DebugAddressRangesVector &AddressRanges =
353a34c753fSRafael Auler         CUOffsetAddressRangesPair.second;
354a34c753fSRafael Auler 
355a34c753fSRafael Auler     // Emit header.
356a34c753fSRafael Auler 
357a34c753fSRafael Auler     // Size of this set: 8 (size of the header) + 4 (padding after header)
358a34c753fSRafael Auler     // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
359a34c753fSRafael Auler     // pair of uint64_t's for the terminating, zero-length range.
360a34c753fSRafael Auler     // Does not include size field itself.
361a34c753fSRafael Auler     uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);
362a34c753fSRafael Auler 
363a34c753fSRafael Auler     // Header field #1: set size.
3644a0ccfa8SKazu Hirata     support::endian::write(RangesStream, Size, llvm::endianness::little);
365a34c753fSRafael Auler 
366a34c753fSRafael Auler     // Header field #2: version number, 2 as per the specification.
367a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint16_t>(2),
3684a0ccfa8SKazu Hirata                            llvm::endianness::little);
369a34c753fSRafael Auler 
3701c2f4bbeSAlexander Yermolovich     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
371a34c753fSRafael Auler     // Header field #3: debug info offset of the correspondent compile unit.
372612f0f45SAlexander Yermolovich     support::endian::write(
373612f0f45SAlexander Yermolovich         RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
3744a0ccfa8SKazu Hirata         llvm::endianness::little);
375a34c753fSRafael Auler 
376a34c753fSRafael Auler     // Header field #4: address size.
377a34c753fSRafael Auler     // 8 since we only write ELF64 binaries for now.
378a34c753fSRafael Auler     RangesStream << char(8);
379a34c753fSRafael Auler 
380a34c753fSRafael Auler     // Header field #5: segment size of target architecture.
381a34c753fSRafael Auler     RangesStream << char(0);
382a34c753fSRafael Auler 
383a34c753fSRafael Auler     // Padding before address table - 4 bytes in the 64-bit-pointer case.
384a34c753fSRafael Auler     support::endian::write(RangesStream, static_cast<uint32_t>(0),
3854a0ccfa8SKazu Hirata                            llvm::endianness::little);
386a34c753fSRafael Auler 
387a34c753fSRafael Auler     writeAddressRanges(RangesStream, AddressRanges, true);
388a34c753fSRafael Auler   }
389a34c753fSRafael Auler }
390a34c753fSRafael Auler 
391e140a8a3SSayhaan Siddiqui DebugAddrWriter::DebugAddrWriter(BinaryContext *BC,
392e140a8a3SSayhaan Siddiqui                                  const uint8_t AddressByteSize)
393e140a8a3SSayhaan Siddiqui     : BC(BC), AddressByteSize(AddressByteSize) {
394dcfa2ab5SAlexander Yermolovich   Buffer = std::make_unique<AddressSectionBuffer>();
395dcfa2ab5SAlexander Yermolovich   AddressStream = std::make_unique<raw_svector_ostream>(*Buffer);
396dcfa2ab5SAlexander Yermolovich }
397a34c753fSRafael Auler 
398a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() {
399a34c753fSRafael Auler   std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
400a34c753fSRafael Auler                                           indexToAdddessEnd());
401a34c753fSRafael Auler   // Sorting address in increasing order of indices.
402c4302e4fSAmir Ayupov   llvm::sort(SortedMap, llvm::less_first());
403a34c753fSRafael Auler   for (auto &Pair : SortedMap)
404a34c753fSRafael Auler     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
405a34c753fSRafael Auler }
406ba1ac98cSAlexander Yermolovich uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {
407e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
408a34c753fSRafael Auler   auto Entry = Map.find(Address);
409a34c753fSRafael Auler   if (Entry == Map.end()) {
410a34c753fSRafael Auler     auto Index = Map.getNextIndex();
411a34c753fSRafael Auler     Entry = Map.insert(Address, Index).first;
412a34c753fSRafael Auler   }
413a34c753fSRafael Auler   return Entry->second;
414a34c753fSRafael Auler }
415a34c753fSRafael Auler 
416dcfa2ab5SAlexander Yermolovich static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter,
417dcfa2ab5SAlexander Yermolovich                               DWARFUnit &CU, const uint64_t Offset) {
418dcfa2ab5SAlexander Yermolovich   DIE *Die = DIEBlder.getUnitDIEbyUnit(CU);
419dcfa2ab5SAlexander Yermolovich   DIEValue GnuAddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_GNU_addr_base);
420dcfa2ab5SAlexander Yermolovich   DIEValue AddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_addr_base);
421dcfa2ab5SAlexander Yermolovich   dwarf::Form BaseAttrForm;
422dcfa2ab5SAlexander Yermolovich   dwarf::Attribute BaseAttr;
423dcfa2ab5SAlexander Yermolovich   // For cases where Skeleton CU does not have DW_AT_GNU_addr_base
424dcfa2ab5SAlexander Yermolovich   if (!GnuAddrBaseAttrInfo && CU.getVersion() < 5)
425dcfa2ab5SAlexander Yermolovich     return;
426dcfa2ab5SAlexander Yermolovich 
427dcfa2ab5SAlexander Yermolovich   if (GnuAddrBaseAttrInfo) {
428dcfa2ab5SAlexander Yermolovich     BaseAttrForm = GnuAddrBaseAttrInfo.getForm();
429dcfa2ab5SAlexander Yermolovich     BaseAttr = GnuAddrBaseAttrInfo.getAttribute();
430dcfa2ab5SAlexander Yermolovich   }
431dcfa2ab5SAlexander Yermolovich 
432dcfa2ab5SAlexander Yermolovich   if (AddrBaseAttrInfo) {
433dcfa2ab5SAlexander Yermolovich     BaseAttrForm = AddrBaseAttrInfo.getForm();
434dcfa2ab5SAlexander Yermolovich     BaseAttr = AddrBaseAttrInfo.getAttribute();
435dcfa2ab5SAlexander Yermolovich   }
436dcfa2ab5SAlexander Yermolovich 
437dcfa2ab5SAlexander Yermolovich   if (GnuAddrBaseAttrInfo || AddrBaseAttrInfo) {
438dcfa2ab5SAlexander Yermolovich     DIEBlder.replaceValue(Die, BaseAttr, BaseAttrForm, DIEInteger(Offset));
439dcfa2ab5SAlexander Yermolovich   } else if (CU.getVersion() >= 5) {
440dcfa2ab5SAlexander Yermolovich     // A case where we were not using .debug_addr section, but after update
441dcfa2ab5SAlexander Yermolovich     // now using it.
442dcfa2ab5SAlexander Yermolovich     DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,
443dcfa2ab5SAlexander Yermolovich                       DIEInteger(Offset));
444dcfa2ab5SAlexander Yermolovich   }
445dcfa2ab5SAlexander Yermolovich }
446dcfa2ab5SAlexander Yermolovich 
447e140a8a3SSayhaan Siddiqui void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
448e140a8a3SSayhaan Siddiqui                                      const uint64_t Offset) {
449e140a8a3SSayhaan Siddiqui   updateAddressBase(DIEBlder, *this, CU, Offset);
450e140a8a3SSayhaan Siddiqui }
451e140a8a3SSayhaan Siddiqui 
452e140a8a3SSayhaan Siddiqui std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) {
453e140a8a3SSayhaan Siddiqui   if (Map.begin() == Map.end())
454e140a8a3SSayhaan Siddiqui     return std::nullopt;
455e140a8a3SSayhaan Siddiqui   std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),
456e140a8a3SSayhaan Siddiqui                                           Map.indexToAdddessEnd());
457a34c753fSRafael Auler   // Sorting address in increasing order of indices.
458c4302e4fSAmir Ayupov   llvm::sort(SortedMap, llvm::less_first());
459a34c753fSRafael Auler 
460a34c753fSRafael Auler   uint32_t Counter = 0;
461a34c753fSRafael Auler   auto WriteAddress = [&](uint64_t Address) -> void {
462a34c753fSRafael Auler     ++Counter;
463e140a8a3SSayhaan Siddiqui     switch (AddressByteSize) {
464a34c753fSRafael Auler     default:
465a34c753fSRafael Auler       assert(false && "Address Size is invalid.");
466a34c753fSRafael Auler       break;
467a34c753fSRafael Auler     case 4:
468dcfa2ab5SAlexander Yermolovich       support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
4694a0ccfa8SKazu Hirata                              llvm::endianness::little);
470a34c753fSRafael Auler       break;
471a34c753fSRafael Auler     case 8:
4724a0ccfa8SKazu Hirata       support::endian::write(*AddressStream, Address, llvm::endianness::little);
473a34c753fSRafael Auler       break;
474a34c753fSRafael Auler     }
475a34c753fSRafael Auler   };
476a34c753fSRafael Auler 
477a34c753fSRafael Auler   for (const IndexAddressPair &Val : SortedMap) {
478a34c753fSRafael Auler     while (Val.first > Counter)
479a34c753fSRafael Auler       WriteAddress(0);
480a34c753fSRafael Auler     WriteAddress(Val.second);
481a34c753fSRafael Auler   }
482e140a8a3SSayhaan Siddiqui   return std::nullopt;
483a34c753fSRafael Auler }
484a34c753fSRafael Auler 
485e140a8a3SSayhaan Siddiqui void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
486e140a8a3SSayhaan Siddiqui                                            const uint64_t Offset) {
487e140a8a3SSayhaan Siddiqui   /// Header for DWARF5 has size 8, so we add it to the offset.
488e140a8a3SSayhaan Siddiqui   updateAddressBase(DIEBlder, *this, CU, Offset + HeaderSize);
489e140a8a3SSayhaan Siddiqui }
490e140a8a3SSayhaan Siddiqui 
491e140a8a3SSayhaan Siddiqui DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets;
492e140a8a3SSayhaan Siddiqui 
493e140a8a3SSayhaan Siddiqui std::optional<uint64_t>
494e140a8a3SSayhaan Siddiqui DebugAddrWriterDwarf5::finalize(const size_t BufferSize) {
495014cd37fSAlexander Yermolovich   // Need to layout all sections within .debug_addr
496014cd37fSAlexander Yermolovich   // Within each section sort Address by index.
4974a0ccfa8SKazu Hirata   const endianness Endian = BC->DwCtx->isLittleEndian()
4984a0ccfa8SKazu Hirata                                 ? llvm::endianness::little
4994a0ccfa8SKazu Hirata                                 : llvm::endianness::big;
500014cd37fSAlexander Yermolovich   const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();
501a7517e12SKazu Hirata   DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec,
5024a0ccfa8SKazu Hirata                               Endian == llvm::endianness::little, 0);
503014cd37fSAlexander Yermolovich   DWARFDebugAddrTable AddrTable;
504014cd37fSAlexander Yermolovich   DIDumpOptions DumpOpts;
505014cd37fSAlexander Yermolovich   // A case where CU has entry in .debug_addr, but we don't modify addresses
506014cd37fSAlexander Yermolovich   // for it.
507e140a8a3SSayhaan Siddiqui   if (Map.begin() == Map.end()) {
508e140a8a3SSayhaan Siddiqui     if (!AddrOffsetSectionBase)
509e140a8a3SSayhaan Siddiqui       return std::nullopt;
510014cd37fSAlexander Yermolovich     // Address base offset is to the first entry.
511014cd37fSAlexander Yermolovich     // The size of header is 8 bytes.
512e140a8a3SSayhaan Siddiqui     uint64_t Offset = *AddrOffsetSectionBase - HeaderSize;
513f230099cSAlexander Yermolovich     auto Iter = UnmodifiedAddressOffsets.find(Offset);
514e140a8a3SSayhaan Siddiqui     if (Iter != UnmodifiedAddressOffsets.end())
515e140a8a3SSayhaan Siddiqui       return Iter->second;
516e140a8a3SSayhaan Siddiqui     UnmodifiedAddressOffsets[Offset] = BufferSize;
517e140a8a3SSayhaan Siddiqui     if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize,
518014cd37fSAlexander Yermolovich                                       DumpOpts.WarningHandler)) {
519014cd37fSAlexander Yermolovich       DumpOpts.RecoverableErrorHandler(std::move(Err));
520e140a8a3SSayhaan Siddiqui       return std::nullopt;
521014cd37fSAlexander Yermolovich     }
522014cd37fSAlexander Yermolovich     uint32_t Index = 0;
523014cd37fSAlexander Yermolovich     for (uint64_t Addr : AddrTable.getAddressEntries())
524e140a8a3SSayhaan Siddiqui       Map.insert(Addr, Index++);
525014cd37fSAlexander Yermolovich   }
526a34c753fSRafael Auler 
527e140a8a3SSayhaan Siddiqui   std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),
528e140a8a3SSayhaan Siddiqui                                           Map.indexToAdddessEnd());
529014cd37fSAlexander Yermolovich   // Sorting address in increasing order of indices.
530c4302e4fSAmir Ayupov   llvm::sort(SortedMap, llvm::less_first());
531014cd37fSAlexander Yermolovich   // Writing out Header
532e140a8a3SSayhaan Siddiqui   const uint32_t Length = SortedMap.size() * AddressByteSize + 4;
533dcfa2ab5SAlexander Yermolovich   support::endian::write(*AddressStream, Length, Endian);
534dcfa2ab5SAlexander Yermolovich   support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);
535e140a8a3SSayhaan Siddiqui   support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize),
536014cd37fSAlexander Yermolovich                          Endian);
537dcfa2ab5SAlexander Yermolovich   support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);
538014cd37fSAlexander Yermolovich 
539014cd37fSAlexander Yermolovich   uint32_t Counter = 0;
540014cd37fSAlexander Yermolovich   auto writeAddress = [&](uint64_t Address) -> void {
541014cd37fSAlexander Yermolovich     ++Counter;
542e140a8a3SSayhaan Siddiqui     switch (AddressByteSize) {
543014cd37fSAlexander Yermolovich     default:
544014cd37fSAlexander Yermolovich       llvm_unreachable("Address Size is invalid.");
545014cd37fSAlexander Yermolovich       break;
546014cd37fSAlexander Yermolovich     case 4:
547dcfa2ab5SAlexander Yermolovich       support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
548014cd37fSAlexander Yermolovich                              Endian);
549014cd37fSAlexander Yermolovich       break;
550014cd37fSAlexander Yermolovich     case 8:
551dcfa2ab5SAlexander Yermolovich       support::endian::write(*AddressStream, Address, Endian);
552014cd37fSAlexander Yermolovich       break;
553014cd37fSAlexander Yermolovich     }
554014cd37fSAlexander Yermolovich   };
555014cd37fSAlexander Yermolovich 
556014cd37fSAlexander Yermolovich   for (const IndexAddressPair &Val : SortedMap) {
557014cd37fSAlexander Yermolovich     while (Val.first > Counter)
558014cd37fSAlexander Yermolovich       writeAddress(0);
559014cd37fSAlexander Yermolovich     writeAddress(Val.second);
560014cd37fSAlexander Yermolovich   }
561e140a8a3SSayhaan Siddiqui   return std::nullopt;
562014cd37fSAlexander Yermolovich }
563014cd37fSAlexander Yermolovich 
5641c6dc43dSAlexander Yermolovich void DebugLocWriter::init() {
565a34c753fSRafael Auler   LocBuffer = std::make_unique<DebugBufferVector>();
566a34c753fSRafael Auler   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
5671c6dc43dSAlexander Yermolovich   // Writing out empty location list to which all references to empty location
5681c6dc43dSAlexander Yermolovich   // lists will point.
5691c6dc43dSAlexander Yermolovich   if (!LocSectionOffset && DwarfVersion < 5) {
5701c6dc43dSAlexander Yermolovich     const char Zeroes[16] = {0};
5711c6dc43dSAlexander Yermolovich     *LocStream << StringRef(Zeroes, 16);
5721c6dc43dSAlexander Yermolovich     LocSectionOffset += 16;
5731c6dc43dSAlexander Yermolovich   }
574a34c753fSRafael Auler }
575a34c753fSRafael Auler 
5761c6dc43dSAlexander Yermolovich uint32_t DebugLocWriter::LocSectionOffset = 0;
57787fb0ea2SRui Zhong void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
57887fb0ea2SRui Zhong                              DebugLocationsVector &LocList) {
579a34c753fSRafael Auler   if (LocList.empty()) {
58087fb0ea2SRui Zhong     replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
58187fb0ea2SRui Zhong                         DebugLocWriter::EmptyListOffset);
582a34c753fSRafael Auler     return;
583a34c753fSRafael Auler   }
584a34c753fSRafael Auler   // Since there is a separate DebugLocWriter for each thread,
585a34c753fSRafael Auler   // we don't need a lock to read the SectionOffset and update it.
5861c6dc43dSAlexander Yermolovich   const uint32_t EntryOffset = LocSectionOffset;
587a34c753fSRafael Auler 
588a34c753fSRafael Auler   for (const DebugLocationEntry &Entry : LocList) {
589a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
5904a0ccfa8SKazu Hirata                            llvm::endianness::little);
591a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
5924a0ccfa8SKazu Hirata                            llvm::endianness::little);
593a34c753fSRafael Auler     support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
5944a0ccfa8SKazu Hirata                            llvm::endianness::little);
595a34c753fSRafael Auler     *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
596a34c753fSRafael Auler                             Entry.Expr.size());
5971c6dc43dSAlexander Yermolovich     LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();
598a34c753fSRafael Auler   }
599a34c753fSRafael Auler   LocStream->write_zeros(16);
6001c6dc43dSAlexander Yermolovich   LocSectionOffset += 16;
60187fb0ea2SRui Zhong   LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen
60287fb0ea2SRui Zhong                                                                 // use
60387fb0ea2SRui Zhong   replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
604a34c753fSRafael Auler }
605a34c753fSRafael Auler 
606a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
607a34c753fSRafael Auler   return std::move(LocBuffer);
608a34c753fSRafael Auler }
609a34c753fSRafael Auler 
610a34c753fSRafael Auler // DWARF 4: 2.6.2
61187fb0ea2SRui Zhong void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}
612a34c753fSRafael Auler 
613014cd37fSAlexander Yermolovich static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
6144a0ccfa8SKazu Hirata   support::endian::write(Stream, static_cast<uint32_t>(4),
6154a0ccfa8SKazu Hirata                          llvm::endianness::little);
616014cd37fSAlexander Yermolovich   support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),
6174a0ccfa8SKazu Hirata                          llvm::endianness::little);
618014cd37fSAlexander Yermolovich 
619014cd37fSAlexander Yermolovich   const char Zeroes[16] = {0};
620014cd37fSAlexander Yermolovich   Stream << StringRef(Zeroes, 16);
621014cd37fSAlexander Yermolovich   encodeULEB128(0, Stream);
6224a0ccfa8SKazu Hirata   support::endian::write(Stream,
6234a0ccfa8SKazu Hirata                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
6244a0ccfa8SKazu Hirata                          llvm::endianness::little);
625014cd37fSAlexander Yermolovich }
626014cd37fSAlexander Yermolovich 
62787fb0ea2SRui Zhong static void writeLegacyLocList(DIEValue &AttrInfo,
62887fb0ea2SRui Zhong                                DebugLocationsVector &LocList,
62987fb0ea2SRui Zhong                                DIEBuilder &DIEBldr, DIE &Die,
6301c6dc43dSAlexander Yermolovich                                DebugAddrWriter &AddrWriter,
631d5235e53SAlexander Yermolovich                                DebugBufferVector &LocBuffer, DWARFUnit &CU,
6321c6dc43dSAlexander Yermolovich                                raw_svector_ostream &LocStream) {
6331c6dc43dSAlexander Yermolovich   if (LocList.empty()) {
63487fb0ea2SRui Zhong     replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
63587fb0ea2SRui Zhong                         DebugLocWriter::EmptyListOffset);
6361c6dc43dSAlexander Yermolovich     return;
6371c6dc43dSAlexander Yermolovich   }
6381c6dc43dSAlexander Yermolovich 
6391c6dc43dSAlexander Yermolovich   const uint32_t EntryOffset = LocBuffer.size();
6401c6dc43dSAlexander Yermolovich   for (const DebugLocationEntry &Entry : LocList) {
6411c6dc43dSAlexander Yermolovich     support::endian::write(LocStream,
6421c6dc43dSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
6434a0ccfa8SKazu Hirata                            llvm::endianness::little);
6441c6dc43dSAlexander Yermolovich     const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
6451c6dc43dSAlexander Yermolovich     encodeULEB128(Index, LocStream);
6461c6dc43dSAlexander Yermolovich 
6471c6dc43dSAlexander Yermolovich     support::endian::write(LocStream,
6481c6dc43dSAlexander Yermolovich                            static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
6494a0ccfa8SKazu Hirata                            llvm::endianness::little);
6501c6dc43dSAlexander Yermolovich     support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()),
6514a0ccfa8SKazu Hirata                            llvm::endianness::little);
6521c6dc43dSAlexander Yermolovich     LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
6531c6dc43dSAlexander Yermolovich                            Entry.Expr.size());
6541c6dc43dSAlexander Yermolovich   }
6551c6dc43dSAlexander Yermolovich   support::endian::write(LocStream,
6561c6dc43dSAlexander Yermolovich                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
6574a0ccfa8SKazu Hirata                          llvm::endianness::little);
65887fb0ea2SRui Zhong   replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
6591c6dc43dSAlexander Yermolovich }
6601c6dc43dSAlexander Yermolovich 
66187fb0ea2SRui Zhong static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,
66287fb0ea2SRui Zhong                                DebugLocationsVector &LocList, DIE &Die,
66387fb0ea2SRui Zhong                                DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter,
66487fb0ea2SRui Zhong                                DebugBufferVector &LocBodyBuffer,
66587fb0ea2SRui Zhong                                std::vector<uint32_t> &RelativeLocListOffsets,
66687fb0ea2SRui Zhong                                DWARFUnit &CU,
6671c6dc43dSAlexander Yermolovich                                raw_svector_ostream &LocBodyStream) {
66887fb0ea2SRui Zhong 
66987fb0ea2SRui Zhong   replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
67087fb0ea2SRui Zhong                       NumberOfEntries);
67187fb0ea2SRui Zhong 
6721c6dc43dSAlexander Yermolovich   RelativeLocListOffsets.push_back(LocBodyBuffer.size());
6731c6dc43dSAlexander Yermolovich   ++NumberOfEntries;
6741c6dc43dSAlexander Yermolovich   if (LocList.empty()) {
6751c6dc43dSAlexander Yermolovich     writeEmptyListDwarf5(LocBodyStream);
6761c6dc43dSAlexander Yermolovich     return;
6771c6dc43dSAlexander Yermolovich   }
6781c6dc43dSAlexander Yermolovich 
6791c6dc43dSAlexander Yermolovich   std::vector<uint64_t> OffsetsArray;
680124ca880SAlexander Yermolovich   auto writeExpression = [&](uint32_t Index) -> void {
681124ca880SAlexander Yermolovich     const DebugLocationEntry &Entry = LocList[Index];
682124ca880SAlexander Yermolovich     encodeULEB128(Entry.Expr.size(), LocBodyStream);
683124ca880SAlexander Yermolovich     LocBodyStream << StringRef(
684124ca880SAlexander Yermolovich         reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
685124ca880SAlexander Yermolovich   };
686124ca880SAlexander Yermolovich   for (unsigned I = 0; I < LocList.size();) {
687124ca880SAlexander Yermolovich     if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,
688c9e8e91aSAlexander Yermolovich                      DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU,
689c9e8e91aSAlexander Yermolovich                                          I, dwarf::DW_LLE_base_addressx,
690c9e8e91aSAlexander Yermolovich                                          dwarf::DW_LLE_offset_pair,
691c9e8e91aSAlexander Yermolovich                                          writeExpression))
692124ca880SAlexander Yermolovich       continue;
693124ca880SAlexander Yermolovich 
694124ca880SAlexander Yermolovich     const DebugLocationEntry &Entry = LocList[I];
6951c6dc43dSAlexander Yermolovich     support::endian::write(LocBodyStream,
6961c6dc43dSAlexander Yermolovich                            static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
6974a0ccfa8SKazu Hirata                            llvm::endianness::little);
6981c6dc43dSAlexander Yermolovich     const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
6991c6dc43dSAlexander Yermolovich     encodeULEB128(Index, LocBodyStream);
7001c6dc43dSAlexander Yermolovich     encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);
701124ca880SAlexander Yermolovich     writeExpression(I);
702124ca880SAlexander Yermolovich     ++I;
7031c6dc43dSAlexander Yermolovich   }
704124ca880SAlexander Yermolovich 
7051c6dc43dSAlexander Yermolovich   support::endian::write(LocBodyStream,
7061c6dc43dSAlexander Yermolovich                          static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
7074a0ccfa8SKazu Hirata                          llvm::endianness::little);
7081c6dc43dSAlexander Yermolovich }
7091c6dc43dSAlexander Yermolovich 
71087fb0ea2SRui Zhong void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,
71187fb0ea2SRui Zhong                                  DIEValue &AttrInfo,
71287fb0ea2SRui Zhong                                  DebugLocationsVector &LocList) {
7131c6dc43dSAlexander Yermolovich   if (DwarfVersion < 5)
714e140a8a3SSayhaan Siddiqui     writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer,
71587fb0ea2SRui Zhong                        CU, *LocStream);
7161c6dc43dSAlexander Yermolovich   else
71787fb0ea2SRui Zhong     writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
718e140a8a3SSayhaan Siddiqui                        AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
71987fb0ea2SRui Zhong                        *LocBodyStream);
7201c6dc43dSAlexander Yermolovich }
7211c6dc43dSAlexander Yermolovich 
7221c6dc43dSAlexander Yermolovich uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;
72387fb0ea2SRui Zhong void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) {
72493ce0965SAlexander Yermolovich   if (LocBodyBuffer->empty()) {
72587fb0ea2SRui Zhong     DIEValue LocListBaseAttrInfo =
72687fb0ea2SRui Zhong         Die.findAttribute(dwarf::DW_AT_loclists_base);
72793ce0965SAlexander Yermolovich     // Pointing to first one, because it doesn't matter. There are no uses of it
72893ce0965SAlexander Yermolovich     // in this CU.
72987fb0ea2SRui Zhong     if (!isSplitDwarf() && LocListBaseAttrInfo.getType())
73087fb0ea2SRui Zhong       DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
73187fb0ea2SRui Zhong                            LocListBaseAttrInfo.getForm(),
73287fb0ea2SRui Zhong                            DIEInteger(getDWARF5RngListLocListHeaderSize()));
7331c6dc43dSAlexander Yermolovich     return;
73493ce0965SAlexander Yermolovich   }
735014cd37fSAlexander Yermolovich 
736014cd37fSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> LocArrayBuffer =
737014cd37fSAlexander Yermolovich       std::make_unique<DebugBufferVector>();
738014cd37fSAlexander Yermolovich   std::unique_ptr<raw_svector_ostream> LocArrayStream =
739014cd37fSAlexander Yermolovich       std::make_unique<raw_svector_ostream>(*LocArrayBuffer);
740014cd37fSAlexander Yermolovich 
7411c6dc43dSAlexander Yermolovich   const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t);
742014cd37fSAlexander Yermolovich   // Write out IndexArray
7431c6dc43dSAlexander Yermolovich   for (uint32_t RelativeOffset : RelativeLocListOffsets)
744014cd37fSAlexander Yermolovich     support::endian::write(
745014cd37fSAlexander Yermolovich         *LocArrayStream,
7461c6dc43dSAlexander Yermolovich         static_cast<uint32_t>(SizeOfArraySection + RelativeOffset),
7474a0ccfa8SKazu Hirata         llvm::endianness::little);
7481c6dc43dSAlexander Yermolovich 
7491c6dc43dSAlexander Yermolovich   std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
7501c6dc43dSAlexander Yermolovich       {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()),
7511c6dc43dSAlexander Yermolovich        5, 8, 0, NumberOfEntries});
752014cd37fSAlexander Yermolovich   *LocStream << *Header;
753014cd37fSAlexander Yermolovich   *LocStream << *LocArrayBuffer;
754014cd37fSAlexander Yermolovich   *LocStream << *LocBodyBuffer;
7551c6dc43dSAlexander Yermolovich 
7561c6dc43dSAlexander Yermolovich   if (!isSplitDwarf()) {
75787fb0ea2SRui Zhong     DIEValue LocListBaseAttrInfo =
75887fb0ea2SRui Zhong         Die.findAttribute(dwarf::DW_AT_loclists_base);
75987fb0ea2SRui Zhong     if (LocListBaseAttrInfo.getType()) {
76087fb0ea2SRui Zhong       DIEBldr.replaceValue(
76187fb0ea2SRui Zhong           &Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(),
76287fb0ea2SRui Zhong           DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize()));
76387fb0ea2SRui Zhong     } else {
76487fb0ea2SRui Zhong       DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,
76587fb0ea2SRui Zhong                        dwarf::DW_FORM_sec_offset,
76687fb0ea2SRui Zhong                        DIEInteger(LoclistBaseOffset + Header->size()));
767014cd37fSAlexander Yermolovich     }
7681c6dc43dSAlexander Yermolovich     LoclistBaseOffset += LocBuffer->size();
7691c6dc43dSAlexander Yermolovich   }
7701c6dc43dSAlexander Yermolovich   clearList(RelativeLocListOffsets);
7711c6dc43dSAlexander Yermolovich   clearList(*LocArrayBuffer);
7721c6dc43dSAlexander Yermolovich   clearList(*LocBodyBuffer);
773014cd37fSAlexander Yermolovich }
774014cd37fSAlexander Yermolovich 
77587fb0ea2SRui Zhong void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {
7761c6dc43dSAlexander Yermolovich   if (DwarfVersion >= 5)
77787fb0ea2SRui Zhong     finalizeDWARF5(DIEBldr, Die);
778014cd37fSAlexander Yermolovich }
779014cd37fSAlexander Yermolovich 
780bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
781bd1ebe9dSAlexander Yermolovich   std::string LE64(ByteSize, 0);
782bd1ebe9dSAlexander Yermolovich   for (size_t I = 0; I < ByteSize; ++I) {
783bd1ebe9dSAlexander Yermolovich     LE64[I] = NewValue & 0xff;
784bd1ebe9dSAlexander Yermolovich     NewValue >>= 8;
785bd1ebe9dSAlexander Yermolovich   }
786bd1ebe9dSAlexander Yermolovich   return LE64;
787bd1ebe9dSAlexander Yermolovich }
788bd1ebe9dSAlexander Yermolovich 
7891c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
7901c2f4bbeSAlexander Yermolovich                                          std::string &&NewValue,
7911c2f4bbeSAlexander Yermolovich                                          uint32_t OldValueSize) {
7921c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(NewValue));
7931c2f4bbeSAlexander Yermolovich }
7941c2f4bbeSAlexander Yermolovich 
7951c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
7961c2f4bbeSAlexander Yermolovich   auto Str = std::string(1, Value);
7971c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Str));
7981c2f4bbeSAlexander Yermolovich }
7991c2f4bbeSAlexander Yermolovich 
8001c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
8011c2f4bbeSAlexander Yermolovich                                      size_t ByteSize) {
8021c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
8031c2f4bbeSAlexander Yermolovich }
8041c2f4bbeSAlexander Yermolovich 
8051c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
8061c2f4bbeSAlexander Yermolovich                                         uint32_t OldValueSize) {
807a34c753fSRafael Auler   std::string Buff;
808a34c753fSRafael Auler   raw_string_ostream OS(Buff);
8091c2f4bbeSAlexander Yermolovich   encodeULEB128(Value, OS, OldValueSize);
810a34c753fSRafael Auler 
8111c2f4bbeSAlexander Yermolovich   Patches.emplace_back(Offset, std::move(Buff));
812a34c753fSRafael Auler }
813a34c753fSRafael Auler 
8141c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
815a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 8);
816a34c753fSRafael Auler }
817a34c753fSRafael Auler 
8181c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
8191c2f4bbeSAlexander Yermolovich                                        uint32_t OldValueSize) {
820a34c753fSRafael Auler   addLEPatch(Offset, NewValue, 4);
821a34c753fSRafael Auler }
822a34c753fSRafael Auler 
8231c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
8241c2f4bbeSAlexander Yermolovich   std::string BinaryContentsStr = std::string(BinaryContents);
825a34c753fSRafael Auler   for (const auto &Patch : Patches) {
8261c2f4bbeSAlexander Yermolovich     uint32_t Offset = Patch.first;
827a34c753fSRafael Auler     const std::string &ByteSequence = Patch.second;
828a34c753fSRafael Auler     assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
829a34c753fSRafael Auler            "Applied patch runs over binary size.");
830a34c753fSRafael Auler     for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
8311c2f4bbeSAlexander Yermolovich       BinaryContentsStr[Offset + I] = ByteSequence[I];
832a34c753fSRafael Auler     }
833a34c753fSRafael Auler   }
8341c2f4bbeSAlexander Yermolovich   return BinaryContentsStr;
8351c2f4bbeSAlexander Yermolovich }
8361c2f4bbeSAlexander Yermolovich 
837bf2b035eSAlexander Yermolovich void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) {
838bf2b035eSAlexander Yermolovich   if (Unit.getVersion() < 5)
839bf2b035eSAlexander Yermolovich     return;
840bf2b035eSAlexander Yermolovich   const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
841bf2b035eSAlexander Yermolovich   const std::optional<StrOffsetsContributionDescriptor> &Contr =
842bf2b035eSAlexander Yermolovich       Unit.getStringOffsetsTableContribution();
843ba1ac98cSAlexander Yermolovich   if (!Contr)
844ba1ac98cSAlexander Yermolovich     return;
845ba1ac98cSAlexander Yermolovich   const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
846ba1ac98cSAlexander Yermolovich   assert(DwarfOffsetByteSize == 4 &&
847ba1ac98cSAlexander Yermolovich          "Dwarf String Offsets Byte Size is not supported.");
848bf2b035eSAlexander Yermolovich   StrOffsets.reserve(Contr->Size);
849ba1ac98cSAlexander Yermolovich   for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)
850bf2b035eSAlexander Yermolovich     StrOffsets.push_back(support::endian::read32le(
851bf2b035eSAlexander Yermolovich         StrOffsetsSection.Data.data() + Contr->Base + Offset));
852ba1ac98cSAlexander Yermolovich }
853ba1ac98cSAlexander Yermolovich 
854*9a3e66e3SSayhaan Siddiqui void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address,
855*9a3e66e3SSayhaan Siddiqui                                              const DWARFUnit &Unit) {
856*9a3e66e3SSayhaan Siddiqui   assert(DebugStrOffsetFinalized.count(Unit.getOffset()) == 0 &&
857*9a3e66e3SSayhaan Siddiqui          "Cannot update address map since debug_str_offsets was already "
858*9a3e66e3SSayhaan Siddiqui          "finalized for this CU.");
859ba1ac98cSAlexander Yermolovich   IndexToAddressMap[Index] = Address;
860f7a21317SAlexander Yermolovich   StrOffsetSectionWasModified = true;
861ba1ac98cSAlexander Yermolovich }
862ba1ac98cSAlexander Yermolovich 
863dcfa2ab5SAlexander Yermolovich void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
864dcfa2ab5SAlexander Yermolovich                                             DIEBuilder &DIEBldr) {
865f7a21317SAlexander Yermolovich   std::optional<AttrInfo> AttrVal =
866f7a21317SAlexander Yermolovich       findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
86799fad7ebSAlexander Yermolovich   if (!AttrVal && !Unit.isDWOUnit())
868bf2b035eSAlexander Yermolovich     return;
86999fad7ebSAlexander Yermolovich   std::optional<uint64_t> Val = std::nullopt;
87099fad7ebSAlexander Yermolovich   if (AttrVal) {
87199fad7ebSAlexander Yermolovich     Val = AttrVal->V.getAsSectionOffset();
87299fad7ebSAlexander Yermolovich   } else {
87399fad7ebSAlexander Yermolovich     if (!Unit.isDWOUnit())
87499fad7ebSAlexander Yermolovich       BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
87599fad7ebSAlexander Yermolovich                    "DW_AT_str_offsets_base Value not present\n";
87699fad7ebSAlexander Yermolovich     Val = 0;
87799fad7ebSAlexander Yermolovich   }
878dcfa2ab5SAlexander Yermolovich   DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
879dcfa2ab5SAlexander Yermolovich   DIEValue StrListBaseAttrInfo =
880dcfa2ab5SAlexander Yermolovich       Die.findAttribute(dwarf::DW_AT_str_offsets_base);
881dcfa2ab5SAlexander Yermolovich   auto RetVal = ProcessedBaseOffsets.find(*Val);
882dcfa2ab5SAlexander Yermolovich   // Handling re-use of str-offsets section.
883dcfa2ab5SAlexander Yermolovich   if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {
884bf2b035eSAlexander Yermolovich     initialize(Unit);
885bf2b035eSAlexander Yermolovich     // Update String Offsets that were modified.
886bf2b035eSAlexander Yermolovich     for (const auto &Entry : IndexToAddressMap)
887bf2b035eSAlexander Yermolovich       StrOffsets[Entry.first] = Entry.second;
888ba1ac98cSAlexander Yermolovich     // Writing out the header for each section.
889bf2b035eSAlexander Yermolovich     support::endian::write(*StrOffsetsStream,
890bf2b035eSAlexander Yermolovich                            static_cast<uint32_t>(StrOffsets.size() * 4 + 4),
8914a0ccfa8SKazu Hirata                            llvm::endianness::little);
892ba1ac98cSAlexander Yermolovich     support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),
8934a0ccfa8SKazu Hirata                            llvm::endianness::little);
894ba1ac98cSAlexander Yermolovich     support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),
8954a0ccfa8SKazu Hirata                            llvm::endianness::little);
896dcfa2ab5SAlexander Yermolovich 
897dcfa2ab5SAlexander Yermolovich     uint64_t BaseOffset = StrOffsetsBuffer->size();
898dcfa2ab5SAlexander Yermolovich     ProcessedBaseOffsets[*Val] = BaseOffset;
899dcfa2ab5SAlexander Yermolovich     if (StrListBaseAttrInfo.getType())
900dcfa2ab5SAlexander Yermolovich       DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
901dcfa2ab5SAlexander Yermolovich                            StrListBaseAttrInfo.getForm(),
902dcfa2ab5SAlexander Yermolovich                            DIEInteger(BaseOffset));
903bf2b035eSAlexander Yermolovich     for (const uint32_t Offset : StrOffsets)
904bf2b035eSAlexander Yermolovich       support::endian::write(*StrOffsetsStream, Offset,
9054a0ccfa8SKazu Hirata                              llvm::endianness::little);
906dcfa2ab5SAlexander Yermolovich   } else {
907dcfa2ab5SAlexander Yermolovich     DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
908dcfa2ab5SAlexander Yermolovich                          StrListBaseAttrInfo.getForm(),
909dcfa2ab5SAlexander Yermolovich                          DIEInteger(RetVal->second));
910f7a21317SAlexander Yermolovich   }
911f7a21317SAlexander Yermolovich 
912f7a21317SAlexander Yermolovich   StrOffsetSectionWasModified = false;
913*9a3e66e3SSayhaan Siddiqui   assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second &&
914*9a3e66e3SSayhaan Siddiqui          "debug_str_offsets was already finalized for this CU.");
915004c1972SAlexander Yermolovich   clear();
916ba1ac98cSAlexander Yermolovich }
917ba1ac98cSAlexander Yermolovich 
918a34c753fSRafael Auler void DebugStrWriter::create() {
919a34c753fSRafael Auler   StrBuffer = std::make_unique<DebugStrBufferVector>();
920a34c753fSRafael Auler   StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
921a34c753fSRafael Auler }
922a34c753fSRafael Auler 
923a34c753fSRafael Auler void DebugStrWriter::initialize() {
92499fad7ebSAlexander Yermolovich   StringRef StrSection;
92599fad7ebSAlexander Yermolovich   if (IsDWO)
92699fad7ebSAlexander Yermolovich     StrSection = DwCtx.getDWARFObj().getStrDWOSection();
92799fad7ebSAlexander Yermolovich   else
92899fad7ebSAlexander Yermolovich     StrSection = DwCtx.getDWARFObj().getStrSection();
929a34c753fSRafael Auler   (*StrStream) << StrSection;
930a34c753fSRafael Auler }
931a34c753fSRafael Auler 
932a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) {
933e579f5c6SAlexander Yermolovich   std::lock_guard<std::mutex> Lock(WriterMutex);
934a34c753fSRafael Auler   if (StrBuffer->empty())
935a34c753fSRafael Auler     initialize();
936a34c753fSRafael Auler   auto Offset = StrBuffer->size();
937a34c753fSRafael Auler   (*StrStream) << Str;
938a34c753fSRafael Auler   StrStream->write_zeros(1);
939a34c753fSRafael Auler   return Offset;
940a34c753fSRafael Auler }
941a34c753fSRafael Auler 
942a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
943a34c753fSRafael Auler                                     MCDwarfLineTableParams Params,
944a34c753fSRafael Auler                                     int64_t LineDelta, uint64_t Address,
945a34c753fSRafael Auler                                     int PointerSize) {
946a34c753fSRafael Auler   // emit the sequence to set the address
947a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
948a34c753fSRafael Auler   OS.emitULEB128IntValue(PointerSize + 1);
949a34c753fSRafael Auler   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
950a34c753fSRafael Auler   OS.emitIntValue(Address, PointerSize);
951a34c753fSRafael Auler 
952a34c753fSRafael Auler   // emit the sequence for the LineDelta (from 1) and a zero address delta.
953a34c753fSRafael Auler   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
954a34c753fSRafael Auler }
955a34c753fSRafael Auler 
956a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable(
957a34c753fSRafael Auler     MCStreamer *MCOS, MCDwarfLineTableParams Params,
958a34c753fSRafael Auler     const DWARFDebugLine::LineTable *Table,
959a34c753fSRafael Auler     const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
960a34c753fSRafael Auler   if (InputSequences.empty())
961a34c753fSRafael Auler     return;
962a34c753fSRafael Auler 
963a34c753fSRafael Auler   constexpr uint64_t InvalidAddress = UINT64_MAX;
964a34c753fSRafael Auler   unsigned FileNum = 1;
965a34c753fSRafael Auler   unsigned LastLine = 1;
966a34c753fSRafael Auler   unsigned Column = 0;
967a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
968a34c753fSRafael Auler   unsigned Isa = 0;
969a34c753fSRafael Auler   unsigned Discriminator = 0;
970a34c753fSRafael Auler   uint64_t LastAddress = InvalidAddress;
971a34c753fSRafael Auler   uint64_t PrevEndOfSequence = InvalidAddress;
972a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
973a34c753fSRafael Auler 
974a34c753fSRafael Auler   auto emitEndOfSequence = [&](uint64_t Address) {
975a34c753fSRafael Auler     MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
976a34c753fSRafael Auler     FileNum = 1;
977a34c753fSRafael Auler     LastLine = 1;
978a34c753fSRafael Auler     Column = 0;
979a34c753fSRafael Auler     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
980a34c753fSRafael Auler     Isa = 0;
981a34c753fSRafael Auler     Discriminator = 0;
982a34c753fSRafael Auler     LastAddress = InvalidAddress;
983a34c753fSRafael Auler   };
984a34c753fSRafael Auler 
985a34c753fSRafael Auler   for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
986a34c753fSRafael Auler     const uint64_t SequenceStart =
987a34c753fSRafael Auler         Table->Rows[Sequence.FirstIndex].Address.Address;
988a34c753fSRafael Auler 
989a34c753fSRafael Auler     // Check if we need to mark the end of the sequence.
990a34c753fSRafael Auler     if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
991a34c753fSRafael Auler         PrevEndOfSequence != SequenceStart) {
992a34c753fSRafael Auler       emitEndOfSequence(PrevEndOfSequence);
993a34c753fSRafael Auler     }
994a34c753fSRafael Auler 
995a34c753fSRafael Auler     for (uint32_t RowIndex = Sequence.FirstIndex;
996a34c753fSRafael Auler          RowIndex <= Sequence.LastIndex; ++RowIndex) {
997a34c753fSRafael Auler       const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
998a34c753fSRafael Auler       int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
999a34c753fSRafael Auler       const uint64_t Address = Row.Address.Address;
1000a34c753fSRafael Auler 
1001a34c753fSRafael Auler       if (FileNum != Row.File) {
1002a34c753fSRafael Auler         FileNum = Row.File;
1003a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_file);
1004a34c753fSRafael Auler         MCOS->emitULEB128IntValue(FileNum);
1005a34c753fSRafael Auler       }
1006a34c753fSRafael Auler       if (Column != Row.Column) {
1007a34c753fSRafael Auler         Column = Row.Column;
1008a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_column);
1009a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Column);
1010a34c753fSRafael Auler       }
1011a34c753fSRafael Auler       if (Discriminator != Row.Discriminator &&
1012a34c753fSRafael Auler           MCOS->getContext().getDwarfVersion() >= 4) {
1013a34c753fSRafael Auler         Discriminator = Row.Discriminator;
1014a34c753fSRafael Auler         unsigned Size = getULEB128Size(Discriminator);
1015a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1016a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Size + 1);
1017a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1018a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Discriminator);
1019a34c753fSRafael Auler       }
1020a34c753fSRafael Auler       if (Isa != Row.Isa) {
1021a34c753fSRafael Auler         Isa = Row.Isa;
1022a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1023a34c753fSRafael Auler         MCOS->emitULEB128IntValue(Isa);
1024a34c753fSRafael Auler       }
1025a34c753fSRafael Auler       if (Row.IsStmt != Flags) {
1026a34c753fSRafael Auler         Flags = Row.IsStmt;
1027a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1028a34c753fSRafael Auler       }
1029a34c753fSRafael Auler       if (Row.BasicBlock)
1030a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1031a34c753fSRafael Auler       if (Row.PrologueEnd)
1032a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1033a34c753fSRafael Auler       if (Row.EpilogueBegin)
1034a34c753fSRafael Auler         MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1035a34c753fSRafael Auler 
1036a34c753fSRafael Auler       // The end of the sequence is not normal in the middle of the input
1037a34c753fSRafael Auler       // sequence, but could happen, e.g. for assembly code.
1038a34c753fSRafael Auler       if (Row.EndSequence) {
1039a34c753fSRafael Auler         emitEndOfSequence(Address);
1040a34c753fSRafael Auler       } else {
1041a34c753fSRafael Auler         if (LastAddress == InvalidAddress)
1042a34c753fSRafael Auler           emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
1043a34c753fSRafael Auler                                   AsmInfo->getCodePointerSize());
1044a34c753fSRafael Auler         else
1045a34c753fSRafael Auler           MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);
1046a34c753fSRafael Auler 
1047a34c753fSRafael Auler         LastAddress = Address;
1048a34c753fSRafael Auler         LastLine = Row.Line;
1049a34c753fSRafael Auler       }
1050a34c753fSRafael Auler 
1051a34c753fSRafael Auler       Discriminator = 0;
1052a34c753fSRafael Auler     }
1053a34c753fSRafael Auler     PrevEndOfSequence = Sequence.EndAddress;
1054a34c753fSRafael Auler   }
1055a34c753fSRafael Auler 
1056a34c753fSRafael Auler   // Finish with the end of the sequence.
1057a34c753fSRafael Auler   if (LastAddress != InvalidAddress)
1058a34c753fSRafael Auler     emitEndOfSequence(PrevEndOfSequence);
1059a34c753fSRafael Auler }
1060a34c753fSRafael Auler 
1061a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles
1062a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with
1063a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag.
1064a34c753fSRafael Auler static inline void emitDwarfLineTable(
1065a34c753fSRafael Auler     MCStreamer *MCOS, MCSection *Section,
1066a34c753fSRafael Auler     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
1067a34c753fSRafael Auler   unsigned FileNum = 1;
1068a34c753fSRafael Auler   unsigned LastLine = 1;
1069a34c753fSRafael Auler   unsigned Column = 0;
1070a34c753fSRafael Auler   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1071a34c753fSRafael Auler   unsigned Isa = 0;
1072a34c753fSRafael Auler   unsigned Discriminator = 0;
1073a34c753fSRafael Auler   MCSymbol *LastLabel = nullptr;
1074a34c753fSRafael Auler   const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();
1075a34c753fSRafael Auler 
1076a34c753fSRafael Auler   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
1077a34c753fSRafael Auler   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
1078a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
1079a34c753fSRafael Auler       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
1080a34c753fSRafael Auler                                      AsmInfo->getCodePointerSize());
1081a34c753fSRafael Auler       FileNum = 1;
1082a34c753fSRafael Auler       LastLine = 1;
1083a34c753fSRafael Auler       Column = 0;
1084a34c753fSRafael Auler       Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
1085a34c753fSRafael Auler       Isa = 0;
1086a34c753fSRafael Auler       Discriminator = 0;
1087a34c753fSRafael Auler       LastLabel = nullptr;
1088a34c753fSRafael Auler       continue;
1089a34c753fSRafael Auler     }
1090a34c753fSRafael Auler 
1091a34c753fSRafael Auler     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
1092a34c753fSRafael Auler 
1093a34c753fSRafael Auler     if (FileNum != LineEntry.getFileNum()) {
1094a34c753fSRafael Auler       FileNum = LineEntry.getFileNum();
1095a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_file);
1096a34c753fSRafael Auler       MCOS->emitULEB128IntValue(FileNum);
1097a34c753fSRafael Auler     }
1098a34c753fSRafael Auler     if (Column != LineEntry.getColumn()) {
1099a34c753fSRafael Auler       Column = LineEntry.getColumn();
1100a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_column);
1101a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Column);
1102a34c753fSRafael Auler     }
1103a34c753fSRafael Auler     if (Discriminator != LineEntry.getDiscriminator() &&
1104014cd37fSAlexander Yermolovich         MCOS->getContext().getDwarfVersion() >= 2) {
1105a34c753fSRafael Auler       Discriminator = LineEntry.getDiscriminator();
1106a34c753fSRafael Auler       unsigned Size = getULEB128Size(Discriminator);
1107a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
1108a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Size + 1);
1109a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
1110a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Discriminator);
1111a34c753fSRafael Auler     }
1112a34c753fSRafael Auler     if (Isa != LineEntry.getIsa()) {
1113a34c753fSRafael Auler       Isa = LineEntry.getIsa();
1114a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
1115a34c753fSRafael Auler       MCOS->emitULEB128IntValue(Isa);
1116a34c753fSRafael Auler     }
1117a34c753fSRafael Auler     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
1118a34c753fSRafael Auler       Flags = LineEntry.getFlags();
1119a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
1120a34c753fSRafael Auler     }
1121a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
1122a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
1123a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
1124a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
1125a34c753fSRafael Auler     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
1126a34c753fSRafael Auler       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
1127a34c753fSRafael Auler 
1128a34c753fSRafael Auler     MCSymbol *Label = LineEntry.getLabel();
1129a34c753fSRafael Auler 
1130a34c753fSRafael Auler     // At this point we want to emit/create the sequence to encode the delta
1131a34c753fSRafael Auler     // in line numbers and the increment of the address from the previous
1132a34c753fSRafael Auler     // Label and the current Label.
1133a34c753fSRafael Auler     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
1134a34c753fSRafael Auler                                    AsmInfo->getCodePointerSize());
1135a34c753fSRafael Auler     Discriminator = 0;
1136a34c753fSRafael Auler     LastLine = LineEntry.getLine();
1137a34c753fSRafael Auler     LastLabel = Label;
1138a34c753fSRafael Auler   }
1139a34c753fSRafael Auler 
1140a34c753fSRafael Auler   assert(LastLabel == nullptr && "end of sequence expected");
1141a34c753fSRafael Auler }
1142a34c753fSRafael Auler 
1143a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
1144f4c16c44SFangrui Song                             std::optional<MCDwarfLineStr> &LineStr,
1145b73c87bcSMaksim Panchenko                             BinaryContext &BC) const {
1146a34c753fSRafael Auler   if (!RawData.empty()) {
1147a34c753fSRafael Auler     assert(MCLineSections.getMCLineEntries().empty() &&
1148a34c753fSRafael Auler            InputSequences.empty() &&
1149a34c753fSRafael Auler            "cannot combine raw data with new line entries");
1150a34c753fSRafael Auler     MCOS->emitLabel(getLabel());
1151a34c753fSRafael Auler     MCOS->emitBytes(RawData);
1152a34c753fSRafael Auler     return;
1153a34c753fSRafael Auler   }
1154a34c753fSRafael Auler 
1155a34c753fSRafael Auler   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
1156a34c753fSRafael Auler 
1157a34c753fSRafael Auler   // Put out the line tables.
1158a34c753fSRafael Auler   for (const auto &LineSec : MCLineSections.getMCLineEntries())
1159a34c753fSRafael Auler     emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
1160a34c753fSRafael Auler 
1161a34c753fSRafael Auler   // Emit line tables for the original code.
1162a34c753fSRafael Auler   emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);
1163a34c753fSRafael Auler 
1164a34c753fSRafael Auler   // This is the end of the section, so set the value of the symbol at the end
1165a34c753fSRafael Auler   // of this section (that was used in a previous expression).
1166a34c753fSRafael Auler   MCOS->emitLabel(LineEndSym);
1167a34c753fSRafael Auler }
1168a34c753fSRafael Auler 
1169014cd37fSAlexander Yermolovich // Helper function to parse .debug_line_str, and populate one we are using.
1170014cd37fSAlexander Yermolovich // For functions that we do not modify we output them as raw data.
1171014cd37fSAlexander Yermolovich // Re-constructing .debug_line_str so that offsets are correct for those
117266e943b1SAlexander Yermolovich // debug line tables.
1173014cd37fSAlexander Yermolovich // Bonus is that when we output a final binary we can re-use .debug_line_str
1174014cd37fSAlexander Yermolovich // section. So we don't have to do the SHF_ALLOC trick we did with
1175014cd37fSAlexander Yermolovich // .debug_line.
1176014cd37fSAlexander Yermolovich static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
1177014cd37fSAlexander Yermolovich                                          MCDwarfLineStr &LineStr,
117866e943b1SAlexander Yermolovich                                          BinaryContext &BC) {
1179014cd37fSAlexander Yermolovich   DataExtractor StrData(LineStrSection.getContents(),
1180014cd37fSAlexander Yermolovich                         BC.DwCtx->isLittleEndian(), 0);
1181014cd37fSAlexander Yermolovich   uint64_t Offset = 0;
1182014cd37fSAlexander Yermolovich   while (StrData.isValidOffset(Offset)) {
118366e943b1SAlexander Yermolovich     const uint64_t StrOffset = Offset;
1184014cd37fSAlexander Yermolovich     Error Err = Error::success();
1185014cd37fSAlexander Yermolovich     const char *CStr = StrData.getCStr(&Offset, &Err);
1186014cd37fSAlexander Yermolovich     if (Err) {
118752cf0711SAmir Ayupov       BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
1188014cd37fSAlexander Yermolovich       continue;
1189014cd37fSAlexander Yermolovich     }
119066e943b1SAlexander Yermolovich     const size_t NewOffset = LineStr.addString(CStr);
119166e943b1SAlexander Yermolovich     assert(StrOffset == NewOffset &&
119266e943b1SAlexander Yermolovich            "New offset in .debug_line_str doesn't match original offset");
1193544b4c6dSKazu Hirata     (void)StrOffset;
1194544b4c6dSKazu Hirata     (void)NewOffset;
1195014cd37fSAlexander Yermolovich   }
1196014cd37fSAlexander Yermolovich }
1197014cd37fSAlexander Yermolovich 
1198a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
1199a34c753fSRafael Auler   MCAssembler &Assembler =
1200a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
1201a34c753fSRafael Auler 
1202a34c753fSRafael Auler   MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();
1203a34c753fSRafael Auler 
1204a34c753fSRafael Auler   auto &LineTables = BC.getDwarfLineTables();
1205a34c753fSRafael Auler 
1206a34c753fSRafael Auler   // Bail out early so we don't switch to the debug_line section needlessly and
1207a34c753fSRafael Auler   // in doing so create an unnecessary (if empty) section.
1208a34c753fSRafael Auler   if (LineTables.empty())
1209a34c753fSRafael Auler     return;
1210a34c753fSRafael Auler   // In a v5 non-split line table, put the strings in a separate section.
1211f4c16c44SFangrui Song   std::optional<MCDwarfLineStr> LineStr;
1212014cd37fSAlexander Yermolovich   ErrorOr<BinarySection &> LineStrSection =
1213014cd37fSAlexander Yermolovich       BC.getUniqueSectionByName(".debug_line_str");
121466e943b1SAlexander Yermolovich 
1215014cd37fSAlexander Yermolovich   // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
121666e943b1SAlexander Yermolovich   // .debug_line, so need to check if section exists.
1217014cd37fSAlexander Yermolovich   if (LineStrSection) {
121853113515SFangrui Song     LineStr.emplace(*BC.Ctx);
121966e943b1SAlexander Yermolovich     parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC);
1220014cd37fSAlexander Yermolovich   }
1221a34c753fSRafael Auler 
1222a34c753fSRafael Auler   // Switch to the section where the table will be emitted into.
1223adf4142fSFangrui Song   Streamer.switchSection(BC.MOFI->getDwarfLineSection());
1224a34c753fSRafael Auler 
1225014cd37fSAlexander Yermolovich   const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
1226a34c753fSRafael Auler   // Handle the rest of the Compile Units.
1227a34c753fSRafael Auler   for (auto &CUIDTablePair : LineTables) {
1228014cd37fSAlexander Yermolovich     Streamer.getContext().setDwarfVersion(
1229014cd37fSAlexander Yermolovich         CUIDTablePair.second.getDwarfVersion());
1230b73c87bcSMaksim Panchenko     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
1231a34c753fSRafael Auler   }
1232014cd37fSAlexander Yermolovich 
1233014cd37fSAlexander Yermolovich   // Resetting DWARF version for rest of the flow.
1234014cd37fSAlexander Yermolovich   BC.Ctx->setDwarfVersion(DwarfVersion);
1235014cd37fSAlexander Yermolovich 
1236014cd37fSAlexander Yermolovich   // Still need to write the section out for the ExecutionEngine, and temp in
1237014cd37fSAlexander Yermolovich   // memory object we are constructing.
123805634f73SJob Noorman   if (LineStr)
1239014cd37fSAlexander Yermolovich     LineStr->emitSection(&Streamer);
1240a34c753fSRafael Auler }
1241a34c753fSRafael Auler 
1242a34c753fSRafael Auler } // namespace bolt
1243a34c753fSRafael Auler } // namespace llvm
1244