1 //===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This program is a utility that aims to be a dropin replacement for
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
15 #define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
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"
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.
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
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;
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
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);
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
63 ErrorOr<std::vector<MemoryBufferRef>>
64 MapArchiveAndGetMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
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).
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);
78 void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
79 ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
82 BinaryHolder(bool Verbose) : Verbose(Verbose) {}
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).
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());
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())
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);
109 return make_error_code(object::object_error::invalid_file_type);
110 Objects.push_back(Derived);
112 return std::move(Objects);
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);
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())
129 return cast<ObjectFileType>(*ErrOrObj);
132 static Triple getTriple(const object::MachOObjectFile &Obj);