2015-01-06 05:29:28 +08:00
|
|
|
//===-- 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
|
|
|
|
|
2015-07-24 14:41:04 +08:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2015-01-06 05:29:28 +08:00
|
|
|
#include "llvm/Object/Archive.h"
|
|
|
|
#include "llvm/Object/Error.h"
|
2015-07-24 14:41:11 +08:00
|
|
|
#include "llvm/Object/MachOUniversal.h"
|
2015-01-06 05:29:28 +08:00
|
|
|
#include "llvm/Object/ObjectFile.h"
|
2016-11-09 19:43:52 +08:00
|
|
|
#include "llvm/Support/Chrono.h"
|
2015-01-06 05:29:28 +08:00
|
|
|
#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 {
|
2015-07-24 14:41:11 +08:00
|
|
|
std::vector<std::unique_ptr<object::Archive>> CurrentArchives;
|
2015-01-06 05:29:28 +08:00
|
|
|
std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
|
2015-07-24 14:41:11 +08:00
|
|
|
std::vector<std::unique_ptr<object::ObjectFile>> CurrentObjectFiles;
|
|
|
|
std::unique_ptr<object::MachOUniversalBinary> CurrentFatBinary;
|
2016-05-09 22:44:14 +08:00
|
|
|
std::string CurrentFatBinaryName;
|
2015-01-06 05:29:28 +08:00
|
|
|
bool Verbose;
|
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Get the MemoryBufferRefs for the file specification in \p
|
|
|
|
/// Filename from the current archive. Multiple buffers are returned
|
|
|
|
/// when there are multiple architectures available for the
|
|
|
|
/// requested file.
|
2015-01-06 05:29:28 +08:00
|
|
|
///
|
|
|
|
/// 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.
|
2015-07-24 14:41:11 +08:00
|
|
|
ErrorOr<std::vector<MemoryBufferRef>>
|
2016-11-09 19:43:52 +08:00
|
|
|
GetArchiveMemberBuffers(StringRef Filename,
|
|
|
|
sys::TimePoint<std::chrono::seconds> Timestamp);
|
2015-01-06 05:29:28 +08:00
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Interpret Filename as an archive member specification map the
|
|
|
|
/// corresponding archive to memory and return the MemoryBufferRefs
|
|
|
|
/// corresponding to the described member. Multiple buffers are
|
|
|
|
/// returned when there are multiple architectures available for the
|
|
|
|
/// requested file.
|
|
|
|
ErrorOr<std::vector<MemoryBufferRef>>
|
2016-11-09 19:43:52 +08:00
|
|
|
MapArchiveAndGetMemberBuffers(StringRef Filename,
|
|
|
|
sys::TimePoint<std::chrono::seconds> Timestamp);
|
2015-01-06 05:29:28 +08:00
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// 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).
|
2015-01-06 05:29:28 +08:00
|
|
|
///
|
2015-07-24 14:41:11 +08:00
|
|
|
/// The returned MemoryBufferRefs points to a buffer owned by this
|
2015-01-06 05:29:28 +08:00
|
|
|
/// object. The buffer is valid until the next call to
|
|
|
|
/// GetMemoryBufferForFile() on this object.
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Multiple buffers are returned when there are multiple
|
|
|
|
/// architectures available for the requested file.
|
|
|
|
ErrorOr<std::vector<MemoryBufferRef>>
|
2016-11-09 19:43:52 +08:00
|
|
|
GetMemoryBuffersForFile(StringRef Filename,
|
|
|
|
sys::TimePoint<std::chrono::seconds> Timestamp);
|
2015-01-06 05:29:28 +08:00
|
|
|
|
2017-10-13 22:41:23 +08:00
|
|
|
void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
|
|
|
|
ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
|
|
|
|
|
|
|
|
public:
|
|
|
|
BinaryHolder(bool Verbose) : Verbose(Verbose) {}
|
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Get the ObjectFiles designated by the \p Filename. This
|
2015-01-06 05:29:28 +08:00
|
|
|
/// might be an archive member specification of the form
|
|
|
|
/// /path/to/archive.a(member.o).
|
|
|
|
///
|
|
|
|
/// Calling this function invalidates the previous mapping owned by
|
2015-07-24 14:41:11 +08:00
|
|
|
/// the BinaryHolder. Multiple buffers are returned when there are
|
|
|
|
/// multiple architectures available for the requested file.
|
|
|
|
ErrorOr<std::vector<const object::ObjectFile *>>
|
|
|
|
GetObjectFiles(StringRef Filename,
|
2016-11-09 19:43:52 +08:00
|
|
|
sys::TimePoint<std::chrono::seconds> Timestamp =
|
|
|
|
sys::TimePoint<std::chrono::seconds>());
|
2015-01-06 05:29:28 +08:00
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Wraps GetObjectFiles() to return a derived ObjectFile type.
|
2015-01-06 05:29:28 +08:00
|
|
|
template <typename ObjectFileType>
|
2015-07-24 14:41:11 +08:00
|
|
|
ErrorOr<std::vector<const ObjectFileType *>>
|
|
|
|
GetFilesAs(StringRef Filename,
|
2016-11-09 19:43:52 +08:00
|
|
|
sys::TimePoint<std::chrono::seconds> Timestamp =
|
|
|
|
sys::TimePoint<std::chrono::seconds>()) {
|
2015-07-24 14:41:11 +08:00
|
|
|
auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp);
|
2015-01-06 05:29:28 +08:00
|
|
|
if (auto Err = ErrOrObjFile.getError())
|
|
|
|
return Err;
|
2015-07-24 14:41:11 +08:00
|
|
|
|
|
|
|
std::vector<const ObjectFileType *> Objects;
|
|
|
|
Objects.reserve((*ErrOrObjFile).size());
|
|
|
|
for (const auto &Obj : *ErrOrObjFile) {
|
|
|
|
const auto *Derived = dyn_cast<ObjectFileType>(Obj);
|
|
|
|
if (!Derived)
|
|
|
|
return make_error_code(object::object_error::invalid_file_type);
|
|
|
|
Objects.push_back(Derived);
|
|
|
|
}
|
|
|
|
return std::move(Objects);
|
2015-01-06 05:29:28 +08:00
|
|
|
}
|
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Access the currently owned ObjectFile with architecture \p T. As
|
|
|
|
/// successfull call to GetObjectFiles() or GetFilesAs() must have
|
|
|
|
/// been performed before calling this.
|
|
|
|
ErrorOr<const object::ObjectFile &> Get(const Triple &T) {
|
|
|
|
return getObjfileForArch(T);
|
2015-01-06 05:29:28 +08:00
|
|
|
}
|
|
|
|
|
2015-07-24 14:41:11 +08:00
|
|
|
/// Access to a derived version of the currently owned
|
2015-01-06 05:29:28 +08:00
|
|
|
/// ObjectFile. The conversion must be known to be valid.
|
2015-07-24 14:41:11 +08:00
|
|
|
template <typename ObjectFileType>
|
|
|
|
ErrorOr<const ObjectFileType &> GetAs(const Triple &T) {
|
|
|
|
auto ErrOrObj = Get(T);
|
|
|
|
if (auto Err = ErrOrObj.getError())
|
|
|
|
return Err;
|
|
|
|
return cast<ObjectFileType>(*ErrOrObj);
|
2015-01-06 05:29:28 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|