X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fbfdio.c;h=92dd9803e70a51fbc5fc634ebb8d8746261673aa;hb=7cac64af7bc6a7f7a86f90a1465f7c3d2b6f07e8;hp=6f8a7c9b84d297c3b59d11a2443ae2ac7102e687;hpb=f1bb16f888ae3230ecac7530db7b2dab3dcddfe2;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/bfdio.c b/bfd/bfdio.c index 6f8a7c9b84..92dd9803e7 100644 --- a/bfd/bfdio.c +++ b/bfd/bfdio.c @@ -1,8 +1,6 @@ /* Low-level I/O routines for BFDs. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-2019 Free Software Foundation, Inc. Written by Cygnus Support. @@ -43,7 +41,7 @@ #endif file_ptr -real_ftell (FILE *file) +_bfd_real_ftell (FILE *file) { #if defined (HAVE_FTELLO64) return ftello64 (file); @@ -55,7 +53,7 @@ real_ftell (FILE *file) } int -real_fseek (FILE *file, file_ptr offset, int whence) +_bfd_real_fseek (FILE *file, file_ptr offset, int whence) { #if defined (HAVE_FSEEKO64) return fseeko64 (file, offset, whence); @@ -84,13 +82,12 @@ close_on_exec (FILE *file) } FILE * -real_fopen (const char *filename, const char *modes) +_bfd_real_fopen (const char *filename, const char *modes) { #ifdef VMS - char vms_modes[4]; char *vms_attr; - /* On VMS, fopen allows file attributes as optionnal arguments. + /* On VMS, fopen allows file attributes as optional arguments. We need to use them but we'd better to use the common prototype. In fopen-vms.h, they are separated from the mode with a comma. Split here. */ @@ -148,12 +145,12 @@ DESCRIPTION . or -1 (setting <>) if an error occurs. *} . file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes); . file_ptr (*bwrite) (struct bfd *abfd, const void *ptr, -. file_ptr nbytes); +. file_ptr nbytes); . {* Return the current IOSTREAM file offset, or -1 (setting <> . if an error occurs. *} . file_ptr (*btell) (struct bfd *abfd); . {* For the following, on successful completion a value of 0 is returned. -. Otherwise, a value of -1 is returned (and <> is set). *} +. Otherwise, a value of -1 is returned (and <> is set). *} . int (*bseek) (struct bfd *abfd, file_ptr offset, int whence); . int (*bclose) (struct bfd *abfd); . int (*bflush) (struct bfd *abfd); @@ -165,8 +162,8 @@ DESCRIPTION . MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and . MAP_LEN to unmap. *} . void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len, -. int prot, int flags, file_ptr offset, -. void **map_addr, bfd_size_type *map_len); +. int prot, int flags, file_ptr offset, +. void **map_addr, bfd_size_type *map_len); .}; .extern const struct bfd_iovec _bfd_memory_iovec; @@ -179,27 +176,40 @@ DESCRIPTION bfd_size_type bfd_bread (void *ptr, bfd_size_type size, bfd *abfd) { - size_t nread; + file_ptr nread; + bfd *element_bfd = abfd; + ufile_ptr offset = 0; + + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) + { + offset += abfd->origin; + abfd = abfd->my_archive; + } /* If this is an archive element, don't read past the end of this element. */ - if (abfd->arelt_data != NULL) + if (element_bfd->arelt_data != NULL) { - bfd_size_type maxbytes = arelt_size (abfd); - - if (abfd->where + size > maxbytes) - { - if (abfd->where >= maxbytes) - return 0; - size = maxbytes - abfd->where; - } + bfd_size_type maxbytes = arelt_size (element_bfd); + + if (abfd->where < offset || abfd->where - offset >= maxbytes) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + if (abfd->where - offset + size > maxbytes) + size = maxbytes - (abfd->where - offset); } - if (abfd->iovec) - nread = abfd->iovec->bread (abfd, ptr, size); - else - nread = 0; - if (nread != (size_t) -1) + if (abfd->iovec == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + + nread = abfd->iovec->bread (abfd, ptr, size); + if (nread != -1) abfd->where += nread; return nread; @@ -208,16 +218,22 @@ bfd_bread (void *ptr, bfd_size_type size, bfd *abfd) bfd_size_type bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd) { - size_t nwrote; + file_ptr nwrote; - if (abfd->iovec) - nwrote = abfd->iovec->bwrite (abfd, ptr, size); - else - nwrote = 0; + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) + abfd = abfd->my_archive; - if (nwrote != (size_t) -1) + if (abfd->iovec == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + + nwrote = abfd->iovec->bwrite (abfd, ptr, size); + if (nwrote != -1) abfd->where += nwrote; - if (nwrote != size) + if ((bfd_size_type) nwrote != size) { #ifdef ENOSPC errno = ENOSPC; @@ -230,32 +246,35 @@ bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd) file_ptr bfd_tell (bfd *abfd) { + ufile_ptr offset = 0; file_ptr ptr; - if (abfd->iovec) + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) { - bfd *parent_bfd = abfd; - ptr = abfd->iovec->btell (abfd); - - while (parent_bfd->my_archive != NULL) - { - ptr -= parent_bfd->origin; - parent_bfd = parent_bfd->my_archive; - } + offset += abfd->origin; + abfd = abfd->my_archive; } - else - ptr = 0; + if (abfd->iovec == NULL) + return 0; + + ptr = abfd->iovec->btell (abfd); abfd->where = ptr; - return ptr; + return ptr - offset; } int bfd_flush (bfd *abfd) { - if (abfd->iovec) - return abfd->iovec->bflush (abfd); - return 0; + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) + abfd = abfd->my_archive; + + if (abfd->iovec == NULL) + return 0; + + return abfd->iovec->bflush (abfd); } /* Returns 0 for success, negative value for failure (in which case @@ -265,11 +284,17 @@ bfd_stat (bfd *abfd, struct stat *statbuf) { int result; - if (abfd->iovec) - result = abfd->iovec->bstat (abfd, statbuf); - else - result = -1; + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) + abfd = abfd->my_archive; + if (abfd->iovec == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + + result = abfd->iovec->bstat (abfd, statbuf); if (result < 0) bfd_set_error (bfd_error_system_call); return result; @@ -282,78 +307,52 @@ int bfd_seek (bfd *abfd, file_ptr position, int direction) { int result; - file_ptr 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; + ufile_ptr offset = 0; - if (abfd->format != bfd_archive && abfd->my_archive == 0) + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) { - if (direction == SEEK_SET && (bfd_vma) position == abfd->where) - return 0; + offset += abfd->origin; + abfd = abfd->my_archive; } - 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. */ + if (abfd->iovec == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; } - file_position = position; - if (direction == SEEK_SET) - { - bfd *parent_bfd = abfd; + /* 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); - while (parent_bfd->my_archive != NULL) - { - file_position += parent_bfd->origin; - parent_bfd = parent_bfd->my_archive; - } - } + if (direction != SEEK_CUR) + position += offset; - if (abfd->iovec) - result = abfd->iovec->bseek (abfd, file_position, direction); - else - result = -1; + if ((direction == SEEK_CUR && position == 0) + || (direction == SEEK_SET && (ufile_ptr) position == abfd->where)) + return 0; + result = abfd->iovec->bseek (abfd, 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) + absurd. */ + if (errno == EINVAL) bfd_set_error (bfd_error_file_truncated); else - { - bfd_set_error (bfd_error_system_call); - errno = hold_errno; - } + bfd_set_error (bfd_error_system_call); } else { /* Adjust `where' field. */ - if (direction == SEEK_SET) - abfd->where = position; - else + if (direction == SEEK_CUR) abfd->where += position; + else + abfd->where = position; } + return result; } @@ -378,10 +377,7 @@ bfd_get_mtime (bfd *abfd) if (abfd->mtime_set) return abfd->mtime; - if (abfd->iovec == NULL) - return 0; - - if (abfd->iovec->bstat (abfd, &buf) != 0) + if (bfd_stat (abfd, &buf) != 0) return 0; abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ @@ -393,7 +389,7 @@ FUNCTION bfd_get_size SYNOPSIS - file_ptr bfd_get_size (bfd *abfd); + ufile_ptr bfd_get_size (bfd *abfd); DESCRIPTION Return the file size (as read from file system) for the file @@ -421,20 +417,40 @@ DESCRIPTION size reasonable?". */ -file_ptr +ufile_ptr bfd_get_size (bfd *abfd) { struct stat buf; - if (abfd->iovec == NULL) - return 0; - - if (abfd->iovec->bstat (abfd, &buf) != 0) + if (bfd_stat (abfd, &buf) != 0) return 0; return buf.st_size; } +/* +FUNCTION + bfd_get_file_size + +SYNOPSIS + ufile_ptr bfd_get_file_size (bfd *abfd); + +DESCRIPTION + Return the file size (as read from file system) for the file + associated with BFD @var{abfd}. It supports both normal files + and archive elements. + +*/ + +ufile_ptr +bfd_get_file_size (bfd *abfd) +{ + if (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) + return arelt_size (abfd); + + return bfd_get_size (abfd); +} /* FUNCTION @@ -442,28 +458,36 @@ FUNCTION SYNOPSIS void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, - int prot, int flags, file_ptr offset, - void **map_addr, bfd_size_type *map_len); + int prot, int flags, file_ptr offset, + void **map_addr, bfd_size_type *map_len); DESCRIPTION Return mmap()ed region of the file, if possible and implemented. - LEN and OFFSET do not need to be page aligned. The page aligned - address and length are written to MAP_ADDR and MAP_LEN. + LEN and OFFSET do not need to be page aligned. The page aligned + address and length are written to MAP_ADDR and MAP_LEN. */ void * bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, int prot, int flags, file_ptr offset, - void **map_addr, bfd_size_type *map_len) + void **map_addr, bfd_size_type *map_len) { - void *ret = (void *)-1; + while (abfd->my_archive != NULL + && !bfd_is_thin_archive (abfd->my_archive)) + { + offset += abfd->origin; + abfd = abfd->my_archive; + } if (abfd->iovec == NULL) - return ret; + { + bfd_set_error (bfd_error_invalid_operation); + return (void *) -1; + } return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset, - map_addr, map_len); + map_addr, map_len); } /* Memory file I/O operations. */ @@ -479,9 +503,9 @@ memory_bread (bfd *abfd, void *ptr, file_ptr size) if (abfd->where + get > bim->size) { if (bim->size < (bfd_size_type) abfd->where) - get = 0; + get = 0; else - get = bim->size - abfd->where; + get = bim->size - abfd->where; bfd_set_error (bfd_error_file_truncated); } memcpy (ptr, bim->buffer + abfd->where, (size_t) get); @@ -502,16 +526,16 @@ memory_bwrite (bfd *abfd, const void *ptr, file_ptr 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_or_free (bim->buffer, newsize); - if (bim->buffer == NULL) - { - bim->size = 0; - return 0; - } - if (newsize > bim->size) - memset (bim->buffer + bim->size, 0, newsize - bim->size); - } + { + bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize); + if (bim->buffer == NULL) + { + bim->size = 0; + return 0; + } + if (newsize > bim->size) + memset (bim->buffer + bim->size, 0, newsize - bim->size); + } } memcpy (bim->buffer + abfd->where, ptr, (size_t) size); return size; @@ -546,33 +570,33 @@ memory_bseek (bfd *abfd, file_ptr position, int direction) if ((bfd_size_type)nwhere > 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 = nwhere; - /* 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_or_free (bim->buffer, newsize); - if (bim->buffer == NULL) - { - errno = EINVAL; - bim->size = 0; - return -1; - } - memset (bim->buffer + oldsize, 0, newsize - oldsize); - } - } + || abfd->direction == both_direction) + { + bfd_size_type newsize, oldsize; + + oldsize = (bim->size + 127) & ~(bfd_size_type) 127; + bim->size = nwhere; + /* 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_or_free (bim->buffer, newsize); + if (bim->buffer == NULL) + { + errno = EINVAL; + bim->size = 0; + return -1; + } + memset (bim->buffer + oldsize, 0, newsize - oldsize); + } + } else - { - abfd->where = bim->size; - errno = EINVAL; - bfd_set_error (bfd_error_file_truncated); - return -1; - } + { + abfd->where = bim->size; + errno = EINVAL; + bfd_set_error (bfd_error_file_truncated); + return -1; + } } return 0; } @@ -587,7 +611,7 @@ memory_bclose (struct bfd *abfd) free (bim); abfd->iostream = NULL; - return TRUE; + return 0; } static int @@ -609,10 +633,10 @@ memory_bstat (bfd *abfd, struct stat *statbuf) static void * memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED, - bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, - void **map_addr ATTRIBUTE_UNUSED, - bfd_size_type *map_len ATTRIBUTE_UNUSED) + bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, + void **map_addr ATTRIBUTE_UNUSED, + bfd_size_type *map_len ATTRIBUTE_UNUSED) { return (void *)-1; }