Beispiel #1
0
error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
  OwningPtr<Binary> ret;
  if (error_code ec =
    createBinary(getBuffer(), ret))
    return ec;
  Result.swap(ret);
  return object_error::success;
}
Beispiel #2
0
error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
  OwningPtr<Binary> ret;
  OwningPtr<MemoryBuffer> Buff;
  if (error_code ec = getMemoryBuffer(Buff))
    return ec;
  if (error_code ec = createBinary(Buff.take(), ret))
    return ec;
  Result.swap(ret);
  return object_error::success;
}
Beispiel #3
0
error_code object::createBinary(MemoryBuffer *Source,
                                OwningPtr<Binary> &Result) {
  OwningPtr<MemoryBuffer> scopedSource(Source);
  if (!Source)
    return make_error_code(errc::invalid_argument);
  sys::fs::file_magic type = sys::fs::identify_magic(Source->getBuffer());
  error_code ec;
  switch (type) {
    case sys::fs::file_magic::archive: {
      OwningPtr<Binary> ret(new Archive(scopedSource.take(), ec));
      if (ec) return ec;
      Result.swap(ret);
      return object_error::success;
    }
    case sys::fs::file_magic::elf_relocatable:
    case sys::fs::file_magic::elf_executable:
    case sys::fs::file_magic::elf_shared_object:
    case sys::fs::file_magic::elf_core: {
      OwningPtr<Binary> ret(
        ObjectFile::createELFObjectFile(scopedSource.take()));
      if (!ret)
        return object_error::invalid_file_type;
      Result.swap(ret);
      return object_error::success;
    }
    case sys::fs::file_magic::macho_object:
    case sys::fs::file_magic::macho_executable:
    case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib:
    case sys::fs::file_magic::macho_core:
    case sys::fs::file_magic::macho_preload_executable:
    case sys::fs::file_magic::macho_dynamically_linked_shared_lib:
    case sys::fs::file_magic::macho_dynamic_linker:
    case sys::fs::file_magic::macho_bundle:
    case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
    case sys::fs::file_magic::macho_dsym_companion: {
      OwningPtr<Binary> ret(
        ObjectFile::createMachOObjectFile(scopedSource.take()));
      if (!ret)
        return object_error::invalid_file_type;
      Result.swap(ret);
      return object_error::success;
    }
    case sys::fs::file_magic::macho_universal_binary: {
      OwningPtr<Binary> ret(new MachOUniversalBinary(scopedSource.take(), ec));
      if (ec) return ec;
      Result.swap(ret);
      return object_error::success;
    }
    case sys::fs::file_magic::coff_object:
    case sys::fs::file_magic::pecoff_executable: {
      OwningPtr<Binary> ret(
          ObjectFile::createCOFFObjectFile(scopedSource.take()));
      if (!ret)
        return object_error::invalid_file_type;
      Result.swap(ret);
      return object_error::success;
    }
    case sys::fs::file_magic::unknown:
    case sys::fs::file_magic::bitcode: {
      // Unrecognized object file format.
      return object_error::invalid_file_type;
    }
  }
  llvm_unreachable("Unexpected Binary File Type");
}
Beispiel #4
0
error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
                                     OwningPtr<MemoryBuffer> &result,
                                     uint64_t FileSize, uint64_t MapSize,
                                     int64_t Offset,
                                     bool RequiresNullTerminator) {
  static int PageSize = sys::Process::GetPageSize();

  // Default is to map the full file.
  if (MapSize == uint64_t(-1)) {
    // If we don't know the file size, use fstat to find out.  fstat on an open
    // file descriptor is cheaper than stat on a random path.
    if (FileSize == uint64_t(-1)) {
      struct stat FileInfo;
      // TODO: This should use fstat64 when available.
      if (fstat(FD, &FileInfo) == -1) {
        return error_code(errno, posix_category());
      }
      FileSize = FileInfo.st_size;
    }
    MapSize = FileSize;
  }

  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
                    PageSize)) {
    off_t RealMapOffset = Offset & ~(PageSize - 1);
    off_t Delta = Offset - RealMapOffset;
    size_t RealMapSize = MapSize + Delta;

    if (const char *Pages = sys::Path::MapInFilePages(FD,
                                                      RealMapSize,
                                                      RealMapOffset)) {
      result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
          StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
      return error_code::success();
    }
  }

  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
  if (!Buf) {
    // Failed to create a buffer. The only way it can fail is if
    // new(std::nothrow) returns 0.
    return make_error_code(errc::not_enough_memory);
  }

  OwningPtr<MemoryBuffer> SB(Buf);
  char *BufPtr = const_cast<char*>(SB->getBufferStart());

  size_t BytesLeft = MapSize;
#ifndef HAVE_PREAD
  if (lseek(FD, Offset, SEEK_SET) == -1)
    return error_code(errno, posix_category());
#endif

  while (BytesLeft) {
#ifdef HAVE_PREAD
    ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
#else
    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
#endif
    if (NumRead == -1) {
      if (errno == EINTR)
        continue;
      // Error while reading.
      return error_code(errno, posix_category());
    }
    if (NumRead == 0) {
      assert(0 && "We got inaccurate FileSize value or fstat reported an "
                   "invalid file size.");
      *BufPtr = '\0'; // null-terminate at the actual size.
      break;
    }
    BytesLeft -= NumRead;
    BufPtr += NumRead;
  }

  result.swap(SB);
  return error_code::success();
}
Beispiel #5
0
static error_code getOpenFileImpl(int FD, const char *Filename,
                                  OwningPtr<MemoryBuffer> &result,
                                  uint64_t FileSize, uint64_t MapSize,
                                  int64_t Offset, bool RequiresNullTerminator) {
  static int PageSize = sys::process::get_self()->page_size();

  // Default is to map the full file.
  if (MapSize == uint64_t(-1)) {
    // If we don't know the file size, use fstat to find out.  fstat on an open
    // file descriptor is cheaper than stat on a random path.
    if (FileSize == uint64_t(-1)) {
      sys::fs::file_status Status;
      error_code EC = sys::fs::status(FD, Status);
      if (EC)
        return EC;

      // If this not a file or a block device (e.g. it's a named pipe
      // or character device), we can't trust the size. Create the memory
      // buffer by copying off the stream.
      sys::fs::file_type Type = Status.type();
      if (Type != sys::fs::file_type::regular_file &&
          Type != sys::fs::file_type::block_file)
        return getMemoryBufferForStream(FD, Filename, result);

      FileSize = Status.getSize();
    }
    MapSize = FileSize;
  }

  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
                    PageSize)) {
    error_code EC;
    result.reset(new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(
        RequiresNullTerminator, FD, MapSize, Offset, EC));
    if (!EC)
      return error_code::success();
  }

  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
  if (!Buf) {
    // Failed to create a buffer. The only way it can fail is if
    // new(std::nothrow) returns 0.
    return make_error_code(errc::not_enough_memory);
  }

  OwningPtr<MemoryBuffer> SB(Buf);
  char *BufPtr = const_cast<char*>(SB->getBufferStart());

  size_t BytesLeft = MapSize;
#ifndef HAVE_PREAD
  if (lseek(FD, Offset, SEEK_SET) == -1)
    return error_code(errno, posix_category());
#endif

  while (BytesLeft) {
#ifdef HAVE_PREAD
    ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
#else
    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
#endif
    if (NumRead == -1) {
      if (errno == EINTR)
        continue;
      // Error while reading.
      return error_code(errno, posix_category());
    }
    if (NumRead == 0) {
      assert(0 && "We got inaccurate FileSize value or fstat reported an "
                   "invalid file size.");
      *BufPtr = '\0'; // null-terminate at the actual size.
      break;
    }
    BytesLeft -= NumRead;
    BufPtr += NumRead;
  }

  result.swap(SB);
  return error_code::success();
}