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 26namespace llvm { 27namespace 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. 40class 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 81public: 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. 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> 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