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 bool Verbose; 46 47 /// Get the MemoryBufferRefs for the file specification in \p 48 /// Filename from the current archive. Multiple buffers are returned 49 /// when there are multiple architectures available for the 50 /// requested file. 51 /// 52 /// This function performs no system calls, it just looks up a 53 /// potential match for the given \p Filename in the currently 54 /// mapped archive if there is one. 55 ErrorOr<std::vector<MemoryBufferRef>> 56 GetArchiveMemberBuffers(StringRef Filename, sys::TimeValue Timestamp); 57 58 /// Interpret Filename as an archive member specification map the 59 /// corresponding archive to memory and return the MemoryBufferRefs 60 /// corresponding to the described member. Multiple buffers are 61 /// returned when there are multiple architectures available for the 62 /// requested file. 63 ErrorOr<std::vector<MemoryBufferRef>> 64 MapArchiveAndGetMemberBuffers(StringRef Filename, sys::TimeValue Timestamp); 65 66 /// Return the MemoryBufferRef that holds the memory mapping for the 67 /// given \p Filename. This function will try to parse archive 68 /// member specifications of the form /path/to/archive.a(member.o). 69 /// 70 /// The returned MemoryBufferRefs points to a buffer owned by this 71 /// object. The buffer is valid until the next call to 72 /// GetMemoryBufferForFile() on this object. 73 /// Multiple buffers are returned when there are multiple 74 /// architectures available for the requested file. 75 ErrorOr<std::vector<MemoryBufferRef>> 76 GetMemoryBuffersForFile(StringRef Filename, sys::TimeValue Timestamp); 77 78 void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf); 79 ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T); 80 81 public: BinaryHolder(bool Verbose)82 BinaryHolder(bool Verbose) : Verbose(Verbose) {} 83 84 /// Get the ObjectFiles designated by the \p Filename. This 85 /// might be an archive member specification of the form 86 /// /path/to/archive.a(member.o). 87 /// 88 /// Calling this function invalidates the previous mapping owned by 89 /// the BinaryHolder. Multiple buffers are returned when there are 90 /// multiple architectures available for the requested file. 91 ErrorOr<std::vector<const object::ObjectFile *>> 92 GetObjectFiles(StringRef Filename, 93 sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()); 94 95 /// Wraps GetObjectFiles() to return a derived ObjectFile type. 96 template <typename ObjectFileType> 97 ErrorOr<std::vector<const ObjectFileType *>> 98 GetFilesAs(StringRef Filename, 99 sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) { 100 auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp); 101 if (auto Err = ErrOrObjFile.getError()) 102 return Err; 103 104 std::vector<const ObjectFileType *> Objects; 105 Objects.reserve((*ErrOrObjFile).size()); 106 for (const auto &Obj : *ErrOrObjFile) { 107 const auto *Derived = dyn_cast<ObjectFileType>(Obj); 108 if (!Derived) 109 return make_error_code(object::object_error::invalid_file_type); 110 Objects.push_back(Derived); 111 } 112 return std::move(Objects); 113 } 114 115 /// Access the currently owned ObjectFile with architecture \p T. As 116 /// successfull call to GetObjectFiles() or GetFilesAs() must have 117 /// been performed before calling this. Get(const Triple & T)118 ErrorOr<const object::ObjectFile &> Get(const Triple &T) { 119 return getObjfileForArch(T); 120 } 121 122 /// Access to a derived version of the currently owned 123 /// ObjectFile. The conversion must be known to be valid. 124 template <typename ObjectFileType> GetAs(const Triple & T)125 ErrorOr<const ObjectFileType &> GetAs(const Triple &T) { 126 auto ErrOrObj = Get(T); 127 if (auto Err = ErrOrObj.getError()) 128 return Err; 129 return cast<ObjectFileType>(*ErrOrObj); 130 } 131 132 static Triple getTriple(const object::MachOObjectFile &Obj); 133 }; 134 } 135 } 136 #endif 137