2002-11-16 Klee Dienes * Makefile.am (BFD32_LIBS): Add bfdwin.lo, bfdio.lo. (BFD32_LIBS_CFILES): Add bfdwin.c, bfdio.c. (BFD_H_FILES): Add bfdwin.c, bfdio.c. (LIBBFD_H_FILES): Add bfdwin.c, bfdio.c. Add dependencies for bfdwin.c, bfdio.c. * bfd.c: Remove bfd_get_mtime, bfd_get_size. * libbfd.c: Remove real_read, bfd_bread, _bfd_window_internal, bfd_init_window, bfd_free_window, bfd_get_file_window, bfd_bwrite, bfd_tell, bfd_flush, bfd_stat, bfd_seek. * bfdio.c: New file. Contains real_read, bfd_bread, bfd_write, bfd_tell, bfd_flush, bfd_stat, bfd_seek, bfd_ge_mtime, bfd_get_size (moved from libbfd.c and bfd.c). * bfdwin.c New file. Contains _bfd_window_internal, bfd_init_window, bfd_free_window, bfd_get_file_window (moved from libbfd.c and bfd.c). * po/SRC-POTFILES.in: Regenerate. * po/bfd.pot: Regenerate. * libbfd.h: Regenerate. * bfd-in2.h: Regenerate. * aclocal.m4: Regenerate. * Makefile.in: Regenerate. * configure: Regenerate. 2002-11-16 Klee Dienes * Makefile.am (DOCFILES): Add bfdwin.texi, bfdio.texi. (PROTOS): Add bfdio.p, bfdwin.p. (SRCDOC): Add bfdio.c, bfdwin.c. (SRCPROT): Add bfdio.c, bfdwin.c. (SRCIPROT): Add bfdio.c, bfdwin.c. (LIBBFD_H_DEP): Add bfdio.c, bfdwin.c. (BFD_H_DEP): Add bfdio.c, bfdwin.c. Add rules for bfdio.texi, bfdwin.text. * bfd.texinfo: Include bfdio.texi. diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/Makefile.am cygnus.bfd/bfd/Makefile.am --- cygnus.cygnus/src/bfd/Makefile.am Sat Nov 16 11:41:21 2002 +++ cygnus.bfd/bfd/Makefile.am Sat Nov 16 17:04:49 2002 @@ -28,7 +28,8 @@ # need two copies of the executable, one to download and one for the # debugger). BFD32_LIBS = \ - archive.lo archures.lo bfd.lo cache.lo coffgen.lo corefile.lo \ + archive.lo archures.lo bfd.lo bfdio.lo bfdwin.lo \ + cache.lo coffgen.lo corefile.lo \ format.lo init.lo libbfd.lo opncls.lo reloc.lo \ section.lo syms.lo targets.lo hash.lo linker.lo \ srec.lo binary.lo tekhex.lo ihex.lo stabs.lo stab-syms.lo \ @@ -37,7 +38,8 @@ BFD64_LIBS = archive64.lo BFD32_LIBS_CFILES = \ - archive.c archures.c bfd.c cache.c coffgen.c corefile.c \ + archive.c archures.c bfd.c bfdio.c bfdwin.c \ + cache.c coffgen.c corefile.c \ format.c init.c libbfd.c opncls.c reloc.c \ section.c syms.c targets.c hash.c linker.c \ srec.c binary.c tekhex.c ihex.c stabs.c stab-syms.c \ @@ -794,9 +796,11 @@ touch stmp-bfd-h BFD_H_FILES = bfd-in.h init.c opncls.c libbfd.c section.c archures.c \ - reloc.c syms.c bfd.c archive.c corefile.c targets.c format.c + reloc.c syms.c bfd.c bfdio.c bfdwin.c \ + archive.c corefile.c targets.c format.c BFD64_H_FILES = archive64.c -LIBBFD_H_FILES = libbfd-in.h init.c libbfd.c cache.c reloc.c archures.c elf.c +LIBBFD_H_FILES = libbfd-in.h init.c libbfd.c bfdio.c bfdwin.c \ + cache.c reloc.c archures.c elf.c LIBCOFF_H_FILES = libcoff-in.h coffcode.h # Could really use a "copy-if-change"... @@ -856,6 +860,8 @@ $(INCDIR)/coff/sym.h libcoff.h libecoff.h $(INCDIR)/coff/ecoff.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h +bfdio.lo: bfdio.c $(INCDIR)/filenames.h +bfdwin.lo: bfdwin.c $(INCDIR)/filenames.h cache.lo: cache.c $(INCDIR)/filenames.h coffgen.lo: coffgen.c $(INCDIR)/filenames.h $(INCDIR)/coff/internal.h \ libcoff.h $(INCDIR)/bfdlink.h diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/bfd.c cygnus.bfd/bfd/bfd.c --- cygnus.cygnus/src/bfd/bfd.c Sat Nov 16 11:41:32 2002 +++ cygnus.bfd/bfd/bfd.c Sat Nov 16 10:47:13 2002 @@ -830,87 +830,6 @@ /* FUNCTION - bfd_get_mtime - -SYNOPSIS - long bfd_get_mtime(bfd *abfd); - -DESCRIPTION - Return the file modification time (as read from the file system, or - from the archive header for archive members). - -*/ - -long -bfd_get_mtime (abfd) - bfd *abfd; -{ - FILE *fp; - struct stat buf; - - if (abfd->mtime_set) - return abfd->mtime; - - fp = bfd_cache_lookup (abfd); - if (0 != fstat (fileno (fp), &buf)) - return 0; - - abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ - return buf.st_mtime; -} - -/* -FUNCTION - bfd_get_size - -SYNOPSIS - long bfd_get_size(bfd *abfd); - -DESCRIPTION - Return the file size (as read from file system) for the file - associated with BFD @var{abfd}. - - The initial motivation for, and use of, this routine is not - so we can get the exact size of the object the BFD applies to, since - that might not be generally possible (archive members for example). - It would be ideal if someone could eventually modify - it so that such results were guaranteed. - - Instead, we want to ask questions like "is this NNN byte sized - object I'm about to try read from file offset YYY reasonable?" - As as example of where we might do this, some object formats - use string tables for which the first <> bytes of the - table contain the size of the table itself, including the size bytes. - If an application tries to read what it thinks is one of these - string tables, without some way to validate the size, and for - some reason the size is wrong (byte swapping error, wrong location - for the string table, etc.), the only clue is likely to be a read - error when it tries to read the table, or a "virtual memory - exhausted" error when it tries to allocate 15 bazillon bytes - of space for the 15 bazillon byte table it is about to read. - This function at least allows us to answer the quesion, "is the - size reasonable?". -*/ - -long -bfd_get_size (abfd) - bfd *abfd; -{ - FILE *fp; - struct stat buf; - - if ((abfd->flags & BFD_IN_MEMORY) != 0) - return ((struct bfd_in_memory *) abfd->iostream)->size; - - fp = bfd_cache_lookup (abfd); - if (0 != fstat (fileno (fp), & buf)) - return 0; - - return buf.st_size; -} - -/* -FUNCTION bfd_get_gp_size SYNOPSIS diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/libbfd.c cygnus.bfd/bfd/libbfd.c --- cygnus.cygnus/src/bfd/libbfd.c Sat Nov 16 11:43:51 2002 +++ cygnus.bfd/bfd/libbfd.c Sat Nov 16 10:47:13 2002 @@ -28,8 +28,6 @@ #define getpagesize() 2048 #endif -static size_t real_read PARAMS ((PTR, size_t, size_t, FILE *)); - /* SECTION Internal functions @@ -222,372 +220,6 @@ return ptr; } - -/* Some IO code */ - -/* Note that archive entries don't have streams; they share their parent's. - This allows someone to play with the iostream behind BFD's back. - - Also, note that the origin pointer points to the beginning of a file's - 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 size_t -real_read (where, a, b, file) - PTR where; - size_t a; - size_t b; - FILE *file; -{ - /* FIXME - this looks like an optimization, but it's really to cover - up for a feature of some OSs (not solaris - sigh) that - ld/pe-dll.c takes advantage of (apparently) when it creates BFDs - internally and tries to link against them. BFD seems to be smart - enough to realize there are no symbol records in the "file" that - doesn't exist but attempts to read them anyway. On Solaris, - attempting to read zero bytes from a NULL file results in a core - dump, but on other platforms it just returns zero bytes read. - This makes it to something reasonable. - DJ */ - if (a == 0 || b == 0) - return 0; - - -#if defined (__VAX) && defined (VMS) - /* Apparently fread on Vax VMS does not keep the record length - information. */ - return read (fileno (file), where, a * b); -#else - return fread (where, a, b, file); -#endif -} - -/* Return value is amount read. */ - -bfd_size_type -bfd_bread (ptr, size, abfd) - PTR ptr; - bfd_size_type size; - bfd *abfd; -{ - size_t nread; - - if ((abfd->flags & BFD_IN_MEMORY) != 0) - { - struct bfd_in_memory *bim; - bfd_size_type get; - - bim = (struct bfd_in_memory *) abfd->iostream; - get = size; - if (abfd->where + get > bim->size) - { - if (bim->size < (bfd_size_type) abfd->where) - get = 0; - else - get = bim->size - abfd->where; - bfd_set_error (bfd_error_file_truncated); - } - memcpy (ptr, bim->buffer + abfd->where, (size_t) get); - abfd->where += get; - return get; - } - - nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); - if (nread != (size_t) -1) - abfd->where += nread; - - /* Set bfd_error if we did not read as much data as we expected. - - If the read failed due to an error set the bfd_error_system_call, - else set bfd_error_file_truncated. - - A BFD backend may wish to override bfd_error_file_truncated to - provide something more useful (eg. no_symbols or wrong_format). */ - if (nread != size) - { - if (ferror (bfd_cache_lookup (abfd))) - bfd_set_error (bfd_error_system_call); - else - bfd_set_error (bfd_error_file_truncated); - } - - 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; -} - -/* Currently, if USE_MMAP is undefined, none if the window stuff is - used. Okay, so it's mis-named. At least the command-line option - "--without-mmap" is more obvious than "--without-windows" or some - such. */ -#ifdef USE_MMAP - -#undef HAVE_MPROTECT /* code's not tested yet */ - -#if HAVE_MMAP || HAVE_MPROTECT || HAVE_MADVISE -#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; - -boolean -bfd_get_file_window (abfd, offset, size, windowp, writable) - bfd *abfd; - file_ptr offset; - bfd_size_type size; - bfd_window *windowp; - boolean writable; -{ - static size_t pagesize; - bfd_window_internal *i = windowp->i; - bfd_size_type 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, (unsigned long) 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) - { - i = ((bfd_window_internal *) - bfd_zmalloc ((bfd_size_type) sizeof (bfd_window_internal))); - windowp->i = i; - if (i == 0) - return false; - i->data = 0; - } -#ifdef HAVE_MMAP - if (ok_to_map - && (i->data == 0 || i->mapped == 1) - && (abfd->flags & BFD_IN_MEMORY) == 0) - { - file_ptr file_offset, offset2; - size_t real_size; - int fd; - FILE *f; - - /* Find the real file and the real offset into it. */ - while (abfd->my_archive != NULL) - { - offset += abfd->origin; - abfd = abfd->my_archive; - } - f = bfd_cache_lookup (abfd); - fd = fileno (f); - - /* Compute offsets and size for mmap and for the user's data. */ - offset2 = 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 | MAP_SHARED), - 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 = (PTR) ((bfd_byte *) i->data + offset2); - windowp->size = size; - i->mapped = 1; - return true; - } - else if (debug_windows) - { - if (ok_to_map) - fprintf (stderr, _("not mapping: data=%lx mapped=%d\n"), - (unsigned long) i->data, (int) i->mapped); - else - fprintf (stderr, _("not mapping: env var not set\n")); - } -#else - ok_to_map = 0; -#endif - -#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); - i->data = (PTR) bfd_realloc (i->data, size_to_alloc); - if (debug_windows) - fprintf (stderr, "\t-> %p\n", i->data); - i->refcount = 1; - if (i->data == NULL) - { - if (size_to_alloc == 0) - return true; - return false; - } - if (bfd_seek (abfd, offset, SEEK_SET) != 0) - return false; - i->size = bfd_bread (i->data, size, abfd); - if (i->size != size) - return false; - i->mapped = 0; -#ifdef HAVE_MPROTECT - if (!writable) - { - if (debug_windows) - fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data, - (long) i->size); - mprotect (i->data, i->size, PROT_READ); - } -#endif - windowp->data = i->data; - windowp->size = i->size; - return true; -} - -#endif /* USE_MMAP */ - -bfd_size_type -bfd_bwrite (ptr, size, abfd) - const PTR ptr; - bfd_size_type size; - bfd *abfd; -{ - size_t nwrote; - - if ((abfd->flags & BFD_IN_MEMORY) != 0) - { - struct bfd_in_memory *bim = (struct bfd_in_memory *) (abfd->iostream); - size = (size_t) size; - if (abfd->where + size > bim->size) - { - bfd_size_type newsize, oldsize; - - oldsize = (bim->size + 127) & ~(bfd_size_type) 127; - bim->size = abfd->where + size; - /* Round up to cut down on memory fragmentation */ - newsize = (bim->size + 127) & ~(bfd_size_type) 127; - if (newsize > oldsize) - { - bim->buffer = (bfd_byte *) bfd_realloc (bim->buffer, newsize); - if (bim->buffer == 0) - { - bim->size = 0; - return 0; - } - } - } - memcpy (bim->buffer + abfd->where, ptr, (size_t) size); - abfd->where += size; - return size; - } - - nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); - if (nwrote != (size_t) -1) - abfd->where += nwrote; - if (nwrote != size) - { -#ifdef ENOSPC - errno = ENOSPC; -#endif - bfd_set_error (bfd_error_system_call); - } - return nwrote; -} - /* INTERNAL_FUNCTION bfd_write_bigendian_4byte_int @@ -611,186 +243,6 @@ return (boolean) (bfd_bwrite ((PTR) buffer, (bfd_size_type) 4, abfd) == 4); } -bfd_vma -bfd_tell (abfd) - bfd *abfd; -{ - file_ptr ptr; - - if ((abfd->flags & BFD_IN_MEMORY) != 0) - return abfd->where; - - ptr = ftell (bfd_cache_lookup (abfd)); - - if (abfd->my_archive) - ptr -= abfd->origin; - abfd->where = ptr; - return ptr; -} - -int -bfd_flush (abfd) - bfd *abfd; -{ - if ((abfd->flags & BFD_IN_MEMORY) != 0) - return 0; - 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; -{ - FILE *f; - int result; - - if ((abfd->flags & BFD_IN_MEMORY) != 0) - abort (); - - 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 - can retrieve the error code). */ - -int -bfd_seek (abfd, position, direction) - bfd *abfd; - file_ptr position; - int direction; -{ - int result; - FILE *f; - long file_position; - /* For the time being, a BFD may not seek to it's end. The problem - is that we don't easily have a way to recognize the end of an - element in an archive. */ - - BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); - - if (direction == SEEK_CUR && position == 0) - return 0; - - if ((abfd->flags & BFD_IN_MEMORY) != 0) - { - struct bfd_in_memory *bim; - - bim = (struct bfd_in_memory *) abfd->iostream; - - if (direction == SEEK_SET) - abfd->where = position; - else - abfd->where += position; - - if (abfd->where > bim->size) - { - if ((abfd->direction == write_direction) || - (abfd->direction == both_direction)) - { - bfd_size_type newsize, oldsize; - oldsize = (bim->size + 127) & ~(bfd_size_type) 127; - bim->size = abfd->where; - /* Round up to cut down on memory fragmentation */ - newsize = (bim->size + 127) & ~(bfd_size_type) 127; - if (newsize > oldsize) - { - bim->buffer = (bfd_byte *) bfd_realloc (bim->buffer, newsize); - if (bim->buffer == 0) - { - bim->size = 0; - return -1; - } - } - } - else - { - abfd->where = bim->size; - bfd_set_error (bfd_error_file_truncated); - return -1; - } - } - return 0; - } - - if (abfd->format != bfd_archive && abfd->my_archive == 0) - { -#if 0 - /* Explanation for this code: I'm only about 95+% sure that the above - conditions are sufficient and that all i/o calls are properly - adjusting the `where' field. So this is sort of an `assert' - that the `where' field is correct. If we can go a while without - tripping the abort, we can probably safely disable this code, - so that the real optimizations happen. */ - file_ptr where_am_i_now; - where_am_i_now = ftell (bfd_cache_lookup (abfd)); - if (abfd->my_archive) - where_am_i_now -= abfd->origin; - if (where_am_i_now != abfd->where) - abort (); -#endif - if (direction == SEEK_SET && (bfd_vma) position == abfd->where) - return 0; - } - else - { - /* We need something smarter to optimize access to archives. - Currently, anything inside an archive is read via the file - handle for the archive. Which means that a bfd_seek on one - component affects the `current position' in the archive, as - well as in any other component. - - It might be sufficient to put a spike through the cache - abstraction, and look to the archive for the file position, - but I think we should try for something cleaner. - - In the meantime, no optimization for archives. */ - } - - f = bfd_cache_lookup (abfd); - file_position = position; - if (direction == SEEK_SET && abfd->my_archive != NULL) - file_position += abfd->origin; - - result = fseek (f, file_position, direction); - if (result != 0) - { - int hold_errno = errno; - - /* Force redetermination of `where' field. */ - bfd_tell (abfd); - - /* An EINVAL error probably means that the file offset was - absurd. */ - if (hold_errno == EINVAL) - bfd_set_error (bfd_error_file_truncated); - else - { - bfd_set_error (bfd_error_system_call); - errno = hold_errno; - } - } - else - { - /* Adjust `where' field. */ - if (direction == SEEK_SET) - abfd->where = position; - else - abfd->where += position; - } - return result; -} /** The do-it-yourself (byte) sex-change kit */ diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/bfdio.c cygnus.bfd/bfd/bfdio.c --- cygnus.cygnus/src/bfd/bfdio.c Wed Dec 31 19:00:00 1969 +++ cygnus.bfd/bfd/bfdio.c Sat Nov 16 19:24:38 2002 @@ -0,0 +1,436 @@ +/* Low-level I/O routines for BFDs. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002 Free Software Foundation, Inc. + Written by Cygnus Support. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" + +#include "bfd.h" +#include "libbfd.h" + +#include + +#ifndef S_IXUSR +#define S_IXUSR 0100 /* Execute by owner. */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 0010 /* Execute by group. */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 0001 /* Execute by others. */ +#endif + +/* Note that archive entries don't have streams; they share their parent's. + This allows someone to play with the iostream behind BFD's back. + + Also, note that the origin pointer points to the beginning of a file's + 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 size_t real_read PARAMS ((PTR where, size_t a, size_t b, FILE *file)); +static size_t +real_read (where, a, b, file) + PTR where; + size_t a; + size_t b; + FILE *file; +{ + /* FIXME - this looks like an optimization, but it's really to cover + up for a feature of some OSs (not solaris - sigh) that + ld/pe-dll.c takes advantage of (apparently) when it creates BFDs + internally and tries to link against them. BFD seems to be smart + enough to realize there are no symbol records in the "file" that + doesn't exist but attempts to read them anyway. On Solaris, + attempting to read zero bytes from a NULL file results in a core + dump, but on other platforms it just returns zero bytes read. + This makes it to something reasonable. - DJ */ + if (a == 0 || b == 0) + return 0; + + +#if defined (__VAX) && defined (VMS) + /* Apparently fread on Vax VMS does not keep the record length + information. */ + return read (fileno (file), where, a * b); +#else + return fread (where, a, b, file); +#endif +} + +/* Return value is amount read. */ + +bfd_size_type +bfd_bread (ptr, size, abfd) + PTR ptr; + bfd_size_type size; + bfd *abfd; +{ + size_t nread; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + { + struct bfd_in_memory *bim; + bfd_size_type get; + + bim = (struct bfd_in_memory *) abfd->iostream; + get = size; + if (abfd->where + get > bim->size) + { + if (bim->size < (bfd_size_type) abfd->where) + get = 0; + else + get = bim->size - abfd->where; + bfd_set_error (bfd_error_file_truncated); + } + memcpy (ptr, bim->buffer + abfd->where, (size_t) get); + abfd->where += get; + return get; + } + + nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); + if (nread != (size_t) -1) + abfd->where += nread; + + /* Set bfd_error if we did not read as much data as we expected. + + If the read failed due to an error set the bfd_error_system_call, + else set bfd_error_file_truncated. + + A BFD backend may wish to override bfd_error_file_truncated to + provide something more useful (eg. no_symbols or wrong_format). */ + if (nread != size) + { + if (ferror (bfd_cache_lookup (abfd))) + bfd_set_error (bfd_error_system_call); + else + bfd_set_error (bfd_error_file_truncated); + } + + return nread; +} + +bfd_size_type +bfd_bwrite (ptr, size, abfd) + const PTR ptr; + bfd_size_type size; + bfd *abfd; +{ + size_t nwrote; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + { + struct bfd_in_memory *bim = (struct bfd_in_memory *) (abfd->iostream); + size = (size_t) size; + if (abfd->where + size > bim->size) + { + bfd_size_type newsize, oldsize; + + oldsize = (bim->size + 127) & ~(bfd_size_type) 127; + bim->size = abfd->where + size; + /* Round up to cut down on memory fragmentation */ + newsize = (bim->size + 127) & ~(bfd_size_type) 127; + if (newsize > oldsize) + { + bim->buffer = (bfd_byte *) bfd_realloc (bim->buffer, newsize); + if (bim->buffer == 0) + { + bim->size = 0; + return 0; + } + } + } + memcpy (bim->buffer + abfd->where, ptr, (size_t) size); + abfd->where += size; + return size; + } + + nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); + if (nwrote != (size_t) -1) + abfd->where += nwrote; + if (nwrote != size) + { +#ifdef ENOSPC + errno = ENOSPC; +#endif + bfd_set_error (bfd_error_system_call); + } + return nwrote; +} + +bfd_vma +bfd_tell (abfd) + bfd *abfd; +{ + file_ptr ptr; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return abfd->where; + + ptr = ftell (bfd_cache_lookup (abfd)); + + if (abfd->my_archive) + ptr -= abfd->origin; + abfd->where = ptr; + return ptr; +} + +int +bfd_flush (abfd) + bfd *abfd; +{ + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return 0; + 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; +{ + FILE *f; + int result; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + abort (); + + 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 + can retrieve the error code). */ + +int +bfd_seek (abfd, position, direction) + bfd *abfd; + file_ptr position; + int direction; +{ + int result; + FILE *f; + long file_position; + /* For the time being, a BFD may not seek to it's end. The problem + is that we don't easily have a way to recognize the end of an + element in an archive. */ + + BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); + + if (direction == SEEK_CUR && position == 0) + return 0; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + { + struct bfd_in_memory *bim; + + bim = (struct bfd_in_memory *) abfd->iostream; + + if (direction == SEEK_SET) + abfd->where = position; + else + abfd->where += position; + + if (abfd->where > bim->size) + { + if ((abfd->direction == write_direction) || + (abfd->direction == both_direction)) + { + bfd_size_type newsize, oldsize; + oldsize = (bim->size + 127) & ~(bfd_size_type) 127; + bim->size = abfd->where; + /* Round up to cut down on memory fragmentation */ + newsize = (bim->size + 127) & ~(bfd_size_type) 127; + if (newsize > oldsize) + { + bim->buffer = (bfd_byte *) bfd_realloc (bim->buffer, newsize); + if (bim->buffer == 0) + { + bim->size = 0; + return -1; + } + } + } + else + { + abfd->where = bim->size; + bfd_set_error (bfd_error_file_truncated); + return -1; + } + } + return 0; + } + + if (abfd->format != bfd_archive && abfd->my_archive == 0) + { +#if 0 + /* Explanation for this code: I'm only about 95+% sure that the above + conditions are sufficient and that all i/o calls are properly + adjusting the `where' field. So this is sort of an `assert' + that the `where' field is correct. If we can go a while without + tripping the abort, we can probably safely disable this code, + so that the real optimizations happen. */ + file_ptr where_am_i_now; + where_am_i_now = ftell (bfd_cache_lookup (abfd)); + if (abfd->my_archive) + where_am_i_now -= abfd->origin; + if (where_am_i_now != abfd->where) + abort (); +#endif + if (direction == SEEK_SET && (bfd_vma) position == abfd->where) + return 0; + } + else + { + /* We need something smarter to optimize access to archives. + Currently, anything inside an archive is read via the file + handle for the archive. Which means that a bfd_seek on one + component affects the `current position' in the archive, as + well as in any other component. + + It might be sufficient to put a spike through the cache + abstraction, and look to the archive for the file position, + but I think we should try for something cleaner. + + In the meantime, no optimization for archives. */ + } + + f = bfd_cache_lookup (abfd); + file_position = position; + if (direction == SEEK_SET && abfd->my_archive != NULL) + file_position += abfd->origin; + + result = fseek (f, file_position, direction); + if (result != 0) + { + int hold_errno = errno; + + /* Force redetermination of `where' field. */ + bfd_tell (abfd); + + /* An EINVAL error probably means that the file offset was + absurd. */ + if (hold_errno == EINVAL) + bfd_set_error (bfd_error_file_truncated); + else + { + bfd_set_error (bfd_error_system_call); + errno = hold_errno; + } + } + else + { + /* Adjust `where' field. */ + if (direction == SEEK_SET) + abfd->where = position; + else + abfd->where += position; + } + return result; +} + +/* +FUNCTION + bfd_get_mtime + +SYNOPSIS + long bfd_get_mtime(bfd *abfd); + +DESCRIPTION + Return the file modification time (as read from the file system, or + from the archive header for archive members). + +*/ + +long +bfd_get_mtime (abfd) + bfd *abfd; +{ + FILE *fp; + struct stat buf; + + if (abfd->mtime_set) + return abfd->mtime; + + fp = bfd_cache_lookup (abfd); + if (0 != fstat (fileno (fp), &buf)) + return 0; + + abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ + return buf.st_mtime; +} + +/* +FUNCTION + bfd_get_size + +SYNOPSIS + long bfd_get_size(bfd *abfd); + +DESCRIPTION + Return the file size (as read from file system) for the file + associated with BFD @var{abfd}. + + The initial motivation for, and use of, this routine is not + so we can get the exact size of the object the BFD applies to, since + that might not be generally possible (archive members for example). + It would be ideal if someone could eventually modify + it so that such results were guaranteed. + + Instead, we want to ask questions like "is this NNN byte sized + object I'm about to try read from file offset YYY reasonable?" + As as example of where we might do this, some object formats + use string tables for which the first <> bytes of the + table contain the size of the table itself, including the size bytes. + If an application tries to read what it thinks is one of these + string tables, without some way to validate the size, and for + some reason the size is wrong (byte swapping error, wrong location + for the string table, etc.), the only clue is likely to be a read + error when it tries to read the table, or a "virtual memory + exhausted" error when it tries to allocate 15 bazillon bytes + of space for the 15 bazillon byte table it is about to read. + This function at least allows us to answer the quesion, "is the + size reasonable?". +*/ + +long +bfd_get_size (abfd) + bfd *abfd; +{ + FILE *fp; + struct stat buf; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return ((struct bfd_in_memory *) abfd->iostream)->size; + + fp = bfd_cache_lookup (abfd); + if (0 != fstat (fileno (fp), & buf)) + return 0; + + return buf.st_size; +} diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/bfdwin.c cygnus.bfd/bfd/bfdwin.c --- cygnus.cygnus/src/bfd/bfdwin.c Wed Dec 31 19:00:00 1969 +++ cygnus.bfd/bfd/bfdwin.c Sat Nov 16 19:44:13 2002 @@ -0,0 +1,255 @@ +/* Support for memory-mapped windows into a BFD. + Copyright 1995, 1996, 2001, 2002 Free Software Foundation, Inc. + Written by Cygnus Support. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" + +#include "bfd.h" +#include "libbfd.h" + +/* Currently, if USE_MMAP is undefined, none if the window stuff is + used. Okay, so it's mis-named. At least the command-line option + "--without-mmap" is more obvious than "--without-windows" or some + such. */ + +#ifdef USE_MMAP + +#undef HAVE_MPROTECT /* code's not tested yet */ + +#if HAVE_MMAP || HAVE_MPROTECT || HAVE_MADVISE +#include +#endif + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +static int debug_windows; + +/* 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. */ + +/* +INTERNAL_DEFINITION + +.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; +} + +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; + +boolean +bfd_get_file_window (abfd, offset, size, windowp, writable) + bfd *abfd; + file_ptr offset; + bfd_size_type size; + bfd_window *windowp; + boolean writable; +{ + static size_t pagesize; + bfd_window_internal *i = windowp->i; + bfd_size_type 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, (unsigned long) 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) + { + i = ((bfd_window_internal *) + bfd_zmalloc ((bfd_size_type) sizeof (bfd_window_internal))); + windowp->i = i; + if (i == 0) + return false; + i->data = 0; + } +#ifdef HAVE_MMAP + if (ok_to_map + && (i->data == 0 || i->mapped == 1) + && (abfd->flags & BFD_IN_MEMORY) == 0) + { + file_ptr file_offset, offset2; + size_t real_size; + int fd; + FILE *f; + + /* Find the real file and the real offset into it. */ + while (abfd->my_archive != NULL) + { + offset += abfd->origin; + abfd = abfd->my_archive; + } + f = bfd_cache_lookup (abfd); + fd = fileno (f); + + /* Compute offsets and size for mmap and for the user's data. */ + offset2 = 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 | MAP_SHARED), + 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 = (PTR) ((bfd_byte *) i->data + offset2); + windowp->size = size; + i->mapped = 1; + return true; + } + else if (debug_windows) + { + if (ok_to_map) + fprintf (stderr, _("not mapping: data=%lx mapped=%d\n"), + (unsigned long) i->data, (int) i->mapped); + else + fprintf (stderr, _("not mapping: env var not set\n")); + } +#else + ok_to_map = 0; +#endif + +#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); + i->data = (PTR) bfd_realloc (i->data, size_to_alloc); + if (debug_windows) + fprintf (stderr, "\t-> %p\n", i->data); + i->refcount = 1; + if (i->data == NULL) + { + if (size_to_alloc == 0) + return true; + return false; + } + if (bfd_seek (abfd, offset, SEEK_SET) != 0) + return false; + i->size = bfd_bread (i->data, size, abfd); + if (i->size != size) + return false; + i->mapped = 0; +#ifdef HAVE_MPROTECT + if (!writable) + { + if (debug_windows) + fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data, + (long) i->size); + mprotect (i->data, i->size, PROT_READ); + } +#endif + windowp->data = i->data; + windowp->size = i->size; + return true; +} + +#endif /* USE_MMAP */ diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/doc/Makefile.am cygnus.bfd/bfd/doc/Makefile.am --- cygnus.cygnus/src/bfd/doc/Makefile.am Sat Oct 12 02:07:25 2002 +++ cygnus.bfd/bfd/doc/Makefile.am Sat Nov 16 19:17:57 2002 @@ -4,13 +4,15 @@ DOCFILES = aoutx.texi archive.texi archures.texi \ bfdt.texi cache.texi coffcode.texi \ - core.texi elf.texi elfcode.texi format.texi libbfd.texi \ + core.texi elf.texi elfcode.texi format.texi \ + libbfd.texi bfdwin.texi bfdio.texi \ opncls.texi reloc.texi section.texi \ syms.texi targets.texi init.texi hash.texi linker.texi \ mmo.texi PROTOS = archive.p archures.p bfd.p \ core.p format.p \ + bfdio.p bfdwin.p \ libbfd.p opncls.p reloc.p \ section.p syms.p targets.p \ format.p core.p init.p @@ -22,6 +24,7 @@ # you don't need these three: SRCDOC = $(srcdir)/../aoutx.h $(srcdir)/../archive.c \ $(srcdir)/../archures.c $(srcdir)/../bfd.c \ + $(srcdir)/../bfdio.c $(srcdir)/../bfdwin.c \ $(srcdir)/../cache.c $(srcdir)/../coffcode.h \ $(srcdir)/../corefile.c $(srcdir)/../elf.c \ $(srcdir)/../elfcode.h $(srcdir)/../format.c \ @@ -34,11 +37,13 @@ SRCPROT = $(srcdir)/../archive.c $(srcdir)/../archures.c \ $(srcdir)/../bfd.c $(srcdir)/../coffcode.h $(srcdir)/../corefile.c \ $(srcdir)/../format.c $(srcdir)/../libbfd.c \ + $(srcdir)/../bfdio.c $(srcdir)/../bfdwin.c \ $(srcdir)/../opncls.c $(srcdir)/../reloc.c \ $(srcdir)/../section.c $(srcdir)/../syms.c \ $(srcdir)/../targets.c $(srcdir)/../init.c SRCIPROT = $(srcdir)/../cache.c $(srcdir)/../libbfd.c \ + $(srcdir)/../bfdio.c $(srcdir)/../bfdwin.c \ $(srcdir)/../reloc.c $(srcdir)/../cpu-h8300.c \ $(srcdir)/../cpu-i960.c $(srcdir)/../archures.c \ $(srcdir)/../init.c @@ -143,6 +148,18 @@ touch s-libbfd libbfd.texi: s-libbfd +s-bfdio: $(MKDOC) $(srcdir)/../bfdio.c $(srcdir)/doc.str + ./$(MKDOC) -f $(srcdir)/doc.str < $(srcdir)/../bfdio.c >bfdio.tmp + $(srcdir)/../../move-if-change bfdio.tmp bfdio.texi + touch s-bfdio +bfdio.texi: s-bfdio + +s-bfdwin: $(MKDOC) $(srcdir)/../bfdwin.c $(srcdir)/doc.str + ./$(MKDOC) -f $(srcdir)/doc.str < $(srcdir)/../bfdwin.c >bfdwin.tmp + $(srcdir)/../../move-if-change bfdwin.tmp bfdwin.texi + touch s-bfdwin +bfdwin.texi: s-bfdwin + s-opncls: $(MKDOC) $(srcdir)/../opncls.c $(srcdir)/doc.str ./$(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../opncls.c >opncls.tmp $(srcdir)/../../move-if-change opncls.tmp opncls.texi @@ -195,6 +212,8 @@ $(srcdir)/../libbfd-in.h \ $(srcdir)/../init.c \ $(srcdir)/../libbfd.c \ + $(srcdir)/../bfdio.c \ + $(srcdir)/../bfdwin.c \ $(srcdir)/../cache.c \ $(srcdir)/../reloc.c \ $(srcdir)/../archures.c \ @@ -239,6 +258,8 @@ $(srcdir)/../init.c \ $(srcdir)/../opncls.c \ $(srcdir)/../libbfd.c \ + $(srcdir)/../bfdio.c \ + $(srcdir)/../bfdwin.c \ $(srcdir)/../section.c \ $(srcdir)/../archures.c \ $(srcdir)/../reloc.c \ diff --exclude=SRC-POTFILES.in --exclude=bfd.pot --exclude=libbfd.h --exclude=bfd-in2.h --exclude=aclocal.m4 --exclude=Makefile.in --exclude=configure --exclude=CVS --exclude=*~ -ruN cygnus.cygnus/src/bfd/doc/bfd.texinfo cygnus.bfd/bfd/doc/bfd.texinfo --- cygnus.cygnus/src/bfd/doc/bfd.texinfo Mon Aug 5 17:33:39 2002 +++ cygnus.bfd/bfd/doc/bfd.texinfo Sat Nov 16 19:58:03 2002 @@ -207,6 +207,7 @@ @node BFD front end, BFD back ends, Overview, Top @chapter BFD front end @include bfdt.texi +@include bfdio.texi @menu * Memory Usage::