+
+static file_ptr
+memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
+{
+ struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
+
+ 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_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;
+}
+
+static file_ptr
+memory_btell (bfd *abfd)
+{
+ return abfd->where;
+}
+
+static int
+memory_bseek (bfd *abfd, file_ptr position, int direction)
+{
+ file_ptr nwhere;
+ struct bfd_in_memory *bim;
+
+ bim = (struct bfd_in_memory *) abfd->iostream;
+
+ if (direction == SEEK_SET)
+ nwhere = position;
+ else
+ nwhere = abfd->where + position;
+
+ if (nwhere < 0)
+ {
+ abfd->where = 0;
+ errno = EINVAL;
+ return -1;
+ }
+
+ 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);
+ }
+ }
+ else
+ {
+ abfd->where = bim->size;
+ errno = EINVAL;
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+memory_bclose (struct bfd *abfd)
+{
+ struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
+
+ free (bim->buffer);
+ free (bim);
+ abfd->iostream = NULL;
+
+ return 0;
+}
+
+static int
+memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
+memory_bstat (bfd *abfd, struct stat *statbuf)
+{
+ struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
+
+ memset (statbuf, 0, sizeof (*statbuf));
+ statbuf->st_size = bim->size;
+
+ return 0;
+}
+
+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)
+{
+ return (void *)-1;
+}
+
+const struct bfd_iovec _bfd_memory_iovec =
+{
+ &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
+ &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
+};