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/Object/Archive.h"
18#include "llvm/Object/Error.h"
19#include "llvm/Object/ObjectFile.h"
20#include "llvm/Support/Errc.h"
21#include "llvm/Support/ErrorOr.h"
22
23namespace llvm {
24namespace dsymutil {
25
26/// \brief The BinaryHolder class is responsible for creating and
27/// owning ObjectFile objects and their underlying MemoryBuffer. This
28/// is different from a simple OwningBinary in that it handles
29/// accessing to archive members.
30///
31/// As an optimization, this class will reuse an already mapped and
32/// parsed Archive object if 2 successive requests target the same
33/// archive file (Which is always the case in debug maps).
34/// Currently it only owns one memory buffer at any given time,
35/// meaning that a mapping request will invalidate the previous memory
36/// mapping.
37class BinaryHolder {
38  std::unique_ptr<object::Archive> CurrentArchive;
39  std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
40  std::unique_ptr<object::ObjectFile> CurrentObjectFile;
41  bool Verbose;
42
43  /// \brief Get the MemoryBufferRef for the file specification in \p
44  /// Filename from the current archive.
45  ///
46  /// This function performs no system calls, it just looks up a
47  /// potential match for the given \p Filename in the currently
48  /// mapped archive if there is one.
49  ErrorOr<MemoryBufferRef> GetArchiveMemberBuffer(StringRef Filename);
50
51  /// \brief Interpret Filename as an archive member specification,
52  /// map the corresponding archive to memory and return the
53  /// MemoryBufferRef corresponding to the described member.
54  ErrorOr<MemoryBufferRef> MapArchiveAndGetMemberBuffer(StringRef Filename);
55
56  /// \brief Return the MemoryBufferRef that holds the memory
57  /// mapping for the given \p Filename. This function will try to
58  /// parse archive member specifications of the form
59  /// /path/to/archive.a(member.o).
60  ///
61  /// The returned MemoryBufferRef points to a buffer owned by this
62  /// object. The buffer is valid until the next call to
63  /// GetMemoryBufferForFile() on this object.
64  ErrorOr<MemoryBufferRef> GetMemoryBufferForFile(StringRef Filename);
65
66public:
67  BinaryHolder(bool Verbose) : Verbose(Verbose) {}
68
69  /// \brief Get the ObjectFile designated by the \p Filename. This
70  /// might be an archive member specification of the form
71  /// /path/to/archive.a(member.o).
72  ///
73  /// Calling this function invalidates the previous mapping owned by
74  /// the BinaryHolder.
75  ErrorOr<const object::ObjectFile &> GetObjectFile(StringRef Filename);
76
77  /// \brief Wraps GetObjectFile() to return a derived ObjectFile type.
78  template <typename ObjectFileType>
79  ErrorOr<const ObjectFileType &> GetFileAs(StringRef Filename) {
80    auto ErrOrObjFile = GetObjectFile(Filename);
81    if (auto Err = ErrOrObjFile.getError())
82      return Err;
83    if (const auto *Derived = dyn_cast<ObjectFileType>(CurrentObjectFile.get()))
84      return *Derived;
85    return make_error_code(object::object_error::invalid_file_type);
86  }
87
88  /// \brief Access the currently owned ObjectFile. As successfull
89  /// call to GetObjectFile() or GetFileAs() must have been performed
90  /// before calling this.
91  const object::ObjectFile &Get() {
92    assert(CurrentObjectFile);
93    return *CurrentObjectFile;
94  }
95
96  /// \brief Access to a derived version of the currently owned
97  /// ObjectFile. The conversion must be known to be valid.
98  template <typename ObjectFileType> const ObjectFileType &GetAs() {
99    return cast<ObjectFileType>(*CurrentObjectFile);
100  }
101};
102}
103}
104#endif
105