brintos

brintos / llvm-project-archived public Read only

0
0
Text · 46.2 KiB · 2687788 Raw
1241 lines · cpp
1//===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements functions and classes for handling debug info.10//11//===----------------------------------------------------------------------===//12 13#include "bolt/Core/DebugData.h"14#include "bolt/Core/BinaryContext.h"15#include "bolt/Core/DIEBuilder.h"16#include "bolt/Utils/Utils.h"17#include "llvm/BinaryFormat/Dwarf.h"18#include "llvm/CodeGen/DIE.h"19#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"20#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"21#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"22#include "llvm/MC/MCAssembler.h"23#include "llvm/MC/MCContext.h"24#include "llvm/MC/MCObjectStreamer.h"25#include "llvm/Support/CommandLine.h"26#include "llvm/Support/EndianStream.h"27#include "llvm/Support/LEB128.h"28#include "llvm/Support/SHA1.h"29#include <algorithm>30#include <cassert>31#include <cstdint>32#include <functional>33#include <memory>34#include <optional>35#include <unordered_map>36#include <vector>37 38#define DEBUG_TYPE "bolt-debug-info"39 40namespace opts {41extern llvm::cl::opt<unsigned> Verbosity;42} // namespace opts43 44namespace llvm {45class MCSymbol;46 47namespace bolt {48 49static void replaceLocValbyForm(DIEBuilder &DIEBldr, DIE &Die, DIEValue DIEVal,50                                dwarf::Form Format, uint64_t NewVal) {51  if (Format == dwarf::DW_FORM_loclistx)52    DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,53                         DIELocList(NewVal));54  else55    DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,56                         DIEInteger(NewVal));57}58 59std::optional<AttrInfo>60findAttributeInfo(const DWARFDie DIE,61                  const DWARFAbbreviationDeclaration *AbbrevDecl,62                  uint32_t Index) {63  const DWARFUnit &U = *DIE.getDwarfUnit();64  uint64_t Offset =65      AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);66  std::optional<DWARFFormValue> Value =67      AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);68  if (!Value)69    return std::nullopt;70  // AttributeSpec71  const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =72      AbbrevDecl->attributes().begin() + Index;73  uint32_t ValSize = 0;74  std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);75  if (ValSizeOpt) {76    ValSize = static_cast<uint32_t>(*ValSizeOpt);77  } else {78    DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();79    uint64_t NewOffset = Offset;80    DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,81                              U.getFormParams());82    // This includes entire size of the entry, which might not be just the83    // encoding part. For example for DW_AT_loc it will include expression84    // location.85    ValSize = NewOffset - Offset;86  }87  return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};88}89 90std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,91                                          dwarf::Attribute Attr) {92  if (!DIE.isValid())93    return std::nullopt;94  const DWARFAbbreviationDeclaration *AbbrevDecl =95      DIE.getAbbreviationDeclarationPtr();96  if (!AbbrevDecl)97    return std::nullopt;98  std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);99  if (!Index)100    return std::nullopt;101  return findAttributeInfo(DIE, AbbrevDecl, *Index);102}103 104[[maybe_unused]]105static void printLE64(const std::string &S) {106  for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {107    errs() << Twine::utohexstr(S[I]);108    errs() << Twine::utohexstr((int8_t)S[I]);109  }110  errs() << "\n";111}112 113// Writes address ranges to Writer as pairs of 64-bit (address, size).114// If RelativeRange is true, assumes the address range to be written must be of115// the form (begin address, range size), otherwise (begin address, end address).116// Terminates the list by writing a pair of two zeroes.117// Returns the number of written bytes.118static uint64_t119writeAddressRanges(raw_svector_ostream &Stream,120                   const DebugAddressRangesVector &AddressRanges,121                   const bool WriteRelativeRanges = false) {122  for (const DebugAddressRange &Range : AddressRanges) {123    support::endian::write(Stream, Range.LowPC, llvm::endianness::little);124    support::endian::write(125        Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,126        llvm::endianness::little);127  }128  // Finish with 0 entries.129  support::endian::write(Stream, 0ULL, llvm::endianness::little);130  support::endian::write(Stream, 0ULL, llvm::endianness::little);131  return AddressRanges.size() * 16 + 16;132}133 134DebugRangesSectionWriter::DebugRangesSectionWriter() {135  RangesBuffer = std::make_unique<DebugBufferVector>();136  RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);137 138  Kind = RangesWriterKind::DebugRangesWriter;139}140 141void DebugRangesSectionWriter::initSection() {142  // Adds an empty range to the buffer.143  writeAddressRanges(*RangesStream, DebugAddressRangesVector{});144}145 146uint64_t DebugRangesSectionWriter::addRanges(147    DebugAddressRangesVector &&Ranges,148    std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {149  if (Ranges.empty())150    return getEmptyRangesOffset();151 152  const auto RI = CachedRanges.find(Ranges);153  if (RI != CachedRanges.end())154    return RI->second;155 156  const uint64_t EntryOffset = addRanges(Ranges);157  CachedRanges.emplace(std::move(Ranges), EntryOffset);158 159  return EntryOffset;160}161 162uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {163  if (Ranges.empty())164    return getEmptyRangesOffset();165 166  // Reading the SectionOffset and updating it should be atomic to guarantee167  // unique and correct offsets in patches.168  std::lock_guard<std::mutex> Lock(WriterMutex);169  const uint32_t EntryOffset = RangesBuffer->size();170  writeAddressRanges(*RangesStream, Ranges);171 172  return EntryOffset;173}174 175uint64_t DebugRangesSectionWriter::getSectionOffset() {176  std::lock_guard<std::mutex> Lock(WriterMutex);177  return RangesBuffer->size();178}179 180void DebugRangesSectionWriter::appendToRangeBuffer(181    const DebugBufferVector &CUBuffer) {182  *RangesStream << CUBuffer;183}184 185uint64_t DebugRangeListsSectionWriter::addRanges(186    DebugAddressRangesVector &&Ranges,187    std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {188  return addRanges(Ranges);189}190 191struct LocListsRangelistsHeader {192  UnitLengthType UnitLength; // Size of loclist entries section, not including193                             // size of header.194  VersionType Version;195  AddressSizeType AddressSize;196  SegmentSelectorType SegmentSelector;197  OffsetEntryCountType OffsetEntryCount;198};199 200static std::unique_ptr<DebugBufferVector>201getDWARF5Header(const LocListsRangelistsHeader &Header) {202  std::unique_ptr<DebugBufferVector> HeaderBuffer =203      std::make_unique<DebugBufferVector>();204  std::unique_ptr<raw_svector_ostream> HeaderStream =205      std::make_unique<raw_svector_ostream>(*HeaderBuffer);206 207  // 7.29 length of the set of entries for this compilation unit, not including208  // the length field itself209  const uint32_t HeaderSize =210      getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);211 212  support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,213                         llvm::endianness::little);214  support::endian::write(*HeaderStream, Header.Version,215                         llvm::endianness::little);216  support::endian::write(*HeaderStream, Header.AddressSize,217                         llvm::endianness::little);218  support::endian::write(*HeaderStream, Header.SegmentSelector,219                         llvm::endianness::little);220  support::endian::write(*HeaderStream, Header.OffsetEntryCount,221                         llvm::endianness::little);222  return HeaderBuffer;223}224 225struct OffsetEntry {226  uint32_t Index;227  uint32_t StartOffset;228  uint32_t EndOffset;229};230template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>231static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,232                         DebugAddrWriter &AddrWriter, DWARFUnit &CU,233                         uint32_t &Index, const ListEntry BaseAddressx,234                         const ListEntry OffsetPair,235                         const std::function<void(uint32_t)> &Func) {236  if (Entries.size() < 2)237    return false;238  uint64_t Base = Entries[Index].LowPC;239  std::vector<OffsetEntry> Offsets;240  uint8_t TempBuffer[64];241  while (Index < Entries.size()) {242    const DebugAddressEntry &Entry = Entries[Index];243    if (Entry.LowPC == 0)244      break;245    // In case rnglists or loclists are not sorted.246    if (Base > Entry.LowPC)247      break;248    uint32_t StartOffset = Entry.LowPC - Base;249    uint32_t EndOffset = Entry.HighPC - Base;250    if (encodeULEB128(EndOffset, TempBuffer) > 2)251      break;252    Offsets.push_back({Index, StartOffset, EndOffset});253    ++Index;254  }255 256  if (Offsets.size() < 2) {257    Index -= Offsets.size();258    return false;259  }260 261  support::endian::write(OS, static_cast<uint8_t>(BaseAddressx),262                         llvm::endianness::little);263  uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU);264  encodeULEB128(BaseIndex, OS);265  for (auto &OffsetEntry : Offsets) {266    support::endian::write(OS, static_cast<uint8_t>(OffsetPair),267                           llvm::endianness::little);268    encodeULEB128(OffsetEntry.StartOffset, OS);269    encodeULEB128(OffsetEntry.EndOffset, OS);270    Func(OffsetEntry.Index);271  }272  return true;273}274 275uint64_t276DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {277  std::lock_guard<std::mutex> Lock(WriterMutex);278 279  RangeEntries.push_back(CurrentOffset);280  std::sort(281      Ranges.begin(), Ranges.end(),282      [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {283        return R1.LowPC < R2.LowPC;284      });285  for (unsigned I = 0; I < Ranges.size();) {286    if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,287                     DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU,288                                        I, dwarf::DW_RLE_base_addressx,289                                        dwarf::DW_RLE_offset_pair,290                                        [](uint32_t Index) -> void {}))291      continue;292 293    const DebugAddressRange &Range = Ranges[I];294    support::endian::write(*CUBodyStream,295                           static_cast<uint8_t>(dwarf::DW_RLE_startx_length),296                           llvm::endianness::little);297    uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU);298    encodeULEB128(Index, *CUBodyStream);299    encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);300    ++I;301  }302 303  support::endian::write(*CUBodyStream,304                         static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),305                         llvm::endianness::little);306  CurrentOffset = CUBodyBuffer->size();307  return RangeEntries.size() - 1;308}309 310void DebugRangeListsSectionWriter::finalizeSection() {311  std::unique_ptr<DebugBufferVector> CUArrayBuffer =312      std::make_unique<DebugBufferVector>();313  std::unique_ptr<raw_svector_ostream> CUArrayStream =314      std::make_unique<raw_svector_ostream>(*CUArrayBuffer);315  constexpr uint32_t SizeOfArrayEntry = 4;316  const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;317  for (uint32_t Offset : RangeEntries)318    support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,319                           llvm::endianness::little);320 321  std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(322      {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer->size()), 5, 8,323       0, static_cast<uint32_t>(RangeEntries.size())});324  *RangesStream << *Header;325  *RangesStream << *CUArrayBuffer;326  *RangesStream << *CUBodyBuffer;327}328 329void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {330  CUBodyBuffer = std::make_unique<DebugBufferVector>();331  CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);332  RangeEntries.clear();333  CurrentOffset = 0;334  CU = &Unit;335}336 337void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,338                                            DebugAddressRangesVector &&Ranges) {339  std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);340  CUAddressRanges.emplace(CUOffset, std::move(Ranges));341}342 343void DebugARangesSectionWriter::writeARangesSection(344    raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {345  // For reference on the format of the .debug_aranges section, see the DWARF4346  // specification, section 6.1.4 Lookup by Address347  // http://www.dwarfstd.org/doc/DWARF4.pdf348  for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {349    const uint64_t Offset = CUOffsetAddressRangesPair.first;350    const DebugAddressRangesVector &AddressRanges =351        CUOffsetAddressRangesPair.second;352 353    // Emit header.354 355    // Size of this set: 8 (size of the header) + 4 (padding after header)356    // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra357    // pair of uint64_t's for the terminating, zero-length range.358    // Does not include size field itself.359    uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);360 361    // Header field #1: set size.362    support::endian::write(RangesStream, Size, llvm::endianness::little);363 364    // Header field #2: version number, 2 as per the specification.365    support::endian::write(RangesStream, static_cast<uint16_t>(2),366                           llvm::endianness::little);367 368    assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");369    // Header field #3: debug info offset of the correspondent compile unit.370    support::endian::write(371        RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),372        llvm::endianness::little);373 374    // Header field #4: address size.375    // 8 since we only write ELF64 binaries for now.376    RangesStream << char(8);377 378    // Header field #5: segment size of target architecture.379    RangesStream << char(0);380 381    // Padding before address table - 4 bytes in the 64-bit-pointer case.382    support::endian::write(RangesStream, static_cast<uint32_t>(0),383                           llvm::endianness::little);384 385    writeAddressRanges(RangesStream, AddressRanges, true);386  }387}388 389DebugAddrWriter::DebugAddrWriter(BinaryContext *BC,390                                 const uint8_t AddressByteSize)391    : BC(BC), AddressByteSize(AddressByteSize) {392  Buffer = std::make_unique<AddressSectionBuffer>();393  AddressStream = std::make_unique<raw_svector_ostream>(*Buffer);394}395 396void DebugAddrWriter::AddressForDWOCU::dump() {397  std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),398                                          indexToAdddessEnd());399  // Sorting address in increasing order of indices.400  llvm::sort(SortedMap, llvm::less_first());401  for (auto &Pair : SortedMap)402    dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";403}404uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {405  std::lock_guard<std::mutex> Lock(WriterMutex);406  auto Entry = Map.find(Address);407  if (Entry == Map.end()) {408    auto Index = Map.getNextIndex();409    Entry = Map.insert(Address, Index).first;410  }411  return Entry->second;412}413 414static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter,415                              DWARFUnit &CU, const uint64_t Offset) {416  DIE *Die = DIEBlder.getUnitDIEbyUnit(CU);417  DIEValue GnuAddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_GNU_addr_base);418  DIEValue AddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_addr_base);419  dwarf::Form BaseAttrForm;420  dwarf::Attribute BaseAttr;421  // For cases where Skeleton CU does not have DW_AT_GNU_addr_base422  if (!GnuAddrBaseAttrInfo && CU.getVersion() < 5)423    return;424 425  if (GnuAddrBaseAttrInfo) {426    BaseAttrForm = GnuAddrBaseAttrInfo.getForm();427    BaseAttr = GnuAddrBaseAttrInfo.getAttribute();428  }429 430  if (AddrBaseAttrInfo) {431    BaseAttrForm = AddrBaseAttrInfo.getForm();432    BaseAttr = AddrBaseAttrInfo.getAttribute();433  }434 435  if (GnuAddrBaseAttrInfo || AddrBaseAttrInfo) {436    DIEBlder.replaceValue(Die, BaseAttr, BaseAttrForm, DIEInteger(Offset));437  } else if (CU.getVersion() >= 5) {438    // A case where we were not using .debug_addr section, but after update439    // now using it.440    DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,441                      DIEInteger(Offset));442  }443}444 445void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,446                                     const uint64_t Offset) {447  updateAddressBase(DIEBlder, *this, CU, Offset);448}449 450std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) {451  if (Map.begin() == Map.end())452    return std::nullopt;453  std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),454                                          Map.indexToAdddessEnd());455  // Sorting address in increasing order of indices.456  llvm::sort(SortedMap, llvm::less_first());457 458  uint32_t Counter = 0;459  auto WriteAddress = [&](uint64_t Address) -> void {460    ++Counter;461    switch (AddressByteSize) {462    default:463      assert(false && "Address Size is invalid.");464      break;465    case 4:466      support::endian::write(*AddressStream, static_cast<uint32_t>(Address),467                             llvm::endianness::little);468      break;469    case 8:470      support::endian::write(*AddressStream, Address, llvm::endianness::little);471      break;472    }473  };474 475  for (const IndexAddressPair &Val : SortedMap) {476    while (Val.first > Counter)477      WriteAddress(0);478    WriteAddress(Val.second);479  }480  return std::nullopt;481}482 483void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,484                                           const uint64_t Offset) {485  /// Header for DWARF5 has size 8, so we add it to the offset.486  updateAddressBase(DIEBlder, *this, CU, Offset + HeaderSize);487}488 489DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets;490 491std::optional<uint64_t>492DebugAddrWriterDwarf5::finalize(const size_t BufferSize) {493  // Need to layout all sections within .debug_addr494  // Within each section sort Address by index.495  const endianness Endian = BC->DwCtx->isLittleEndian()496                                ? llvm::endianness::little497                                : llvm::endianness::big;498  const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();499  DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec,500                              Endian == llvm::endianness::little, 0);501  DWARFDebugAddrTable AddrTable;502  DIDumpOptions DumpOpts;503  // A case where CU has entry in .debug_addr, but we don't modify addresses504  // for it.505  if (Map.begin() == Map.end()) {506    if (!AddrOffsetSectionBase)507      return std::nullopt;508    // Address base offset is to the first entry.509    // The size of header is 8 bytes.510    uint64_t Offset = *AddrOffsetSectionBase - HeaderSize;511    auto Iter = UnmodifiedAddressOffsets.find(Offset);512    if (Iter != UnmodifiedAddressOffsets.end())513      return Iter->second;514    UnmodifiedAddressOffsets[Offset] = BufferSize;515    if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize,516                                      DumpOpts.WarningHandler)) {517      DumpOpts.RecoverableErrorHandler(std::move(Err));518      return std::nullopt;519    }520    uint32_t Index = 0;521    for (uint64_t Addr : AddrTable.getAddressEntries())522      Map.insert(Addr, Index++);523  }524 525  std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),526                                          Map.indexToAdddessEnd());527  // Sorting address in increasing order of indices.528  llvm::sort(SortedMap, llvm::less_first());529  // Writing out Header530  const uint32_t Length = SortedMap.size() * AddressByteSize + 4;531  support::endian::write(*AddressStream, Length, Endian);532  support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);533  support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize),534                         Endian);535  support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);536 537  uint32_t Counter = 0;538  auto writeAddress = [&](uint64_t Address) -> void {539    ++Counter;540    switch (AddressByteSize) {541    default:542      llvm_unreachable("Address Size is invalid.");543      break;544    case 4:545      support::endian::write(*AddressStream, static_cast<uint32_t>(Address),546                             Endian);547      break;548    case 8:549      support::endian::write(*AddressStream, Address, Endian);550      break;551    }552  };553 554  for (const IndexAddressPair &Val : SortedMap) {555    while (Val.first > Counter)556      writeAddress(0);557    writeAddress(Val.second);558  }559  return std::nullopt;560}561 562void DebugLocWriter::init() {563  LocBuffer = std::make_unique<DebugBufferVector>();564  LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);565  // Writing out empty location list to which all references to empty location566  // lists will point.567  if (!LocSectionOffset && DwarfVersion < 5) {568    const char Zeroes[16] = {0};569    *LocStream << StringRef(Zeroes, 16);570    LocSectionOffset += 16;571  }572}573 574uint32_t DebugLocWriter::LocSectionOffset = 0;575void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,576                             DebugLocationsVector &LocList) {577  if (LocList.empty()) {578    replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),579                        DebugLocWriter::EmptyListOffset);580    return;581  }582  // Since there is a separate DebugLocWriter for each thread,583  // we don't need a lock to read the SectionOffset and update it.584  const uint32_t EntryOffset = LocSectionOffset;585 586  for (const DebugLocationEntry &Entry : LocList) {587    support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),588                           llvm::endianness::little);589    support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),590                           llvm::endianness::little);591    support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),592                           llvm::endianness::little);593    *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),594                            Entry.Expr.size());595    LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();596  }597  LocStream->write_zeros(16);598  LocSectionOffset += 16;599  LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen600                                                                // use601  replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);602}603 604std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {605  return std::move(LocBuffer);606}607 608// DWARF 4: 2.6.2609void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}610 611static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {612  support::endian::write(Stream, static_cast<uint32_t>(4),613                         llvm::endianness::little);614  support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),615                         llvm::endianness::little);616 617  const char Zeroes[16] = {0};618  Stream << StringRef(Zeroes, 16);619  encodeULEB128(0, Stream);620  support::endian::write(Stream,621                         static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),622                         llvm::endianness::little);623}624 625static void writeLegacyLocList(DIEValue &AttrInfo,626                               DebugLocationsVector &LocList,627                               DIEBuilder &DIEBldr, DIE &Die,628                               DebugAddrWriter &AddrWriter,629                               DebugBufferVector &LocBuffer, DWARFUnit &CU,630                               raw_svector_ostream &LocStream) {631  if (LocList.empty()) {632    replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),633                        DebugLocWriter::EmptyListOffset);634    return;635  }636 637  const uint32_t EntryOffset = LocBuffer.size();638  for (const DebugLocationEntry &Entry : LocList) {639    support::endian::write(LocStream,640                           static_cast<uint8_t>(dwarf::DW_LLE_startx_length),641                           llvm::endianness::little);642    const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);643    encodeULEB128(Index, LocStream);644 645    support::endian::write(LocStream,646                           static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),647                           llvm::endianness::little);648    support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()),649                           llvm::endianness::little);650    LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),651                           Entry.Expr.size());652  }653  support::endian::write(LocStream,654                         static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),655                         llvm::endianness::little);656  replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);657}658 659static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,660                               DebugLocationsVector &LocList, DIE &Die,661                               DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter,662                               DebugBufferVector &LocBodyBuffer,663                               std::vector<uint32_t> &RelativeLocListOffsets,664                               DWARFUnit &CU,665                               raw_svector_ostream &LocBodyStream) {666 667  replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,668                      NumberOfEntries);669 670  RelativeLocListOffsets.push_back(LocBodyBuffer.size());671  ++NumberOfEntries;672  if (LocList.empty()) {673    writeEmptyListDwarf5(LocBodyStream);674    return;675  }676 677  auto writeExpression = [&](uint32_t Index) -> void {678    const DebugLocationEntry &Entry = LocList[Index];679    encodeULEB128(Entry.Expr.size(), LocBodyStream);680    LocBodyStream << StringRef(681        reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());682  };683  for (unsigned I = 0; I < LocList.size();) {684    if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,685                     DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU,686                                         I, dwarf::DW_LLE_base_addressx,687                                         dwarf::DW_LLE_offset_pair,688                                         writeExpression))689      continue;690 691    const DebugLocationEntry &Entry = LocList[I];692    support::endian::write(LocBodyStream,693                           static_cast<uint8_t>(dwarf::DW_LLE_startx_length),694                           llvm::endianness::little);695    const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);696    encodeULEB128(Index, LocBodyStream);697    encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);698    writeExpression(I);699    ++I;700  }701 702  support::endian::write(LocBodyStream,703                         static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),704                         llvm::endianness::little);705}706 707void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,708                                 DIEValue &AttrInfo,709                                 DebugLocationsVector &LocList) {710  if (DwarfVersion < 5)711    writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer,712                       CU, *LocStream);713  else714    writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,715                       AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,716                       *LocBodyStream);717}718 719uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;720void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) {721  if (LocBodyBuffer->empty()) {722    DIEValue LocListBaseAttrInfo =723        Die.findAttribute(dwarf::DW_AT_loclists_base);724    // Pointing to first one, because it doesn't matter. There are no uses of it725    // in this CU.726    if (!isSplitDwarf() && LocListBaseAttrInfo.getType())727      DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,728                           LocListBaseAttrInfo.getForm(),729                           DIEInteger(getDWARF5RngListLocListHeaderSize()));730    return;731  }732 733  std::unique_ptr<DebugBufferVector> LocArrayBuffer =734      std::make_unique<DebugBufferVector>();735  std::unique_ptr<raw_svector_ostream> LocArrayStream =736      std::make_unique<raw_svector_ostream>(*LocArrayBuffer);737 738  const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t);739  // Write out IndexArray740  for (uint32_t RelativeOffset : RelativeLocListOffsets)741    support::endian::write(742        *LocArrayStream,743        static_cast<uint32_t>(SizeOfArraySection + RelativeOffset),744        llvm::endianness::little);745 746  std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(747      {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer->size()), 5, 8,748       0, NumberOfEntries});749  *LocStream << *Header;750  *LocStream << *LocArrayBuffer;751  *LocStream << *LocBodyBuffer;752 753  if (!isSplitDwarf()) {754    DIEValue LocListBaseAttrInfo =755        Die.findAttribute(dwarf::DW_AT_loclists_base);756    if (LocListBaseAttrInfo.getType()) {757      DIEBldr.replaceValue(758          &Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(),759          DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize()));760    } else {761      DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,762                       dwarf::DW_FORM_sec_offset,763                       DIEInteger(LoclistBaseOffset + Header->size()));764    }765    LoclistBaseOffset += LocBuffer->size();766  }767  clearList(RelativeLocListOffsets);768  clearList(*LocArrayBuffer);769  clearList(*LocBodyBuffer);770}771 772void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {773  if (DwarfVersion >= 5)774    finalizeDWARF5(DIEBldr, Die);775}776 777static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {778  std::string LE64(ByteSize, 0);779  for (size_t I = 0; I < ByteSize; ++I) {780    LE64[I] = NewValue & 0xff;781    NewValue >>= 8;782  }783  return LE64;784}785 786void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,787                                         std::string &&NewValue,788                                         uint32_t OldValueSize) {789  Patches.emplace_back(Offset, std::move(NewValue));790}791 792void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {793  auto Str = std::string(1, Value);794  Patches.emplace_back(Offset, std::move(Str));795}796 797void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,798                                     size_t ByteSize) {799  Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));800}801 802void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,803                                        uint32_t OldValueSize) {804  std::string Buff;805  raw_string_ostream OS(Buff);806  encodeULEB128(Value, OS, OldValueSize);807 808  Patches.emplace_back(Offset, std::move(Buff));809}810 811void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {812  addLEPatch(Offset, NewValue, 8);813}814 815void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,816                                       uint32_t OldValueSize) {817  addLEPatch(Offset, NewValue, 4);818}819 820std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {821  std::string BinaryContentsStr = std::string(BinaryContents);822  for (const auto &Patch : Patches) {823    uint32_t Offset = Patch.first;824    const std::string &ByteSequence = Patch.second;825    assert(Offset + ByteSequence.size() <= BinaryContents.size() &&826           "Applied patch runs over binary size.");827    for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {828      BinaryContentsStr[Offset + I] = ByteSequence[I];829    }830  }831  return BinaryContentsStr;832}833 834void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) {835  if (Unit.getVersion() < 5)836    return;837  const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();838  const std::optional<StrOffsetsContributionDescriptor> &Contr =839      Unit.getStringOffsetsTableContribution();840  if (!Contr)841    return;842  const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();843  assert(DwarfOffsetByteSize == 4 &&844         "Dwarf String Offsets Byte Size is not supported.");845  StrOffsets.reserve(Contr->Size);846  for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)847    StrOffsets.push_back(support::endian::read32le(848        StrOffsetsSection.Data.data() + Contr->Base + Offset));849}850 851void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address,852                                             const DWARFUnit &Unit) {853  assert(DebugStrOffsetFinalized.count(Unit.getOffset()) == 0 &&854         "Cannot update address map since debug_str_offsets was already "855         "finalized for this CU.");856  IndexToAddressMap[Index] = Address;857  StrOffsetSectionWasModified = true;858}859 860void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,861                                            DIEBuilder &DIEBldr) {862  std::optional<AttrInfo> AttrVal =863      findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);864  if (!AttrVal && !Unit.isDWOUnit())865    return;866  std::optional<uint64_t> Val = std::nullopt;867  if (AttrVal) {868    Val = AttrVal->V.getAsSectionOffset();869  } else {870    if (!Unit.isDWOUnit())871      BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "872                   "DW_AT_str_offsets_base Value not present\n";873    Val = 0;874  }875  DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);876  DIEValue StrListBaseAttrInfo =877      Die.findAttribute(dwarf::DW_AT_str_offsets_base);878  auto RetVal = ProcessedBaseOffsets.find(*Val);879  // Handling reuse of str-offsets section.880  if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {881    initialize(Unit);882    // Update String Offsets that were modified.883    for (const auto &Entry : IndexToAddressMap)884      StrOffsets[Entry.first] = Entry.second;885    // Writing out the header for each section.886    support::endian::write(*StrOffsetsStream,887                           static_cast<uint32_t>(StrOffsets.size() * 4 + 4),888                           llvm::endianness::little);889    support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),890                           llvm::endianness::little);891    support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),892                           llvm::endianness::little);893 894    uint64_t BaseOffset = StrOffsetsBuffer->size();895    ProcessedBaseOffsets[*Val] = BaseOffset;896    if (StrListBaseAttrInfo.getType())897      DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,898                           StrListBaseAttrInfo.getForm(),899                           DIEInteger(BaseOffset));900    for (const uint32_t Offset : StrOffsets)901      support::endian::write(*StrOffsetsStream, Offset,902                             llvm::endianness::little);903  } else {904    DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,905                         StrListBaseAttrInfo.getForm(),906                         DIEInteger(RetVal->second));907  }908 909  StrOffsetSectionWasModified = false;910  assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second &&911         "debug_str_offsets was already finalized for this CU.");912  clear();913}914 915void DebugStrWriter::create() {916  StrBuffer = std::make_unique<DebugStrBufferVector>();917  StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);918}919 920void DebugStrWriter::initialize() {921  StringRef StrSection;922  if (IsDWO)923    StrSection = DwCtx.getDWARFObj().getStrDWOSection();924  else925    StrSection = DwCtx.getDWARFObj().getStrSection();926  (*StrStream) << StrSection;927}928 929uint32_t DebugStrWriter::addString(StringRef Str) {930  std::lock_guard<std::mutex> Lock(WriterMutex);931  if (StrBuffer->empty())932    initialize();933  auto Offset = StrBuffer->size();934  (*StrStream) << Str;935  StrStream->write_zeros(1);936  return Offset;937}938 939static void emitDwarfSetLineAddrAbs(MCStreamer &OS,940                                    MCDwarfLineTableParams Params,941                                    int64_t LineDelta, uint64_t Address,942                                    int PointerSize) {943  // emit the sequence to set the address944  OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);945  OS.emitULEB128IntValue(PointerSize + 1);946  OS.emitIntValue(dwarf::DW_LNE_set_address, 1);947  OS.emitIntValue(Address, PointerSize);948 949  // emit the sequence for the LineDelta (from 1) and a zero address delta.950  MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);951}952 953static inline void emitBinaryDwarfLineTable(954    MCStreamer *MCOS, MCDwarfLineTableParams Params,955    const DWARFDebugLine::LineTable *Table,956    const std::vector<DwarfLineTable::RowSequence> &InputSequences) {957  if (InputSequences.empty())958    return;959 960  constexpr uint64_t InvalidAddress = UINT64_MAX;961  unsigned FileNum = 1;962  unsigned LastLine = 1;963  unsigned Column = 0;964  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;965  unsigned Isa = 0;966  unsigned Discriminator = 0;967  uint64_t LastAddress = InvalidAddress;968  uint64_t PrevEndOfSequence = InvalidAddress;969  const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();970 971  auto emitEndOfSequence = [&](uint64_t Address) {972    MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);973    FileNum = 1;974    LastLine = 1;975    Column = 0;976    Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;977    Isa = 0;978    Discriminator = 0;979    LastAddress = InvalidAddress;980  };981 982  for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {983    const uint64_t SequenceStart =984        Table->Rows[Sequence.FirstIndex].Address.Address;985 986    // Check if we need to mark the end of the sequence.987    if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&988        PrevEndOfSequence != SequenceStart) {989      emitEndOfSequence(PrevEndOfSequence);990    }991 992    for (uint32_t RowIndex = Sequence.FirstIndex;993         RowIndex <= Sequence.LastIndex; ++RowIndex) {994      const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];995      int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;996      const uint64_t Address = Row.Address.Address;997 998      if (FileNum != Row.File) {999        FileNum = Row.File;1000        MCOS->emitInt8(dwarf::DW_LNS_set_file);1001        MCOS->emitULEB128IntValue(FileNum);1002      }1003      if (Column != Row.Column) {1004        Column = Row.Column;1005        MCOS->emitInt8(dwarf::DW_LNS_set_column);1006        MCOS->emitULEB128IntValue(Column);1007      }1008      if (Discriminator != Row.Discriminator &&1009          MCOS->getContext().getDwarfVersion() >= 4) {1010        Discriminator = Row.Discriminator;1011        unsigned Size = getULEB128Size(Discriminator);1012        MCOS->emitInt8(dwarf::DW_LNS_extended_op);1013        MCOS->emitULEB128IntValue(Size + 1);1014        MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);1015        MCOS->emitULEB128IntValue(Discriminator);1016      }1017      if (Isa != Row.Isa) {1018        Isa = Row.Isa;1019        MCOS->emitInt8(dwarf::DW_LNS_set_isa);1020        MCOS->emitULEB128IntValue(Isa);1021      }1022      if (Row.IsStmt != Flags) {1023        Flags = Row.IsStmt;1024        MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);1025      }1026      if (Row.BasicBlock)1027        MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);1028      if (Row.PrologueEnd)1029        MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);1030      if (Row.EpilogueBegin)1031        MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);1032 1033      // The end of the sequence is not normal in the middle of the input1034      // sequence, but could happen, e.g. for assembly code.1035      if (Row.EndSequence) {1036        emitEndOfSequence(Address);1037      } else {1038        if (LastAddress == InvalidAddress)1039          emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,1040                                  AsmInfo->getCodePointerSize());1041        else1042          MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);1043 1044        LastAddress = Address;1045        LastLine = Row.Line;1046      }1047 1048      Discriminator = 0;1049    }1050    PrevEndOfSequence = Sequence.EndAddress;1051  }1052 1053  // Finish with the end of the sequence.1054  if (LastAddress != InvalidAddress)1055    emitEndOfSequence(PrevEndOfSequence);1056}1057 1058// This function is similar to the one from MCDwarfLineTable, except it handles1059// end-of-sequence entries differently by utilizing line entries with1060// DWARF2_FLAG_END_SEQUENCE flag.1061static inline void emitDwarfLineTable(1062    MCStreamer *MCOS, MCSection *Section,1063    const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {1064  unsigned FileNum = 1;1065  unsigned LastLine = 1;1066  unsigned Column = 0;1067  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;1068  unsigned Isa = 0;1069  unsigned Discriminator = 0;1070  MCSymbol *LastLabel = nullptr;1071  const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();1072 1073  // Loop through each MCDwarfLineEntry and encode the dwarf line number table.1074  for (const MCDwarfLineEntry &LineEntry : LineEntries) {1075    if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {1076      MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),1077                                     AsmInfo->getCodePointerSize());1078      FileNum = 1;1079      LastLine = 1;1080      Column = 0;1081      Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;1082      Isa = 0;1083      Discriminator = 0;1084      LastLabel = nullptr;1085      continue;1086    }1087 1088    int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;1089 1090    if (FileNum != LineEntry.getFileNum()) {1091      FileNum = LineEntry.getFileNum();1092      MCOS->emitInt8(dwarf::DW_LNS_set_file);1093      MCOS->emitULEB128IntValue(FileNum);1094    }1095    if (Column != LineEntry.getColumn()) {1096      Column = LineEntry.getColumn();1097      MCOS->emitInt8(dwarf::DW_LNS_set_column);1098      MCOS->emitULEB128IntValue(Column);1099    }1100    if (Discriminator != LineEntry.getDiscriminator() &&1101        MCOS->getContext().getDwarfVersion() >= 2) {1102      Discriminator = LineEntry.getDiscriminator();1103      unsigned Size = getULEB128Size(Discriminator);1104      MCOS->emitInt8(dwarf::DW_LNS_extended_op);1105      MCOS->emitULEB128IntValue(Size + 1);1106      MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);1107      MCOS->emitULEB128IntValue(Discriminator);1108    }1109    if (Isa != LineEntry.getIsa()) {1110      Isa = LineEntry.getIsa();1111      MCOS->emitInt8(dwarf::DW_LNS_set_isa);1112      MCOS->emitULEB128IntValue(Isa);1113    }1114    if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {1115      Flags = LineEntry.getFlags();1116      MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);1117    }1118    if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)1119      MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);1120    if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)1121      MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);1122    if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)1123      MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);1124 1125    MCSymbol *Label = LineEntry.getLabel();1126 1127    // At this point we want to emit/create the sequence to encode the delta1128    // in line numbers and the increment of the address from the previous1129    // Label and the current Label.1130    MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,1131                                   AsmInfo->getCodePointerSize());1132    Discriminator = 0;1133    LastLine = LineEntry.getLine();1134    LastLabel = Label;1135  }1136 1137  assert(LastLabel == nullptr && "end of sequence expected");1138}1139 1140void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,1141                            std::optional<MCDwarfLineStr> &LineStr,1142                            BinaryContext &BC) const {1143  if (!RawData.empty()) {1144    assert(MCLineSections.getMCLineEntries().empty() &&1145           InputSequences.empty() &&1146           "cannot combine raw data with new line entries");1147    MCOS->emitLabel(getLabel());1148    MCOS->emitBytes(RawData);1149    return;1150  }1151 1152  MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;1153 1154  // Put out the line tables.1155  for (const auto &LineSec : MCLineSections.getMCLineEntries())1156    emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);1157 1158  // Emit line tables for the original code.1159  emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);1160 1161  // This is the end of the section, so set the value of the symbol at the end1162  // of this section (that was used in a previous expression).1163  MCOS->emitLabel(LineEndSym);1164}1165 1166// Helper function to parse .debug_line_str, and populate one we are using.1167// For functions that we do not modify we output them as raw data.1168// Re-constructing .debug_line_str so that offsets are correct for those1169// debug line tables.1170// Bonus is that when we output a final binary we can reuse .debug_line_str1171// section. So we don't have to do the SHF_ALLOC trick we did with1172// .debug_line.1173static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,1174                                         MCDwarfLineStr &LineStr,1175                                         BinaryContext &BC) {1176  DataExtractor StrData(LineStrSection.getContents(),1177                        BC.DwCtx->isLittleEndian(), 0);1178  uint64_t Offset = 0;1179  while (StrData.isValidOffset(Offset)) {1180    const uint64_t StrOffset = Offset;1181    Error Err = Error::success();1182    const char *CStr = StrData.getCStr(&Offset, &Err);1183    if (Err) {1184      BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";1185      continue;1186    }1187    const size_t NewOffset = LineStr.addString(CStr);1188    assert(StrOffset == NewOffset &&1189           "New offset in .debug_line_str doesn't match original offset");1190    (void)StrOffset;1191    (void)NewOffset;1192  }1193}1194 1195void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {1196  MCAssembler &Assembler =1197      static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();1198 1199  MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();1200 1201  auto &LineTables = BC.getDwarfLineTables();1202 1203  // Bail out early so we don't switch to the debug_line section needlessly and1204  // in doing so create an unnecessary (if empty) section.1205  if (LineTables.empty())1206    return;1207  // In a v5 non-split line table, put the strings in a separate section.1208  std::optional<MCDwarfLineStr> LineStr;1209  ErrorOr<BinarySection &> LineStrSection =1210      BC.getUniqueSectionByName(".debug_line_str");1211 1212  // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower1213  // .debug_line, so need to check if section exists.1214  if (LineStrSection) {1215    LineStr.emplace(*BC.Ctx);1216    parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC);1217  }1218 1219  // Switch to the section where the table will be emitted into.1220  Streamer.switchSection(BC.MOFI->getDwarfLineSection());1221 1222  const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();1223  // Handle the rest of the Compile Units.1224  for (auto &CUIDTablePair : LineTables) {1225    Streamer.getContext().setDwarfVersion(1226        CUIDTablePair.second.getDwarfVersion());1227    CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);1228  }1229 1230  // Resetting DWARF version for rest of the flow.1231  BC.Ctx->setDwarfVersion(DwarfVersion);1232 1233  // Still need to write the section out for the ExecutionEngine, and temp in1234  // memory object we are constructing.1235  if (LineStr)1236    LineStr->emitSection(&Streamer);1237}1238 1239} // namespace bolt1240} // namespace llvm1241