blob: 04871b5d585501fa2abb6a0876f3178c2b878784 [file] [log] [blame]
//===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This program is a utility that aims to be a dropin replacement for
// Darwin's dsymutil.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
#define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
#include "llvm/Object/Archive.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorOr.h"
namespace llvm {
namespace dsymutil {
/// \brief The BinaryHolder class is responsible for creating and
/// owning ObjectFile objects and their underlying MemoryBuffer. This
/// is different from a simple OwningBinary in that it handles
/// accessing to archive members.
///
/// As an optimization, this class will reuse an already mapped and
/// parsed Archive object if 2 successive requests target the same
/// archive file (Which is always the case in debug maps).
/// Currently it only owns one memory buffer at any given time,
/// meaning that a mapping request will invalidate the previous memory
/// mapping.
class BinaryHolder {
std::unique_ptr<object::Archive> CurrentArchive;
std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
std::unique_ptr<object::ObjectFile> CurrentObjectFile;
bool Verbose;
/// \brief Get the MemoryBufferRef for the file specification in \p
/// Filename from the current archive.
///
/// This function performs no system calls, it just looks up a
/// potential match for the given \p Filename in the currently
/// mapped archive if there is one.
ErrorOr<MemoryBufferRef> GetArchiveMemberBuffer(StringRef Filename);
/// \brief Interpret Filename as an archive member specification,
/// map the corresponding archive to memory and return the
/// MemoryBufferRef corresponding to the described member.
ErrorOr<MemoryBufferRef> MapArchiveAndGetMemberBuffer(StringRef Filename);
/// \brief Return the MemoryBufferRef that holds the memory
/// mapping for the given \p Filename. This function will try to
/// parse archive member specifications of the form
/// /path/to/archive.a(member.o).
///
/// The returned MemoryBufferRef points to a buffer owned by this
/// object. The buffer is valid until the next call to
/// GetMemoryBufferForFile() on this object.
ErrorOr<MemoryBufferRef> GetMemoryBufferForFile(StringRef Filename);
public:
BinaryHolder(bool Verbose) : Verbose(Verbose) {}
/// \brief Get the ObjectFile designated by the \p Filename. This
/// might be an archive member specification of the form
/// /path/to/archive.a(member.o).
///
/// Calling this function invalidates the previous mapping owned by
/// the BinaryHolder.
ErrorOr<const object::ObjectFile &> GetObjectFile(StringRef Filename);
/// \brief Wraps GetObjectFile() to return a derived ObjectFile type.
template <typename ObjectFileType>
ErrorOr<const ObjectFileType &> GetFileAs(StringRef Filename) {
auto ErrOrObjFile = GetObjectFile(Filename);
if (auto Err = ErrOrObjFile.getError())
return Err;
if (const auto *Derived = dyn_cast<ObjectFileType>(CurrentObjectFile.get()))
return *Derived;
return make_error_code(object::object_error::invalid_file_type);
}
/// \brief Access the currently owned ObjectFile. As successfull
/// call to GetObjectFile() or GetFileAs() must have been performed
/// before calling this.
const object::ObjectFile &Get() {
assert(CurrentObjectFile);
return *CurrentObjectFile;
}
/// \brief Access to a derived version of the currently owned
/// ObjectFile. The conversion must be known to be valid.
template <typename ObjectFileType> const ObjectFileType &GetAs() {
return cast<ObjectFileType>(*CurrentObjectFile);
}
};
}
}
#endif