mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
91bd91f22f
This object is meant to own the ObjectFiles and their underlying MemoryBuffer. It is basically the equivalent of an OwningBinary except that it efficiently handles Archives. It is optimized for efficiently providing mappings of members of the same archive when they are opened successively (which is standard in Darwin debug maps, objects from the same archive will be contiguous). Of course, the BinaryHolder will also be used by the DWARF linker once it is commited, but for now only the debug map parser uses it. With this change, you can run llvm-dsymutil on your Darwin debug build of clang and get a complete debug map for it. Differential Revision: http://reviews.llvm.org/D6690 llvm-svn: 225207
112 lines
3.6 KiB
C++
112 lines
3.6 KiB
C++
//===-- BinaryHolder.cpp --------------------------------------------------===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "BinaryHolder.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace llvm {
|
|
namespace dsymutil {
|
|
|
|
ErrorOr<MemoryBufferRef>
|
|
BinaryHolder::GetMemoryBufferForFile(StringRef Filename) {
|
|
if (Verbose)
|
|
outs() << "trying to open '" << Filename << "'\n";
|
|
|
|
// Try that first as it doesn't involve any filesystem access.
|
|
if (auto ErrOrArchiveMember = GetArchiveMemberBuffer(Filename))
|
|
return *ErrOrArchiveMember;
|
|
|
|
// If the name ends with a closing paren, there is a huge chance
|
|
// it is an archive member specification.
|
|
if (Filename.endswith(")"))
|
|
if (auto ErrOrArchiveMember = MapArchiveAndGetMemberBuffer(Filename))
|
|
return *ErrOrArchiveMember;
|
|
|
|
// Otherwise, just try opening a standard file. If this is an
|
|
// archive member specifiaction and any of the above didn't handle it
|
|
// (either because the archive is not there anymore, or because the
|
|
// archive doesn't contain the requested member), this will still
|
|
// provide a sensible error message.
|
|
auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(Filename);
|
|
if (auto Err = ErrOrFile.getError())
|
|
return Err;
|
|
|
|
if (Verbose)
|
|
outs() << "\tloaded file.\n";
|
|
CurrentArchive.reset();
|
|
CurrentMemoryBuffer = std::move(ErrOrFile.get());
|
|
return CurrentMemoryBuffer->getMemBufferRef();
|
|
}
|
|
|
|
ErrorOr<MemoryBufferRef>
|
|
BinaryHolder::GetArchiveMemberBuffer(StringRef Filename) {
|
|
if (!CurrentArchive)
|
|
return make_error_code(errc::no_such_file_or_directory);
|
|
|
|
StringRef CurArchiveName = CurrentArchive->getFileName();
|
|
if (!Filename.startswith(Twine(CurArchiveName, "(").str()))
|
|
return make_error_code(errc::no_such_file_or_directory);
|
|
|
|
// Remove the archive name and the parens around the archive member name.
|
|
Filename = Filename.substr(CurArchiveName.size() + 1).drop_back();
|
|
|
|
for (const auto &Child : CurrentArchive->children()) {
|
|
if (auto NameOrErr = Child.getName())
|
|
if (*NameOrErr == Filename) {
|
|
if (Verbose)
|
|
outs() << "\tfound member in current archive.\n";
|
|
return Child.getMemoryBufferRef();
|
|
}
|
|
}
|
|
|
|
return make_error_code(errc::no_such_file_or_directory);
|
|
}
|
|
|
|
ErrorOr<MemoryBufferRef>
|
|
BinaryHolder::MapArchiveAndGetMemberBuffer(StringRef Filename) {
|
|
StringRef ArchiveFilename = Filename.substr(0, Filename.find('('));
|
|
|
|
auto ErrOrBuff = MemoryBuffer::getFileOrSTDIN(ArchiveFilename);
|
|
if (auto Err = ErrOrBuff.getError())
|
|
return Err;
|
|
|
|
if (Verbose)
|
|
outs() << "\topened new archive '" << ArchiveFilename << "'\n";
|
|
auto ErrOrArchive = object::Archive::create((*ErrOrBuff)->getMemBufferRef());
|
|
if (auto Err = ErrOrArchive.getError())
|
|
return Err;
|
|
|
|
CurrentArchive = std::move(*ErrOrArchive);
|
|
CurrentMemoryBuffer = std::move(*ErrOrBuff);
|
|
|
|
return GetArchiveMemberBuffer(Filename);
|
|
}
|
|
|
|
ErrorOr<const object::ObjectFile &>
|
|
BinaryHolder::GetObjectFile(StringRef Filename) {
|
|
auto ErrOrMemBufferRef = GetMemoryBufferForFile(Filename);
|
|
if (auto Err = ErrOrMemBufferRef.getError())
|
|
return Err;
|
|
|
|
auto ErrOrObjectFile =
|
|
object::ObjectFile::createObjectFile(*ErrOrMemBufferRef);
|
|
if (auto Err = ErrOrObjectFile.getError())
|
|
return Err;
|
|
|
|
CurrentObjectFile = std::move(*ErrOrObjectFile);
|
|
return *CurrentObjectFile;
|
|
}
|
|
}
|
|
}
|