brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · 27d7151 Raw
183 lines · c
1//===-- BinaryHolder.h - Utility class for accessing binaries -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This program is a utility that aims to be a dropin replacement for10// Darwin's dsymutil.11//12//===----------------------------------------------------------------------===//13#ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H14#define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H15 16#include "llvm/ADT/DenseMap.h"17#include "llvm/ADT/StringMap.h"18#include "llvm/Object/Archive.h"19#include "llvm/Object/Error.h"20#include "llvm/Object/MachOUniversal.h"21#include "llvm/Object/ObjectFile.h"22#include "llvm/Support/Chrono.h"23#include "llvm/Support/Errc.h"24#include "llvm/Support/ErrorOr.h"25#include "llvm/Support/VirtualFileSystem.h"26#include "llvm/TargetParser/Triple.h"27 28#include <mutex>29 30namespace llvm {31namespace dsymutil {32 33/// The BinaryHolder class is responsible for creating and owning34/// ObjectFiles and their underlying MemoryBuffers. It differs from a simple35/// OwningBinary in that it handles accessing and caching of archives and its36/// members.37class BinaryHolder {38public:39  using TimestampTy = sys::TimePoint<std::chrono::seconds>;40 41  struct Options {42    Options(bool Verbose = false, bool Warn = true)43        : Verbose(Verbose), Warn(Warn) {}44    bool Verbose;45    bool Warn;46  };47 48  BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS,49               BinaryHolder::Options Opts = {});50 51  // Forward declarations for friend declaration.52  class ObjectEntry;53  class ArchiveEntry;54 55  /// Base class shared by cached entries, representing objects and archives.56  class EntryBase {57  protected:58    std::unique_ptr<MemoryBuffer> MemBuffer;59    std::unique_ptr<object::MachOUniversalBinary> FatBinary;60    std::string FatBinaryName;61  };62 63  /// Cached entry holding one or more (in case of a fat binary) object files.64  class ObjectEntry : public EntryBase {65  public:66    /// Load the given object binary in memory.67    Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,68               TimestampTy Timestamp, BinaryHolder::Options = {});69 70    /// Access all owned ObjectFiles.71    std::vector<const object::ObjectFile *> getObjects() const;72 73    /// Access to a derived version of all the currently owned ObjectFiles. The74    /// conversion might be invalid, in which case an Error is returned.75    template <typename ObjectFileType>76    Expected<std::vector<const ObjectFileType *>> getObjectsAs() const {77      std::vector<const ObjectFileType *> Result;78      Result.reserve(Objects.size());79      for (auto &Object : Objects) {80        const auto *Derived = dyn_cast<ObjectFileType>(Object.get());81        if (!Derived)82          return errorCodeToError(object::object_error::invalid_file_type);83        Result.push_back(Derived);84      }85      return Result;86    }87 88    /// Access the owned ObjectFile with architecture \p T.89    Expected<const object::ObjectFile &> getObject(const Triple &T) const;90 91    /// Access to a derived version of the currently owned ObjectFile with92    /// architecture \p T. The conversion must be known to be valid.93    template <typename ObjectFileType>94    Expected<const ObjectFileType &> getObjectAs(const Triple &T) const {95      auto Object = getObject(T);96      if (!Object)97        return Object.takeError();98      return cast<ObjectFileType>(*Object);99    }100 101  private:102    std::vector<std::unique_ptr<object::ObjectFile>> Objects;103    friend ArchiveEntry;104  };105 106  /// Cached entry holding one or more (in the of a fat binary) archive files.107  class ArchiveEntry : public EntryBase {108  public:109    struct KeyTy {110      std::string Filename;111      TimestampTy Timestamp;112 113      KeyTy() = default;114      KeyTy(StringRef Filename, TimestampTy Timestamp)115          : Filename(Filename.str()), Timestamp(Timestamp) {}116    };117 118    /// Load the given object binary in memory.119    Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,120               TimestampTy Timestamp, BinaryHolder::Options = {});121 122    Expected<const ObjectEntry &> getObjectEntry(StringRef Filename,123                                                 TimestampTy Timestamp,124                                                 BinaryHolder::Options = {});125 126  private:127    std::vector<std::unique_ptr<object::Archive>> Archives;128    DenseMap<KeyTy, std::unique_ptr<ObjectEntry>> MemberCache;129    std::mutex MemberCacheMutex;130  };131 132  Expected<const ObjectEntry &>133  getObjectEntry(StringRef Filename, TimestampTy Timestamp = TimestampTy());134 135  void clear();136  void eraseObjectEntry(StringRef Filename);137 138private:139  /// Cache of static archives. Objects that are part of a static archive are140  /// stored under this object, rather than in the map below.141  StringMap<std::unique_ptr<ArchiveEntry>> ArchiveCache;142  StringMap<uint32_t> ArchiveRefCounter;143  std::mutex ArchiveCacheMutex;144 145  /// Object entries for objects that are not in a static archive.146  StringMap<std::unique_ptr<ObjectEntry>> ObjectCache;147  StringMap<uint32_t> ObjectRefCounter;148  std::mutex ObjectCacheMutex;149 150  /// Virtual File System instance.151  IntrusiveRefCntPtr<vfs::FileSystem> VFS;152 153  Options Opts;154};155 156} // namespace dsymutil157 158template <> struct DenseMapInfo<dsymutil::BinaryHolder::ArchiveEntry::KeyTy> {159 160  static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getEmptyKey() {161    return dsymutil::BinaryHolder::ArchiveEntry::KeyTy();162  }163 164  static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getTombstoneKey() {165    return dsymutil::BinaryHolder::ArchiveEntry::KeyTy("/", {});166  }167 168  static unsigned169  getHashValue(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &K) {170    return hash_combine(DenseMapInfo<StringRef>::getHashValue(K.Filename),171                        DenseMapInfo<unsigned>::getHashValue(172                            K.Timestamp.time_since_epoch().count()));173  }174 175  static bool isEqual(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &LHS,176                      const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &RHS) {177    return LHS.Filename == RHS.Filename && LHS.Timestamp == RHS.Timestamp;178  }179};180 181} // namespace llvm182#endif183