Changes for mmap; details in change log.
authorKen Raeburn <raeburn@cygnus>
Mon, 6 Nov 1995 10:08:03 +0000 (10:08 +0000)
committerKen Raeburn <raeburn@cygnus>
Mon, 6 Nov 1995 10:08:03 +0000 (10:08 +0000)
Added some new interfaces, and a new entry in the target vector.  Under the new
interfaces, mmap will be used if available, otherwise malloc/seek/read, as
before.  Old interfaces all still intact.

Most configurations (including all used by "--enable-targets=all") simply
changed to call the default routine for that entry in the target vector.  I
might've missed some targets only included in special configurations.

Support for a.out symbol and string table reading now goes through new
interfaces, and will use mmap when available.

Linker hooks (e.g., avoiding reallocation under malloc) not ready yet.

12 files changed:
bfd/ChangeLog
bfd/aoutx.h
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/config.in [new file with mode: 0644]
bfd/configure
bfd/configure.in
bfd/libbfd.c
bfd/libcoff-in.h
bfd/libcoff.h
bfd/oasys.c
bfd/targets.c

index c0a9a3413870f404d8a531f6f2928dd4e3f62401..b8fc05081f7e54e780d3ac5e73856091e2dcd694 100644 (file)
@@ -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
index 657130212e22f4a69ca7f8852b533522b4170b74..8d7ea3ab94ba391a358aab86de975ea5d8be2f69 100644 (file)
@@ -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;
index d027196c907ded2b49a286aea2d4d5c0510c2c8e..d69f7636fb1fcc2a9a8672e73ef0962ccade93fa 100644 (file)
@@ -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
index 109c1fc3db9744ce63a9cf82e6250f75b3b62b85..394979d164219acaafa6c267fa87a010ec0252de 100644 (file)
@@ -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 (file)
index 0000000..49dbce1
--- /dev/null
@@ -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
index 724ab8a1dba65559df71001a84d1bc6b37bac833..f07af90b1e4ac53a5d4636d987a13563f8743068 100755 (executable)
@@ -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
index 61e04712b3794091b148c1b3a591140f97c07d25..8ef6b013fdcc2206b69bd2985595f53b4ac066a4 100644 (file)
@@ -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])
index 2925754cbd764056afb3f60adae26449ceabb478..5f682ecebe7ef820dd4f6777c6a2158cf9b0600d 100644 (file)
@@ -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;
 }
 \f
@@ -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;
 }
 \f
-/** 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;
-}
-\f
 /** 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
index 7b818aa413bee54d5f751ee1f42542f649eec222..1c90879a569dee4cf13f96c5bb65a33fd2c5da7b 100644 (file)
@@ -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
index f75c42b92a4f54e694f2b932a15c982a5daf2d7c..69f2377092a1ed845accdaf1863d7ddfc3c263af 100644 (file)
@@ -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
index 4e543af181a617220a6820f823d756785f72e5db..76370645c6ccf513c28726d97f37d99518b11857 100644 (file)
@@ -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 */
index 78a57a5ec6d4011f1e62ee6ba03a390af5846b38..911f2a783a0b3179d3c4a8a3085c2b26a31ceeae 100644 (file)
@@ -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 *));