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