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: BinaryHolder(bool Verbose)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. Get(const Triple & T)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> GetAs(const Triple & T)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