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