Move free_all_objfiles to program_space
[deliverable/binutils-gdb.git] / bfd / bfdio.c
index 71991bd47eed3cbb1f08ea21eb3ab11b0d5d7ad3..92dd9803e70a51fbc5fc634ebb8d8746261673aa 100644 (file)
@@ -1,6 +1,6 @@
 /* Low-level I/O routines for BFDs.
 
-   Copyright (C) 1990-2016 Free Software Foundation, Inc.
+   Copyright (C) 1990-2019 Free Software Foundation, Inc.
 
    Written by Cygnus Support.
 
@@ -41,7 +41,7 @@
 #endif
 
 file_ptr
-real_ftell (FILE *file)
+_bfd_real_ftell (FILE *file)
 {
 #if defined (HAVE_FTELLO64)
   return ftello64 (file);
@@ -53,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);
@@ -82,7 +82,7 @@ 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_attr;
@@ -145,12 +145,12 @@ DESCRIPTION
 .     or -1 (setting <<bfd_error>>) 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 <<bfd_error>>
 .     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  <<bfd_error>> is set).  *}
+.     Otherwise, a value of -1 is returned (and <<bfd_error>> is set).  *}
 .  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
 .  int (*bclose) (struct bfd *abfd);
 .  int (*bflush) (struct bfd *abfd);
@@ -162,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;
@@ -176,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;
@@ -205,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;
@@ -227,33 +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
-            && !bfd_is_thin_archive (parent_bfd->my_archive))
-       {
-         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
@@ -263,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;
@@ -280,79 +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->my_archive == NULL || bfd_is_thin_archive (abfd->my_archive))
+  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.  */
-    }
-
-  file_position = position;
-  if (direction == SEEK_SET)
+  if (abfd->iovec == NULL)
     {
-      bfd *parent_bfd = abfd;
-
-      while (parent_bfd->my_archive != NULL
-            && !bfd_is_thin_archive (parent_bfd->my_archive))
-        {
-          file_position += parent_bfd->origin;
-          parent_bfd = parent_bfd->my_archive;
-        }
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
     }
 
-  if (abfd->iovec)
-    result = abfd->iovec->bseek (abfd, file_position, direction);
-  else
-    result = -1;
+  /* 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 (result != 0)
-    {
-      int hold_errno = errno;
+  if (direction != SEEK_CUR)
+    position += offset;
 
-      /* Force redetermination of `where' field.  */
-      bfd_tell (abfd);
+  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)
+    {
       /* 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;
 }
 
@@ -377,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 */
@@ -392,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
@@ -420,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
@@ -441,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.  */
@@ -478,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);
@@ -501,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;
@@ -545,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;
 }
@@ -608,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;
 }
This page took 0.031138 seconds and 4 git commands to generate.