Home | History | Annotate | Download | only in dsymutil
      1 //===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This program is a utility that aims to be a dropin replacement for
     11 // Darwin's dsymutil.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
     15 #define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
     16 
     17 #include "llvm/ADT/Triple.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/Errc.h"
     23 #include "llvm/Support/ErrorOr.h"
     24 #include "llvm/Support/TimeValue.h"
     25 
     26 namespace llvm {
     27 namespace dsymutil {
     28 
     29 /// \brief The BinaryHolder class is responsible for creating and
     30 /// owning ObjectFile objects and their underlying MemoryBuffer. This
     31 /// is different from a simple OwningBinary in that it handles
     32 /// accessing to archive members.
     33 ///
     34 /// As an optimization, this class will reuse an already mapped and
     35 /// parsed Archive object if 2 successive requests target the same
     36 /// archive file (Which is always the case in debug maps).
     37 /// Currently it only owns one memory buffer at any given time,
     38 /// meaning that a mapping request will invalidate the previous memory
     39 /// mapping.
     40 class BinaryHolder {
     41   std::vector<std::unique_ptr<object::Archive>> CurrentArchives;
     42   std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
     43   std::vector<std::unique_ptr<object::ObjectFile>> CurrentObjectFiles;
     44   std::unique_ptr<object::MachOUniversalBinary> CurrentFatBinary;
     45   std::string CurrentFatBinaryName;
     46   bool Verbose;
     47 
     48   /// Get the MemoryBufferRefs for the file specification in \p
     49   /// Filename from the current archive. Multiple buffers are returned
     50   /// when there are multiple architectures available for the
     51   /// requested file.
     52   ///
     53   /// This function performs no system calls, it just looks up a
     54   /// potential match for the given \p Filename in the currently
     55   /// mapped archive if there is one.
     56   ErrorOr<std::vector<MemoryBufferRef>>
     57   GetArchiveMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
     58 
     59   /// Interpret Filename as an archive member specification map the
     60   /// corresponding archive to memory and return the MemoryBufferRefs
     61   /// corresponding to the described member. Multiple buffers are
     62   /// returned when there are multiple architectures available for the
     63   /// requested file.
     64   ErrorOr<std::vector<MemoryBufferRef>>
     65   MapArchiveAndGetMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
     66 
     67   /// Return the MemoryBufferRef that holds the memory mapping for the
     68   /// given \p Filename. This function will try to parse archive
     69   /// member specifications of the form /path/to/archive.a(member.o).
     70   ///
     71   /// The returned MemoryBufferRefs points to a buffer owned by this
     72   /// object. The buffer is valid until the next call to
     73   /// GetMemoryBufferForFile() on this object.
     74   /// Multiple buffers are returned when there are multiple
     75   /// architectures available for the requested file.
     76   ErrorOr<std::vector<MemoryBufferRef>>
     77   GetMemoryBuffersForFile(StringRef Filename, sys::TimeValue Timestamp);
     78 
     79   void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
     80   ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
     81 
     82 public:
     83   BinaryHolder(bool Verbose) : Verbose(Verbose) {}
     84 
     85   /// Get the ObjectFiles designated by the \p Filename. This
     86   /// might be an archive member specification of the form
     87   /// /path/to/archive.a(member.o).
     88   ///
     89   /// Calling this function invalidates the previous mapping owned by
     90   /// the BinaryHolder. Multiple buffers are returned when there are
     91   /// multiple architectures available for the requested file.
     92   ErrorOr<std::vector<const object::ObjectFile *>>
     93   GetObjectFiles(StringRef Filename,
     94                  sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime());
     95 
     96   /// Wraps GetObjectFiles() to return a derived ObjectFile type.
     97   template <typename ObjectFileType>
     98   ErrorOr<std::vector<const ObjectFileType *>>
     99   GetFilesAs(StringRef Filename,
    100              sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) {
    101     auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp);
    102     if (auto Err = ErrOrObjFile.getError())
    103       return Err;
    104 
    105     std::vector<const ObjectFileType *> Objects;
    106     Objects.reserve((*ErrOrObjFile).size());
    107     for (const auto &Obj : *ErrOrObjFile) {
    108       const auto *Derived = dyn_cast<ObjectFileType>(Obj);
    109       if (!Derived)
    110         return make_error_code(object::object_error::invalid_file_type);
    111       Objects.push_back(Derived);
    112     }
    113     return std::move(Objects);
    114   }
    115 
    116   /// Access the currently owned ObjectFile with architecture \p T. As
    117   /// successfull call to GetObjectFiles() or GetFilesAs() must have
    118   /// been performed before calling this.
    119   ErrorOr<const object::ObjectFile &> Get(const Triple &T) {
    120     return getObjfileForArch(T);
    121   }
    122 
    123   /// Access to a derived version of the currently owned
    124   /// ObjectFile. The conversion must be known to be valid.
    125   template <typename ObjectFileType>
    126   ErrorOr<const ObjectFileType &> GetAs(const Triple &T) {
    127     auto ErrOrObj = Get(T);
    128     if (auto Err = ErrOrObj.getError())
    129       return Err;
    130     return cast<ObjectFileType>(*ErrOrObj);
    131   }
    132 };
    133 }
    134 }
    135 #endif
    136