Beispiel #1
0
ErrorOr<std::vector<MemoryBufferRef>>
BinaryHolder::MapArchiveAndGetMemberBuffers(
    StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
  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";

  changeBackingMemoryBuffer(std::move(*ErrOrBuff));
  std::vector<MemoryBufferRef> ArchiveBuffers;
  auto ErrOrFat = object::MachOUniversalBinary::create(
      CurrentMemoryBuffer->getMemBufferRef());
  if (!ErrOrFat) {
    consumeError(ErrOrFat.takeError());
    // Not a fat binary must be a standard one.
    ArchiveBuffers.push_back(CurrentMemoryBuffer->getMemBufferRef());
  } else {
    CurrentFatBinary = std::move(*ErrOrFat);
    CurrentFatBinaryName = ArchiveFilename;
    ArchiveBuffers = getMachOFatMemoryBuffers(
        CurrentFatBinaryName, *CurrentMemoryBuffer, *CurrentFatBinary);
  }

  for (auto MemRef : ArchiveBuffers) {
    auto ErrOrArchive = object::Archive::create(MemRef);
    if (!ErrOrArchive)
      return errorToErrorCode(ErrOrArchive.takeError());
    CurrentArchives.push_back(std::move(*ErrOrArchive));
  }
  return GetArchiveMemberBuffers(Filename, Timestamp);
}
Beispiel #2
0
ErrorOr<std::vector<MemoryBufferRef>> BinaryHolder::GetArchiveMemberBuffers(
    StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
  if (CurrentArchives.empty())
    return make_error_code(errc::no_such_file_or_directory);

  StringRef CurArchiveName = CurrentArchives.front()->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();

  std::vector<MemoryBufferRef> Buffers;
  Buffers.reserve(CurrentArchives.size());

  for (const auto &CurrentArchive : CurrentArchives) {
    Error Err = Error::success();
    for (auto Child : CurrentArchive->children(Err)) {
      if (auto NameOrErr = Child.getName()) {
        if (*NameOrErr == Filename) {
          auto ModTimeOrErr = Child.getLastModified();
          if (!ModTimeOrErr)
            return errorToErrorCode(ModTimeOrErr.takeError());
          if (Timestamp != sys::TimePoint<>() &&
              Timestamp != ModTimeOrErr.get()) {
            if (Verbose)
              outs() << "\tmember had timestamp mismatch.\n";
            continue;
          }
          if (Verbose)
            outs() << "\tfound member in current archive.\n";
          auto ErrOrMem = Child.getMemoryBufferRef();
          if (!ErrOrMem)
            return errorToErrorCode(ErrOrMem.takeError());
          Buffers.push_back(*ErrOrMem);
        }
      }
    }
    if (Err)
      return errorToErrorCode(std::move(Err));
  }

  if (Buffers.empty())
    return make_error_code(errc::no_such_file_or_directory);
  return Buffers;
}
Beispiel #3
0
void ObjectFile::parse() {
  // Parse a memory buffer as a COFF file.
  auto BinOrErr = createBinary(MB);
  if (!BinOrErr)
    error(errorToErrorCode(BinOrErr.takeError()),
                           "Failed to parse object file");
  std::unique_ptr<Binary> Bin = std::move(*BinOrErr);

  if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {
    Bin.release();
    COFFObj.reset(Obj);
  } else {
    error(Twine(getName()) + " is not a COFF file.");
  }

  // Read section and symbol tables.
  initializeChunks();
  initializeSymbols();
  initializeSEH();
}
Beispiel #4
0
ErrorOr<std::vector<const object::ObjectFile *>>
BinaryHolder::GetObjectFiles(StringRef Filename,
                             sys::TimePoint<std::chrono::seconds> Timestamp) {
  auto ErrOrMemBufferRefs = GetMemoryBuffersForFile(Filename, Timestamp);
  if (auto Err = ErrOrMemBufferRefs.getError())
    return Err;

  std::vector<const object::ObjectFile *> Objects;
  Objects.reserve(ErrOrMemBufferRefs->size());

  CurrentObjectFiles.clear();
  for (auto MemBuf : *ErrOrMemBufferRefs) {
    auto ErrOrObjectFile = object::ObjectFile::createObjectFile(MemBuf);
    if (!ErrOrObjectFile)
      return errorToErrorCode(ErrOrObjectFile.takeError());

    Objects.push_back(ErrOrObjectFile->get());
    CurrentObjectFiles.push_back(std::move(*ErrOrObjectFile));
  }

  return std::move(Objects);
}