diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c0a9a34138..b8fc05081f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -8,6 +8,40 @@ Sun Nov 5 21:44:13 1995 Ken Raeburn * 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 * core.c: Renamed to corefile.c diff --git a/bfd/aoutx.h b/bfd/aoutx.h index 657130212e..8d7ea3ab94 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 d027196c90..d69f7636fb 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 109c1fc3db..394979d164 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 0000000000..49dbce18a0 --- /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 is included. */ +#undef NEED_DECLARATION_MALLOC + +/* Whether free must be declared even if is included. */ +#undef NEED_DECLARATION_FREE + +/* Name of host specific header file to include in trad-core.c. */ +#undef TRAD_HEADER + +/* Define only if 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 header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H diff --git a/bfd/configure b/bfd/configure index 724ab8a1db..f07af90b1e 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 < +#include +#include + +#ifdef BSD +# ifndef BSD4_1 +# define HAVE_GETPAGESIZE +# endif +#endif + +#ifndef HAVE_GETPAGESIZE +# include +# 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 < +/* 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 <&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 61e04712b3..8ef6b013fd 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 2925754cbd..5f682ecebe 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 +#include +#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. getshort 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 7b818aa413..1c90879a56 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 f75c42b92a..69f2377092 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 4e543af181..76370645c6 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 78a57a5ec6..911f2a783a 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 *));