//===-- BinaryHolder.h - Utility class for accessing binaries -------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This program is a utility that aims to be a dropin replacement for // Darwin's dsymutil. // //===----------------------------------------------------------------------===// #ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H #define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H #include "llvm/ADT/Triple.h" #include "llvm/Object/Archive.h" #include "llvm/Object/Error.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorOr.h" namespace llvm { namespace dsymutil { /// \brief The BinaryHolder class is responsible for creating and /// owning ObjectFile objects and their underlying MemoryBuffer. This /// is different from a simple OwningBinary in that it handles /// accessing to archive members. /// /// As an optimization, this class will reuse an already mapped and /// parsed Archive object if 2 successive requests target the same /// archive file (Which is always the case in debug maps). /// Currently it only owns one memory buffer at any given time, /// meaning that a mapping request will invalidate the previous memory /// mapping. class BinaryHolder { std::vector> CurrentArchives; std::unique_ptr CurrentMemoryBuffer; std::vector> CurrentObjectFiles; std::unique_ptr CurrentFatBinary; std::string CurrentFatBinaryName; bool Verbose; /// Get the MemoryBufferRefs for the file specification in \p /// Filename from the current archive. Multiple buffers are returned /// when there are multiple architectures available for the /// requested file. /// /// This function performs no system calls, it just looks up a /// potential match for the given \p Filename in the currently /// mapped archive if there is one. ErrorOr> GetArchiveMemberBuffers(StringRef Filename, sys::TimePoint Timestamp); /// Interpret Filename as an archive member specification map the /// corresponding archive to memory and return the MemoryBufferRefs /// corresponding to the described member. Multiple buffers are /// returned when there are multiple architectures available for the /// requested file. ErrorOr> MapArchiveAndGetMemberBuffers(StringRef Filename, sys::TimePoint Timestamp); /// Return the MemoryBufferRef that holds the memory mapping for the /// given \p Filename. This function will try to parse archive /// member specifications of the form /path/to/archive.a(member.o). /// /// The returned MemoryBufferRefs points to a buffer owned by this /// object. The buffer is valid until the next call to /// GetMemoryBufferForFile() on this object. /// Multiple buffers are returned when there are multiple /// architectures available for the requested file. ErrorOr> GetMemoryBuffersForFile(StringRef Filename, sys::TimePoint Timestamp); void changeBackingMemoryBuffer(std::unique_ptr &&MemBuf); ErrorOr getObjfileForArch(const Triple &T); public: BinaryHolder(bool Verbose) : Verbose(Verbose) {} /// Get the ObjectFiles designated by the \p Filename. This /// might be an archive member specification of the form /// /path/to/archive.a(member.o). /// /// Calling this function invalidates the previous mapping owned by /// the BinaryHolder. Multiple buffers are returned when there are /// multiple architectures available for the requested file. ErrorOr> GetObjectFiles(StringRef Filename, sys::TimePoint Timestamp = sys::TimePoint()); /// Wraps GetObjectFiles() to return a derived ObjectFile type. template ErrorOr> GetFilesAs(StringRef Filename, sys::TimePoint Timestamp = sys::TimePoint()) { auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp); if (auto Err = ErrOrObjFile.getError()) return Err; std::vector Objects; Objects.reserve((*ErrOrObjFile).size()); for (const auto &Obj : *ErrOrObjFile) { const auto *Derived = dyn_cast(Obj); if (!Derived) return make_error_code(object::object_error::invalid_file_type); Objects.push_back(Derived); } return std::move(Objects); } /// Access the currently owned ObjectFile with architecture \p T. As /// successfull call to GetObjectFiles() or GetFilesAs() must have /// been performed before calling this. ErrorOr Get(const Triple &T) { return getObjfileForArch(T); } /// Access to a derived version of the currently owned /// ObjectFile. The conversion must be known to be valid. template ErrorOr GetAs(const Triple &T) { auto ErrOrObj = Get(T); if (auto Err = ErrOrObj.getError()) return Err; return cast(*ErrOrObj); } }; } } #endif