aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog34
-rw-r--r--bfd/aoutx.h70
-rw-r--r--bfd/bfd-in.h22
-rw-r--r--bfd/bfd-in2.h29
-rw-r--r--bfd/config.in55
-rwxr-xr-xbfd/configure152
-rw-r--r--bfd/configure.in4
-rw-r--r--bfd/libbfd.c351
-rw-r--r--bfd/libcoff-in.h3
-rw-r--r--bfd/libcoff.h3
-rw-r--r--bfd/oasys.c5
-rw-r--r--bfd/targets.c9
12 files changed, 625 insertions, 112 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c0a9a34..b8fc050 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -8,6 +8,40 @@ Sun Nov 5 21:44:13 1995 Ken Raeburn <raeburn@cygnus.com>
* ecoff.c (_bfd_ecoff_slurp_armap): Cast _bfd_read_ar_hdr return
value.
+ Permit use of mmap when available:
+
+ * configure.in: Check for mmap, madvise, mprotect.
+ * config.in, configure: Regenerated.
+
+ * libbfd.c (struct _bfd_window_internal): Define type.
+ (bfd_init_window, bfd_free_window, bfd_get_file_window): New
+ functions.
+ (ok_to_map): New static variable for debugging.
+ (_bfd_generic_get_section_contents_in_window): New function.
+ * bfd-in.h (bfd_window_internal): Declare type.
+ (bfd_window): Define type.
+ (bfd_init_window, bfd_free_window, bfd_get_file_window): Declare.
+ * libbfd-in.h (_bfd_generic_get_section_contents_in_window):
+ Declare.
+
+ * libaout.h (struct aoutdata): Add two window fields.
+ (obj_aout_sym_window, obj_aout_string_window): New macros.
+ * aoutx.h (some_aout_object_p): Initialize windows.
+ (aout_get_external_symbols): Get symbol data and strings in
+ windows instead of explicitly allocated buffers.
+ (slurp_symbol_table): Free window instead of memory.
+ (bfd_free_cached_info): Release windows instead of freeing storage
+ directly.
+ (aout_link_free_symbols): Ditto.
+
+ * targets.c (bfd_target): Add new field for
+ get_section_contents_in_window.
+ (BFD_JUMP_TABLE_GENERIC): Updated.
+ * aout-adobe.c, aout-target.h, binary.c, bout.c, coff-alpha.c,
+ coff-mips.c, elfxx-target.h, i386msdos.c, i386os9k.c, ieee.c,
+ libcoff-in.h, oasys.c, srec.c, tekhex.c, versados.c: Added new
+ macros for get_section_contents_in_window field.
+
Sat Nov 4 12:23:26 1995 Fred Fish <fnf@cygnus.com>
* core.c: Renamed to corefile.c
diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index 6571302..8d7ea3a 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -497,7 +497,9 @@ NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
obj_aout_external_syms (abfd) = NULL;
+ bfd_init_window (&obj_aout_sym_window (abfd));
obj_aout_external_strings (abfd) = NULL;
+ bfd_init_window (&obj_aout_string_window (abfd));
obj_aout_sym_hashes (abfd) = NULL;
if (! NAME(aout,make_sections) (abfd))
@@ -1226,24 +1228,11 @@ aout_get_external_symbols (abfd)
count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
- /* We allocate using malloc to make the values easy to free
- later on. If we put them on the obstack it might not be
- possible to free them. */
- syms = ((struct external_nlist *)
- malloc ((size_t) count * EXTERNAL_NLIST_SIZE));
- if (syms == (struct external_nlist *) NULL && count != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
- || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd)
- != exec_hdr (abfd)->a_syms))
- {
- free (syms);
- return false;
- }
+ if (bfd_get_file_window (abfd,
+ obj_sym_filepos (abfd), exec_hdr (abfd)->a_syms,
+ &obj_aout_sym_window (abfd), 1) == false)
+ return false;
+ syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
obj_aout_external_syms (abfd) = syms;
obj_aout_external_sym_count (abfd) = count;
@@ -1263,28 +1252,25 @@ aout_get_external_symbols (abfd)
return false;
stringsize = GET_WORD (abfd, string_chars);
- strings = (char *) malloc ((size_t) stringsize + 1);
- if (strings == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* Skip space for the string count in the buffer for convenience
- when using indexes. */
- if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD,
- abfd)
- != stringsize - BYTES_IN_WORD)
- {
- free (strings);
- return false;
- }
+ if (bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize,
+ &obj_aout_string_window (abfd), 1) == false)
+ return false;
+ strings = (char *) obj_aout_string_window (abfd).data;
/* Ensure that a zero index yields an empty string. */
strings[0] = '\0';
- /* Sanity preservation. */
- strings[stringsize] = '\0';
+ /* Using the "window" interface, we don't know that there's
+ writeable storage after the last byte of the string table.
+ Besides, every string in the string table should be null
+ terminated. Check it here so the application doesn't crash,
+ but don't expend huge effort trying to correct a broken
+ object file. */
+ if (stringsize > BYTES_IN_WORD && strings[stringsize - 1] != 0)
+ {
+ fprintf (stderr, "string table missing ending null\n");
+ strings[stringsize - 1] = 0;
+ }
obj_aout_external_strings (abfd) = strings;
obj_aout_external_string_size (abfd) = stringsize;
@@ -1755,7 +1741,7 @@ NAME(aout,slurp_symbol_table) (abfd)
if (old_external_syms == (struct external_nlist *) NULL
&& obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
{
- free (obj_aout_external_syms (abfd));
+ bfd_free_window (&obj_aout_sym_window (abfd));
obj_aout_external_syms (abfd) = NULL;
}
@@ -2784,8 +2770,10 @@ NAME(aout,bfd_free_cached_info) (abfd)
#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; }
BFCI_FREE (obj_aout_symbols (abfd));
- BFCI_FREE (obj_aout_external_syms (abfd));
- BFCI_FREE (obj_aout_external_strings (abfd));
+ obj_aout_external_syms (abfd) = 0;
+ bfd_free_window (&obj_aout_sym_window (abfd));
+ bfd_free_window (&obj_aout_string_window (abfd));
+ obj_aout_external_strings (abfd) = 0;
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
BFCI_FREE (o->relocation);
#undef BFCI_FREE
@@ -2957,12 +2945,12 @@ aout_link_free_symbols (abfd)
{
if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
{
- free ((PTR) obj_aout_external_syms (abfd));
+ bfd_free_window (&obj_aout_sym_window (abfd));
obj_aout_external_syms (abfd) = (struct external_nlist *) NULL;
}
if (obj_aout_external_strings (abfd) != (char *) NULL)
{
- free ((PTR) obj_aout_external_strings (abfd));
+ bfd_free_window (&obj_aout_string_window (abfd));
obj_aout_external_strings (abfd) = (char *) NULL;
}
return true;
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index d027196..d69f763 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -600,6 +600,28 @@ extern boolean bfd_sunos_size_dynamic_sections
extern boolean bfd_linux_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+} bfd_window;
+
+void bfd_init_window PARAMS ((bfd_window *));
+void bfd_free_window PARAMS ((bfd_window *));
+int bfd_get_file_window PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, int));
+
/* XCOFF support routines for the linker. */
extern boolean bfd_xcoff_link_record_set
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 109c1fc..394979d 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -600,6 +600,28 @@ extern boolean bfd_sunos_size_dynamic_sections
extern boolean bfd_linux_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+} bfd_window;
+
+void bfd_init_window PARAMS ((bfd_window *));
+void bfd_free_window PARAMS ((bfd_window *));
+int bfd_get_file_window PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, int));
+
/* XCOFF support routines for the linker. */
extern boolean bfd_xcoff_link_record_set
@@ -2184,7 +2206,9 @@ typedef struct bfd_target
CAT(NAME,_close_and_cleanup),\
CAT(NAME,_bfd_free_cached_info),\
CAT(NAME,_new_section_hook),\
-CAT(NAME,_get_section_contents)
+CAT(NAME,_get_section_contents),\
+CAT(NAME,_get_section_contents_in_window)
+
/* Called when the BFD is being closed to do any necessary cleanup. */
boolean (*_close_and_cleanup) PARAMS ((bfd *));
/* Ask the BFD to free all cached information. */
@@ -2194,6 +2218,9 @@ CAT(NAME,_get_section_contents)
/* Read the contents of a section. */
boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *,
+ file_ptr, bfd_size_type));
/* Entry points to copy private data. */
#define BFD_JUMP_TABLE_COPY(NAME)\
diff --git a/bfd/config.in b/bfd/config.in
new file mode 100644
index 0000000..49dbce1
--- /dev/null
+++ b/bfd/config.in
@@ -0,0 +1,55 @@
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Do we need to use the b modifier when opening binary files? */
+#undef USE_BINARY_FOPEN
+
+/* Whether malloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Whether free must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_FREE
+
+/* Name of host specific header file to include in trad-core.c. */
+#undef TRAD_HEADER
+
+/* Define only if <sys/procfs.h> is available *and* it defines prstatus_t. */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define if you have the fcntl function. */
+#undef HAVE_FCNTL
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the madvise function. */
+#undef HAVE_MADVISE
+
+/* Define if you have the mprotect function. */
+#undef HAVE_MPROTECT
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
diff --git a/bfd/configure b/bfd/configure
index 724ab8a..f07af90 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -1502,6 +1502,158 @@ test -n "${selvecs}" && tdefaults="${tdefaults} -DSELECT_VECS='${selvecs}'"
test -n "${selarchs}" && tdefaults="${tdefaults} -DSELECT_ARCHITECTURES='${selarchs}'"
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_mmap'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 1514 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifdef BSD
+# ifndef BSD4_1
+# define HAVE_GETPAGESIZE
+# endif
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif
+# else
+# ifdef NBPC
+# define getpagesize() NBPC
+# else
+# define getpagesize() PAGESIZE /* SVR4 */
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __osf__
+# define valloc malloc
+#endif
+
+#ifdef __cplusplus
+extern "C" { void *valloc(unsigned), *malloc(unsigned); }
+#else
+char *valloc(), *malloc();
+#endif
+
+int
+main()
+{
+ char *buf1, *buf2, *buf3;
+ int i = getpagesize(), j;
+ int i2 = getpagesize()*2;
+ int fd;
+
+ buf1 = (char *)valloc(i2);
+ buf2 = (char *)valloc(i);
+ buf3 = (char *)malloc(i2);
+ for (j = 0; j < i2; ++j)
+ *(buf1 + j) = rand();
+ fd = open("conftestmmap", O_CREAT | O_RDWR, 0666);
+ write(fd, buf1, i2);
+ mmap(buf2, i, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, fd, 0);
+ for (j = 0; j < i; ++j)
+ if (*(buf1 + j) != *(buf2 + j))
+ exit(1);
+ lseek(fd, (long)i, 0);
+ read(fd, buf2, i); /* read into mapped memory -- file should not change */
+ /* (it does in i386 SVR4.0 - Jim Avera, jima@netcom.com) */
+ lseek(fd, (long)0, 0);
+ read(fd, buf3, i2);
+ for (j = 0; j < i2; ++j)
+ if (*(buf1 + j) != *(buf3 + j))
+ exit(1);
+ exit(0);
+}
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_mmap=yes
+else
+ ac_cv_func_mmap=no
+fi
+fi
+rm -fr conftest*
+fi
+echo "$ac_t""$ac_cv_func_mmap" 1>&6
+if test $ac_cv_func_mmap = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+for ac_func in madvise mprotect
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1613 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr '[a-z]' '[A-Z]'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
rm -f doc/config.status
trap '' 1 2 15
cat > confcache <<\EOF
diff --git a/bfd/configure.in b/bfd/configure.in
index 61e0471..8ef6b01 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -528,6 +528,10 @@ test -n "${selvecs}" && tdefaults="${tdefaults} -DSELECT_VECS='${selvecs}'"
test -n "${selarchs}" && tdefaults="${tdefaults} -DSELECT_ARCHITECTURES='${selarchs}'"
AC_SUBST(tdefaults)
+dnl AC_CHECK_HEADERS(sys/mman.h)
+AC_FUNC_MMAP
+AC_CHECK_FUNCS(madvise mprotect)
+
rm -f doc/config.status
AC_OUTPUT(Makefile doc/Makefile,
[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac])
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 2925754..5f682ec 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -16,12 +16,14 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
+static int real_read PARAMS ((PTR, size_t, size_t, FILE *));
+
/*
SECTION
Internal functions
@@ -145,10 +147,11 @@ _bfd_nocore_core_file_failing_signal (ignore_abfd)
}
/*ARGSUSED*/
-bfd_target *
+const bfd_target *
_bfd_dummy_target (ignore_abfd)
bfd *ignore_abfd;
{
+ bfd_set_error (bfd_error_wrong_format);
return 0;
}
@@ -179,15 +182,14 @@ bfd_zmalloc (size)
contents (0 for non-archive elements). For archive entries this is the
first octet in the file, NOT the beginning of the archive header. */
-static
-int
+static int
real_read (where, a,b, file)
PTR where;
- int a;
- int b;
+ size_t a;
+ size_t b;
FILE *file;
{
- return fread(where, a,b,file);
+ return fread (where, a, b, file);
}
/* Return value is amount read (FIXME: how are errors and end of file dealt
@@ -201,7 +203,7 @@ bfd_read (ptr, size, nitems, abfd)
bfd *abfd;
{
int nread;
- nread = real_read (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd));
+ nread = real_read (ptr, 1, (size_t)(size*nitems), bfd_cache_lookup(abfd));
#ifdef FILE_OFFSET_IS_CHAR_INDEX
if (nread > 0)
abfd->where += nread;
@@ -225,6 +227,219 @@ bfd_read (ptr, size, nitems, abfd)
return nread;
}
+/* The window support stuff should probably be broken out into
+ another file.... */
+/* The idea behind the next and refcount fields is that one mapped
+ region can suffice for multiple read-only windows or multiple
+ non-overlapping read-write windows. It's not implemented yet
+ though. */
+struct _bfd_window_internal {
+ struct _bfd_window_internal *next;
+ PTR data;
+ bfd_size_type size;
+ int refcount : 31; /* should be enough... */
+ unsigned mapped : 1; /* 1 = mmap, 0 = malloc */
+};
+
+void
+bfd_init_window (windowp)
+ bfd_window *windowp;
+{
+ windowp->data = 0;
+ windowp->i = 0;
+ windowp->size = 0;
+}
+
+#undef HAVE_MPROTECT /* code's not tested yet */
+
+#if HAVE_MMAP || HAVE_MPROTECT
+#include <sys/types.h>
+#include <sys/mman.h>
+#endif
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+static int debug_windows;
+
+void
+bfd_free_window (windowp)
+ bfd_window *windowp;
+{
+ bfd_window_internal *i = windowp->i;
+ windowp->i = 0;
+ windowp->data = 0;
+ if (i == 0)
+ return;
+ i->refcount--;
+ if (debug_windows)
+ fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n",
+ windowp, windowp->data, windowp->size, windowp->i);
+ if (i->refcount != 0)
+ return;
+
+ if (i->mapped)
+ {
+#ifdef HAVE_MMAP
+ munmap (i->data, i->size);
+ goto no_free;
+#else
+ abort ();
+#endif
+ }
+#ifdef HAVE_MPROTECT
+ mprotect (i->data, i->size, PROT_READ | PROT_WRITE);
+#endif
+ free (i->data);
+#ifdef HAVE_MMAP
+ no_free:
+#endif
+ i->data = 0;
+ /* There should be no more references to i at this point. */
+ free (i);
+}
+
+static int ok_to_map = 1;
+
+int
+bfd_get_file_window (abfd, offset, size, windowp, writable)
+ bfd *abfd;
+ file_ptr offset;
+ bfd_size_type size;
+ bfd_window *windowp;
+ int writable;
+{
+ static size_t pagesize;
+ bfd_window_internal *i = windowp->i;
+ size_t size_to_alloc = size;
+
+ if (debug_windows)
+ fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
+ abfd, (long) offset, (long) size,
+ windowp, windowp->data, windowp->size, windowp->i,
+ writable);
+
+ /* Make sure we know the page size, so we can be friendly to mmap. */
+ if (pagesize == 0)
+ pagesize = getpagesize ();
+ if (pagesize == 0)
+ abort ();
+
+ if (i == 0)
+ {
+ windowp->i = i = (bfd_window_internal *) bfd_zmalloc (sizeof (bfd_window_internal));
+ if (i == 0)
+ return false;
+ i->data = 0;
+ }
+#ifdef HAVE_MMAP
+ if (ok_to_map && (i->data == 0 || i->mapped == 1))
+ {
+ 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 = offset % pagesize;
+ if (offset2 < 0)
+ abort ();
+ file_offset = offset - offset2;
+ real_size = offset + size - file_offset;
+ real_size = real_size + pagesize - 1;
+ real_size -= real_size % pagesize;
+
+ /* If we're re-using a memory region, make sure it's big enough. */
+ if (i->data && i->size < size)
+ {
+ munmap (i->data, 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,
+ fd, file_offset);
+ if (i->data == (PTR) -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 = i->data + offset2;
+ windowp->size = size;
+ i->mapped = 1;
+ return true;
+ }
+ else if (debug_windows)
+ {
+ if (ok_to_map)
+ fprintf (stderr, "not mapping: data=%x mapped=%d\n",
+ i->data, i->mapped);
+ else
+ fprintf (stderr, "not mapping: env var not set\n");
+ }
+#else
+ ok_to_map = 0;
+#endif
+
+#ifdef HAVE_MPROTECT
+ if (!writable)
+ {
+ size_to_alloc += pagesize - 1;
+ size_to_alloc -= size_to_alloc % pagesize;
+ }
+#endif
+ if (debug_windows)
+ fprintf (stderr, "\n\t%s(%6ld)",
+ i->data ? "realloc" : " malloc", (long) size_to_alloc);
+ if (i->data)
+ i->data = realloc (i->data, size_to_alloc);
+ else
+ i->data = malloc (size_to_alloc);
+ if (debug_windows)
+ fprintf (stderr, "\t-> %p\n", i->data);
+ i->refcount = 1;
+ if (i->data == 0)
+ return size_to_alloc == 0;
+ if (bfd_seek (abfd, offset, SEEK_SET) != 0)
+ return false;
+ i->size = bfd_read (i->data, size, 1, 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
+ windowp->data = i->data;
+ windowp->size = i->size;
+ return true;
+}
+
bfd_size_type
bfd_write (ptr, size, nitems, abfd)
CONST PTR ptr;
@@ -232,12 +447,13 @@ bfd_write (ptr, size, nitems, abfd)
bfd_size_type nitems;
bfd *abfd;
{
- int nwrote = fwrite (ptr, 1, (int) (size * nitems), bfd_cache_lookup (abfd));
+ long nwrote = fwrite (ptr, 1, (size_t) (size * nitems),
+ bfd_cache_lookup (abfd));
#ifdef FILE_OFFSET_IS_CHAR_INDEX
if (nwrote > 0)
abfd->where += nwrote;
#endif
- if (nwrote != size * nitems)
+ if ((bfd_size_type) nwrote != size * nitems)
{
#ifdef ENOSPC
if (nwrote >= 0)
@@ -293,12 +509,25 @@ bfd_flush (abfd)
return fflush (bfd_cache_lookup(abfd));
}
+/* Returns 0 for success, negative value for failure (in which case
+ bfd_get_error can retrieve the error code). */
int
bfd_stat (abfd, statbuf)
bfd *abfd;
struct stat *statbuf;
{
- return fstat (fileno(bfd_cache_lookup(abfd)), statbuf);
+ FILE *f;
+ int result;
+ f = bfd_cache_lookup (abfd);
+ if (f == NULL)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return -1;
+ }
+ result = fstat (fileno (f), statbuf);
+ if (result < 0)
+ bfd_set_error (bfd_error_system_call);
+ return result;
}
/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
@@ -306,9 +535,9 @@ bfd_stat (abfd, statbuf)
int
bfd_seek (abfd, position, direction)
- bfd * CONST abfd;
- CONST file_ptr position;
- CONST int direction;
+ bfd *abfd;
+ file_ptr position;
+ int direction;
{
int result;
FILE *f;
@@ -383,59 +612,6 @@ bfd_seek (abfd, position, direction)
return result;
}
-/** Make a string table */
-
-/*>bfd.h<
- Add string to table pointed to by table, at location starting with free_ptr.
- resizes the table if necessary (if it's NULL, creates it, ignoring
- table_length). Updates free_ptr, table, table_length */
-
-boolean
-bfd_add_to_string_table (table, new_string, table_length, free_ptr)
- char **table;
- char *new_string;
- unsigned int *table_length;
- char **free_ptr;
-{
- size_t string_length = strlen (new_string) + 1; /* include null here */
- char *base = *table;
- size_t space_length = *table_length;
- unsigned int offset = (base ? *free_ptr - base : 0);
-
- if (base == NULL) {
- /* Avoid a useless regrow if we can (but of course we still
- take it next time). */
- space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ?
- DEFAULT_STRING_SPACE_SIZE : string_length+1);
- base = bfd_zmalloc ((bfd_size_type) space_length);
-
- if (base == NULL) {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- }
-
- if ((size_t)(offset + string_length) >= space_length) {
- /* Make sure we will have enough space */
- while ((size_t)(offset + string_length) >= space_length)
- space_length += space_length/2; /* grow by 50% */
-
- base = (char *) realloc (base, space_length);
- if (base == NULL) {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- }
-
- memcpy (base + offset, new_string, string_length);
- *table = base;
- *table_length = space_length;
- *free_ptr = base + offset + string_length;
-
- return true;
-}
-
/** The do-it-yourself (byte) sex-change kit */
/* The middle letter e.g. get<b>short indicates Big or Little endian
@@ -823,6 +999,47 @@ _bfd_generic_get_section_contents (abfd, section, location, offset, count)
return (true);
}
+boolean
+_bfd_generic_get_section_contents_in_window (abfd, section, w, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ bfd_window *w;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (count == 0)
+ return true;
+ if (abfd->xvec->_bfd_get_section_contents != _bfd_generic_get_section_contents)
+ {
+ /* We don't know what changes the bfd's get_section_contents
+ method may have to make. So punt trying to map the file
+ window, and let get_section_contents do its thing. */
+ /* @@ FIXME : If the internal window has a refcount of 1 and was
+ allocated with malloc instead of mmap, just reuse it. */
+ bfd_free_window (w);
+ w->i = (bfd_window_internal *) bfd_zmalloc (sizeof (bfd_window_internal));
+ if (w->i == NULL)
+ return false;
+ w->i->data = (PTR) malloc ((size_t) count);
+ if (w->i->data == NULL)
+ {
+ free (w->i);
+ w->i = NULL;
+ return false;
+ }
+ w->i->mapped = 0;
+ w->i->refcount = 1;
+ w->size = w->i->size = count;
+ w->data = w->i->data;
+ return bfd_get_section_contents (abfd, section, w->data, offset, count);
+ }
+ if ((bfd_size_type) (offset+count) > section->_raw_size
+ || (bfd_get_file_window (abfd, section->filepos + offset, count, w, 1)
+ == false))
+ return false;
+ return true;
+}
+
/* This generic function can only be used in implementations where creating
NEW sections is disallowed. It is useful in patching existing sections
in read-write files, though. See other set_section_contents functions
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 7b818aa..1c90879 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -314,6 +314,9 @@ extern boolean _bfd_coff_generic_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
struct internal_reloc *, struct internal_syment *, asection **));
+#define coff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
/* Functions in xcofflink.c. */
extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index f75c42b..69f2377 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -314,6 +314,9 @@ extern boolean _bfd_coff_generic_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
struct internal_reloc *, struct internal_syment *, asection **));
+#define coff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
/* Functions in xcofflink.c. */
extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
diff --git a/bfd/oasys.c b/bfd/oasys.c
index 4e543af..7637064 100644
--- a/bfd/oasys.c
+++ b/bfd/oasys.c
@@ -1484,6 +1484,7 @@ oasys_sizeof_headers (abfd, exec)
((boolean (*) \
PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \
bfd_true)
+#define oasys_read_ar_hdr bfd_nullvoidptr
#define oasys_update_armap_timestamp bfd_true
#define oasys_bfd_is_local_label bfd_generic_is_local_label
@@ -1496,6 +1497,9 @@ oasys_sizeof_headers (abfd, exec)
#define oasys_set_arch_mach bfd_default_set_arch_mach
+#define oasys_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
#define oasys_bfd_get_relocated_section_contents \
bfd_generic_get_relocated_section_contents
#define oasys_bfd_relax_section bfd_generic_relax_section
@@ -1519,7 +1523,6 @@ const bfd_target oasys_vec =
0, /* leading underscore */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
- 1, /* minimum alignment */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
diff --git a/bfd/targets.c b/bfd/targets.c
index 78a57a5..911f2a7 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -246,7 +246,9 @@ The general target vector.
.CAT(NAME,_close_and_cleanup),\
.CAT(NAME,_bfd_free_cached_info),\
.CAT(NAME,_new_section_hook),\
-.CAT(NAME,_get_section_contents)
+.CAT(NAME,_get_section_contents),\
+.CAT(NAME,_get_section_contents_in_window)
+.
. {* Called when the BFD is being closed to do any necessary cleanup. *}
. boolean (*_close_and_cleanup) PARAMS ((bfd *));
. {* Ask the BFD to free all cached information. *}
@@ -256,6 +258,9 @@ The general target vector.
. {* Read the contents of a section. *}
. boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
. file_ptr, bfd_size_type));
+. boolean (*_bfd_get_section_contents_in_window)
+. PARAMS ((bfd *, sec_ptr, bfd_window *,
+. file_ptr, bfd_size_type));
.
. {* Entry points to copy private data. *}
.#define BFD_JUMP_TABLE_COPY(NAME)\
@@ -315,7 +320,7 @@ The general target vector.
. struct orl *map,
. unsigned int orl_count,
. int stridx));
-. PTR (*_bfd_read_ar_hdr) PARAMS ((bfd *));
+. PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
. boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));