Line 1... |
Line 1... |
/* Support for memory-mapped windows into a BFD.
|
/* Support for memory-mapped windows into a BFD.
|
Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007, 2008, 2009
|
Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2011
|
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
Written by Cygnus Support.
|
Written by Cygnus Support.
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
Line 126... |
Line 126... |
if (pagesize == 0)
|
if (pagesize == 0)
|
pagesize = getpagesize ();
|
pagesize = getpagesize ();
|
if (pagesize == 0)
|
if (pagesize == 0)
|
abort ();
|
abort ();
|
|
|
if (i == 0)
|
if (i == NULL)
|
{
|
{
|
i = bfd_zmalloc (sizeof (bfd_window_internal));
|
i = bfd_zmalloc (sizeof (bfd_window_internal));
|
windowp->i = i;
|
if (i == NULL)
|
if (i == 0)
|
|
return FALSE;
|
return FALSE;
|
i->data = 0;
|
i->data = NULL;
|
}
|
}
|
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
if (ok_to_map
|
if (ok_to_map
|
&& (i->data == 0 || i->mapped == 1)
|
&& (i->data == NULL || i->mapped == 1)
|
&& (abfd->flags & BFD_IN_MEMORY) == 0)
|
&& (abfd->flags & BFD_IN_MEMORY) == 0)
|
{
|
{
|
file_ptr file_offset, offset2;
|
file_ptr file_offset, offset2;
|
size_t real_size;
|
size_t real_size;
|
int fd;
|
int fd;
|
Line 154... |
Line 153... |
|
|
/* Seek into the file, to ensure it is open if cacheable. */
|
/* Seek into the file, to ensure it is open if cacheable. */
|
if (abfd->iostream == NULL
|
if (abfd->iostream == NULL
|
&& (abfd->iovec == NULL
|
&& (abfd->iovec == NULL
|
|| abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
|
|| abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
|
return FALSE;
|
goto free_and_fail;
|
fd = fileno ((FILE *) abfd->iostream);
|
|
|
|
|
fd = fileno ((FILE *) abfd->iostream);
|
/* Compute offsets and size for mmap and for the user's data. */
|
/* Compute offsets and size for mmap and for the user's data. */
|
offset2 = offset % pagesize;
|
offset2 = offset % pagesize;
|
if (offset2 < 0)
|
if (offset2 < 0)
|
abort ();
|
abort ();
|
file_offset = offset - offset2;
|
file_offset = offset - offset2;
|
real_size = offset + size - file_offset;
|
real_size = offset + size - file_offset;
|
real_size = real_size + pagesize - 1;
|
real_size = real_size + pagesize - 1;
|
real_size -= real_size % pagesize;
|
real_size -= real_size % pagesize;
|
|
|
/* If we're re-using a memory region, make sure it's big enough. */
|
/* If we're re-using a memory region, make sure it's big enough. */
|
if (i->data && i->size < size)
|
if (i->data != NULL && i->size < size)
|
{
|
{
|
munmap (i->data, i->size);
|
munmap (i->data, i->size);
|
i->data = 0;
|
i->data = NULL;
|
}
|
}
|
i->data = mmap (i->data, real_size,
|
i->data = mmap (i->data, real_size,
|
writable ? PROT_WRITE | PROT_READ : PROT_READ,
|
writable ? PROT_WRITE | PROT_READ : PROT_READ,
|
(writable
|
(writable
|
? MAP_FILE | MAP_PRIVATE
|
? MAP_FILE | MAP_PRIVATE
|
Line 183... |
Line 182... |
if (i->data == (void *) -1)
|
if (i->data == (void *) -1)
|
{
|
{
|
/* An error happened. Report it, or try using malloc, or
|
/* An error happened. Report it, or try using malloc, or
|
something. */
|
something. */
|
bfd_set_error (bfd_error_system_call);
|
bfd_set_error (bfd_error_system_call);
|
i->data = 0;
|
|
windowp->data = 0;
|
windowp->data = 0;
|
if (debug_windows)
|
if (debug_windows)
|
fprintf (stderr, "\t\tmmap failed!\n");
|
fprintf (stderr, "\t\tmmap failed!\n");
|
return FALSE;
|
goto free_and_fail;
|
}
|
}
|
if (debug_windows)
|
if (debug_windows)
|
fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
|
fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
|
(long) real_size, i->data, (long) offset2);
|
(long) real_size, i->data, (long) offset2);
|
i->size = real_size;
|
i->size = real_size;
|
windowp->data = (bfd_byte *) i->data + offset2;
|
windowp->data = (bfd_byte *) i->data + offset2;
|
windowp->size = size;
|
windowp->size = size;
|
i->mapped = 1;
|
i->mapped = 1;
|
|
i->refcount = 1;
|
|
windowp->i = i;
|
return TRUE;
|
return TRUE;
|
}
|
}
|
else if (debug_windows)
|
else if (debug_windows)
|
{
|
{
|
if (ok_to_map)
|
if (ok_to_map)
|
Line 226... |
Line 226... |
if (debug_windows)
|
if (debug_windows)
|
fprintf (stderr, "\t-> %p\n", i->data);
|
fprintf (stderr, "\t-> %p\n", i->data);
|
if (i->data == NULL)
|
if (i->data == NULL)
|
{
|
{
|
if (size_to_alloc == 0)
|
if (size_to_alloc == 0)
|
|
{
|
|
windowp->i = i;
|
return TRUE;
|
return TRUE;
|
return FALSE;
|
}
|
|
goto free_and_fail;
|
}
|
}
|
i->refcount = 1;
|
i->refcount = 1;
|
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
|
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
|
return FALSE;
|
goto free_and_fail;
|
i->size = bfd_bread (i->data, size, abfd);
|
i->size = bfd_bread (i->data, size, abfd);
|
if (i->size != size)
|
if (i->size != size)
|
return FALSE;
|
goto free_and_fail;
|
i->mapped = 0;
|
i->mapped = 0;
|
#ifdef HAVE_MPROTECT
|
#ifdef HAVE_MPROTECT
|
if (!writable)
|
if (!writable)
|
{
|
{
|
if (debug_windows)
|
if (debug_windows)
|
Line 247... |
Line 250... |
mprotect (i->data, i->size, PROT_READ);
|
mprotect (i->data, i->size, PROT_READ);
|
}
|
}
|
#endif
|
#endif
|
windowp->data = i->data;
|
windowp->data = i->data;
|
windowp->size = i->size;
|
windowp->size = i->size;
|
|
windowp->i = i;
|
return TRUE;
|
return TRUE;
|
|
|
|
free_and_fail:
|
|
/* We have a bfd_window_internal, but an error occurred. Free it. */
|
|
free (i);
|
|
return FALSE;
|
}
|
}
|
|
|
#endif /* USE_MMAP */
|
#endif /* USE_MMAP */
|
|
|
No newline at end of file
|
No newline at end of file
|