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/Object/Archive.h" 18 #include "llvm/Object/Error.h" 19 #include "llvm/Object/ObjectFile.h" 20 #include "llvm/Support/Errc.h" 21 #include "llvm/Support/ErrorOr.h" 22 23 namespace llvm { 24 namespace dsymutil { 25 26 /// \brief The BinaryHolder class is responsible for creating and 27 /// owning ObjectFile objects and their underlying MemoryBuffer. This 28 /// is different from a simple OwningBinary in that it handles 29 /// accessing to archive members. 30 /// 31 /// As an optimization, this class will reuse an already mapped and 32 /// parsed Archive object if 2 successive requests target the same 33 /// archive file (Which is always the case in debug maps). 34 /// Currently it only owns one memory buffer at any given time, 35 /// meaning that a mapping request will invalidate the previous memory 36 /// mapping. 37 class BinaryHolder { 38 std::unique_ptr<object::Archive> CurrentArchive; 39 std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer; 40 std::unique_ptr<object::ObjectFile> CurrentObjectFile; 41 bool Verbose; 42 43 /// \brief Get the MemoryBufferRef for the file specification in \p 44 /// Filename from the current archive. 45 /// 46 /// This function performs no system calls, it just looks up a 47 /// potential match for the given \p Filename in the currently 48 /// mapped archive if there is one. 49 ErrorOr<MemoryBufferRef> GetArchiveMemberBuffer(StringRef Filename); 50 51 /// \brief Interpret Filename as an archive member specification, 52 /// map the corresponding archive to memory and return the 53 /// MemoryBufferRef corresponding to the described member. 54 ErrorOr<MemoryBufferRef> MapArchiveAndGetMemberBuffer(StringRef Filename); 55 56 /// \brief Return the MemoryBufferRef that holds the memory 57 /// mapping for the given \p Filename. This function will try to 58 /// parse archive member specifications of the form 59 /// /path/to/archive.a(member.o). 60 /// 61 /// The returned MemoryBufferRef points to a buffer owned by this 62 /// object. The buffer is valid until the next call to 63 /// GetMemoryBufferForFile() on this object. 64 ErrorOr<MemoryBufferRef> GetMemoryBufferForFile(StringRef Filename); 65 66 public: BinaryHolder(bool Verbose)67 BinaryHolder(bool Verbose) : Verbose(Verbose) {} 68 69 /// \brief Get the ObjectFile designated by the \p Filename. This 70 /// might be an archive member specification of the form 71 /// /path/to/archive.a(member.o). 72 /// 73 /// Calling this function invalidates the previous mapping owned by 74 /// the BinaryHolder. 75 ErrorOr<const object::ObjectFile &> GetObjectFile(StringRef Filename); 76 77 /// \brief Wraps GetObjectFile() to return a derived ObjectFile type. 78 template <typename ObjectFileType> GetFileAs(StringRef Filename)79 ErrorOr<const ObjectFileType &> GetFileAs(StringRef Filename) { 80 auto ErrOrObjFile = GetObjectFile(Filename); 81 if (auto Err = ErrOrObjFile.getError()) 82 return Err; 83 if (const auto *Derived = dyn_cast<ObjectFileType>(CurrentObjectFile.get())) 84 return *Derived; 85 return make_error_code(object::object_error::invalid_file_type); 86 } 87 88 /// \brief Access the currently owned ObjectFile. As successfull 89 /// call to GetObjectFile() or GetFileAs() must have been performed 90 /// before calling this. Get()91 const object::ObjectFile &Get() { 92 assert(CurrentObjectFile); 93 return *CurrentObjectFile; 94 } 95 96 /// \brief Access to a derived version of the currently owned 97 /// ObjectFile. The conversion must be known to be valid. GetAs()98 template <typename ObjectFileType> const ObjectFileType &GetAs() { 99 return cast<ObjectFileType>(*CurrentObjectFile); 100 } 101 }; 102 } 103 } 104 #endif 105