brintos

brintos / llvm-project-archived public Read only

0
0
Text · 46.9 KiB · 1fc5bba Raw
1259 lines · cpp
1//===- tools/dsymutil/DwarfLinkerForBinary.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 "DwarfLinkerForBinary.h"10#include "BinaryHolder.h"11#include "DebugMap.h"12#include "MachOUtils.h"13#include "SwiftModule.h"14#include "dsymutil.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/DenseMap.h"17#include "llvm/ADT/FoldingSet.h"18#include "llvm/ADT/Hashing.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/SmallString.h"21#include "llvm/ADT/StringRef.h"22#include "llvm/ADT/StringSet.h"23#include "llvm/ADT/Twine.h"24#include "llvm/BinaryFormat/Dwarf.h"25#include "llvm/BinaryFormat/MachO.h"26#include "llvm/BinaryFormat/Swift.h"27#include "llvm/CodeGen/AccelTable.h"28#include "llvm/CodeGen/AsmPrinter.h"29#include "llvm/CodeGen/DIE.h"30#include "llvm/CodeGen/NonRelocatableStringpool.h"31#include "llvm/Config/config.h"32#include "llvm/DWARFLinker/Classic/DWARFLinker.h"33#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"34#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"35#include "llvm/DebugInfo/DIContext.h"36#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"37#include "llvm/DebugInfo/DWARF/DWARFContext.h"38#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"39#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"40#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"41#include "llvm/DebugInfo/DWARF/DWARFDie.h"42#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"43#include "llvm/DebugInfo/DWARF/DWARFSection.h"44#include "llvm/DebugInfo/DWARF/DWARFUnit.h"45#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"46#include "llvm/MC/MCAsmBackend.h"47#include "llvm/MC/MCAsmInfo.h"48#include "llvm/MC/MCCodeEmitter.h"49#include "llvm/MC/MCContext.h"50#include "llvm/MC/MCDwarf.h"51#include "llvm/MC/MCInstrInfo.h"52#include "llvm/MC/MCObjectFileInfo.h"53#include "llvm/MC/MCObjectWriter.h"54#include "llvm/MC/MCRegisterInfo.h"55#include "llvm/MC/MCSection.h"56#include "llvm/MC/MCStreamer.h"57#include "llvm/MC/MCSubtargetInfo.h"58#include "llvm/MC/MCTargetOptions.h"59#include "llvm/MC/MCTargetOptionsCommandFlags.h"60#include "llvm/MC/TargetRegistry.h"61#include "llvm/Object/MachO.h"62#include "llvm/Object/ObjectFile.h"63#include "llvm/Object/SymbolicFile.h"64#include "llvm/Support/Allocator.h"65#include "llvm/Support/Casting.h"66#include "llvm/Support/Compiler.h"67#include "llvm/Support/DJB.h"68#include "llvm/Support/DataExtractor.h"69#include "llvm/Support/Error.h"70#include "llvm/Support/ErrorHandling.h"71#include "llvm/Support/ErrorOr.h"72#include "llvm/Support/FileSystem.h"73#include "llvm/Support/Format.h"74#include "llvm/Support/LEB128.h"75#include "llvm/Support/MathExtras.h"76#include "llvm/Support/MemoryBuffer.h"77#include "llvm/Support/Path.h"78#include "llvm/Support/ThreadPool.h"79#include "llvm/Support/ToolOutputFile.h"80#include "llvm/Support/WithColor.h"81#include "llvm/Support/raw_ostream.h"82#include "llvm/Target/TargetMachine.h"83#include "llvm/Target/TargetOptions.h"84#include "llvm/TargetParser/Triple.h"85#include <algorithm>86#include <cassert>87#include <cinttypes>88#include <climits>89#include <cstdint>90#include <cstdlib>91#include <cstring>92#include <limits>93#include <memory>94#include <optional>95#include <string>96#include <system_error>97#include <tuple>98#include <utility>99#include <vector>100 101namespace llvm {102 103static mc::RegisterMCTargetOptionsFlags MOF;104 105using namespace dwarf_linker;106 107namespace dsymutil {108 109static void dumpDIE(const DWARFDie *DIE, bool Verbose) {110  if (!DIE || !Verbose)111    return;112 113  DIDumpOptions DumpOpts;114  DumpOpts.ChildRecurseDepth = 0;115  DumpOpts.Verbose = Verbose;116 117  WithColor::note() << "    in DIE:\n";118  DIE->dump(errs(), 6 /* Indent */, DumpOpts);119}120 121/// Report a warning to the user, optionally including information about a122/// specific \p DIE related to the warning.123void DwarfLinkerForBinary::reportWarning(Twine Warning, Twine Context,124                                         const DWARFDie *DIE) const {125  // FIXME: implement warning logging which does not block other threads.126  if (ErrorHandlerMutex.try_lock()) {127    warn(Warning, Context);128    dumpDIE(DIE, Options.Verbose);129    ErrorHandlerMutex.unlock();130  }131}132 133void DwarfLinkerForBinary::reportError(Twine Error, Twine Context,134                                       const DWARFDie *DIE) const {135  // FIXME: implement error logging which does not block other threads.136  if (ErrorHandlerMutex.try_lock()) {137    error(Error, Context);138    dumpDIE(DIE, Options.Verbose);139    ErrorHandlerMutex.unlock();140  }141}142 143ErrorOr<const object::ObjectFile &>144DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,145                                 const Triple &Triple) {146  auto ObjectEntry =147      BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());148  if (!ObjectEntry) {149    auto Err = ObjectEntry.takeError();150    reportWarning(Twine(Obj.getObjectFilename()) + ": " +151                      toStringWithoutConsuming(Err),152                  Obj.getObjectFilename());153    return errorToErrorCode(std::move(Err));154  }155 156  auto Object = ObjectEntry->getObject(Triple);157  if (!Object) {158    auto Err = Object.takeError();159    reportWarning(Twine(Obj.getObjectFilename()) + ": " +160                      toStringWithoutConsuming(Err),161                  Obj.getObjectFilename());162    return errorToErrorCode(std::move(Err));163  }164 165  return *Object;166}167 168static Error remarksErrorHandler(const DebugMapObject &DMO,169                                 DwarfLinkerForBinary &Linker,170                                 std::unique_ptr<FileError> FE) {171  bool IsArchive = DMO.getObjectFilename().ends_with(")");172  // Don't report errors for missing remark files from static173  // archives.174  if (!IsArchive)175    return Error(std::move(FE));176 177  std::string Message = FE->message();178  Error E = FE->takeError();179  Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) {180    if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory)181      return Error(std::move(EC));182 183    Linker.reportWarning(Message, DMO.getObjectFilename());184    return Error(Error::success());185  });186 187  if (!NewE)188    return Error::success();189 190  return createFileError(FE->getFileName(), std::move(NewE));191}192Error DwarfLinkerForBinary::emitRelocations(193    const DebugMap &DM, std::vector<ObjectWithRelocMap> &ObjectsForLinking) {194  // Return early if the "Resources" directory is not being written to.195  if (!Options.ResourceDir)196    return Error::success();197 198  RelocationMap RM(DM.getTriple(), DM.getBinaryPath());199  for (auto &Obj : ObjectsForLinking) {200    if (!Obj.OutRelocs->isInitialized())201      continue;202    Obj.OutRelocs->addValidRelocs(RM);203  }204 205  SmallString<128> Path;206  // Create the "Relocations" directory in the "Resources" directory, and207  // create an architecture-specific directory in the "Relocations" directory.208  StringRef ArchName = Triple::getArchName(RM.getTriple().getArch(),209                                           RM.getTriple().getSubArch());210  sys::path::append(Path, *Options.ResourceDir, "Relocations", ArchName);211  if (std::error_code EC = sys::fs::create_directories(Path.str(), true,212                                                       sys::fs::perms::all_all))213    return errorCodeToError(EC);214 215  // Append the file name.216  sys::path::append(Path, sys::path::filename(DM.getBinaryPath()));217  Path.append(".yml");218 219  std::error_code EC;220  raw_fd_ostream OS(Path.str(), EC, sys::fs::OF_Text);221  if (EC)222    return errorCodeToError(EC);223 224  RM.print(OS);225  return Error::success();226}227 228static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,229                         StringRef ArchName, const remarks::RemarkLinker &RL) {230  // Make sure we don't create the directories and the file if there is nothing231  // to serialize.232  if (RL.empty())233    return Error::success();234 235  SmallString<128> Path;236  // Create the "Remarks" directory in the "Resources" directory.237  sys::path::append(Path, *Options.ResourceDir, "Remarks");238  if (std::error_code EC = sys::fs::create_directories(Path.str(), true,239                                                       sys::fs::perms::all_all))240    return errorCodeToError(EC);241 242  // Append the file name.243  // For fat binaries, also append a dash and the architecture name.244  sys::path::append(Path, sys::path::filename(BinaryPath));245  if (Options.NumDebugMaps > 1) {246    // More than one debug map means we have a fat binary.247    Path += '-';248    Path += ArchName;249  }250 251  std::error_code EC;252  raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC,253                    Options.RemarksFormat == remarks::Format::Bitstream254                        ? sys::fs::OF_None255                        : sys::fs::OF_Text);256  if (EC)257    return errorCodeToError(EC);258 259  if (Error E = RL.serialize(OS, Options.RemarksFormat))260    return E;261 262  return Error::success();263}264 265ErrorOr<std::unique_ptr<DWARFFile>> DwarfLinkerForBinary::loadObject(266    const DebugMapObject &Obj, const DebugMap &DebugMap,267    remarks::RemarkLinker &RL,268    std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM) {269  auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());270  std::unique_ptr<DWARFFile> Res;271 272  if (ErrorOrObj) {273    auto Context = DWARFContext::create(274        *ErrorOrObj, DWARFContext::ProcessDebugRelocations::Process, nullptr,275        "",276        [&](Error Err) {277          handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {278            reportError(Info.message());279          });280        },281        [&](Error Warning) {282          handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {283            reportWarning(Info.message());284          });285        });286    DLBRM->init(*Context);287    Res = std::make_unique<DWARFFile>(288        Obj.getObjectFilename(), std::move(Context),289        std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj, DLBRM),290        [&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });291 292    Error E = RL.link(*ErrorOrObj);293    // FIXME: Remark parsing errors are not propagated to the user.294    if (Error NewE = handleErrors(295            std::move(E), [&](std::unique_ptr<FileError> EC) -> Error {296              return remarksErrorHandler(Obj, *this, std::move(EC));297            }))298      return errorToErrorCode(std::move(NewE));299 300    return std::move(Res);301  }302 303  return ErrorOrObj.getError();304}305 306static bool binaryHasStrippableSwiftReflectionSections(307    const DebugMap &Map, const LinkOptions &Options, BinaryHolder &BinHolder) {308  // If the input binary has strippable swift5 reflection sections, there is no309  // need to copy them to the .dSYM. Only copy them for binaries where the310  // linker omitted the reflection metadata.311  if (!Map.getBinaryPath().empty() &&312      Options.FileType == DWARFLinkerBase::OutputFileType::Object) {313 314    auto ObjectEntry = BinHolder.getObjectEntry(Map.getBinaryPath());315    // If ObjectEntry or Object has an error, no binary exists, therefore no316    // reflection sections exist.317    if (!ObjectEntry) {318      // Any errors will be diagnosed later in the main loop, ignore them here.319      llvm::consumeError(ObjectEntry.takeError());320      return false;321    }322 323    auto Object =324        ObjectEntry->getObjectAs<object::MachOObjectFile>(Map.getTriple());325    if (!Object) {326      // Any errors will be diagnosed later in the main loop, ignore them here.327      llvm::consumeError(Object.takeError());328      return false;329    }330 331    for (auto &Section : Object->sections()) {332      llvm::Expected<llvm::StringRef> NameOrErr =333          Object->getSectionName(Section.getRawDataRefImpl());334      if (!NameOrErr) {335        llvm::consumeError(NameOrErr.takeError());336        continue;337      }338      NameOrErr->consume_back("__TEXT");339      auto ReflectionSectionKind =340          Object->mapReflectionSectionNameToEnumValue(*NameOrErr);341      if (Object->isReflectionSectionStrippable(ReflectionSectionKind)) {342        return true;343      }344    }345  }346  return false;347}348 349/// Calculate the start of the strippable swift reflection sections in Dwarf.350/// Note that there's an assumption that the reflection sections will appear351/// in alphabetic order.352static std::vector<uint64_t>353calculateStartOfStrippableReflectionSections(const DebugMap &Map) {354  using llvm::binaryformat::Swift5ReflectionSectionKind;355  uint64_t AssocTySize = 0;356  uint64_t FieldMdSize = 0;357  for (const auto &Obj : Map.objects()) {358    auto OF =359        llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename());360    if (!OF) {361      llvm::consumeError(OF.takeError());362      continue;363    }364    if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {365      for (auto &Section : MO->sections()) {366        llvm::Expected<llvm::StringRef> NameOrErr =367            MO->getSectionName(Section.getRawDataRefImpl());368        if (!NameOrErr) {369          llvm::consumeError(NameOrErr.takeError());370          continue;371        }372        NameOrErr->consume_back("__TEXT");373        auto ReflSectionKind =374            MO->mapReflectionSectionNameToEnumValue(*NameOrErr);375        switch (ReflSectionKind) {376        case Swift5ReflectionSectionKind::assocty:377          AssocTySize += Section.getSize();378          break;379        case Swift5ReflectionSectionKind::fieldmd:380          FieldMdSize += Section.getSize();381          break;382        default:383          break;384        }385      }386    }387  }388  // Initialize the vector with enough space to fit every reflection section389  // kind.390  std::vector<uint64_t> SectionToOffset(Swift5ReflectionSectionKind::last, 0);391  SectionToOffset[Swift5ReflectionSectionKind::assocty] = 0;392  SectionToOffset[Swift5ReflectionSectionKind::fieldmd] =393      llvm::alignTo(AssocTySize, 4);394  SectionToOffset[Swift5ReflectionSectionKind::reflstr] = llvm::alignTo(395      SectionToOffset[Swift5ReflectionSectionKind::fieldmd] + FieldMdSize, 4);396 397  return SectionToOffset;398}399 400void DwarfLinkerForBinary::collectRelocationsToApplyToSwiftReflectionSections(401    const object::SectionRef &Section, StringRef &Contents,402    const llvm::object::MachOObjectFile *MO,403    const std::vector<uint64_t> &SectionToOffsetInDwarf,404    const llvm::dsymutil::DebugMapObject *Obj,405    std::vector<MachOUtils::DwarfRelocationApplicationInfo> &RelocationsToApply)406    const {407  for (auto It = Section.relocation_begin(); It != Section.relocation_end();408       ++It) {409    object::DataRefImpl RelocDataRef = It->getRawDataRefImpl();410    MachO::any_relocation_info MachOReloc = MO->getRelocation(RelocDataRef);411 412    if (!object::MachOObjectFile::isMachOPairedReloc(413            MO->getAnyRelocationType(MachOReloc), MO->getArch())) {414      reportWarning(415          "Unimplemented relocation type in strippable reflection section ",416          Obj->getObjectFilename());417      continue;418    }419 420    auto CalculateAddressOfSymbolInDwarfSegment =421        [&]() -> std::optional<int64_t> {422      auto Symbol = It->getSymbol();423      auto SymbolAbsoluteAddress = Symbol->getAddress();424      if (!SymbolAbsoluteAddress)425        return {};426      auto Section = Symbol->getSection();427      if (!Section) {428        llvm::consumeError(Section.takeError());429        return {};430      }431 432      if ((*Section)->getObject()->section_end() == *Section)433        return {};434 435      auto SectionStart = (*Section)->getAddress();436      auto SymbolAddressInSection = *SymbolAbsoluteAddress - SectionStart;437      auto SectionName = (*Section)->getName();438      if (!SectionName)439        return {};440      auto ReflSectionKind =441          MO->mapReflectionSectionNameToEnumValue(*SectionName);442 443      int64_t SectionStartInLinkedBinary =444          SectionToOffsetInDwarf[ReflSectionKind];445 446      auto Addr = SectionStartInLinkedBinary + SymbolAddressInSection;447      return Addr;448    };449 450    // The first symbol should always be in the section we're currently451    // iterating over.452    auto FirstSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();453    ++It;454 455    bool ShouldSubtractDwarfVM = false;456    // For the second symbol there are two possibilities.457    std::optional<int64_t> SecondSymbolAddress;458    auto Sym = It->getSymbol();459    if (Sym != MO->symbol_end()) {460      Expected<StringRef> SymbolName = Sym->getName();461      if (SymbolName) {462        if (const auto *Mapping = Obj->lookupSymbol(*SymbolName)) {463          // First possibility: the symbol exists in the binary, and exists in a464          // non-strippable section (for example, typeref, or __TEXT,__const),465          // in which case we look up its address in the  binary, which dsymutil466          // will copy verbatim.467          SecondSymbolAddress = Mapping->getValue().BinaryAddress;468          // Since the symbols live in different segments, we have to substract469          // the start of the Dwarf's vmaddr so the value calculated points to470          // the correct place.471          ShouldSubtractDwarfVM = true;472        }473      }474    }475 476    if (!SecondSymbolAddress) {477      // Second possibility, this symbol is not present in the main binary, and478      // must be in one of the strippable sections (for example, reflstr).479      // Calculate its address in the same way as we did the first one.480      SecondSymbolAddress = CalculateAddressOfSymbolInDwarfSegment();481    }482 483    if (!FirstSymbolAddress || !SecondSymbolAddress)484      continue;485 486    auto SectionName = Section.getName();487    if (!SectionName)488      continue;489 490    int32_t Addend;491    memcpy(&Addend, Contents.data() + It->getOffset(), sizeof(int32_t));492    int32_t Value = (*SecondSymbolAddress + Addend) - *FirstSymbolAddress;493    auto ReflSectionKind =494        MO->mapReflectionSectionNameToEnumValue(*SectionName);495    uint64_t AddressFromDwarfVM =496        SectionToOffsetInDwarf[ReflSectionKind] + It->getOffset();497    RelocationsToApply.emplace_back(AddressFromDwarfVM, Value,498                                    ShouldSubtractDwarfVM);499  }500}501 502Error DwarfLinkerForBinary::copySwiftInterfaces(StringRef Architecture) const {503  std::error_code EC;504  SmallString<128> InputPath;505  SmallString<128> Path;506  sys::path::append(Path, *Options.ResourceDir, "Swift", Architecture);507  if ((EC = sys::fs::create_directories(Path.str(), true,508                                        sys::fs::perms::all_all)))509    return make_error<StringError>(510        "cannot create directory: " + toString(errorCodeToError(EC)), EC);511  unsigned BaseLength = Path.size();512 513  for (auto &I : ParseableSwiftInterfaces) {514    StringRef ModuleName = I.first;515    StringRef InterfaceFile = I.second;516    if (!Options.PrependPath.empty()) {517      InputPath.clear();518      sys::path::append(InputPath, Options.PrependPath, InterfaceFile);519      InterfaceFile = InputPath;520    }521    sys::path::append(Path, ModuleName);522    Path.append(".swiftinterface");523    if (Options.Verbose)524      outs() << "copy parseable Swift interface " << InterfaceFile << " -> "525             << Path.str() << '\n';526 527    // copy_file attempts an APFS clone first, so this should be cheap.528    if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))529      reportWarning(Twine("cannot copy parseable Swift interface ") +530                    InterfaceFile + ": " + toString(errorCodeToError(EC)));531    Path.resize(BaseLength);532  }533  return Error::success();534}535 536void DwarfLinkerForBinary::copySwiftReflectionMetadata(537    const llvm::dsymutil::DebugMapObject *Obj, classic::DwarfStreamer *Streamer,538    std::vector<uint64_t> &SectionToOffsetInDwarf,539    std::vector<MachOUtils::DwarfRelocationApplicationInfo>540        &RelocationsToApply) {541  using binaryformat::Swift5ReflectionSectionKind;542  auto OF =543      llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename());544  if (!OF) {545    llvm::consumeError(OF.takeError());546    return;547  }548  if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {549    // Collect the swift reflection sections before emitting them. This is550    // done so we control the order they're emitted.551    std::array<std::optional<object::SectionRef>,552               Swift5ReflectionSectionKind::last + 1>553        SwiftSections;554    for (auto &Section : MO->sections()) {555      llvm::Expected<llvm::StringRef> NameOrErr =556          MO->getSectionName(Section.getRawDataRefImpl());557      if (!NameOrErr) {558        llvm::consumeError(NameOrErr.takeError());559        continue;560      }561      NameOrErr->consume_back("__TEXT");562      auto ReflSectionKind =563          MO->mapReflectionSectionNameToEnumValue(*NameOrErr);564      if (MO->isReflectionSectionStrippable(ReflSectionKind))565        SwiftSections[ReflSectionKind] = Section;566    }567    // Make sure we copy the sections in alphabetic order.568    auto SectionKindsToEmit = {Swift5ReflectionSectionKind::assocty,569                               Swift5ReflectionSectionKind::fieldmd,570                               Swift5ReflectionSectionKind::reflstr};571    for (auto SectionKind : SectionKindsToEmit) {572      if (!SwiftSections[SectionKind])573        continue;574      auto &Section = *SwiftSections[SectionKind];575      llvm::Expected<llvm::StringRef> SectionContents = Section.getContents();576      if (!SectionContents)577        continue;578      const auto *MO =579          llvm::cast<llvm::object::MachOObjectFile>(Section.getObject());580      collectRelocationsToApplyToSwiftReflectionSections(581          Section, *SectionContents, MO, SectionToOffsetInDwarf, Obj,582          RelocationsToApply);583      // Update the section start with the current section's contribution, so584      // the next section we copy from a different .o file points to the correct585      // place.586      SectionToOffsetInDwarf[SectionKind] += Section.getSize();587      Streamer->emitSwiftReflectionSection(SectionKind, *SectionContents,588                                           Section.getAlignment().value(),589                                           Section.getSize());590    }591  }592}593 594bool DwarfLinkerForBinary::link(const DebugMap &Map) {595  if (Options.DWARFLinkerType == DsymutilDWARFLinkerType::Parallel)596    return linkImpl<parallel::DWARFLinker>(Map, Options.FileType);597 598  return linkImpl<classic::DWARFLinker>(Map, Options.FileType);599}600 601template <typename Linker>602void setAcceleratorTables(Linker &GeneralLinker,603                          DsymutilAccelTableKind TableKind,604                          uint16_t MaxDWARFVersion) {605  switch (TableKind) {606  case DsymutilAccelTableKind::Apple:607    GeneralLinker.addAccelTableKind(Linker::AccelTableKind::Apple);608    return;609  case DsymutilAccelTableKind::Dwarf:610    GeneralLinker.addAccelTableKind(Linker::AccelTableKind::DebugNames);611    return;612  case DsymutilAccelTableKind::Pub:613    GeneralLinker.addAccelTableKind(Linker::AccelTableKind::Pub);614    return;615  case DsymutilAccelTableKind::Default:616    if (MaxDWARFVersion >= 5)617      GeneralLinker.addAccelTableKind(Linker::AccelTableKind::DebugNames);618    else619      GeneralLinker.addAccelTableKind(Linker::AccelTableKind::Apple);620    return;621  case DsymutilAccelTableKind::None:622    // Nothing to do.623    return;624  }625 626  llvm_unreachable("All cases handled above!");627}628 629template <typename Linker>630bool DwarfLinkerForBinary::linkImpl(631    const DebugMap &Map, typename Linker::OutputFileType ObjectType) {632 633  std::vector<ObjectWithRelocMap> ObjectsForLinking;634 635  DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());636 637  std::unique_ptr<Linker> GeneralLinker = Linker::createLinker(638      [&](const Twine &Error, StringRef Context, const DWARFDie *DIE) {639        reportError(Error, Context, DIE);640      },641      [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {642        reportWarning(Warning, Context, DIE);643      });644 645  std::unique_ptr<classic::DwarfStreamer> Streamer;646  if (!Options.NoOutput) {647    if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr =648            classic::DwarfStreamer::createStreamer(649                Map.getTriple(), ObjectType, OutFile,650                [&](const Twine &Warning, StringRef Context,651                    const DWARFDie *DIE) {652                  reportWarning(Warning, Context, DIE);653                }))654      Streamer = std::move(*StreamerOrErr);655    else {656      handleAllErrors(StreamerOrErr.takeError(), [&](const ErrorInfoBase &EI) {657        reportError(EI.message(), "dwarf streamer init");658      });659      return false;660    }661 662    if constexpr (std::is_same<Linker, parallel::DWARFLinker>::value) {663      GeneralLinker->setOutputDWARFHandler(664          Map.getTriple(),665          [&](std::shared_ptr<parallel::SectionDescriptorBase> Section) {666            Streamer->emitSectionContents(Section->getContents(),667                                          Section->getKind());668          });669    } else670      GeneralLinker->setOutputDWARFEmitter(Streamer.get());671  }672 673  remarks::RemarkLinker RL;674  if (!Options.RemarksPrependPath.empty())675    RL.setExternalFilePrependPath(Options.RemarksPrependPath);676  RL.setKeepAllRemarks(Options.RemarksKeepAll);677  GeneralLinker->setObjectPrefixMap(&Options.ObjectPrefixMap);678 679  GeneralLinker->setVerbosity(Options.Verbose);680  GeneralLinker->setStatistics(Options.Statistics);681  GeneralLinker->setVerifyInputDWARF(Options.VerifyInputDWARF);682  GeneralLinker->setNoODR(Options.NoODR);683  GeneralLinker->setUpdateIndexTablesOnly(Options.Update);684  GeneralLinker->setNumThreads(Options.Threads);685  GeneralLinker->setPrependPath(Options.PrependPath);686  GeneralLinker->setKeepFunctionForStatic(Options.KeepFunctionForStatic);687  GeneralLinker->setInputVerificationHandler(688      [&](const DWARFFile &File, llvm::StringRef Output) {689        std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);690        if (Options.Verbose)691          errs() << Output;692        warn("input verification failed", File.FileName);693        HasVerificationErrors = true;694      });695  auto Loader = [&](StringRef ContainerName,696                    StringRef Path) -> ErrorOr<DWARFFile &> {697    auto &Obj = DebugMap.addDebugMapObject(698        Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);699 700    auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();701    if (ErrorOr<std::unique_ptr<DWARFFile>> ErrorOrObj =702            loadObject(Obj, DebugMap, RL, DLBRelocMap)) {703      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);704      return *ObjectsForLinking.back().Object;705    } else {706      // Try and emit more helpful warnings by applying some heuristics.707      StringRef ObjFile = ContainerName;708      bool IsClangModule = sys::path::extension(Path) == ".pcm";709      bool IsArchive = ObjFile.ends_with(")");710 711      if (IsClangModule) {712        StringRef ModuleCacheDir = sys::path::parent_path(Path);713        if (sys::fs::exists(ModuleCacheDir)) {714          // If the module's parent directory exists, we assume that the715          // module cache has expired and was pruned by clang.  A more716          // adventurous dsymutil would invoke clang to rebuild the module717          // now.718          if (!ModuleCacheHintDisplayed) {719            WithColor::note()720                << "The clang module cache may have expired since "721                   "this object file was built. Rebuilding the "722                   "object file will rebuild the module cache.\n";723            ModuleCacheHintDisplayed = true;724          }725        } else if (IsArchive) {726          // If the module cache directory doesn't exist at all and the727          // object file is inside a static library, we assume that the728          // static library was built on a different machine. We don't want729          // to discourage module debugging for convenience libraries within730          // a project though.731          if (!ArchiveHintDisplayed) {732            WithColor::note()733                << "Linking a static library that was built with "734                   "-gmodules, but the module cache was not found.  "735                   "Redistributable static libraries should never be "736                   "built with module debugging enabled.  The debug "737                   "experience will be degraded due to incomplete "738                   "debug information.\n";739            ArchiveHintDisplayed = true;740          }741        }742      }743 744      return ErrorOrObj.getError();745    }746 747    llvm_unreachable("Unhandled DebugMap object");748  };749  GeneralLinker->setSwiftInterfacesMap(&ParseableSwiftInterfaces);750  bool ReflectionSectionsPresentInBinary = false;751  // If there is no output specified, no point in checking the binary for swift5752  // reflection sections.753  if (!Options.NoOutput) {754    ReflectionSectionsPresentInBinary =755        binaryHasStrippableSwiftReflectionSections(Map, Options, BinHolder);756  }757 758  std::vector<MachOUtils::DwarfRelocationApplicationInfo> RelocationsToApply;759  if (!Options.NoOutput && !ReflectionSectionsPresentInBinary) {760    auto SectionToOffsetInDwarf =761        calculateStartOfStrippableReflectionSections(Map);762    for (const auto &Obj : Map.objects())763      copySwiftReflectionMetadata(Obj.get(), Streamer.get(),764                                  SectionToOffsetInDwarf, RelocationsToApply);765  }766 767  uint16_t MaxDWARFVersion = 0;768  std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =769      [&MaxDWARFVersion](const DWARFUnit &Unit) {770        MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);771      };772 773  llvm::StringSet<> SwiftModules;774  for (const auto &Obj : Map.objects()) {775    // N_AST objects (swiftmodule files) should get dumped directly into the776    // appropriate DWARF section.777    if (Obj->getType() == MachO::N_AST) {778      if (Options.Verbose)779        outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";780 781      StringRef File = Obj->getObjectFilename();782      if (!SwiftModules.insert(File).second)783        continue;784 785      auto ErrorOrMem = MemoryBuffer::getFile(File);786      if (!ErrorOrMem) {787        reportWarning("Could not open '" + File + "'");788        continue;789      }790      auto FromInterfaceOrErr =791          IsBuiltFromSwiftInterface((*ErrorOrMem)->getBuffer());792      if (!FromInterfaceOrErr) {793        reportWarning("Could not parse binary Swift module: " +794                          toString(FromInterfaceOrErr.takeError()),795                      Obj->getObjectFilename());796        // Only skip swiftmodules that could be parsed and are positively797        // identified as textual. Do so only when the option allows.798      } else if (*FromInterfaceOrErr &&799                 !Options.IncludeSwiftModulesFromInterface) {800        if (Options.Verbose)801          outs() << "Skipping compiled textual Swift interface: "802                 << Obj->getObjectFilename() << "\n";803        continue;804      }805 806      sys::fs::file_status Stat;807      if (auto Err = sys::fs::status(File, Stat)) {808        reportWarning(Err.message());809        continue;810      }811      if (!Options.NoTimestamp) {812        // The modification can have sub-second precision so we need to cast813        // away the extra precision that's not present in the debug map.814        auto ModificationTime =815            std::chrono::time_point_cast<std::chrono::seconds>(816                Stat.getLastModificationTime());817        if (Obj->getTimestamp() != sys::TimePoint<>() &&818            ModificationTime != Obj->getTimestamp()) {819          // Not using the helper here as we can easily stream TimePoint<>.820          WithColor::warning()821              << File << ": timestamp mismatch between swift interface file ("822              << sys::TimePoint<>(ModificationTime) << ") and debug map ("823              << sys::TimePoint<>(Obj->getTimestamp()) << ")\n";824          continue;825        }826      }827 828      // Copy the module into the .swift_ast section.829      if (!Options.NoOutput)830        Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());831 832      continue;833    }834 835    auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();836    if (ErrorOr<std::unique_ptr<DWARFFile>> ErrorOrObj =837            loadObject(*Obj, Map, RL, DLBRelocMap)) {838      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);839      GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object, Loader,840                                   OnCUDieLoaded);841    } else {842      ObjectsForLinking.push_back(843          {std::make_unique<DWARFFile>(Obj->getObjectFilename(), nullptr,844                                       nullptr),845           DLBRelocMap});846      GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object);847    }848  }849 850  // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.851  if (MaxDWARFVersion == 0)852    MaxDWARFVersion = 3;853 854  if (Error E = GeneralLinker->setTargetDWARFVersion(MaxDWARFVersion))855    return error(toString(std::move(E)));856 857  setAcceleratorTables<Linker>(*GeneralLinker, Options.TheAccelTableKind,858                               MaxDWARFVersion);859 860  // link debug info for loaded object files.861  if (Error E = GeneralLinker->link())862    return error(toString(std::move(E)));863 864  StringRef ArchName = Map.getTriple().getArchName();865  if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))866    return error(toString(std::move(E)));867 868  if (Options.NoOutput)869    return true;870 871  if (Error E = emitRelocations(Map, ObjectsForLinking))872    return error(toString(std::move(E)));873 874  if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {875    StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());876    if (auto E = copySwiftInterfaces(ArchName))877      return error(toString(std::move(E)));878  }879 880  auto MapTriple = Map.getTriple();881  if ((MapTriple.isOSDarwin() || MapTriple.isOSBinFormatMachO()) &&882      !Map.getBinaryPath().empty() &&883      ObjectType == Linker::OutputFileType::Object)884    return MachOUtils::generateDsymCompanion(885        Options.VFS, Map, *Streamer->getAsmPrinter().OutStreamer, OutFile,886        RelocationsToApply);887 888  Streamer->finish();889  return true;890}891 892/// Iterate over the relocations of the given \p Section and893/// store the ones that correspond to debug map entries into the894/// ValidRelocs array.895void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(896    const object::SectionRef &Section, const object::MachOObjectFile &Obj,897    const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) {898  Expected<StringRef> ContentsOrErr = Section.getContents();899  if (!ContentsOrErr) {900    consumeError(ContentsOrErr.takeError());901    Linker.reportWarning("error reading section", DMO.getObjectFilename());902    return;903  }904  DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0);905  bool SkipNext = false;906 907  for (const object::RelocationRef &Reloc : Section.relocations()) {908    if (SkipNext) {909      SkipNext = false;910      continue;911    }912 913    object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();914    MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);915 916    if (object::MachOObjectFile::isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),917                           Obj.getArch())) {918      SkipNext = true;919      Linker.reportWarning("unsupported relocation in " + *Section.getName() +920                               " section.",921                           DMO.getObjectFilename());922      continue;923    }924 925    unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);926    uint64_t Offset64 = Reloc.getOffset();927    if ((RelocSize != 4 && RelocSize != 8)) {928      Linker.reportWarning("unsupported relocation in " + *Section.getName() +929                               " section.",930                           DMO.getObjectFilename());931      continue;932    }933    uint64_t OffsetCopy = Offset64;934    // Mach-o uses REL relocations, the addend is at the relocation offset.935    uint64_t Addend = Data.getUnsigned(&OffsetCopy, RelocSize);936    uint64_t SymAddress;937    int64_t SymOffset;938 939    if (Obj.isRelocationScattered(MachOReloc)) {940      // The address of the base symbol for scattered relocations is941      // stored in the reloc itself. The actual addend will store the942      // base address plus the offset.943      SymAddress = Obj.getScatteredRelocationValue(MachOReloc);944      SymOffset = int64_t(Addend) - SymAddress;945    } else {946      SymAddress = Addend;947      SymOffset = 0;948    }949 950    auto Sym = Reloc.getSymbol();951    if (Sym != Obj.symbol_end()) {952      Expected<StringRef> SymbolName = Sym->getName();953      if (!SymbolName) {954        consumeError(SymbolName.takeError());955        Linker.reportWarning("error getting relocation symbol name.",956                             DMO.getObjectFilename());957        continue;958      }959      if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))960        ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping->getKey(),961                                 Mapping->getValue());962    } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {963      // Do not store the addend. The addend was the address of the symbol in964      // the object file, the address in the binary that is stored in the debug965      // map doesn't need to be offset.966      ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset,967                               Mapping->getKey(), Mapping->getValue());968    }969  }970}971 972/// Dispatch the valid relocation finding logic to the973/// appropriate handler depending on the object file format.974bool DwarfLinkerForBinary::AddressManager::findValidRelocs(975    const object::SectionRef &Section, const object::ObjectFile &Obj,976    const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) {977  // Dispatch to the right handler depending on the file type.978  if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))979    findValidRelocsMachO(Section, *MachOObj, DMO, Relocs);980  else981    Linker.reportWarning(Twine("unsupported object file type: ") +982                             Obj.getFileName(),983                         DMO.getObjectFilename());984  if (Relocs.empty())985    return false;986 987  // Sort the relocations by offset. We will walk the DIEs linearly in988  // the file, this allows us to just keep an index in the relocation989  // array that we advance during our walk, rather than resorting to990  // some associative container. See DwarfLinkerForBinary::NextValidReloc.991  llvm::sort(Relocs);992  return true;993}994 995/// Look for relocations in the debug_info and debug_addr section that match996/// entries in the debug map. These relocations will drive the Dwarf link by997/// indicating which DIEs refer to symbols present in the linked binary.998/// \returns whether there are any valid relocations in the debug info.999bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections(1000    const object::ObjectFile &Obj, const DebugMapObject &DMO) {1001  // Find the debug_info section.1002  bool FoundValidRelocs = false;1003  for (const object::SectionRef &Section : Obj.sections()) {1004    StringRef SectionName;1005    if (Expected<StringRef> NameOrErr = Section.getName())1006      SectionName = *NameOrErr;1007    else1008      consumeError(NameOrErr.takeError());1009 1010    SectionName = SectionName.substr(SectionName.find_first_not_of("._"));1011    if (SectionName == "debug_info")1012      FoundValidRelocs |=1013          findValidRelocs(Section, Obj, DMO, ValidDebugInfoRelocs);1014    if (SectionName == "debug_addr")1015      FoundValidRelocs |=1016          findValidRelocs(Section, Obj, DMO, ValidDebugAddrRelocs);1017  }1018  return FoundValidRelocs;1019}1020 1021std::vector<ValidReloc> DwarfLinkerForBinary::AddressManager::getRelocations(1022    const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {1023  std::vector<ValidReloc> Res;1024 1025  auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {1026    return (uint64_t)Reloc.Offset < StartPos;1027  });1028 1029  while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&1030         (uint64_t)CurReloc->Offset < EndPos) {1031    Res.push_back(*CurReloc);1032    CurReloc++;1033  }1034 1035  return Res;1036}1037 1038void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) {1039  const auto &Mapping = Reloc.SymbolMapping;1040  const uint64_t ObjectAddress = Mapping.ObjectAddress1041                                     ? uint64_t(*Mapping.ObjectAddress)1042                                     : std::numeric_limits<uint64_t>::max();1043 1044  outs() << "Found valid debug map entry: " << Reloc.SymbolName << "\t"1045         << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,1046                   uint64_t(Mapping.BinaryAddress));1047}1048 1049int64_t1050DwarfLinkerForBinary::AddressManager::getRelocValue(const ValidReloc &Reloc) {1051  int64_t AddrAdjust = relocate(Reloc);1052  if (Reloc.SymbolMapping.ObjectAddress)1053    AddrAdjust -= uint64_t(*Reloc.SymbolMapping.ObjectAddress);1054  return AddrAdjust;1055}1056 1057std::optional<int64_t>1058DwarfLinkerForBinary::AddressManager::hasValidRelocationAt(1059    const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset,1060    uint64_t EndOffset, bool Verbose) {1061  std::vector<ValidReloc> Relocs =1062      getRelocations(AllRelocs, StartOffset, EndOffset);1063  if (Relocs.size() == 0)1064    return std::nullopt;1065 1066  if (Verbose)1067    printReloc(Relocs[0]);1068 1069  return getRelocValue(Relocs[0]);1070}1071 1072/// Get the starting and ending (exclusive) offset for the1073/// attribute with index \p Idx descibed by \p Abbrev. \p Offset is1074/// supposed to point to the position of the first attribute described1075/// by \p Abbrev.1076/// \return [StartOffset, EndOffset) as a pair.1077static std::pair<uint64_t, uint64_t>1078getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,1079                    uint64_t Offset, const DWARFUnit &Unit) {1080  DataExtractor Data = Unit.getDebugInfoExtractor();1081 1082  for (unsigned I = 0; I < Idx; ++I)1083    DWARFFormValue::skipValue(Abbrev->getFormByIndex(I), Data, &Offset,1084                              Unit.getFormParams());1085 1086  uint64_t End = Offset;1087  DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End,1088                            Unit.getFormParams());1089 1090  return std::make_pair(Offset, End);1091}1092 1093std::optional<int64_t>1094DwarfLinkerForBinary::AddressManager::getExprOpAddressRelocAdjustment(1095    DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,1096    uint64_t EndOffset, bool Verbose) {1097  switch (Op.getCode()) {1098  default: {1099    assert(false && "Specified operation does not have address operand");1100  } break;1101  case dwarf::DW_OP_const2u:1102  case dwarf::DW_OP_const4u:1103  case dwarf::DW_OP_const8u:1104  case dwarf::DW_OP_const2s:1105  case dwarf::DW_OP_const4s:1106  case dwarf::DW_OP_const8s:1107  case dwarf::DW_OP_addr: {1108    return hasValidRelocationAt(ValidDebugInfoRelocs, StartOffset, EndOffset,1109                                Verbose);1110  } break;1111  case dwarf::DW_OP_constx:1112  case dwarf::DW_OP_addrx: {1113    return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset,1114                                Verbose);1115  } break;1116  }1117 1118  return std::nullopt;1119}1120 1121std::optional<int64_t>1122DwarfLinkerForBinary::AddressManager::getSubprogramRelocAdjustment(1123    const DWARFDie &DIE, bool Verbose) {1124  const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();1125 1126  std::optional<uint32_t> LowPcIdx =1127      Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);1128  if (!LowPcIdx)1129    return std::nullopt;1130 1131  dwarf::Form Form = Abbrev->getFormByIndex(*LowPcIdx);1132 1133  switch (Form) {1134  case dwarf::DW_FORM_addr: {1135    uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());1136    uint64_t LowPcOffset, LowPcEndOffset;1137    std::tie(LowPcOffset, LowPcEndOffset) =1138        getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit());1139    return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset,1140                                LowPcEndOffset, Verbose);1141  }1142  case dwarf::DW_FORM_addrx:1143  case dwarf::DW_FORM_addrx1:1144  case dwarf::DW_FORM_addrx2:1145  case dwarf::DW_FORM_addrx3:1146  case dwarf::DW_FORM_addrx4: {1147    std::optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);1148    if (std::optional<uint64_t> AddressOffset =1149            DIE.getDwarfUnit()->getIndexedAddressOffset(1150                AddrValue->getRawUValue()))1151      return hasValidRelocationAt(1152          ValidDebugAddrRelocs, *AddressOffset,1153          *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(), Verbose);1154 1155    Linker.reportWarning("no base offset for address table", SrcFileName);1156    return std::nullopt;1157  }1158  default:1159    return std::nullopt;1160  }1161}1162 1163std::optional<StringRef>1164DwarfLinkerForBinary::AddressManager::getLibraryInstallName() {1165  return LibInstallName;1166}1167 1168uint64_t1169DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {1170  return Reloc.SymbolMapping.BinaryAddress + Reloc.Addend;1171}1172 1173void DwarfLinkerForBinary::AddressManager::updateAndSaveValidRelocs(1174    bool IsDWARF5, uint64_t OriginalUnitOffset, int64_t LinkedOffset,1175    uint64_t StartOffset, uint64_t EndOffset) {1176  std::vector<ValidReloc> InRelocs =1177      getRelocations(ValidDebugInfoRelocs, StartOffset, EndOffset);1178  if (IsDWARF5)1179    InRelocs = getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);1180  DwarfLinkerRelocMap->updateAndSaveValidRelocs(1181      IsDWARF5, InRelocs, OriginalUnitOffset, LinkedOffset);1182}1183 1184void DwarfLinkerForBinary::AddressManager::updateRelocationsWithUnitOffset(1185    uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {1186  DwarfLinkerRelocMap->updateRelocationsWithUnitOffset(OriginalUnitOffset,1187                                                       OutputUnitOffset);1188}1189/// Apply the valid relocations found by findValidRelocs() to1190/// the buffer \p Data, taking into account that Data is at \p BaseOffset1191/// in the debug_info section.1192///1193/// Like for findValidRelocs(), this function must be called with1194/// monotonic \p BaseOffset values.1195///1196/// \returns whether any reloc has been applied.1197bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(1198    MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {1199 1200  std::vector<ValidReloc> Relocs = getRelocations(1201      ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());1202 1203  for (const ValidReloc &CurReloc : Relocs) {1204    assert(CurReloc.Offset - BaseOffset < Data.size());1205    assert(CurReloc.Offset - BaseOffset + CurReloc.Size <= Data.size());1206    char Buf[8];1207    uint64_t Value = relocate(CurReloc);1208    for (unsigned I = 0; I != CurReloc.Size; ++I) {1209      unsigned Index = IsLittleEndian ? I : (CurReloc.Size - I - 1);1210      Buf[I] = uint8_t(Value >> (Index * 8));1211    }1212    assert(CurReloc.Size <= sizeof(Buf));1213    memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);1214  }1215  return Relocs.size() > 0;1216}1217 1218void DwarfLinkerForBinaryRelocationMap::init(DWARFContext &Context) {1219  for (const std::unique_ptr<DWARFUnit> &CU : Context.compile_units())1220    StoredValidDebugInfoRelocsMap.insert(1221        std::make_pair(CU->getOffset(), std::vector<ValidReloc>()));1222  // FIXME: Support relocations debug_addr (DWARF5).1223}1224 1225void DwarfLinkerForBinaryRelocationMap::addValidRelocs(RelocationMap &RM) {1226  for (const auto &DebugInfoRelocs : StoredValidDebugInfoRelocsMap) {1227    for (const auto &InfoReloc : DebugInfoRelocs.second)1228      RM.addRelocationMapEntry(InfoReloc);1229  }1230  // FIXME: Support relocations debug_addr (DWARF5).1231}1232 1233void DwarfLinkerForBinaryRelocationMap::updateRelocationsWithUnitOffset(1234    uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {1235  std::vector<ValidReloc> &StoredValidDebugInfoRelocs =1236      StoredValidDebugInfoRelocsMap[OriginalUnitOffset];1237  for (ValidReloc &R : StoredValidDebugInfoRelocs) {1238    R.Offset = (uint64_t)R.Offset + OutputUnitOffset;1239  }1240  // FIXME: Support relocations debug_addr (DWARF5).1241}1242 1243void DwarfLinkerForBinaryRelocationMap::updateAndSaveValidRelocs(1244    bool IsDWARF5, std::vector<ValidReloc> &InRelocs, uint64_t UnitOffset,1245    int64_t LinkedOffset) {1246  std::vector<ValidReloc> &OutRelocs =1247      StoredValidDebugInfoRelocsMap[UnitOffset];1248  if (IsDWARF5)1249    OutRelocs = StoredValidDebugAddrRelocsMap[UnitOffset];1250 1251  for (ValidReloc &R : InRelocs) {1252    OutRelocs.emplace_back(R.Offset + LinkedOffset, R.Size, R.Addend,1253                           R.SymbolName, R.SymbolMapping);1254  }1255}1256 1257} // namespace dsymutil1258} // namespace llvm1259