Example #1
0
static file_ptr
cache_btell (struct bfd *abfd)
{
  FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
  if (f == NULL)
    return abfd->where;
  return _bfd_real_ftell (f);
}
Example #2
0
static int
cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
{
  FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : CACHE_NORMAL);
  if (f == NULL)
    return -1;
  return _bfd_real_fseek (f, offset, whence);
}
Example #3
0
static int
cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
{
  FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : 0);
  if (f == NULL)
    return -1;
#if defined(__BEOS__) || defined(__HAIKU__)
  _bfdio_files[fileno(f)] = 1;
#endif
  return real_fseek (f, offset, whence);
}
Example #4
0
static int
cache_bstat (struct bfd *abfd, struct stat *sb)
{
  int sts;
  FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
  if (f == NULL)
    return -1;
  sts = fstat (fileno (f), sb);
  if (sts < 0)
    bfd_set_error (bfd_error_system_call);
  return sts;
}
Example #5
0
static int
cache_bflush (struct bfd *abfd)
{
  int sts;
  FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
  if (f == NULL)
    return 0;
  sts = fflush (f);
  if (sts < 0)
    bfd_set_error (bfd_error_system_call);
  return sts;
}
Example #6
0
static file_ptr
cache_bread_1 (struct bfd *abfd, void *buf, file_ptr nbytes)
{
  FILE *f;
  file_ptr nread;
  /* FIXME - this looks like an optimization, but it's really to cover
     up for a feature of some OSs (not solaris - sigh) that
     ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
     internally and tries to link against them.  BFD seems to be smart
     enough to realize there are no symbol records in the "file" that
     doesn't exist but attempts to read them anyway.  On Solaris,
     attempting to read zero bytes from a NULL file results in a core
     dump, but on other platforms it just returns zero bytes read.
     This makes it to something reasonable. - DJ */
  if (nbytes == 0)
    return 0;

  f = bfd_cache_lookup (abfd, CACHE_NORMAL);
  if (f == NULL)
    return 0;

#if defined (__VAX) && defined (VMS)
  /* Apparently fread on Vax VMS does not keep the record length
     information.  */
  nread = read (fileno (f), buf, nbytes);
  /* Set bfd_error if we did not read as much data as we expected.  If
     the read failed due to an error set the bfd_error_system_call,
     else set bfd_error_file_truncated.  */
  if (nread == (file_ptr)-1)
    {
      bfd_set_error (bfd_error_system_call);
      return nread;
    }
#else
  nread = fread (buf, 1, nbytes, f);
  /* Set bfd_error if we did not read as much data as we expected.  If
     the read failed due to an error set the bfd_error_system_call,
     else set bfd_error_file_truncated.  */
  if (nread < nbytes && ferror (f))
    {
      bfd_set_error (bfd_error_system_call);
      return nread;
    }
#endif
  if (nread < nbytes)
    /* This may or may not be an error, but in case the calling code
       bails out because of it, set the right error code.  */
    bfd_set_error (bfd_error_file_truncated);
  return nread;
}
Example #7
0
static file_ptr
cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
{
  file_ptr nwrite;
  FILE *f = bfd_cache_lookup (abfd, 0);
  if (f == NULL)
    return 0;
  nwrite = fwrite (where, 1, nbytes, f);
  if (nwrite < nbytes && ferror (f))
    {
      bfd_set_error (bfd_error_system_call);
      return -1;
    }
  return nwrite;
}
Example #8
0
static file_ptr
cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
{
  file_ptr nwrite;
  FILE *f = bfd_cache_lookup (abfd, 0);
  if (f == NULL)
    return 0;
#if defined(__BEOS__) || defined(__HAIKU__)
  {
    if (_bfdio_files[fileno(f)] == 1)
      {
        file_ptr eof;
        file_ptr pos;

        pos = ftell (f);
        fseek (f, 0L, SEEK_END);
        eof = ftell(f);

        if (eof < pos)
          {
            file_ptr diff;
            static char zeros[512];

            diff = pos - eof;

            while (diff >= sizeof (zeros))
              {
                fwrite(zeros, sizeof (zeros), 1, f);
                diff -= sizeof (zeros);
              }
            if (diff > 0)
              fwrite(zeros, diff, 1, f);
          }
        else
          fseek (f, pos, SEEK_SET);

        _bfdio_files[fileno(f)] = 0;
      }
  }
#endif
  nwrite = fwrite (where, 1, nbytes, f);
  if (nwrite < nbytes && ferror (f))
    {
      bfd_set_error (bfd_error_system_call);
      return -1;
    }
  return nwrite;
}
Example #9
0
static file_ptr
cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
{
  file_ptr nread = 0;
  FILE *f;

  f = bfd_cache_lookup (abfd, CACHE_NORMAL);
  if (f == NULL)
    return -1;

  /* Some filesystems are unable to handle reads that are too large
     (for instance, NetApp shares with oplocks turned off).  To avoid
     hitting this limitation, we read the buffer in chunks of 8MB max.  */
  while (nread < nbytes)
    {
      const file_ptr max_chunk_size = 0x800000;
      file_ptr chunk_size = nbytes - nread;
      file_ptr chunk_nread;

      if (chunk_size > max_chunk_size)
	chunk_size = max_chunk_size;

      chunk_nread = cache_bread_1 (f, (char *) buf + nread, chunk_size);

      /* Update the nread count.

	 We just have to be careful of the case when cache_bread_1 returns
	 a negative count:  If this is our first read, then set nread to
	 that negative count in order to return that negative value to the
	 caller.  Otherwise, don't add it to our total count, or we would
	 end up returning a smaller number of bytes read than we actually
	 did.  */
      if (nread == 0 || chunk_nread > 0)
	nread += chunk_nread;

      if (chunk_nread < chunk_size)
	break;
    }

  return nread;
}
Example #10
0
static bfd_boolean
_bfd_get_file_window_mmap(bfd *abfd, ufile_ptr offset, bfd_size_type size,
                          bfd_window *windowp, bfd_window_internal *i,
                          bfd_boolean writable)
{
  static size_t pagesize;
  bfd_size_type size_to_alloc = size;

  if (debug_windows)
    fprintf(stderr,
            "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
            (void *)abfd, (long)offset, (long)size, (void *)windowp,
            windowp->data, (unsigned long)windowp->size,
            (void *)windowp->i, writable);

  /* Make sure we know the page size, so we can be friendly to mmap: */
  if (pagesize == 0)
    pagesize = (size_t)getpagesize();
  if (pagesize == 0)
    abort();

# ifdef HAVE_MMAP
  if (ok_to_map
      && ((i->data == 0) || (i->mapped == 1))
      && ((abfd->flags & BFD_IN_MEMORY) == 0))
    {
      file_ptr file_offset, offset2;
      size_t real_size;
      int fd;
      FILE *f;

      /* Find the real file and the real offset into it: */
      while (abfd->my_archive != NULL)
	{
	  offset += abfd->origin;
	  abfd = abfd->my_archive;
	}
      f = bfd_cache_lookup(abfd);
      fd = fileno(f);

      /* Compute offsets and size for mmap and for the user's data: */
      offset2 = (file_ptr)(offset % pagesize);
      if (offset2 < 0)
	abort();
      file_offset = ((file_ptr)offset - offset2);
      real_size = (size_t)(offset + size - (unsigned long)file_offset);
      real_size = (real_size + pagesize - 1UL);
      real_size -= (real_size % pagesize);

      /* If we are re-using a memory region, make sure it is big enough: */
      if (i->data && (i->size < size))
	{
	  munmap(i->data, (size_t)i->size);
	  i->data = 0;
	}
      i->data = mmap(i->data, real_size,
                     (writable ? (PROT_WRITE | PROT_READ) : PROT_READ),
                     (writable
                      ? (MAP_FILE | MAP_PRIVATE)
                      : (MAP_FILE | MAP_SHARED)),
                     fd, (off_t)file_offset);
      if (i->data == (void *)-1)
	{
	  /* An error happened.  Report it, or try using malloc, or
	   * something: */
	  bfd_set_error(bfd_error_system_call);
	  i->data = 0;
	  windowp->data = 0;
	  if (debug_windows)
	    fprintf(stderr, "\t\tmmap failed!\n");
	  return FALSE;
	}
      if (debug_windows)
	fprintf(stderr, "\n\tmapped %ld at %p, offset is %ld\n",
                (long)real_size, i->data, (long)offset2);
      i->size = real_size;
      windowp->data = ((bfd_byte *)i->data + offset2);
      windowp->size = size;
      i->mapped = 1;
      return TRUE;
    }
  else if (debug_windows)
    {
      if (ok_to_map)
	fprintf(stderr, _("not mapping: data=%lx mapped=%d\n"),
                (unsigned long)i->data, (int)i->mapped);
      else
	fprintf(stderr, _("not mapping: env var not set\n"));
    }
# else
  ok_to_map = 0;
# endif /* HAVE_MMAP */

# ifdef HAVE_MPROTECT
  if (!writable)
    {
      size_to_alloc += (pagesize - 1);
      size_to_alloc -= (size_to_alloc % pagesize);
    }
# endif /* HAVE_MPROTECT */
  if (debug_windows)
    fprintf(stderr, "\n\t%s(%6ld)",
            (i->data ? "realloc" : " malloc"), (long)size_to_alloc);
  i->data = bfd_realloc(i->data, size_to_alloc);
  if (debug_windows)
    fprintf(stderr, "\t-> %p\n", i->data);
  i->refcount = 1;
  if (i->data == NULL)
    {
      if (size_to_alloc == 0)
	return TRUE;
      return FALSE;
    }
  if (bfd_seek(abfd, (file_ptr)offset, SEEK_SET) != 0)
    return FALSE;
  i->size = bfd_bread(i->data, size, abfd);
  if (i->size != size)
    return FALSE;
  i->mapped = 0;
# ifdef HAVE_MPROTECT
  if (!writable)
    {
      if (debug_windows)
	fprintf(stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data,
                (long)i->size);
      mprotect(i->data, i->size, PROT_READ);
    }
# endif /* HAVE_MPROTECT */
  windowp->data = i->data;
  windowp->size = i->size;
  return TRUE;
}