| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- //===-- 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;
- }
- }
- }
|