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