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/Chrono.h"
23 #include "llvm/Support/Errc.h"
24 #include "llvm/Support/ErrorOr.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;
45 std::string CurrentFatBinaryName;
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
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,
58 sys::TimePoint<std::chrono::seconds> Timestamp);
60 /// Interpret Filename as an archive member specification map the
61 /// corresponding archive to memory and return the MemoryBufferRefs
62 /// corresponding to the described member. Multiple buffers are
63 /// returned when there are multiple architectures available for the
65 ErrorOr<std::vector<MemoryBufferRef>>
66 MapArchiveAndGetMemberBuffers(StringRef Filename,
67 sys::TimePoint<std::chrono::seconds> Timestamp);
69 /// Return the MemoryBufferRef that holds the memory mapping for the
70 /// given \p Filename. This function will try to parse archive
71 /// member specifications of the form /path/to/archive.a(member.o).
73 /// The returned MemoryBufferRefs points to a buffer owned by this
74 /// object. The buffer is valid until the next call to
75 /// GetMemoryBufferForFile() on this object.
76 /// Multiple buffers are returned when there are multiple
77 /// architectures available for the requested file.
78 ErrorOr<std::vector<MemoryBufferRef>>
79 GetMemoryBuffersForFile(StringRef Filename,
80 sys::TimePoint<std::chrono::seconds> Timestamp);
82 void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
83 ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
86 BinaryHolder(bool Verbose) : Verbose(Verbose) {}
88 /// Get the ObjectFiles designated by the \p Filename. This
89 /// might be an archive member specification of the form
90 /// /path/to/archive.a(member.o).
92 /// Calling this function invalidates the previous mapping owned by
93 /// the BinaryHolder. Multiple buffers are returned when there are
94 /// multiple architectures available for the requested file.
95 ErrorOr<std::vector<const object::ObjectFile *>>
96 GetObjectFiles(StringRef Filename,
97 sys::TimePoint<std::chrono::seconds> Timestamp =
98 sys::TimePoint<std::chrono::seconds>());
100 /// Wraps GetObjectFiles() to return a derived ObjectFile type.
101 template <typename ObjectFileType>
102 ErrorOr<std::vector<const ObjectFileType *>>
103 GetFilesAs(StringRef Filename,
104 sys::TimePoint<std::chrono::seconds> Timestamp =
105 sys::TimePoint<std::chrono::seconds>()) {
106 auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp);
107 if (auto Err = ErrOrObjFile.getError())
110 std::vector<const ObjectFileType *> Objects;
111 Objects.reserve((*ErrOrObjFile).size());
112 for (const auto &Obj : *ErrOrObjFile) {
113 const auto *Derived = dyn_cast<ObjectFileType>(Obj);
115 return make_error_code(object::object_error::invalid_file_type);
116 Objects.push_back(Derived);
118 return std::move(Objects);
121 /// Access the currently owned ObjectFile with architecture \p T. As
122 /// successfull call to GetObjectFiles() or GetFilesAs() must have
123 /// been performed before calling this.
124 ErrorOr<const object::ObjectFile &> Get(const Triple &T) {
125 return getObjfileForArch(T);
128 /// Access to a derived version of the currently owned
129 /// ObjectFile. The conversion must be known to be valid.
130 template <typename ObjectFileType>
131 ErrorOr<const ObjectFileType &> GetAs(const Triple &T) {
132 auto ErrOrObj = Get(T);
133 if (auto Err = ErrOrObj.getError())
135 return cast<ObjectFileType>(*ErrOrObj);