brintos

brintos / llvm-project-archived public Read only

0
0
Text · 86.4 KiB · 816acb2 Raw
2116 lines · cpp
1//===- bolt/Rewrite/DWARFRewriter.cpp -------------------------------------===//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#include "bolt/Rewrite/DWARFRewriter.h"10#include "bolt/Core/BinaryContext.h"11#include "bolt/Core/BinaryFunction.h"12#include "bolt/Core/DIEBuilder.h"13#include "bolt/Core/DebugData.h"14#include "bolt/Core/DynoStats.h"15#include "bolt/Core/ParallelUtilities.h"16#include "bolt/Rewrite/RewriteInstance.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/BinaryFormat/Dwarf.h"21#include "llvm/CodeGen/AsmPrinter.h"22#include "llvm/CodeGen/DIE.h"23#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"24#include "llvm/DebugInfo/DWARF/DWARFContext.h"25#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"26#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"27#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"28#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"29#include "llvm/DebugInfo/DWARF/DWARFUnit.h"30#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"31#include "llvm/MC/MCAsmBackend.h"32#include "llvm/MC/MCAssembler.h"33#include "llvm/MC/MCObjectWriter.h"34#include "llvm/MC/MCStreamer.h"35#include "llvm/MC/MCTargetOptionsCommandFlags.h"36#include "llvm/Object/ObjectFile.h"37#include "llvm/Support/Casting.h"38#include "llvm/Support/CommandLine.h"39#include "llvm/Support/Debug.h"40#include "llvm/Support/Endian.h"41#include "llvm/Support/Error.h"42#include "llvm/Support/FileSystem.h"43#include "llvm/Support/LEB128.h"44#include "llvm/Support/ThreadPool.h"45#include "llvm/Support/raw_ostream.h"46#include <algorithm>47#include <cstdint>48#include <functional>49#include <iterator>50#include <memory>51#include <optional>52#include <string>53#include <unordered_map>54#include <utility>55#include <vector>56 57#undef DEBUG_TYPE58#define DEBUG_TYPE "bolt"59 60static mc::RegisterMCTargetOptionsFlags MOF;61 62static void printDie(const DWARFDie &DIE) {63  DIDumpOptions DumpOpts;64  DumpOpts.ShowForm = true;65  DumpOpts.Verbose = true;66  DumpOpts.ChildRecurseDepth = 0;67  DumpOpts.ShowChildren = false;68  DIE.dump(dbgs(), 0, DumpOpts);69}70 71/// Lazily parse DWARF DIE and print it out.72[[maybe_unused]]73static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {74  uint64_t OriginalOffsets = DIEOffset;75  uint64_t NextCUOffset = DU.getNextUnitOffset();76  DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();77  DWARFDebugInfoEntry DIEEntry;78  if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) {79    if (DIEEntry.getAbbreviationDeclarationPtr()) {80      DWARFDie DDie(&DU, &DIEEntry);81      printDie(DDie);82    } else {83      dbgs() << "Failed to extract abbreviation for"84             << Twine::utohexstr(OriginalOffsets) << "\n";85    }86  } else {87    dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets)88           << " \n";89  }90}91 92using namespace bolt;93 94/// Take a set of DWARF address ranges corresponding to the input binary and95/// translate them to a set of address ranges in the output binary.96static DebugAddressRangesVector97translateInputToOutputRanges(const BinaryFunction &BF,98                             const DWARFAddressRangesVector &InputRanges) {99  DebugAddressRangesVector OutputRanges;100 101  // If the function hasn't changed return the same ranges.102  if (!BF.isEmitted()) {103    OutputRanges.resize(InputRanges.size());104    llvm::transform(InputRanges, OutputRanges.begin(),105                    [](const DWARFAddressRange &Range) {106                      return DebugAddressRange(Range.LowPC, Range.HighPC);107                    });108    return OutputRanges;109  }110 111  for (const DWARFAddressRange &Range : InputRanges)112    llvm::append_range(OutputRanges, BF.translateInputToOutputRange(113                                         {Range.LowPC, Range.HighPC}));114 115  // Post-processing pass to sort and merge ranges.116  llvm::sort(OutputRanges);117  DebugAddressRangesVector MergedRanges;118  uint64_t PrevHighPC = 0;119  for (const DebugAddressRange &Range : OutputRanges) {120    if (Range.LowPC <= PrevHighPC) {121      MergedRanges.back().HighPC =122          std::max(MergedRanges.back().HighPC, Range.HighPC);123    } else {124      MergedRanges.emplace_back(Range.LowPC, Range.HighPC);125    }126    PrevHighPC = MergedRanges.back().HighPC;127  }128 129  return MergedRanges;130}131 132/// Similar to translateInputToOutputRanges() but operates on location lists.133static DebugLocationsVector134translateInputToOutputLocationList(const BinaryFunction &BF,135                                   const DebugLocationsVector &InputLL) {136  DebugLocationsVector OutputLL;137 138  // If the function hasn't changed - there's nothing to update.139  if (!BF.isEmitted())140    return InputLL;141 142  for (const DebugLocationEntry &Entry : InputLL) {143    DebugAddressRangesVector OutRanges =144        BF.translateInputToOutputRange({Entry.LowPC, Entry.HighPC});145    if (!OutRanges.empty() && !OutputLL.empty()) {146      if (OutRanges.front().LowPC == OutputLL.back().HighPC &&147          Entry.Expr == OutputLL.back().Expr) {148        OutputLL.back().HighPC =149            std::max(OutputLL.back().HighPC, OutRanges.front().HighPC);150        OutRanges.erase(OutRanges.begin());151      }152    }153    llvm::transform(OutRanges, std::back_inserter(OutputLL),154                    [&Entry](const DebugAddressRange &R) {155                      return DebugLocationEntry{R.LowPC, R.HighPC, Entry.Expr};156                    });157  }158 159  // Sort and merge adjacent entries with identical locations.160  llvm::stable_sort(161      OutputLL, [](const DebugLocationEntry &A, const DebugLocationEntry &B) {162        return A.LowPC < B.LowPC;163      });164  DebugLocationsVector MergedLL;165  uint64_t PrevHighPC = 0;166  const SmallVectorImpl<uint8_t> *PrevExpr = nullptr;167  for (const DebugLocationEntry &Entry : OutputLL) {168    if (Entry.LowPC <= PrevHighPC && *PrevExpr == Entry.Expr) {169      MergedLL.back().HighPC = std::max(Entry.HighPC, MergedLL.back().HighPC);170    } else {171      const uint64_t Begin = std::max(Entry.LowPC, PrevHighPC);172      const uint64_t End = std::max(Begin, Entry.HighPC);173      MergedLL.emplace_back(DebugLocationEntry{Begin, End, Entry.Expr});174    }175    PrevHighPC = MergedLL.back().HighPC;176    PrevExpr = &MergedLL.back().Expr;177  }178 179  return MergedLL;180}181 182using namespace dwarf_linker;183using namespace dwarf_linker::classic;184 185namespace llvm {186namespace bolt {187/// Emits debug information into .debug_info or .debug_types section.188class DIEStreamer : public DwarfStreamer {189  DIEBuilder *DIEBldr;190  GDBIndex &GDBIndexSection;191 192private:193  /// Emit the compilation unit header for \p Unit in the debug_info194  /// section.195  ///196  /// A Dwarf 4 section header is encoded as:197  ///  uint32_t   Unit length (omitting this field)198  ///  uint16_t   Version199  ///  uint32_t   Abbreviation table offset200  ///  uint8_t    Address size201  /// Leading to a total of 11 bytes.202  ///203  /// A Dwarf 5 section header is encoded as:204  ///  uint32_t   Unit length (omitting this field)205  ///  uint16_t   Version206  ///  uint8_t    Unit type207  ///  uint8_t    Address size208  ///  uint32_t   Abbreviation table offset209  /// Leading to a total of 12 bytes.210  void emitCompileUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,211                             unsigned DwarfVersion) {212 213    AsmPrinter &Asm = getAsmPrinter();214    switchToDebugInfoSection(DwarfVersion);215 216    emitCommonHeader(Unit, UnitDIE, DwarfVersion);217 218    if (DwarfVersion >= 5 &&219        Unit.getUnitType() != dwarf::UnitType::DW_UT_compile) {220      std::optional<uint64_t> DWOId = Unit.getDWOId();221      assert(DWOId &&222             "DWOId does not exist and this is not a DW_UT_compile Unit");223      Asm.emitInt64(*DWOId);224    }225  }226 227  void emitCommonHeader(DWARFUnit &Unit, DIE &UnitDIE, uint16_t Version) {228    dwarf::UnitType UT = dwarf::UnitType(Unit.getUnitType());229    llvm::AsmPrinter &Asm = getAsmPrinter();230 231    // Emit size of content not including length itself232    Asm.emitInt32(Unit.getHeaderSize() + UnitDIE.getSize() - 4);233    Asm.emitInt16(Version);234 235    // DWARF v5 reorders the address size and adds a unit type.236    if (Version >= 5) {237      Asm.emitInt8(UT);238      Asm.emitInt8(Asm.MAI->getCodePointerSize());239    }240 241    Asm.emitInt32(0);242    if (Version <= 4) {243      Asm.emitInt8(Asm.MAI->getCodePointerSize());244    }245  }246 247  void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,248                          unsigned DwarfVersion) {249    AsmPrinter &Asm = getAsmPrinter();250    const uint64_t TypeSignature = cast<DWARFTypeUnit>(Unit).getTypeHash();251    DIE *TypeDIE = DIEBldr->getTypeDIE(Unit);252    const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit);253    GDBIndexSection.addGDBTypeUnitEntry(254        {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()});255    if (Unit.getVersion() < 5) {256      // Switch the section to .debug_types section.257      std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer;258      llvm::MCContext &MC = Asm.OutContext;259      const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo();260 261      MS->switchSection(MOFI->getDwarfTypesSection(0));262      MC.setDwarfVersion(DwarfVersion);263    } else264      switchToDebugInfoSection(DwarfVersion);265 266    emitCommonHeader(Unit, UnitDIE, DwarfVersion);267    Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature));268    Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0);269  }270 271  void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) {272    if (Unit.isTypeUnit())273      emitTypeUnitHeader(Unit, UnitDIE, Unit.getVersion());274    else275      emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion());276  }277 278  void emitDIE(DIE &Die) override {279    AsmPrinter &Asm = getAsmPrinter();280    Asm.emitDwarfDIE(Die);281  }282 283public:284  DIEStreamer(DIEBuilder *DIEBldr, GDBIndex &GDBIndexSection,285              DWARFLinkerBase::OutputFileType OutFileType,286              raw_pwrite_stream &OutFile,287              DWARFLinkerBase::MessageHandlerTy Warning)288      : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr),289        GDBIndexSection(GDBIndexSection) {};290 291  using DwarfStreamer::emitCompileUnitHeader;292 293  void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {294    emitUnitHeader(Unit, UnitDIE);295    emitDIE(UnitDIE);296  }297};298 299/// Finds attributes FormValue and Offset.300///301/// \param DIE die to look up in.302/// \param Attrs finds the first attribute that matches and extracts it.303/// \return an optional AttrInfo with DWARFFormValue and Offset.304std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,305                                          std::vector<dwarf::Attribute> Attrs) {306  for (dwarf::Attribute &Attr : Attrs)307    if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr))308      return Info;309  return std::nullopt;310}311 312} // namespace bolt313} // namespace llvm314 315using namespace llvm;316using namespace llvm::support::endian;317using namespace object;318using namespace bolt;319 320namespace opts {321 322extern cl::OptionCategory BoltCategory;323extern cl::opt<unsigned> Verbosity;324extern cl::opt<std::string> OutputFilename;325 326static cl::opt<bool> KeepARanges(327    "keep-aranges",328    cl::desc(329        "keep or generate .debug_aranges section if .gdb_index is written"),330    cl::Hidden, cl::cat(BoltCategory));331 332static cl::opt<unsigned>333    DebugThreadCount("debug-thread-count",334                     cl::desc("specifies thread count for the multithreading "335                              "for updating DWO debug info"),336                     cl::init(1), cl::cat(BoltCategory));337 338static cl::opt<std::string> DwarfOutputPath(339    "dwarf-output-path",340    cl::desc("Path to where .dwo files will be written out to."), cl::init(""),341    cl::cat(BoltCategory));342 343static cl::opt<bool> CreateDebugNames(344    "create-debug-names-section",345    cl::desc("Creates .debug_names section, if the input binary doesn't have "346             "it already, for DWARF5 CU/TUs."),347    cl::init(false), cl::cat(BoltCategory));348 349static cl::opt<bool>350    DebugSkeletonCu("debug-skeleton-cu",351                    cl::desc("prints out offsets for abbrev and debug_info of "352                             "Skeleton CUs that get patched."),353                    cl::ZeroOrMore, cl::Hidden, cl::init(false),354                    cl::cat(BoltCategory));355 356static cl::opt<unsigned> BatchSize(357    "cu-processing-batch-size",358    cl::desc(359        "Specifies the size of batches for processing CUs. Higher number has "360        "better performance, but more memory usage. Default value is 1."),361    cl::Hidden, cl::init(1), cl::cat(BoltCategory));362 363static cl::opt<bool> AlwaysConvertToRanges(364    "always-convert-to-ranges",365    cl::desc("This option is for testing purposes only. It forces BOLT to "366             "convert low_pc/high_pc to ranges always."),367    cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory));368 369extern cl::opt<std::string> CompDirOverride;370} // namespace opts371 372/// If DW_AT_low_pc exists sets LowPC and returns true.373static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,374                     uint64_t &SectionIndex) {375  DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc);376  if (!DvalLowPc)377    return false;378 379  dwarf::Form Form = DvalLowPc.getForm();380  bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;381  uint64_t LowPcValue = DvalLowPc.getDIEInteger().getValue();382  if (Form == dwarf::DW_FORM_GNU_addr_index || Form == dwarf::DW_FORM_addrx ||383      AddrOffset) {384 385    uint32_t Index = AddrOffset ? (LowPcValue >> 32) : LowPcValue;386    std::optional<object::SectionedAddress> SA =387        DU.getAddrOffsetSectionItem(Index);388    if (!SA)389      return false;390    if (AddrOffset)391      SA->Address += (LowPcValue & 0xffffffff);392 393    LowPC = SA->Address;394    SectionIndex = SA->SectionIndex;395  } else {396    LowPC = LowPcValue;397    SectionIndex = 0;398  }399  return true;400}401 402/// If DW_AT_high_pc exists sets HighPC and returns true.403static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {404  DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);405  if (!DvalHighPc)406    return false;407  if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)408    HighPC = DvalHighPc.getDIEInteger().getValue();409  else410    HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();411  return true;412}413 414/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns415/// true.416static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,417                            uint64_t &LowPC, uint64_t &HighPC,418                            uint64_t &SectionIndex) {419  uint64_t TempLowPC = LowPC;420  uint64_t TempHighPC = HighPC;421  uint64_t TempSectionIndex = SectionIndex;422  if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) &&423      getHighPC(Die, TempLowPC, TempHighPC)) {424    LowPC = TempLowPC;425    HighPC = TempHighPC;426    SectionIndex = TempSectionIndex;427    return true;428  }429  return false;430}431 432static Expected<llvm::DWARFAddressRangesVector>433getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {434  uint64_t LowPC, HighPC, Index;435  if (getLowAndHighPC(Die, DU, LowPC, HighPC, Index))436    return DWARFAddressRangesVector{{LowPC, HighPC, Index}};437  if (DIEValue Dval = Die.findAttribute(dwarf::DW_AT_ranges)) {438    if (Dval.getForm() == dwarf::DW_FORM_rnglistx)439      return DU.findRnglistFromIndex(Dval.getDIEInteger().getValue());440 441    return DU.findRnglistFromOffset(Dval.getDIEInteger().getValue());442  }443 444  return DWARFAddressRangesVector();445}446 447static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,448                                            const DIEValue &AttrVal) {449  DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue());450  if (std::optional<object::SectionedAddress> SA =451          DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU))452    return SA->Address;453  return std::nullopt;454}455 456static std::unique_ptr<DIEStreamer>457createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,458                  StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,459                  GDBIndex &GDBIndexSection) {460 461  std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(462      &DIEBldr, GDBIndexSection, DWARFLinkerBase::OutputFileType::Object,463      OutFile,464      [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});465  Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);466  if (Err)467    errs()468        << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"469        << toString(std::move(Err)) << "\n";470  return Streamer;471}472 473static void emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer,474                     DWARFUnit &Unit) {475  DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit);476  Streamer.emitUnit(Unit, *UnitDIE);477}478 479static void emitDWOBuilder(const std::string &DWOName,480                           DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,481                           DWARFUnit &SplitCU, DWARFUnit &CU,482                           DebugLocWriter &LocWriter,483                           DebugStrOffsetsWriter &StrOffstsWriter,484                           DebugStrWriter &StrWriter, GDBIndex &GDBIndexSection,485                           DebugRangesSectionWriter &TempRangesSectionWriter) {486  // Populate debug_info and debug_abbrev for current dwo into StringRef.487  DWODIEBuilder.generateAbbrevs();488  DWODIEBuilder.finish();489 490  SmallVector<char, 20> OutBuffer;491  std::shared_ptr<raw_svector_ostream> ObjOS =492      std::make_shared<raw_svector_ostream>(OutBuffer);493  const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile();494  auto TheTriple = std::make_unique<Triple>(File->makeTriple());495  std::unique_ptr<DIEStreamer> Streamer =496      createDIEStreamer(*TheTriple, *ObjOS, "DwoStreamerInitAug2",497                        DWODIEBuilder, GDBIndexSection);498  if (SplitCU.getContext().getMaxDWOVersion() >= 5) {499    for (std::unique_ptr<llvm::DWARFUnit> &CU :500         SplitCU.getContext().dwo_info_section_units()) {501      if (!CU->isTypeUnit())502        continue;503      emitUnit(DWODIEBuilder, *Streamer, *CU);504    }505    emitUnit(DWODIEBuilder, *Streamer, SplitCU);506  } else {507    emitUnit(DWODIEBuilder, *Streamer, SplitCU);508 509    // emit debug_types sections for dwarf4510    for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector())511      emitUnit(DWODIEBuilder, *Streamer, *CU);512  }513 514  Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(),515                        SplitCU.getContext().getMaxVersion());516  Streamer->finish();517 518  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =519      MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);520  std::unique_ptr<object::ObjectFile> Obj = cantFail(521      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),522      "error creating in-memory object");523 524  DWARFRewriter::OverriddenSectionsMap OverriddenSections;525  for (const SectionRef &Secs : Obj->sections()) {526    StringRef Contents = cantFail(Secs.getContents());527    StringRef Name = cantFail(Secs.getName());528    DWARFSectionKind Kind =529        StringSwitch<DWARFSectionKind>(Name)530            .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV)531            .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO)532            .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES)533            .Default(DWARFSectionKind::DW_SECT_EXT_unknown);534    if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown)535      continue;536    OverriddenSections[Kind] = Contents;537  }538  Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter,539                         StrOffstsWriter, StrWriter, TempRangesSectionWriter);540}541 542using DWARFUnitVec = std::vector<DWARFUnit *>;543using CUPartitionVector = std::vector<DWARFUnitVec>;544/// Partitions CUs in to buckets. Bucket size is controlled by545/// cu-processing-batch-size. All the CUs that have cross CU reference reference546/// as a source are put in to the same initial bucket.547static CUPartitionVector partitionCUs(DWARFContext &DwCtx) {548  CUPartitionVector Vec(2);549  unsigned Counter = 0;550  const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev();551  for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) {552    Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet =553        Abbr->getAbbreviationDeclarationSet(CU->getAbbreviationsOffset());554    if (!AbbrDeclSet) {555      consumeError(AbbrDeclSet.takeError());556      return Vec;557    }558    bool CrossCURefFound = false;559    for (const DWARFAbbreviationDeclaration &Decl : *AbbrDeclSet.get()) {560      for (const DWARFAbbreviationDeclaration::AttributeSpec &Attr :561           Decl.attributes()) {562        if (Attr.Form == dwarf::DW_FORM_ref_addr) {563          CrossCURefFound = true;564          break;565        }566      }567      if (CrossCURefFound)568        break;569    }570    if (CrossCURefFound) {571      Vec[0].push_back(CU.get());572    } else {573      ++Counter;574      Vec.back().push_back(CU.get());575    }576    if (Counter % opts::BatchSize == 0 && !Vec.back().empty())577      Vec.push_back({});578  }579  return Vec;580}581 582void DWARFRewriter::updateDebugInfo() {583  ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");584  if (!DebugInfo)585    return;586 587  ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();588  StrWriter = std::make_unique<DebugStrWriter>(*BC.DwCtx, false);589  StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>(BC);590 591  /// Stores and serializes information that will be put into the592  /// .debug_addr DWARF section.593  std::unique_ptr<DebugAddrWriter> FinalAddrWriter;594 595  if (BC.isDWARF5Used()) {596    FinalAddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC);597    RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>();598  } else {599    FinalAddrWriter = std::make_unique<DebugAddrWriter>(&BC);600  }601 602  if (BC.isDWARFLegacyUsed()) {603    LegacyRangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();604    LegacyRangesSectionWriter->initSection();605  }606 607  uint32_t CUIndex = 0;608  std::mutex AccessMutex;609  // Needs to be invoked in the same order as CUs are processed.610  llvm::DenseMap<uint64_t, uint64_t> LocListWritersIndexByCU;611  auto createRangeLocListAddressWriters = [&](DWARFUnit &CU) {612    std::lock_guard<std::mutex> Lock(AccessMutex);613    const uint16_t DwarfVersion = CU.getVersion();614    if (DwarfVersion >= 5) {615      auto AddrW = std::make_unique<DebugAddrWriterDwarf5>(616          &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase());617      RangeListsSectionWriter->setAddressWriter(AddrW.get());618      LocListWritersByCU[CUIndex] =619          std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false, *AddrW);620 621      if (std::optional<uint64_t> DWOId = CU.getDWOId()) {622        assert(RangeListsWritersByCU.count(*DWOId) == 0 &&623               "RangeLists writer for DWO unit already exists.");624        auto DWORangeListsSectionWriter =625            std::make_unique<DebugRangeListsSectionWriter>();626        DWORangeListsSectionWriter->initSection(CU);627        DWORangeListsSectionWriter->setAddressWriter(AddrW.get());628        RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter);629      }630      AddressWritersByCU[CU.getOffset()] = std::move(AddrW);631    } else {632      auto AddrW =633          std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize());634      AddressWritersByCU[CU.getOffset()] = std::move(AddrW);635      LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();636      if (std::optional<uint64_t> DWOId = CU.getDWOId()) {637        assert(LegacyRangesWritersByCU.count(*DWOId) == 0 &&638               "LegacyRangeLists writer for DWO unit already exists.");639        auto LegacyRangesSectionWriterByCU =640            std::make_unique<DebugRangesSectionWriter>();641        LegacyRangesSectionWriterByCU->initSection(CU);642        LegacyRangesWritersByCU[*DWOId] =643            std::move(LegacyRangesSectionWriterByCU);644      }645    }646    LocListWritersIndexByCU[CU.getOffset()] = CUIndex++;647  };648 649  DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,650                                         *StrWriter);651  GDBIndex GDBIndexSection(BC);652  auto processSplitCU = [&](DWARFUnit &Unit, DWARFUnit &SplitCU,653                            DebugRangesSectionWriter &TempRangesSectionWriter,654                            DebugAddrWriter &AddressWriter,655                            const std::string &DWOName,656                            const std::optional<std::string> &DwarfOutputPath,657                            DIEBuilder &DWODIEBuilder) {658    DWODIEBuilder.buildDWOUnit(SplitCU);659    DebugStrOffsetsWriter DWOStrOffstsWriter(BC);660    DebugStrWriter DWOStrWriter((SplitCU).getContext(), true);661    DWODIEBuilder.updateDWONameCompDirForTypes(662        DWOStrOffstsWriter, DWOStrWriter, SplitCU, DwarfOutputPath, DWOName);663    DebugLoclistWriter DebugLocDWoWriter(Unit, Unit.getVersion(), true,664                                         AddressWriter);665 666    updateUnitDebugInfo(SplitCU, DWODIEBuilder, DebugLocDWoWriter,667                        TempRangesSectionWriter, AddressWriter);668    DebugLocDWoWriter.finalize(DWODIEBuilder,669                               *DWODIEBuilder.getUnitDIEbyUnit(SplitCU));670    if (Unit.getVersion() >= 5)671      TempRangesSectionWriter.finalizeSection();672 673    emitDWOBuilder(DWOName, DWODIEBuilder, *this, SplitCU, Unit,674                   DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter,675                   GDBIndexSection, TempRangesSectionWriter);676  };677  auto processMainBinaryCU = [&](DWARFUnit &Unit, DIEBuilder &DIEBlder) {678    std::optional<DWARFUnit *> SplitCU;679    std::optional<uint64_t> RangesBase;680    std::optional<uint64_t> DWOId = Unit.getDWOId();681    if (DWOId)682      SplitCU = BC.getDWOCU(*DWOId);683    DebugLocWriter &DebugLocWriter =684        *LocListWritersByCU[LocListWritersIndexByCU[Unit.getOffset()]].get();685    DebugRangesSectionWriter &RangesSectionWriter =686        Unit.getVersion() >= 5 ? *RangeListsSectionWriter687                               : *LegacyRangesSectionWriter;688    DebugAddrWriter &AddressWriter =689        *AddressWritersByCU[Unit.getOffset()].get();690    if (Unit.getVersion() >= 5)691      RangeListsSectionWriter->setAddressWriter(&AddressWriter);692    if (Unit.getVersion() >= 5) {693      RangesBase = RangesSectionWriter.getSectionOffset() +694                   getDWARF5RngListLocListHeaderSize();695      RangesSectionWriter.initSection(Unit);696      if (!SplitCU)697        StrOffstsWriter->finalizeSection(Unit, DIEBlder);698    } else if (SplitCU) {699      RangesBase = LegacyRangesSectionWriter->getSectionOffset();700    }701 702    updateUnitDebugInfo(Unit, DIEBlder, DebugLocWriter, RangesSectionWriter,703                        AddressWriter, RangesBase);704    DebugLocWriter.finalize(DIEBlder, *DIEBlder.getUnitDIEbyUnit(Unit));705    if (Unit.getVersion() >= 5)706      RangesSectionWriter.finalizeSection();707  };708 709  DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);710  DIEBlder.buildTypeUnits(StrOffstsWriter.get());711  SmallVector<char, 20> OutBuffer;712  std::unique_ptr<raw_svector_ostream> ObjOS =713      std::make_unique<raw_svector_ostream>(OutBuffer);714  const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();715  auto TheTriple = std::make_unique<Triple>(File->makeTriple());716  std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer(717      *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection);718  CUOffsetMap OffsetMap =719      finalizeTypeSections(DIEBlder, *Streamer, GDBIndexSection);720 721  CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);722  const unsigned int ThreadCount =723      std::min(opts::DebugThreadCount, opts::ThreadCount);724  for (std::vector<DWARFUnit *> &Vec : PartVec) {725    DIEBlder.buildCompileUnits(Vec);726    llvm::SmallVector<std::unique_ptr<DIEBuilder>, 72> DWODIEBuildersByCU;727    ThreadPoolInterface &ThreadPool =728        ParallelUtilities::getThreadPool(ThreadCount);729    for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) {730      createRangeLocListAddressWriters(*CU);731      std::optional<DWARFUnit *> SplitCU;732      std::optional<uint64_t> DWOId = CU->getDWOId();733      if (DWOId)734        SplitCU = BC.getDWOCU(*DWOId);735      if (!SplitCU)736        continue;737      DebugAddrWriter &AddressWriter =738          *AddressWritersByCU[CU->getOffset()].get();739      DebugRangesSectionWriter &TempRangesSectionWriter =740          CU->getVersion() >= 5 ? *RangeListsWritersByCU[*DWOId].get()741                                : *LegacyRangesWritersByCU[*DWOId].get();742      std::optional<std::string> DwarfOutputPath =743          opts::DwarfOutputPath.empty()744              ? std::nullopt745              : std::optional<std::string>(opts::DwarfOutputPath.c_str());746      std::string DWOName = DIEBlder.updateDWONameCompDir(747          *StrOffstsWriter, *StrWriter, *CU, DwarfOutputPath, std::nullopt);748      auto DWODIEBuilderPtr = std::make_unique<DIEBuilder>(749          BC, &(**SplitCU).getContext(), DebugNamesTable, CU);750      DIEBuilder &DWODIEBuilder =751          *DWODIEBuildersByCU.emplace_back(std::move(DWODIEBuilderPtr));752      if (CU->getVersion() >= 5)753        StrOffstsWriter->finalizeSection(*CU, DIEBlder);754      // Important to capture CU and SplitCU by value here, otherwise when the755      // thread is executed at some point after the current iteration of the756      // loop, dereferencing CU/SplitCU in the call to processSplitCU means it757      // will dereference a different variable than the one intended, causing a758      // seg fault.759      ThreadPool.async([&, DwarfOutputPath, DWOName, CU, SplitCU] {760        processSplitCU(*CU, **SplitCU, TempRangesSectionWriter, AddressWriter,761                       DWOName, DwarfOutputPath, DWODIEBuilder);762      });763    }764    ThreadPool.wait();765    for (std::unique_ptr<DIEBuilder> &DWODIEBuilderPtr : DWODIEBuildersByCU)766      DWODIEBuilderPtr->updateDebugNamesTable();767    for (DWARFUnit *CU : DIEBlder.getProcessedCUs())768      processMainBinaryCU(*CU, DIEBlder);769    finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,770                         DIEBlder.getProcessedCUs(), *FinalAddrWriter);771  }772 773  DebugNamesTable.emitAccelTable();774 775  finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS, OffsetMap,776                        *FinalAddrWriter);777  GDBIndexSection.updateGdbIndexSection(OffsetMap, CUIndex,778                                        *ARangesSectionWriter);779}780 781void DWARFRewriter::updateUnitDebugInfo(782    DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,783    DebugRangesSectionWriter &RangesSectionWriter,784    DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase) {785  // Cache debug ranges so that the offset for identical ranges could be reused.786  std::map<DebugAddressRangesVector, uint64_t> CachedRanges;787 788  uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize();789  uint64_t NextCUOffset = Unit.getNextUnitOffset();790  const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs =791      DIEBldr.getDIEsByUnit(Unit);792 793  // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.794  auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal,795                               const DIEValue &HighPCVal, uint64_t LowPC,796                               const uint64_t HighPC) {797    dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc;798    dwarf::Form FormLowPC = dwarf::DW_FORM_addr;799    dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc;800    dwarf::Form FormHighPC = dwarf::DW_FORM_data4;801    const uint32_t Size = HighPC - LowPC;802    // Whatever was generated is not low_pc/high_pc, so will reset to803    // default for size 1.804    if (!LowPCVal || !HighPCVal) {805      if (Unit.getVersion() >= 5)806        FormLowPC = dwarf::DW_FORM_addrx;807      else if (Unit.isDWOUnit())808        FormLowPC = dwarf::DW_FORM_GNU_addr_index;809    } else {810      AttrLowPC = LowPCVal.getAttribute();811      FormLowPC = LowPCVal.getForm();812      AttrHighPC = HighPCVal.getAttribute();813      FormHighPC = HighPCVal.getForm();814    }815 816    if (FormLowPC == dwarf::DW_FORM_addrx ||817        FormLowPC == dwarf::DW_FORM_GNU_addr_index)818      LowPC = AddressWriter.getIndexFromAddress(LowPC, Unit);819 820    if (LowPCVal)821      DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));822    else823      DIEBldr.addValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));824    if (HighPCVal) {825      DIEBldr.replaceValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));826    } else {827      DIEBldr.deleteValue(Die, dwarf::DW_AT_ranges);828      DIEBldr.addValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));829    }830  };831 832  for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) {833    DIE *Die = DI->Die;834    switch (Die->getTag()) {835    case dwarf::DW_TAG_compile_unit:836    case dwarf::DW_TAG_skeleton_unit: {837      // For dwarf5 section 3.1.3838      // The following attributes are not part of a split full compilation unit839      // entry but instead are inherited (if present) from the corresponding840      // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges,841      // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base,842      // DW_AT_addr_base and DW_AT_rnglists_base.843      if (Unit.getVersion() == 5 && Unit.isDWOUnit())844        continue;845      auto ModuleRangesOrError = getDIEAddressRanges(*Die, Unit);846      if (!ModuleRangesOrError) {847        consumeError(ModuleRangesOrError.takeError());848        break;849      }850      DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError;851      DebugAddressRangesVector OutputRanges =852          BC.translateModuleAddressRanges(ModuleRanges);853      DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);854      // For a case where LLD GCs only function used in the CU.855      // If CU doesn't have DW_AT_low_pc we are not going to convert,856      // so don't need to do anything.857      if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo)858        OutputRanges.push_back({0, 0});859      const uint64_t RangesSectionOffset =860          RangesSectionWriter.addRanges(OutputRanges);861      // Don't emit the zero low_pc arange.862      if (!Unit.isDWOUnit() && !OutputRanges.empty() &&863          OutputRanges.back().LowPC)864        ARangesSectionWriter->addCURanges(Unit.getOffset(),865                                          std::move(OutputRanges));866      updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset,867                                     RangesBase);868      DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list);869      if (LineTablePatchMap.count(&Unit))870        DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list,871                             StmtListAttrVal.getForm(),872                             DIEInteger(LineTablePatchMap[&Unit]));873      break;874    }875 876    case dwarf::DW_TAG_subprogram: {877      // Get function address either from ranges or [LowPC, HighPC) pair.878      uint64_t Address = UINT64_MAX;879      uint64_t SectionIndex, HighPC;880      DebugAddressRangesVector FunctionRanges;881      if (!getLowAndHighPC(*Die, Unit, Address, HighPC, SectionIndex)) {882        Expected<DWARFAddressRangesVector> RangesOrError =883            getDIEAddressRanges(*Die, Unit);884        if (!RangesOrError) {885          consumeError(RangesOrError.takeError());886          break;887        }888        DWARFAddressRangesVector Ranges = *RangesOrError;889        // Not a function definition.890        if (Ranges.empty())891          break;892 893        for (const DWARFAddressRange &Range : Ranges) {894          if (const BinaryFunction *Function =895                  BC.getBinaryFunctionAtAddress(Range.LowPC))896            FunctionRanges.append(Function->getOutputAddressRanges());897        }898      } else {899        if (const BinaryFunction *Function =900                BC.getBinaryFunctionAtAddress(Address))901          FunctionRanges = Function->getOutputAddressRanges();902      }903 904      // Clear cached ranges as the new function will have its own set.905      CachedRanges.clear();906      DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);907      DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);908      if (FunctionRanges.empty()) {909        if (LowPCVal && HighPCVal)910          FunctionRanges.push_back({0, HighPCVal.getDIEInteger().getValue()});911        else912          FunctionRanges.push_back({0, 1});913      }914 915      if (FunctionRanges.size() == 1 && !opts::AlwaysConvertToRanges) {916        updateLowPCHighPC(Die, LowPCVal, HighPCVal, FunctionRanges.back().LowPC,917                          FunctionRanges.back().HighPC);918        break;919      }920 921      updateDWARFObjectAddressRanges(922          Unit, DIEBldr, *Die, RangesSectionWriter.addRanges(FunctionRanges));923 924      break;925    }926    case dwarf::DW_TAG_lexical_block:927    case dwarf::DW_TAG_inlined_subroutine:928    case dwarf::DW_TAG_try_block:929    case dwarf::DW_TAG_catch_block: {930      uint64_t RangesSectionOffset = 0;931      Expected<DWARFAddressRangesVector> RangesOrError =932          getDIEAddressRanges(*Die, Unit);933      const BinaryFunction *Function =934          RangesOrError && !RangesOrError->empty()935              ? BC.getBinaryFunctionContainingAddress(936                    RangesOrError->front().LowPC)937              : nullptr;938      DebugAddressRangesVector OutputRanges;939      if (Function) {940        OutputRanges = translateInputToOutputRanges(*Function, *RangesOrError);941        LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) {942          dbgs() << "BOLT-DEBUG: problem with DIE at 0x"943                 << Twine::utohexstr(Die->getOffset()) << " in CU at 0x"944                 << Twine::utohexstr(Unit.getOffset()) << '\n';945        });946        if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) {947          RangesSectionOffset = RangesSectionWriter.addRanges(948              std::move(OutputRanges), CachedRanges);949          OutputRanges.clear();950        } else if (OutputRanges.empty()) {951          OutputRanges.push_back({0, RangesOrError.get().front().HighPC});952        }953      } else if (!RangesOrError) {954        consumeError(RangesOrError.takeError());955      } else {956        OutputRanges.push_back({0, !RangesOrError->empty()957                                       ? RangesOrError.get().front().HighPC958                                       : 0});959      }960      DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);961      DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);962      if (OutputRanges.size() == 1) {963        updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC,964                          OutputRanges.back().HighPC);965        break;966      }967      updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset);968      break;969    }970    case dwarf::DW_TAG_call_site: {971      auto patchPC = [&](DIE *Die, DIEValue &AttrVal, StringRef Entry) -> void {972        std::optional<uint64_t> Address = getAsAddress(Unit, AttrVal);973        const BinaryFunction *Function =974            BC.getBinaryFunctionContainingAddress(*Address);975        uint64_t UpdatedAddress = *Address;976        if (Function)977          UpdatedAddress =978              Function->translateInputToOutputAddress(UpdatedAddress);979 980        if (AttrVal.getForm() == dwarf::DW_FORM_addrx) {981          const uint32_t Index =982              AddressWriter.getIndexFromAddress(UpdatedAddress, Unit);983          DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),984                               DIEInteger(Index));985        } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) {986          DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),987                               DIEInteger(UpdatedAddress));988        } else {989          errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n";990        }991      };992      DIEValue CallPcAttrVal = Die->findAttribute(dwarf::DW_AT_call_pc);993      if (CallPcAttrVal)994        patchPC(Die, CallPcAttrVal, "DW_AT_call_pc");995 996      DIEValue CallRetPcAttrVal =997          Die->findAttribute(dwarf::DW_AT_call_return_pc);998      if (CallRetPcAttrVal)999        patchPC(Die, CallRetPcAttrVal, "DW_AT_call_return_pc");1000 1001      break;1002    }1003    default: {1004      // Handle any tag that can have DW_AT_location attribute.1005      DIEValue LocAttrInfo = Die->findAttribute(dwarf::DW_AT_location);1006      DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);1007      if (LocAttrInfo) {1008        if (doesFormBelongToClass(LocAttrInfo.getForm(),1009                                  DWARFFormValue::FC_Constant,1010                                  Unit.getVersion()) ||1011            doesFormBelongToClass(LocAttrInfo.getForm(),1012                                  DWARFFormValue::FC_SectionOffset,1013                                  Unit.getVersion())) {1014          uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx1015                                ? LocAttrInfo.getDIELocList().getValue()1016                                : LocAttrInfo.getDIEInteger().getValue();1017          DebugLocationsVector InputLL;1018 1019          std::optional<object::SectionedAddress> SectionAddress =1020              Unit.getBaseAddress();1021          uint64_t BaseAddress = 0;1022          if (SectionAddress)1023            BaseAddress = SectionAddress->Address;1024 1025          if (Unit.getVersion() >= 5 &&1026              LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx) {1027            std::optional<uint64_t> LocOffset = Unit.getLoclistOffset(Offset);1028            assert(LocOffset && "Location Offset is invalid.");1029            Offset = *LocOffset;1030          }1031 1032          Error E = Unit.getLocationTable().visitLocationList(1033              &Offset, [&](const DWARFLocationEntry &Entry) {1034                switch (Entry.Kind) {1035                default:1036                  llvm_unreachable("Unsupported DWARFLocationEntry Kind.");1037                case dwarf::DW_LLE_end_of_list:1038                  return false;1039                case dwarf::DW_LLE_base_address: {1040                  assert(Entry.SectionIndex == SectionedAddress::UndefSection &&1041                         "absolute address expected");1042                  BaseAddress = Entry.Value0;1043                  break;1044                }1045                case dwarf::DW_LLE_offset_pair:1046                  assert(1047                      (Entry.SectionIndex == SectionedAddress::UndefSection &&1048                       (!Unit.isDWOUnit() || Unit.getVersion() == 5)) &&1049                      "absolute address expected");1050                  InputLL.emplace_back(DebugLocationEntry{1051                      BaseAddress + Entry.Value0, BaseAddress + Entry.Value1,1052                      Entry.Loc});1053                  break;1054                case dwarf::DW_LLE_start_length:1055                  InputLL.emplace_back(DebugLocationEntry{1056                      Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc});1057                  break;1058                case dwarf::DW_LLE_base_addressx: {1059                  std::optional<object::SectionedAddress> EntryAddress =1060                      Unit.getAddrOffsetSectionItem(Entry.Value0);1061                  assert(EntryAddress && "base Address not found.");1062                  BaseAddress = EntryAddress->Address;1063                  break;1064                }1065                case dwarf::DW_LLE_startx_length: {1066                  std::optional<object::SectionedAddress> EntryAddress =1067                      Unit.getAddrOffsetSectionItem(Entry.Value0);1068                  assert(EntryAddress && "Address does not exist.");1069                  InputLL.emplace_back(DebugLocationEntry{1070                      EntryAddress->Address,1071                      EntryAddress->Address + Entry.Value1, Entry.Loc});1072                  break;1073                }1074                case dwarf::DW_LLE_startx_endx: {1075                  std::optional<object::SectionedAddress> StartAddress =1076                      Unit.getAddrOffsetSectionItem(Entry.Value0);1077                  assert(StartAddress && "Start Address does not exist.");1078                  std::optional<object::SectionedAddress> EndAddress =1079                      Unit.getAddrOffsetSectionItem(Entry.Value1);1080                  assert(EndAddress && "Start Address does not exist.");1081                  InputLL.emplace_back(DebugLocationEntry{1082                      StartAddress->Address, EndAddress->Address, Entry.Loc});1083                  break;1084                }1085                }1086                return true;1087              });1088 1089          if (E || InputLL.empty()) {1090            consumeError(std::move(E));1091            errs() << "BOLT-WARNING: empty location list detected at 0x"1092                   << Twine::utohexstr(Offset) << " for DIE at 0x" << Die1093                   << " in CU at 0x" << Twine::utohexstr(Unit.getOffset())1094                   << '\n';1095          } else {1096            const uint64_t Address = InputLL.front().LowPC;1097            DebugLocationsVector OutputLL;1098            if (const BinaryFunction *Function =1099                    BC.getBinaryFunctionContainingAddress(Address)) {1100              OutputLL = translateInputToOutputLocationList(*Function, InputLL);1101              LLVM_DEBUG(if (OutputLL.empty()) {1102                dbgs() << "BOLT-DEBUG: location list translated to an empty "1103                          "one at 0x"1104                       << Die << " in CU at 0x"1105                       << Twine::utohexstr(Unit.getOffset()) << '\n';1106              });1107            } else {1108              // It's possible for a subprogram to be removed and to have1109              // address of 0. Adding this entry to output to preserve debug1110              // information.1111              OutputLL = InputLL;1112            }1113            DebugLocWriter.addList(DIEBldr, *Die, LocAttrInfo, OutputLL);1114          }1115        } else {1116          assert((doesFormBelongToClass(LocAttrInfo.getForm(),1117                                        DWARFFormValue::FC_Exprloc,1118                                        Unit.getVersion()) ||1119                  doesFormBelongToClass(LocAttrInfo.getForm(),1120                                        DWARFFormValue::FC_Block,1121                                        Unit.getVersion())) &&1122                 "unexpected DW_AT_location form");1123          if (Unit.isDWOUnit() || Unit.getVersion() >= 5) {1124            std::vector<uint8_t> Sblock;1125            DIEValueList *AttrLocValList;1126            if (doesFormBelongToClass(LocAttrInfo.getForm(),1127                                      DWARFFormValue::FC_Exprloc,1128                                      Unit.getVersion())) {1129              for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) {1130                Sblock.push_back(Val.getDIEInteger().getValue());1131              }1132              DIELoc *LocAttr = const_cast<DIELoc *>(&LocAttrInfo.getDIELoc());1133              AttrLocValList = static_cast<DIEValueList *>(LocAttr);1134            } else {1135              for (const DIEValue &Val : LocAttrInfo.getDIEBlock().values()) {1136                Sblock.push_back(Val.getDIEInteger().getValue());1137              }1138              DIEBlock *BlockAttr =1139                  const_cast<DIEBlock *>(&LocAttrInfo.getDIEBlock());1140              AttrLocValList = static_cast<DIEValueList *>(BlockAttr);1141            }1142            ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock);1143            DataExtractor Data(1144                StringRef((const char *)Expr.data(), Expr.size()),1145                Unit.getContext().isLittleEndian(), 0);1146            DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),1147                                    Unit.getFormParams().Format);1148            uint32_t PrevOffset = 0;1149            DIEValueList *NewAttr;1150            DIEValue Value;1151            uint32_t NewExprSize = 0;1152            DIELoc *Loc = nullptr;1153            DIEBlock *Block = nullptr;1154            if (LocAttrInfo.getForm() == dwarf::DW_FORM_exprloc) {1155              Loc = DIEBldr.allocateDIEValue<DIELoc>();1156              NewAttr = Loc;1157              Value = DIEValue(LocAttrInfo.getAttribute(),1158                               LocAttrInfo.getForm(), Loc);1159            } else if (doesFormBelongToClass(LocAttrInfo.getForm(),1160                                             DWARFFormValue::FC_Block,1161                                             Unit.getVersion())) {1162              Block = DIEBldr.allocateDIEValue<DIEBlock>();1163              NewAttr = Block;1164              Value = DIEValue(LocAttrInfo.getAttribute(),1165                               LocAttrInfo.getForm(), Block);1166            } else {1167              errs() << "BOLT-WARNING: Unexpected Form value in Updating "1168                        "DW_AT_Location\n";1169              continue;1170            }1171 1172            for (const DWARFExpression::Operation &Expr : LocExpr) {1173              uint32_t CurEndOffset = PrevOffset + 1;1174              if (Expr.getDescription().Op.size() == 1)1175                CurEndOffset = Expr.getOperandEndOffset(0);1176              if (Expr.getDescription().Op.size() == 2)1177                CurEndOffset = Expr.getOperandEndOffset(1);1178              if (Expr.getDescription().Op.size() > 2)1179                errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported "1180                          "number of operands.\n";1181              // not addr index, just copy.1182              if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||1183                    Expr.getCode() == dwarf::DW_OP_addrx)) {1184                auto Itr = AttrLocValList->values().begin();1185                std::advance(Itr, PrevOffset);1186                uint32_t CopyNum = CurEndOffset - PrevOffset;1187                NewExprSize += CopyNum;1188                while (CopyNum--) {1189                  DIEBldr.addValue(NewAttr, *Itr);1190                  std::advance(Itr, 1);1191                }1192              } else {1193                const uint64_t Index = Expr.getRawOperand(0);1194                std::optional<object::SectionedAddress> EntryAddress =1195                    Unit.getAddrOffsetSectionItem(Index);1196                assert(EntryAddress && "Address is not found.");1197                assert(Index <= std::numeric_limits<uint32_t>::max() &&1198                       "Invalid Operand Index.");1199                const uint32_t AddrIndex = AddressWriter.getIndexFromAddress(1200                    EntryAddress->Address, Unit);1201                // update Index into .debug_address section for DW_AT_location.1202                // The Size field is not stored in IR, we need to minus 1 in1203                // offset for each expr.1204                SmallString<8> Tmp;1205                raw_svector_ostream OSE(Tmp);1206                encodeULEB128(AddrIndex, OSE);1207 1208                DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),1209                                 dwarf::DW_FORM_data1,1210                                 DIEInteger(Expr.getCode()));1211                NewExprSize += 1;1212                for (uint8_t Byte : Tmp) {1213                  DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),1214                                   dwarf::DW_FORM_data1, DIEInteger(Byte));1215                  NewExprSize += 1;1216                }1217              }1218              PrevOffset = CurEndOffset;1219            }1220 1221            // update the size since the index might be changed1222            if (Loc)1223              Loc->setSize(NewExprSize);1224            else1225              Block->setSize(NewExprSize);1226            DIEBldr.replaceValue(Die, LocAttrInfo.getAttribute(),1227                                 LocAttrInfo.getForm(), Value);1228          }1229        }1230      } else if (LowPCAttrInfo) {1231        uint64_t Address = 0;1232        uint64_t SectionIndex = 0;1233        if (getLowPC(*Die, Unit, Address, SectionIndex)) {1234          uint64_t NewAddress = 0;1235          if (const BinaryFunction *Function =1236                  BC.getBinaryFunctionContainingAddress(Address)) {1237            NewAddress = Function->translateInputToOutputAddress(Address);1238            LLVM_DEBUG(dbgs()1239                       << "BOLT-DEBUG: Fixing low_pc 0x"1240                       << Twine::utohexstr(Address) << " for DIE with tag "1241                       << Die->getTag() << " to 0x"1242                       << Twine::utohexstr(NewAddress) << '\n');1243          }1244 1245          dwarf::Form Form = LowPCAttrInfo.getForm();1246          assert(Form != dwarf::DW_FORM_LLVM_addrx_offset &&1247                 "DW_FORM_LLVM_addrx_offset is not supported");1248          std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);1249          if (Form == dwarf::DW_FORM_addrx ||1250              Form == dwarf::DW_FORM_GNU_addr_index) {1251            const uint32_t Index = AddressWriter.getIndexFromAddress(1252                NewAddress ? NewAddress : Address, Unit);1253            DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),1254                                 LowPCAttrInfo.getForm(), DIEInteger(Index));1255          } else {1256            DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),1257                                 LowPCAttrInfo.getForm(),1258                                 DIEInteger(NewAddress));1259          }1260        } else if (opts::Verbosity >= 1) {1261          errs() << "BOLT-WARNING: unexpected form value for attribute "1262                    "LowPCAttrInfo\n";1263        }1264      }1265    }1266    }1267  }1268  if (DIEOffset > NextCUOffset)1269    errs() << "BOLT-WARNING: corrupt DWARF detected at 0x"1270           << Twine::utohexstr(Unit.getOffset()) << '\n';1271}1272 1273void DWARFRewriter::updateDWARFObjectAddressRanges(1274    DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,1275    std::optional<uint64_t> RangesBase) {1276 1277  if (RangesBase) {1278    // If DW_AT_GNU_ranges_base is present, update it. No further modifications1279    // are needed for ranges base.1280 1281    DIEValue RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_GNU_ranges_base);1282    if (!RangesBaseInfo) {1283      RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_rnglists_base);1284    }1285 1286    if (RangesBaseInfo) {1287      if (RangesBaseInfo.getAttribute() == dwarf::DW_AT_GNU_ranges_base) {1288        auto RangesWriterIterator =1289            LegacyRangesWritersByCU.find(*Unit.getDWOId());1290        assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&1291               "RangesWriter does not exist for DWOId");1292        RangesWriterIterator->second->setDie(&Die);1293      } else {1294        DIEBldr.replaceValue(&Die, RangesBaseInfo.getAttribute(),1295                             RangesBaseInfo.getForm(),1296                             DIEInteger(static_cast<uint32_t>(*RangesBase)));1297      }1298      RangesBase = std::nullopt;1299    }1300  }1301 1302  DIEValue LowPCAttrInfo = Die.findAttribute(dwarf::DW_AT_low_pc);1303  DIEValue RangesAttrInfo = Die.findAttribute(dwarf::DW_AT_ranges);1304  if (RangesAttrInfo) {1305    // Case 1: The object was already non-contiguous and had DW_AT_ranges.1306    // In this case we simply need to update the value of DW_AT_ranges1307    // and introduce DW_AT_GNU_ranges_base if required.1308    // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx1309    bool NeedConverted = false;1310 1311    if (Unit.getVersion() >= 5 &&1312        RangesAttrInfo.getForm() == dwarf::DW_FORM_sec_offset)1313      NeedConverted = true;1314 1315    if (NeedConverted || RangesAttrInfo.getForm() == dwarf::DW_FORM_rnglistx)1316      DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx,1317                           DIEInteger(DebugRangesOffset));1318    else1319      DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, RangesAttrInfo.getForm(),1320                           DIEInteger(DebugRangesOffset));1321 1322    if (!RangesBase) {1323      if (LowPCAttrInfo &&1324          LowPCAttrInfo.getForm() != dwarf::DW_FORM_GNU_addr_index &&1325          LowPCAttrInfo.getForm() != dwarf::DW_FORM_addrx)1326        DIEBldr.replaceValue(&Die, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm(),1327                             DIEInteger(0));1328      return;1329    }1330 1331    if (!(Die.getTag() == dwarf::DW_TAG_compile_unit ||1332          Die.getTag() == dwarf::DW_TAG_skeleton_unit))1333      return;1334 1335    // If we are at this point we are in the CU/Skeleton CU, and1336    // DW_AT_GNU_ranges_base or DW_AT_rnglists_base doesn't exist.1337    if (Unit.getVersion() <= 4) {1338      DIEBldr.addValue(&Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,1339                       DIEInteger(INT_MAX));1340      auto RangesWriterIterator =1341          LegacyRangesWritersByCU.find(*Unit.getDWOId());1342      assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&1343             "RangesWriter does not exist for DWOId");1344      RangesWriterIterator->second->setDie(&Die);1345    } else if (Unit.getVersion() >= 5) {1346      DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,1347                       dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));1348    }1349    return;1350  }1351 1352  // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back1353  // to back. Replace with new attributes and patch the DIE.1354  DIEValue HighPCAttrInfo = Die.findAttribute(dwarf::DW_AT_high_pc);1355  if (LowPCAttrInfo && HighPCAttrInfo) {1356 1357    convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, DebugRangesOffset,1358                                  LowPCAttrInfo, HighPCAttrInfo, RangesBase);1359  } else if (!(Unit.isDWOUnit() &&1360               Die.getTag() == dwarf::DW_TAG_compile_unit)) {1361    if (opts::Verbosity >= 1)1362      errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"1363             << Twine::utohexstr(Unit.getOffset()) << '\n';1364  }1365}1366 1367void DWARFRewriter::updateLineTableOffsets(const MCAssembler &Asm) {1368  ErrorOr<BinarySection &> DbgInfoSection =1369      BC.getUniqueSectionByName(".debug_info");1370  ErrorOr<BinarySection &> TypeInfoSection =1371      BC.getUniqueSectionByName(".debug_types");1372  assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) ||1373          BC.DwCtx->getNumTypeUnits() == 0) &&1374         "Was not able to retrieve Debug Types section.");1375 1376  // There is no direct connection between CU and TU, but same offsets,1377  // encoded in DW_AT_stmt_list, into .debug_line get modified.1378  // We take advantage of that to map original CU line table offsets to new1379  // ones.1380  std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap;1381 1382  auto GetStatementListValue =1383      [](const DWARFDie &DIE) -> std::optional<uint64_t> {1384    std::optional<DWARFFormValue> StmtList = DIE.find(dwarf::DW_AT_stmt_list);1385    if (!StmtList)1386      return std::nullopt;1387    std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList);1388    assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list.");1389    return *Offset;1390  };1391 1392  SmallVector<DWARFUnit *, 1> TUs;1393  for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->info_section_units()) {1394    if (CU->isTypeUnit()) {1395      TUs.push_back(CU.get());1396      continue;1397    }1398    const unsigned CUID = CU->getOffset();1399    MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();1400    if (!Label)1401      continue;1402 1403    std::optional<uint64_t> StmtOffset =1404        GetStatementListValue(CU->getUnitDIE());1405    if (!StmtOffset)1406      continue;1407 1408    const uint64_t LineTableOffset =1409        Asm.getSymbolOffset(*Label);1410    DebugLineOffsetMap[*StmtOffset] = LineTableOffset;1411    assert(DbgInfoSection && ".debug_info section must exist");1412    LineTablePatchMap[CU.get()] = LineTableOffset;1413  }1414 1415  for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units())1416    TUs.push_back(TU.get());1417 1418  for (DWARFUnit *TU : TUs) {1419    std::optional<uint64_t> StmtOffset =1420        GetStatementListValue(TU->getUnitDIE());1421    if (!StmtOffset)1422      continue;1423    auto Iter = DebugLineOffsetMap.find(*StmtOffset);1424    if (Iter == DebugLineOffsetMap.end()) {1425      // Implementation depends on TU sharing DW_AT_stmt_list with a CU.1426      // Only case that it hasn't been true was for manually modified assembly1427      // file. Adding this warning in case assumption is false.1428      errs()1429          << "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x"1430          << Twine::utohexstr(TU->getOffset())1431          << " is not sharing "1432             ".debug_line entry with CU. DW_AT_stmt_list for this TU won't be "1433             "updated.\n";1434      continue;1435    }1436    TypeUnitRelocMap[TU] = Iter->second;1437  }1438 1439  // Set .debug_info as finalized so it won't be skipped over when1440  // we process sections while writing out the new binary. This ensures1441  // that the pending relocations will be processed and not ignored.1442  if (DbgInfoSection)1443    DbgInfoSection->setIsFinalized();1444 1445  if (TypeInfoSection)1446    TypeInfoSection->setIsFinalized();1447}1448 1449CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,1450                                                DIEStreamer &Streamer,1451                                                GDBIndex &GDBIndexSection) {1452  // update TypeUnit DW_AT_stmt_list with new .debug_line information.1453  auto updateLineTable = [&](const DWARFUnit &Unit) -> void {1454    DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(Unit);1455    DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list);1456    if (!StmtAttrInfo || !TypeUnitRelocMap.count(&Unit))1457      return;1458    DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list,1459                          StmtAttrInfo.getForm(),1460                          DIEInteger(TypeUnitRelocMap[&Unit]));1461  };1462 1463  // generate and populate abbrevs here1464  DIEBlder.generateAbbrevs();1465  DIEBlder.finish();1466  DIEBlder.updateDebugNamesTable();1467  SmallVector<char, 20> OutBuffer;1468  std::shared_ptr<raw_svector_ostream> ObjOS =1469      std::make_shared<raw_svector_ostream>(OutBuffer);1470  const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();1471  auto TheTriple = std::make_unique<Triple>(File->makeTriple());1472  std::unique_ptr<DIEStreamer> TypeStreamer = createDIEStreamer(1473      *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection);1474 1475  // generate debug_info and CUMap1476  CUOffsetMap CUMap;1477  for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) {1478    if (!CU->isTypeUnit())1479      continue;1480    updateLineTable(*CU);1481    emitUnit(DIEBlder, Streamer, *CU);1482    uint32_t StartOffset = CUOffset;1483    DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU);1484    CUOffset += CU->getHeaderSize();1485    CUOffset += UnitDIE->getSize();1486    CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};1487  }1488 1489  // Emit Type Unit of DWARF 4 to .debug_type section1490  for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) {1491    updateLineTable(*TU);1492    emitUnit(DIEBlder, *TypeStreamer, *TU);1493  }1494 1495  TypeStreamer->finish();1496 1497  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =1498      MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);1499  std::unique_ptr<object::ObjectFile> Obj = cantFail(1500      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),1501      "error creating in-memory object");1502 1503  for (const SectionRef &Section : Obj->sections()) {1504    StringRef Contents = cantFail(Section.getContents());1505    StringRef Name = cantFail(Section.getName());1506    if (Name == ".debug_types")1507      BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents),1508                                     Contents.size());1509  }1510  return CUMap;1511}1512 1513void DWARFRewriter::finalizeDebugSections(1514    DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,1515    DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap,1516    DebugAddrWriter &FinalAddrWriter) {1517  if (StrWriter->isInitialized()) {1518    RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");1519    std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =1520        StrWriter->releaseBuffer();1521    BC.registerOrUpdateNoteSection(".debug_str",1522                                   copyByteArray(*DebugStrSectionContents),1523                                   DebugStrSectionContents->size());1524  }1525 1526  if (StrOffstsWriter->isFinalized()) {1527    RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets");1528    std::unique_ptr<DebugStrOffsetsBufferVector>1529        DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer();1530    BC.registerOrUpdateNoteSection(1531        ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents),1532        DebugStrOffsetsSectionContents->size());1533  }1534 1535  if (BC.isDWARFLegacyUsed()) {1536    std::unique_ptr<DebugBufferVector> RangesSectionContents =1537        LegacyRangesSectionWriter->releaseBuffer();1538    BC.registerOrUpdateNoteSection(".debug_ranges",1539                                   copyByteArray(*RangesSectionContents),1540                                   RangesSectionContents->size());1541  }1542 1543  if (BC.isDWARF5Used()) {1544    std::unique_ptr<DebugBufferVector> RangesSectionContents =1545        RangeListsSectionWriter->releaseBuffer();1546    BC.registerOrUpdateNoteSection(".debug_rnglists",1547                                   copyByteArray(*RangesSectionContents),1548                                   RangesSectionContents->size());1549  }1550 1551  if (BC.isDWARF5Used()) {1552    std::unique_ptr<DebugBufferVector> LocationListSectionContents =1553        makeFinalLocListsSection(DWARFVersion::DWARF5);1554    if (!LocationListSectionContents->empty())1555      BC.registerOrUpdateNoteSection(1556          ".debug_loclists", copyByteArray(*LocationListSectionContents),1557          LocationListSectionContents->size());1558  }1559 1560  if (BC.isDWARFLegacyUsed()) {1561    std::unique_ptr<DebugBufferVector> LocationListSectionContents =1562        makeFinalLocListsSection(DWARFVersion::DWARFLegacy);1563    if (!LocationListSectionContents->empty())1564      BC.registerOrUpdateNoteSection(1565          ".debug_loc", copyByteArray(*LocationListSectionContents),1566          LocationListSectionContents->size());1567  }1568 1569  if (FinalAddrWriter.isInitialized()) {1570    std::unique_ptr<AddressSectionBuffer> AddressSectionContents =1571        FinalAddrWriter.releaseBuffer();1572    BC.registerOrUpdateNoteSection(".debug_addr",1573                                   copyByteArray(*AddressSectionContents),1574                                   AddressSectionContents->size());1575  }1576 1577  Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion());1578  Streamer.finish();1579 1580  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =1581      MemoryBuffer::getMemBuffer(ObjOS.str(), "in-memory object file", false);1582  std::unique_ptr<object::ObjectFile> Obj = cantFail(1583      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),1584      "error creating in-memory object");1585 1586  for (const SectionRef &Secs : Obj->sections()) {1587    StringRef Contents = cantFail(Secs.getContents());1588    StringRef Name = cantFail(Secs.getName());1589    if (Name == ".debug_abbrev") {1590      BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents),1591                                     Contents.size());1592    } else if (Name == ".debug_info") {1593      BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents),1594                                     Contents.size());1595    }1596  }1597 1598  // Skip .debug_aranges if we are re-generating .gdb_index.1599  if (opts::KeepARanges || !BC.getGdbIndexSection()) {1600    SmallVector<char, 16> ARangesBuffer;1601    raw_svector_ostream OS(ARangesBuffer);1602 1603    auto MAB = std::unique_ptr<MCAsmBackend>(1604        BC.TheTarget->createMCAsmBackend(*BC.STI, *BC.MRI, MCTargetOptions()));1605 1606    ARangesSectionWriter->writeARangesSection(OS, CUMap);1607    const StringRef &ARangesContents = OS.str();1608 1609    BC.registerOrUpdateNoteSection(".debug_aranges",1610                                   copyByteArray(ARangesContents),1611                                   ARangesContents.size());1612  }1613 1614  if (DebugNamesTable.isCreated()) {1615    RewriteInstance::addToDebugSectionsToOverwrite(".debug_names");1616    std::unique_ptr<DebugBufferVector> DebugNamesSectionContents =1617        DebugNamesTable.releaseBuffer();1618    BC.registerOrUpdateNoteSection(".debug_names",1619                                   copyByteArray(*DebugNamesSectionContents),1620                                   DebugNamesSectionContents->size());1621  }1622}1623 1624void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,1625                                         DIEStreamer &Streamer,1626                                         CUOffsetMap &CUMap,1627                                         const std::list<DWARFUnit *> &CUs,1628                                         DebugAddrWriter &FinalAddrWriter) {1629  for (DWARFUnit *CU : CUs) {1630    auto AddressWriterIterator = AddressWritersByCU.find(CU->getOffset());1631    assert(AddressWriterIterator != AddressWritersByCU.end() &&1632           "AddressWriter does not exist for CU");1633    DebugAddrWriter *AddressWriter = AddressWriterIterator->second.get();1634    const size_t BufferOffset = FinalAddrWriter.getBufferSize();1635    std::optional<uint64_t> Offset = AddressWriter->finalize(BufferOffset);1636    /// If Offset already exists in UnmodifiedAddressOffsets, then update with1637    /// Offset, else update with BufferOffset.1638    if (Offset)1639      AddressWriter->updateAddrBase(DIEBlder, *CU, *Offset);1640    else if (AddressWriter->isInitialized())1641      AddressWriter->updateAddrBase(DIEBlder, *CU, BufferOffset);1642    if (AddressWriter->isInitialized()) {1643      std::unique_ptr<AddressSectionBuffer> AddressSectionContents =1644          AddressWriter->releaseBuffer();1645      FinalAddrWriter.appendToAddressBuffer(*AddressSectionContents);1646    }1647    if (CU->getVersion() != 4)1648      continue;1649    std::optional<uint64_t> DWOId = CU->getDWOId();1650    if (!DWOId)1651      continue;1652    auto RangesWriterIterator = LegacyRangesWritersByCU.find(*DWOId);1653    assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&1654           "RangesWriter does not exist for DWOId");1655    std::unique_ptr<DebugRangesSectionWriter> &LegacyRangesWriter =1656        RangesWriterIterator->second;1657    DIE *Die = LegacyRangesWriter->getDie();1658    if (!Die)1659      continue;1660    DIEValue DvalGNUBase = Die->findAttribute(dwarf::DW_AT_GNU_ranges_base);1661    assert(DvalGNUBase && "GNU_ranges_base attribute does not exist for DWOId");1662    DIEBlder.replaceValue(1663        Die, dwarf::DW_AT_GNU_ranges_base, DvalGNUBase.getForm(),1664        DIEInteger(LegacyRangesSectionWriter->getSectionOffset()));1665    std::unique_ptr<DebugBufferVector> RangesWritersContents =1666        LegacyRangesWriter->releaseBuffer();1667    LegacyRangesSectionWriter->appendToRangeBuffer(*RangesWritersContents);1668  }1669  DIEBlder.generateAbbrevs();1670  DIEBlder.finish();1671  DIEBlder.updateDebugNamesTable();1672  // generate debug_info and CUMap1673  for (DWARFUnit *CU : CUs) {1674    emitUnit(DIEBlder, Streamer, *CU);1675    const uint32_t StartOffset = CUOffset;1676    DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU);1677    CUOffset += CU->getHeaderSize();1678    CUOffset += UnitDIE->getSize();1679    CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};1680  }1681}1682 1683// Creates all the data structures necessary for creating MCStreamer.1684// They are passed by reference because they need to be kept around.1685// Also creates known debug sections. These are sections handled by1686// handleDebugDataPatching.1687namespace {1688 1689std::unique_ptr<BinaryContext>1690createDwarfOnlyBC(const object::ObjectFile &File) {1691  return cantFail(BinaryContext::createBinaryContext(1692      File.makeTriple(), std::make_shared<orc::SymbolStringPool>(),1693      File.getFileName(), nullptr, false,1694      DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore,1695                           nullptr, "", WithColor::defaultErrorHandler,1696                           WithColor::defaultWarningHandler),1697      {llvm::outs(), llvm::errs()}));1698}1699 1700StringMap<DWARFRewriter::KnownSectionsEntry>1701createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {1702  StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = {1703      {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},1704      {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},1705      {"debug_str_offsets.dwo",1706       {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}},1707      {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}},1708      {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},1709      {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},1710      {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},1711      {"debug_loclists.dwo",1712       {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},1713      {"debug_rnglists.dwo",1714       {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}};1715  return KnownSectionsTemp;1716}1717 1718StringRef getSectionName(const SectionRef &Section) {1719  Expected<StringRef> SectionName = Section.getName();1720  assert(SectionName && "Invalid section name.");1721  StringRef Name = *SectionName;1722  Name = Name.substr(Name.find_first_not_of("._"));1723  return Name;1724}1725 1726/// Extracts the slice of the .debug_str.dwo section for a given CU from a DWP1727/// file, based on the .debug_str_offsets.dwo section. This helps address DWO1728/// bloat that may occur after updates.1729///1730/// A slice of .debug_str.dwo may be composed of several non-contiguous1731/// fragments. These non-contiguous string views will be written out1732/// sequentially, avoiding the copying overhead caused by assembling them.1733///1734/// The .debug_str_offsets for the first CU often does not need to be updated,1735/// so copying is only performed when .debug_str_offsets requires updating.1736static void UpdateStrAndStrOffsets(StringRef StrDWOContent,1737                                   StringRef StrOffsetsContent,1738                                   SmallVectorImpl<StringRef> &StrDWOOutData,1739                                   std::string &StrOffsetsOutData,1740                                   unsigned DwarfVersion, bool IsLittleEndian) {1741  const llvm::endianness Endian =1742      IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;1743  const uint64_t HeaderOffset = (DwarfVersion >= 5) ? 8 : 0;1744  constexpr size_t SizeOfOffset = sizeof(int32_t);1745  const uint64_t NumOffsets =1746      (StrOffsetsContent.size() - HeaderOffset) / SizeOfOffset;1747 1748  DataExtractor Extractor(StrOffsetsContent, IsLittleEndian, 0);1749  uint64_t ExtractionOffset = HeaderOffset;1750 1751  using StringFragment = DWARFUnitIndex::Entry::SectionContribution;1752  const auto getStringLength = [](StringRef Content,1753                                  uint64_t Offset) -> uint64_t {1754    size_t NullPos = Content.find('\0', Offset);1755    return (NullPos != StringRef::npos) ? (NullPos - Offset + 1) : 0;1756  };1757  const auto isContiguous = [](const StringFragment &Fragment,1758                               uint64_t NextOffset) -> bool {1759    return NextOffset == Fragment.getOffset() + Fragment.getLength();1760  };1761  std::optional<StringFragment> CurrentFragment;1762  uint64_t AccumulatedStrLen = 0;1763  for (uint64_t I = 0; I < NumOffsets; ++I) {1764    const uint64_t StrOffset = Extractor.getU32(&ExtractionOffset);1765    const uint64_t StringLength = getStringLength(StrDWOContent, StrOffset);1766    if (!CurrentFragment) {1767      // First init.1768      CurrentFragment = StringFragment(StrOffset, StringLength);1769    } else {1770      if (isContiguous(*CurrentFragment, StrOffset)) {1771        // Expanding the current fragment.1772        CurrentFragment->setLength(CurrentFragment->getLength() + StringLength);1773      } else {1774        // Saving the current fragment and start a new one.1775        StrDWOOutData.push_back(StrDWOContent.substr(1776            CurrentFragment->getOffset(), CurrentFragment->getLength()));1777        CurrentFragment = StringFragment(StrOffset, StringLength);1778      }1779    }1780    if (AccumulatedStrLen != StrOffset) {1781      // Updating str offsets.1782      if (StrOffsetsOutData.empty())1783        StrOffsetsOutData = StrOffsetsContent.str();1784      llvm::support::endian::write32(1785          &StrOffsetsOutData[HeaderOffset + I * SizeOfOffset],1786          static_cast<uint32_t>(AccumulatedStrLen), Endian);1787    }1788    AccumulatedStrLen += StringLength;1789  }1790  if (CurrentFragment)1791    StrDWOOutData.push_back(StrDWOContent.substr(CurrentFragment->getOffset(),1792                                                 CurrentFragment->getLength()));1793}1794 1795// Exctracts an appropriate slice if input is DWP.1796// Applies patches or overwrites the section.1797std::optional<StringRef> updateDebugData(1798    DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,1799    const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,1800    MCStreamer &Streamer, DWARFRewriter &Writer,1801    const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,1802    std::unique_ptr<DebugBufferVector> &OutputBuffer,1803    DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,1804    DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,1805    const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {1806 1807  using DWOSectionContribution =1808      const DWARFUnitIndex::Entry::SectionContribution;1809  auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry,1810                          StringRef OutData, DWARFSectionKind Sec,1811                          uint64_t &DWPOffset) -> StringRef {1812    if (DWOEntry) {1813      DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec);1814      DWPOffset = DWOContrubution->getOffset();1815      OutData = OutData.substr(DWPOffset, DWOContrubution->getLength());1816    }1817    return OutData;1818  };1819 1820  auto SectionIter = KnownSections.find(SectionName);1821  if (SectionIter == KnownSections.end())1822    return std::nullopt;1823  Streamer.switchSection(SectionIter->second.first);1824  uint64_t DWPOffset = 0;1825 1826  auto getOverridenSection =1827      [&](DWARFSectionKind Kind) -> std::optional<StringRef> {1828    auto Iter = OverridenSections.find(Kind);1829    if (Iter == OverridenSections.end()) {1830      errs()1831          << "BOLT-WARNING: [internal-dwarf-error]: Could not find overridden "1832             "section for: "1833          << Twine::utohexstr(DWOId) << ".\n";1834      return std::nullopt;1835    }1836    return Iter->second;1837  };1838  switch (SectionIter->second.second) {1839  default: {1840    if (SectionName != "debug_str.dwo")1841      errs() << "BOLT-WARNING: unsupported debug section: " << SectionName1842             << "\n";1843    if (StrWriter.isInitialized()) {1844      if (CUDWOEntry)1845        return StrWriter.getBufferStr();1846      OutputBuffer = StrWriter.releaseBuffer();1847      return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),1848                       OutputBuffer->size());1849    }1850    return SectionContents;1851  }1852  case DWARFSectionKind::DW_SECT_INFO: {1853    return getOverridenSection(DWARFSectionKind::DW_SECT_INFO);1854  }1855  case DWARFSectionKind::DW_SECT_EXT_TYPES: {1856    return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES);1857  }1858  case DWARFSectionKind::DW_SECT_STR_OFFSETS: {1859    if (StrOffstsWriter.isFinalized()) {1860      if (CUDWOEntry)1861        return StrOffstsWriter.getBufferStr();1862      OutputBuffer = StrOffstsWriter.releaseBuffer();1863      return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),1864                       OutputBuffer->size());1865    }1866    return getSliceData(CUDWOEntry, SectionContents,1867                        DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);1868  }1869  case DWARFSectionKind::DW_SECT_ABBREV: {1870    return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV);1871  }1872  case DWARFSectionKind::DW_SECT_EXT_LOC:1873  case DWARFSectionKind::DW_SECT_LOCLISTS: {1874    OutputBuffer = LocWriter.getBuffer();1875    // Creating explicit StringRef here, otherwise1876    // with implicit conversion it will take null byte as end of1877    // string.1878    return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),1879                     OutputBuffer->size());1880  }1881  case DWARFSectionKind::DW_SECT_LINE: {1882    return getSliceData(CUDWOEntry, SectionContents,1883                        DWARFSectionKind::DW_SECT_LINE, DWPOffset);1884  }1885  case DWARFSectionKind::DW_SECT_RNGLISTS: {1886    assert(RangeListsWriter && "RangeListsWriter was not created.");1887    OutputBuffer = RangeListsWriter->releaseBuffer();1888    return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),1889                     OutputBuffer->size());1890  }1891  }1892}1893 1894} // namespace1895 1896void DWARFRewriter::writeDWOFiles(1897    DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,1898    const std::string &DWOName, DebugLocWriter &LocWriter,1899    DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,1900    DebugRangesSectionWriter &TempRangesSectionWriter) {1901  // Setup DWP code once.1902  DWARFContext *DWOCtx = BC.getDWOContext();1903  const uint64_t DWOId = *CU.getDWOId();1904  const DWARFUnitIndex *CUIndex = nullptr;1905  bool IsDWP = false;1906  if (DWOCtx) {1907    CUIndex = &DWOCtx->getCUIndex();1908    IsDWP = !CUIndex->getRows().empty();1909  }1910 1911  // Skipping CUs that we failed to load.1912  std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);1913  if (!DWOCU) {1914    errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID "1915           << Twine::utohexstr(DWOId) << " is not found.\n";1916    return;1917  }1918 1919  std::string CompDir = CU.getCompilationDir();1920  SmallString<16> AbsolutePath(DWOName);1921 1922  if (!opts::DwarfOutputPath.empty())1923    CompDir = opts::DwarfOutputPath.c_str();1924  else if (!opts::CompDirOverride.empty())1925    CompDir = opts::CompDirOverride;1926  else if (!sys::fs::exists(CompDir))1927    CompDir = ".";1928  // Prevent failures when DWOName is already an absolute path.1929  sys::path::make_absolute(CompDir, AbsolutePath);1930 1931  std::error_code EC;1932  std::unique_ptr<ToolOutputFile> TempOut =1933      std::make_unique<ToolOutputFile>(AbsolutePath, EC, sys::fs::OF_None);1934 1935  const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;1936  if (IsDWP)1937    CUDWOEntry = CUIndex->getFromHash(DWOId);1938 1939  const object::ObjectFile *File =1940      (*DWOCU)->getContext().getDWARFObj().getFile();1941  std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);1942  std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());1943  const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();1944  StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);1945 1946  DebugRangeListsSectionWriter *RangeListssWriter = nullptr;1947  if (CU.getVersion() == 5) {1948    RangeListssWriter =1949        llvm::dyn_cast<DebugRangeListsSectionWriter>(&TempRangesSectionWriter);1950 1951    // Handling .debug_rnglists.dwo separately. The original .o/.dwo might not1952    // have .debug_rnglists so won't be part of the loop below.1953    if (!RangeListssWriter->empty()) {1954      std::unique_ptr<DebugBufferVector> OutputData;1955      if (std::optional<StringRef> OutData =1956              updateDebugData((*DWOCU)->getContext(), "debug_rnglists.dwo", "",1957                              KnownSections, *Streamer, *this, CUDWOEntry,1958                              DWOId, OutputData, RangeListssWriter, LocWriter,1959                              StrOffstsWriter, StrWriter, OverridenSections))1960        Streamer->emitBytes(*OutData);1961    }1962  }1963 1964  StringRef StrDWOContent;1965  StringRef StrOffsetsContent;1966  llvm::SmallVector<StringRef, 3> StrDWOOutData;1967  std::string StrOffsetsOutData;1968  for (const SectionRef &Section : File->sections()) {1969    std::unique_ptr<DebugBufferVector> OutputData;1970    StringRef SectionName = getSectionName(Section);1971    if (SectionName == "debug_rnglists.dwo")1972      continue;1973    Expected<StringRef> ContentsExp = Section.getContents();1974    assert(ContentsExp && "Invalid contents.");1975    if (IsDWP && SectionName == "debug_str.dwo") {1976      if (StrWriter.isInitialized())1977        StrDWOContent = StrWriter.getBufferStr();1978      else1979        StrDWOContent = *ContentsExp;1980      continue;1981    }1982    if (std::optional<StringRef> OutData = updateDebugData(1983            (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,1984            *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,1985            LocWriter, StrOffstsWriter, StrWriter, OverridenSections)) {1986      if (IsDWP && SectionName == "debug_str_offsets.dwo") {1987        StrOffsetsContent = *OutData;1988        continue;1989      }1990      Streamer->emitBytes(*OutData);1991    }1992  }1993 1994  if (IsDWP) {1995    // Handling both .debug_str.dwo and .debug_str_offsets.dwo concurrently. In1996    // the original DWP, .debug_str is a deduplicated global table, and the1997    // .debug_str.dwo slice for a single CU needs to be extracted according to1998    // .debug_str_offsets.dwo.1999    UpdateStrAndStrOffsets(StrDWOContent, StrOffsetsContent, StrDWOOutData,2000                           StrOffsetsOutData, CU.getVersion(),2001                           (*DWOCU)->getContext().isLittleEndian());2002    auto SectionIter = KnownSections.find("debug_str.dwo");2003    if (SectionIter != KnownSections.end()) {2004      Streamer->switchSection(SectionIter->second.first);2005      for (size_t i = 0; i < StrDWOOutData.size(); ++i) {2006        StringRef OutData = StrDWOOutData[i];2007        if (!OutData.empty())2008          Streamer->emitBytes(OutData);2009      }2010    }2011    SectionIter = KnownSections.find("debug_str_offsets.dwo");2012    if (SectionIter != KnownSections.end()) {2013      Streamer->switchSection(SectionIter->second.first);2014      if (!StrOffsetsOutData.empty())2015        Streamer->emitBytes(StrOffsetsOutData);2016      else2017        Streamer->emitBytes(StrOffsetsContent);2018    }2019  }2020  Streamer->finish();2021  TempOut->keep();2022}2023 2024std::unique_ptr<DebugBufferVector>2025DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {2026  auto LocBuffer = std::make_unique<DebugBufferVector>();2027  auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);2028  auto Writer =2029      std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));2030 2031  for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc :2032       LocListWritersByCU) {2033    DebugLocWriter *LocWriter = Loc.second.get();2034    auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter);2035 2036    // Filter out DWARF4, writing out DWARF52037    if (Version == DWARFVersion::DWARF5 &&2038        (!LocListWriter || LocListWriter->getDwarfVersion() <= 4))2039      continue;2040 2041    // Filter out DWARF5, writing out DWARF42042    if (Version == DWARFVersion::DWARFLegacy &&2043        (LocListWriter && LocListWriter->getDwarfVersion() >= 5))2044      continue;2045 2046    // Skipping DWARF4/5 split dwarf.2047    if (LocListWriter && LocListWriter->getDwarfVersion() <= 4)2048      continue;2049    std::unique_ptr<DebugBufferVector> CurrCULocationLists =2050        LocWriter->getBuffer();2051    *LocStream << *CurrCULocationLists;2052  }2053 2054  return LocBuffer;2055}2056 2057void DWARFRewriter::convertToRangesPatchDebugInfo(2058    DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,2059    uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,2060    DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) {2061  dwarf::Form LowForm = LowPCAttrInfo.getForm();2062  dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;2063  dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;2064 2065  if (Unit.getVersion() >= 5) {2066    RangeBaseAttribute = dwarf::DW_AT_rnglists_base;2067    RangesForm = dwarf::DW_FORM_rnglistx;2068  } else if (Unit.getVersion() < 4) {2069    RangesForm = dwarf::DW_FORM_data4;2070  }2071  bool IsUnitDie = Die.getTag() == dwarf::DW_TAG_compile_unit ||2072                   Die.getTag() == dwarf::DW_TAG_skeleton_unit;2073  if (!IsUnitDie)2074    DIEBldr.deleteValue(&Die, LowPCAttrInfo.getAttribute());2075 2076  // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or2077  // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is2078  // when it's absent.2079  if (IsUnitDie) {2080    if (LowForm == dwarf::DW_FORM_addrx) {2081      auto AddrWriterIterator = AddressWritersByCU.find(Unit.getOffset());2082      assert(AddrWriterIterator != AddressWritersByCU.end() &&2083             "AddressWriter does not exist for CU");2084      DebugAddrWriter *AddrWriter = AddrWriterIterator->second.get();2085      const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit);2086      DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),2087                           LowPCAttrInfo.getForm(), DIEInteger(Index));2088    } else {2089      DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),2090                           LowPCAttrInfo.getForm(), DIEInteger(0));2091    }2092    // Original CU didn't have DW_AT_*_base. We converted it's children (or2093    // dwo), so need to insert it into CU.2094    if (RangesBase) {2095      if (Unit.getVersion() >= 5) {2096        DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,2097                         DIEInteger(*RangesBase));2098      } else {2099        DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,2100                         DIEInteger(INT_MAX));2101        auto RangesWriterIterator =2102            LegacyRangesWritersByCU.find(*Unit.getDWOId());2103        assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&2104               "RangesWriter does not exist for DWOId");2105        RangesWriterIterator->second->setDie(&Die);2106      }2107    }2108  }2109 2110  // HighPC was converted into DW_AT_ranges.2111  // For DWARF5 we only access ranges through index.2112 2113  DIEBldr.replaceValue(&Die, HighPCAttrInfo.getAttribute(), dwarf::DW_AT_ranges,2114                       RangesForm, DIEInteger(RangesSectionOffset));2115}2116