brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · 53f9e18 Raw
294 lines · c
1//===- tools/dsymutil/DwarfLinkerForBinary.h --------------------*- C++ -*-===//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#ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H10#define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H11 12#include "BinaryHolder.h"13#include "DebugMap.h"14#include "LinkUtils.h"15#include "MachOUtils.h"16#include "RelocationMap.h"17#include "llvm/DebugInfo/DWARF/DWARFContext.h"18#include "llvm/Remarks/RemarkFormat.h"19#include "llvm/Remarks/RemarkLinker.h"20#include <mutex>21#include <optional>22 23namespace llvm {24using namespace dwarf_linker;25 26namespace dsymutil {27 28/// DwarfLinkerForBinaryRelocationMap contains the logic to handle the29/// relocations and to store them inside an associated RelocationMap.30class DwarfLinkerForBinaryRelocationMap {31public:32  void init(DWARFContext &Context);33 34  bool isInitialized() {35    return StoredValidDebugInfoRelocsMap.getMemorySize() != 0;36  }37 38  void addValidRelocs(RelocationMap &RM);39 40  void updateAndSaveValidRelocs(bool IsDWARF5,41                                std::vector<ValidReloc> &InRelocs,42                                uint64_t UnitOffset, int64_t LinkedOffset);43 44  void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,45                                       uint64_t OutputUnitOffset);46 47  /// Map compilation unit offset to the valid relocations to store48  /// @{49  DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugInfoRelocsMap;50  DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugAddrRelocsMap;51  /// @}52 53  DwarfLinkerForBinaryRelocationMap() = default;54};55 56struct ObjectWithRelocMap {57  ObjectWithRelocMap(58      std::unique_ptr<DWARFFile> Object,59      std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs)60      : Object(std::move(Object)), OutRelocs(OutRelocs) {}61  std::unique_ptr<DWARFFile> Object;62  std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs;63};64 65/// The core of the Dsymutil Dwarf linking logic.66///67/// The link of the dwarf information from the object files will be68/// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects69/// and pass information to the DWARFLinker. DWARFLinker70/// optimizes DWARF taking into account valid relocations.71/// Finally, optimized DWARF is passed to DwarfLinkerForBinary through72/// DWARFEmitter interface.73class DwarfLinkerForBinary {74public:75  DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,76                       LinkOptions Options, std::mutex &ErrorHandlerMutex)77      : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)),78        ErrorHandlerMutex(ErrorHandlerMutex) {}79 80  /// Link the contents of the DebugMap.81  bool link(const DebugMap &);82 83  void reportWarning(Twine Warning, Twine Context = {},84                     const DWARFDie *DIE = nullptr) const;85  void reportError(Twine Error, Twine Context = {},86                   const DWARFDie *DIE = nullptr) const;87 88  /// Returns true if input verification is enabled and verification errors were89  /// found.90  bool InputVerificationFailed() const { return HasVerificationErrors; }91 92  /// Flags passed to DwarfLinker::lookForDIEsToKeep93  enum TraversalFlags {94    TF_Keep = 1 << 0,            ///< Mark the traversed DIEs as kept.95    TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.96    TF_DependencyWalk = 1 << 2,  ///< Walking the dependencies of a kept DIE.97    TF_ParentWalk = 1 << 3,      ///< Walking up the parents of a kept DIE.98    TF_ODR = 1 << 4,             ///< Use the ODR while keeping dependents.99    TF_SkipPC = 1 << 5,          ///< Skip all location attributes.100  };101 102private:103 104  /// Keeps track of relocations.105  class AddressManager : public dwarf_linker::AddressesMap {106 107    const DwarfLinkerForBinary &Linker;108 109    /// The valid relocations for the current DebugMapObject.110    /// These vectors are sorted by relocation offset.111    /// {112    std::vector<ValidReloc> ValidDebugInfoRelocs;113    std::vector<ValidReloc> ValidDebugAddrRelocs;114    /// }115 116    StringRef SrcFileName;117 118    uint8_t DebugMapObjectType;119 120    std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DwarfLinkerRelocMap;121 122    std::optional<std::string> LibInstallName;123 124    /// Returns list of valid relocations from \p Relocs,125    /// between \p StartOffset and \p NextOffset.126    ///127    /// \returns true if any relocation is found.128    std::vector<ValidReloc>129    getRelocations(const std::vector<ValidReloc> &Relocs, uint64_t StartPos,130                   uint64_t EndPos);131 132    /// Resolve specified relocation \p Reloc.133    ///134    /// \returns resolved value.135    uint64_t relocate(const ValidReloc &Reloc) const;136 137    /// \returns value for the specified \p Reloc.138    int64_t getRelocValue(const ValidReloc &Reloc);139 140    /// Print contents of debug map entry for the specified \p Reloc.141    void printReloc(const ValidReloc &Reloc);142 143  public:144    AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,145                   const DebugMapObject &DMO,146                   std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM)147        : Linker(Linker), SrcFileName(DMO.getObjectFilename()),148          DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM) {149      if (DMO.getRelocationMap().has_value()) {150        DebugMapObjectType = MachO::N_LIB;151        LibInstallName.emplace(DMO.getInstallName().value());152        const RelocationMap &RM = DMO.getRelocationMap().value();153        for (const auto &Reloc : RM.relocations()) {154          const auto *DebugMapEntry = DMO.lookupSymbol(Reloc.SymbolName);155          if (!DebugMapEntry)156            continue;157          std::optional<uint64_t> ObjAddress;158          ObjAddress.emplace(DebugMapEntry->getValue().ObjectAddress.value());159          ValidDebugInfoRelocs.emplace_back(160              Reloc.Offset, Reloc.Size, Reloc.Addend, Reloc.SymbolName,161              SymbolMapping(ObjAddress, DebugMapEntry->getValue().BinaryAddress,162                            DebugMapEntry->getValue().Size));163          // FIXME: Support relocations debug_addr.164        }165      } else {166        findValidRelocsInDebugSections(Obj, DMO);167      }168    }169    ~AddressManager() override { clear(); }170 171    bool hasValidRelocs() override {172      return !ValidDebugInfoRelocs.empty() || !ValidDebugAddrRelocs.empty();173    }174 175    /// \defgroup FindValidRelocations Translate debug map into a list176    /// of relevant relocations177    ///178    /// @{179    bool findValidRelocsInDebugSections(const object::ObjectFile &Obj,180                                        const DebugMapObject &DMO);181 182    bool findValidRelocs(const object::SectionRef &Section,183                         const object::ObjectFile &Obj,184                         const DebugMapObject &DMO,185                         std::vector<ValidReloc> &ValidRelocs);186 187    void findValidRelocsMachO(const object::SectionRef &Section,188                              const object::MachOObjectFile &Obj,189                              const DebugMapObject &DMO,190                              std::vector<ValidReloc> &ValidRelocs);191    /// @}192 193    /// Checks that there is a relocation in the \p Relocs array against a194    /// debug map entry between \p StartOffset and \p NextOffset.195    /// Print debug output if \p Verbose is set.196    ///197    /// \returns relocation value if relocation exist, otherwise std::nullopt.198    std::optional<int64_t>199    hasValidRelocationAt(const std::vector<ValidReloc> &Relocs,200                         uint64_t StartOffset, uint64_t EndOffset,201                         bool Verbose);202 203    std::optional<int64_t> getExprOpAddressRelocAdjustment(204        DWARFUnit &U, const DWARFExpression::Operation &Op,205        uint64_t StartOffset, uint64_t EndOffset, bool Verbose) override;206 207    std::optional<int64_t> getSubprogramRelocAdjustment(const DWARFDie &DIE,208                                                        bool Verbose) override;209 210    std::optional<StringRef> getLibraryInstallName() override;211 212    bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,213                          bool IsLittleEndian) override;214 215    bool needToSaveValidRelocs() override { return true; }216 217    void updateAndSaveValidRelocs(bool IsDWARF5, uint64_t OriginalUnitOffset,218                                  int64_t LinkedOffset, uint64_t StartOffset,219                                  uint64_t EndOffset) override;220 221    void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,222                                         uint64_t OutputUnitOffset) override;223 224    void clear() override {225      ValidDebugInfoRelocs.clear();226      ValidDebugAddrRelocs.clear();227    }228  };229 230private:231  /// \defgroup Helpers Various helper methods.232  ///233  /// @{234  template <typename OutStreamer>235  bool createStreamer(const Triple &TheTriple,236                      typename OutStreamer::OutputFileType FileType,237                      std::unique_ptr<OutStreamer> &Streamer,238                      raw_fd_ostream &OutFile);239 240  /// Attempt to load a debug object from disk.241  ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,242                                                 const Triple &triple);243  ErrorOr<std::unique_ptr<dwarf_linker::DWARFFile>>244  loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,245             remarks::RemarkLinker &RL,246             std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);247 248  void collectRelocationsToApplyToSwiftReflectionSections(249      const object::SectionRef &Section, StringRef &Contents,250      const llvm::object::MachOObjectFile *MO,251      const std::vector<uint64_t> &SectionToOffsetInDwarf,252      const llvm::dsymutil::DebugMapObject *Obj,253      std::vector<MachOUtils::DwarfRelocationApplicationInfo>254          &RelocationsToApply) const;255 256  Error copySwiftInterfaces(StringRef Architecture) const;257 258  void copySwiftReflectionMetadata(259      const llvm::dsymutil::DebugMapObject *Obj,260      classic::DwarfStreamer *Streamer,261      std::vector<uint64_t> &SectionToOffsetInDwarf,262      std::vector<MachOUtils::DwarfRelocationApplicationInfo>263          &RelocationsToApply);264 265  template <typename Linker>266  bool linkImpl(const DebugMap &Map,267                typename Linker::OutputFileType ObjectType);268 269  Error emitRelocations(const DebugMap &DM,270                        std::vector<ObjectWithRelocMap> &ObjectsForLinking);271 272  raw_fd_ostream &OutFile;273  BinaryHolder &BinHolder;274  LinkOptions Options;275  std::mutex &ErrorHandlerMutex;276 277  std::vector<std::string> EmptyWarnings;278 279  /// A list of all .swiftinterface files referenced by the debug280  /// info, mapping Module name to path on disk. The entries need to281  /// be uniqued and sorted and there are only few entries expected282  /// per compile unit, which is why this is a std::map.283  std::map<std::string, std::string> ParseableSwiftInterfaces;284 285  bool ModuleCacheHintDisplayed = false;286  bool ArchiveHintDisplayed = false;287  bool HasVerificationErrors = false;288};289 290} // end namespace dsymutil291} // end namespace llvm292 293#endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H294