* reloc.c (bfd_check_overflow): Add casts before shifts which may
[binutils-gdb.git] / bfd / libbfd.c
index 291b1fd731b67e638b339aaf4123ea27d3a1a7e8..cd8f896cb71549b8440b054506ae42e289dbf25f 100644 (file)
@@ -155,22 +155,60 @@ _bfd_dummy_target (ignore_abfd)
   return 0;
 }
 \f
+/* Allocate memory using malloc.  */
 
-#ifndef bfd_zmalloc
-/* allocate and clear storage */
+PTR
+bfd_malloc (size)
+     size_t size;
+{
+  PTR ptr;
 
-char *
+  ptr = (PTR) malloc (size);
+  if (ptr == NULL && size != 0)
+    bfd_set_error (bfd_error_no_memory);
+  return ptr;
+}
+
+/* Reallocate memory using realloc.  */
+
+PTR
+bfd_realloc (ptr, size)
+     PTR ptr;
+     size_t size;
+{
+  PTR ret;
+
+  if (ptr == NULL)
+    ret = malloc (size);
+  else
+    ret = realloc (ptr, size);
+
+  if (ret == NULL)
+    bfd_set_error (bfd_error_no_memory);
+
+  return ret;
+}
+
+/* Allocate memory using malloc and clear it.  */
+
+PTR
 bfd_zmalloc (size)
-     bfd_size_type size;
+     size_t size;
 {
-  char *ptr = (char *) malloc ((size_t) size);
+  PTR ptr;
 
-  if (ptr && size)
-   memset(ptr, 0, (size_t) size);
+  ptr = (PTR) malloc (size);
+
+  if (size != 0)
+    {
+      if (ptr == NULL)
+       bfd_set_error (bfd_error_no_memory);
+      else
+       memset (ptr, 0, size);
+    }
 
   return ptr;
 }
-#endif /* bfd_zmalloc */
 \f
 /* Some IO code */
 
@@ -203,6 +241,24 @@ bfd_read (ptr, size, nitems, abfd)
      bfd *abfd;
 {
   int 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 * nitems;
+      if (abfd->where + get > bim->size)
+       {
+         get = bim->size - abfd->where;
+         bfd_set_error (bfd_error_file_truncated);
+       }
+      memcpy (ptr, bim->buffer + abfd->where, get);
+      abfd->where += get;
+      return get;
+    }
+
   nread = real_read (ptr, 1, (size_t)(size*nitems), bfd_cache_lookup(abfd));
 #ifdef FILE_OFFSET_IS_CHAR_INDEX
   if (nread > 0)
@@ -252,7 +308,7 @@ bfd_init_window (windowp)
 
 #undef HAVE_MPROTECT /* code's not tested yet */
 
-#if HAVE_MMAP || HAVE_MPROTECT
+#if HAVE_MMAP || HAVE_MPROTECT || HAVE_MADVISE
 #include <sys/types.h>
 #include <sys/mman.h>
 #endif
@@ -263,6 +319,12 @@ bfd_init_window (windowp)
 
 static int debug_windows;
 
+/* 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
+
 void
 bfd_free_window (windowp)
      bfd_window *windowp;
@@ -299,6 +361,7 @@ bfd_free_window (windowp)
   /* There should be no more references to i at this point.  */
   free (i);
 }
+#endif
 
 static int ok_to_map = 1;
 
@@ -308,12 +371,16 @@ bfd_get_file_window (abfd, offset, size, windowp, writable)
      file_ptr offset;
      bfd_size_type size;
      bfd_window *windowp;
-     int writable;
+     boolean writable;
 {
   static size_t pagesize;
   bfd_window_internal *i = windowp->i;
   size_t size_to_alloc = size;
 
+#ifndef USE_MMAP
+  abort ();
+#endif
+
   if (debug_windows)
     fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
             abfd, (long) offset, (long) size,
@@ -334,7 +401,9 @@ bfd_get_file_window (abfd, offset, size, windowp, writable)
       i->data = 0;
     }
 #ifdef HAVE_MMAP
-  if (ok_to_map && (i->data == 0 || i->mapped == 1))
+  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;
@@ -367,7 +436,9 @@ bfd_get_file_window (abfd, offset, size, windowp, writable)
        }
       i->data = mmap (i->data, real_size,
                      writable ? PROT_WRITE | PROT_READ : PROT_READ,
-                     writable ? MAP_FILE | MAP_PRIVATE : MAP_FILE,
+                     (writable
+                      ? MAP_FILE | MAP_PRIVATE
+                      : MAP_FILE | MAP_SHARED),
                      fd, file_offset);
       if (i->data == (PTR) -1)
        {
@@ -384,7 +455,7 @@ bfd_get_file_window (abfd, offset, size, windowp, writable)
        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->data = (PTR) ((bfd_byte *) i->data + offset2);
       windowp->size = size;
       i->mapped = 1;
       return true;
@@ -392,8 +463,8 @@ bfd_get_file_window (abfd, offset, size, windowp, writable)
   else if (debug_windows)
     {
       if (ok_to_map)
-       fprintf (stderr, "not mapping: data=%x mapped=%d\n",
-                i->data, i->mapped);
+       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");
     }
@@ -411,10 +482,7 @@ bfd_get_file_window (abfd, offset, size, windowp, writable)
   if (debug_windows)
     fprintf (stderr, "\n\t%s(%6ld)",
             i->data ? "realloc" : " malloc", (long) size_to_alloc);
-  if (i->data)
-    i->data = (PTR) realloc (i->data, size_to_alloc);
-  else
-    i->data = (PTR) malloc (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;
@@ -452,8 +520,13 @@ bfd_write (ptr, size, nitems, abfd)
      bfd_size_type nitems;
      bfd *abfd;
 {
-  long nwrote = fwrite (ptr, 1, (size_t) (size * nitems),
-                       bfd_cache_lookup (abfd));
+  long nwrote;
+
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    abort ();
+
+  nwrote = fwrite (ptr, 1, (size_t) (size * nitems),
+                  bfd_cache_lookup (abfd));
 #ifdef FILE_OFFSET_IS_CHAR_INDEX
   if (nwrote > 0)
     abfd->where += nwrote;
@@ -499,6 +572,9 @@ bfd_tell (abfd)
 {
   file_ptr ptr;
 
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    return abfd->where;
+
   ptr = ftell (bfd_cache_lookup(abfd));
 
   if (abfd->my_archive)
@@ -511,6 +587,8 @@ int
 bfd_flush (abfd)
      bfd *abfd;
 {
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    return 0;
   return fflush (bfd_cache_lookup(abfd));
 }
 
@@ -523,6 +601,10 @@ bfd_stat (abfd, statbuf)
 {
   FILE *f;
   int result;
+
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    abort ();
+
   f = bfd_cache_lookup (abfd);
   if (f == NULL)
     {
@@ -555,6 +637,16 @@ bfd_seek (abfd, position, direction)
 
   if (direction == SEEK_CUR && position == 0)
     return 0;
+
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    {
+      if (direction == SEEK_SET)
+       abfd->where = position;
+      else
+       abfd->where += position;
+      return 0;
+    }
+
 #ifdef FILE_OFFSET_IS_CHAR_INDEX
   if (abfd->format != bfd_archive && abfd->my_archive == 0)
     {
@@ -1012,6 +1104,7 @@ _bfd_generic_get_section_contents_in_window (abfd, section, w, offset, count)
      file_ptr offset;
      bfd_size_type count;
 {
+#ifdef USE_MMAP
   if (count == 0)
     return true;
   if (abfd->xvec->_bfd_get_section_contents != _bfd_generic_get_section_contents)
@@ -1025,7 +1118,7 @@ _bfd_generic_get_section_contents_in_window (abfd, section, w, offset, count)
       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);
+      w->i->data = (PTR) bfd_malloc ((size_t) count);
       if (w->i->data == NULL)
        {
          free (w->i);
@@ -1039,10 +1132,13 @@ _bfd_generic_get_section_contents_in_window (abfd, section, w, offset, count)
       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)
+      || (bfd_get_file_window (abfd, section->filepos + offset, count, w, true)
          == false))
     return false;
   return true;
+#else
+  abort ();
+#endif
 }
 
 /* This generic function can only be used in implementations where creating