This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[rfa] Add bfd-in-memory io vector
- From: Andrew Cagney <cagney at gnu dot org>
- To: binutils at sources dot redhat dot com
- Date: Fri, 30 Apr 2004 17:50:08 -0400
- Subject: [rfa] Add bfd-in-memory io vector
Hello,
This adds a bfd-in-memory IO vector to BFD. Note that it doesn't
completly consolidate code using "struct bfd_in_memory" as some of it is
pretty evil (grep for remaining references to BFD_IN_MEMORY). I'll do
another pass at eliminating more of the BFD_IN_MEMORY references in a
follow-up patch.
I've tested this on i386 GNU/Linux with no regressions. However, given
my experience with the previous IOVEC change, I'm not sure how
significant that result is :-/
Anyway, Ok?
Andrew
2004-04-30 Andrew Cagney <cagney@redhat.com>
* libbfd-in.h (_bfd_in_memory): Declare.
* libbfd.h: Re-generate.
* opncls.c (bim_bread, bim_bwrite, bim_btell, bim_bflush, bim_bstat)
(bim_bseek, bim_bclose, bim_iovec, _bfd_in_memory): Implement BFD
in memory.
(bfd_close): Delete bfd-in-memory code.
(bfd_make_writable): Use _bfd_in_memory.
* bfdio.c (bfd_bread, bfd_bwrite, bfd_tell, bfd_flush, bfd_stat)
(bfd_seek, bfd_get_size): Delete bfd-in-memory code.
* elfcode.h (bfd_from_remote_memory): Use _bfd_in_memory.
* xcofflink.c (bfd_xcoff_link_generate_rtinit): Ditto.
* coff-alpha.c (alpha_ecoff_get_elt_at_filepos): Ditto.
Index: bfdio.c
===================================================================
RCS file: /cvs/src/src/bfd/bfdio.c,v
retrieving revision 1.6
diff -p -u -r1.6 bfdio.c
--- bfdio.c 21 Apr 2004 17:05:11 -0000 1.6
+++ bfdio.c 30 Apr 2004 21:38:39 -0000
@@ -97,7 +97,6 @@ DESCRIPTION
*/
-
/* Return value is amount read. */
bfd_size_type
@@ -105,26 +104,6 @@ bfd_bread (void *ptr, bfd_size_type size
{
size_t nread;
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- {
- struct bfd_in_memory *bim;
- bfd_size_type get;
-
- bim = 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 = abfd->iovec->bread (abfd, ptr, size);
if (nread != (size_t) -1)
abfd->where += nread;
@@ -137,33 +116,6 @@ bfd_bwrite (const void *ptr, bfd_size_ty
{
size_t nwrote;
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- {
- struct bfd_in_memory *bim = 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_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 = abfd->iovec->bwrite (abfd, ptr, size);
if (nwrote != (size_t) -1)
abfd->where += nwrote;
@@ -182,9 +134,6 @@ bfd_tell (bfd *abfd)
{
file_ptr ptr;
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- return abfd->where;
-
ptr = abfd->iovec->btell (abfd);
if (abfd->my_archive)
@@ -196,8 +145,6 @@ bfd_tell (bfd *abfd)
int
bfd_flush (bfd *abfd)
{
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- return 0;
return abfd->iovec->bflush (abfd);
}
@@ -208,9 +155,6 @@ bfd_stat (bfd *abfd, struct stat *statbu
{
int result;
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- abort ();
-
result = abfd->iovec->bstat (abfd, statbuf);
if (result < 0)
bfd_set_error (bfd_error_system_call);
@@ -234,47 +178,6 @@ bfd_seek (bfd *abfd, file_ptr position,
if (direction == SEEK_CUR && position == 0)
return 0;
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- {
- struct bfd_in_memory *bim;
-
- bim = 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_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
@@ -407,9 +310,6 @@ long
bfd_get_size (bfd *abfd)
{
struct stat buf;
-
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- return ((struct bfd_in_memory *) abfd->iostream)->size;
if (abfd->iovec->bstat (abfd, &buf) != 0)
return 0;
Index: coff-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-alpha.c,v
retrieving revision 1.20
diff -p -u -r1.20 coff-alpha.c
--- coff-alpha.c 30 Apr 2004 14:23:39 -0000 1.20
+++ coff-alpha.c 30 Apr 2004 21:38:39 -0000
@@ -2086,7 +2086,6 @@ alpha_ecoff_get_elt_at_filepos (archive,
bfd_byte ab[8];
bfd_size_type size;
bfd_byte *buf, *p;
- struct bfd_in_memory *bim;
nbfd = _bfd_get_elt_at_filepos (archive, filepos);
if (nbfd == NULL)
@@ -2181,19 +2180,11 @@ alpha_ecoff_get_elt_at_filepos (archive,
}
/* Now the uncompressed file contents are in buf. */
- bim = ((struct bfd_in_memory *)
- bfd_alloc (nbfd, (bfd_size_type) sizeof (struct bfd_in_memory)));
- if (bim == NULL)
+ if (!_bfd_in_memory (nbfd, nbfd->flags, buf, size))
goto error_return;
- bim->size = size;
- bim->buffer = buf;
nbfd->mtime_set = TRUE;
nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10);
-
- nbfd->flags |= BFD_IN_MEMORY;
- nbfd->iostream = (PTR) bim;
- BFD_ASSERT (! nbfd->cacheable);
return nbfd;
Index: elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.55
diff -p -u -r1.55 elfcode.h
--- elfcode.h 22 Apr 2004 14:45:31 -0000 1.55
+++ elfcode.h 30 Apr 2004 21:38:40 -0000
@@ -1690,28 +1690,22 @@ NAME(_bfd_elf,bfd_from_remote_memory)
memcpy (contents, &x_ehdr, sizeof x_ehdr);
/* Now we have a memory image of the ELF file contents. Make a BFD. */
- bim = bfd_malloc (sizeof (struct bfd_in_memory));
- if (bim == NULL)
+ nbfd = _bfd_new_bfd ();
+ if (nbfd == NULL)
{
free (contents);
bfd_set_error (bfd_error_no_memory);
return NULL;
}
- nbfd = _bfd_new_bfd ();
- if (nbfd == NULL)
+ if (!_bfd_in_memory (nbfd, 0, contents, contents_size))
{
- free (bim);
free (contents);
+ bfd_close (nbfd);
bfd_set_error (bfd_error_no_memory);
return NULL;
}
nbfd->filename = "<in-memory>";
nbfd->xvec = templ->xvec;
- bim->size = contents_size;
- bim->buffer = contents;
- nbfd->iostream = bim;
- nbfd->flags = BFD_IN_MEMORY;
- nbfd->direction = read_direction;
nbfd->mtime = time (NULL);
nbfd->mtime_set = TRUE;
Index: libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.33
diff -p -u -r1.33 libbfd-in.h
--- libbfd-in.h 30 Apr 2004 14:23:39 -0000 1.33
+++ libbfd-in.h 30 Apr 2004 21:38:40 -0000
@@ -50,6 +50,9 @@ struct bfd_in_memory
bfd_byte *buffer;
};
+int _bfd_in_memory (struct bfd *abfd, flagword flags, void *buffer,
+ bfd_size_type size);
+
/* tdata for an archive. For an input archive, cache
needs to be free()'d. For an output archive, symdefs do. */
Index: opncls.c
===================================================================
RCS file: /cvs/src/src/bfd/opncls.c,v
retrieving revision 1.23
diff -p -u -r1.23 opncls.c
--- opncls.c 23 Apr 2004 00:22:57 -0000 1.23
+++ opncls.c 30 Apr 2004 21:38:40 -0000
@@ -1,7 +1,7 @@
/* opncls.c -- open and close a BFD.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
- 2001, 2002, 2003
- Free Software Foundation, Inc.
+
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -501,6 +501,185 @@ bfd_openr_iovec (const char *filename, c
return nbfd;
}
+
+
+/* BFD in memory. */
+
+static file_ptr
+bim_btell (struct bfd *abfd)
+{
+ return abfd->where;
+}
+
+static int
+bim_bseek (struct bfd *abfd, file_ptr offset, int whence)
+{
+ struct bfd_in_memory *bim;
+
+ bim = abfd->iostream;
+
+ if (whence == SEEK_SET)
+ abfd->where = offset;
+ else
+ abfd->where += offset;
+
+ 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_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;
+}
+
+static file_ptr
+bim_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
+{
+ struct bfd_in_memory *bim;
+ bfd_size_type get;
+
+ bim = abfd->iostream;
+ get = nbytes;
+ if (abfd->where + get > bim->size)
+ {
+ if (bim->size < (bfd_size_type) abfd->where)
+ get = 0;
+ else
+ get = bim->size - abfd->where;
+ }
+ memcpy (buf, bim->buffer + abfd->where, (size_t) get);
+ abfd->where += get;
+ return get;
+}
+
+static file_ptr
+bim_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
+{
+ struct bfd_in_memory *bim = abfd->iostream;
+ size_t size;
+
+ size = (size_t) nbytes;
+ 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_realloc (bim->buffer, newsize);
+ if (bim->buffer == 0)
+ {
+ bim->size = 0;
+ return 0;
+ }
+ }
+ }
+ memcpy (bim->buffer + abfd->where, where, size);
+ abfd->where += size;
+ return size;
+}
+
+static int
+bim_bclose (struct bfd *abfd ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
+bim_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
+bim_bstat (struct bfd *abfd, struct stat *sb)
+{
+ struct bfd_in_memory *bim = abfd->iostream;
+
+ /* Assume we just "made" the BFD, and fake it. */
+ memset (sb, 0, sizeof (*sb));
+ time (&sb->st_mtime);
+ sb->st_uid = getuid ();
+ sb->st_gid = getgid ();
+ sb->st_mode = 0644;
+ sb->st_size = bim->size;
+ return 0;
+}
+
+static const struct bfd_iovec bim_iovec = {
+ &bim_bread, &bim_bwrite, &bim_btell, &bim_bseek,
+ &bim_bclose, &bim_bflush, &bim_bstat
+};
+
+/*
+INTERNAL_FUNCTION
+ _bfd_in_memory
+
+SYNOPSIS
+ bfd_boolean _bfd_in_memory (bfd *abfd, flagword flags,
+ void *buffer, bfd_size_type size);
+
+DESCRIPTION
+
+ Convert @var{abfd} into a memory <<bfd> containing @var{size}
+ bytes of data at @var{buffer}. If @var{buffer} is NULL, make
+ the @var{abfd} writeable.
+
+*/
+
+int
+_bfd_in_memory (struct bfd *abfd, flagword flags, void *buffer,
+ bfd_size_type size)
+{
+ struct bfd_in_memory *bim;
+
+ bim = ((struct bfd_in_memory *)
+ bfd_alloc (abfd, (bfd_size_type) sizeof (struct bfd_in_memory)));
+ if (bim == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
+
+ bim->size = size;
+ bim->buffer = buffer;
+ abfd->iostream = bim;
+ abfd->iovec = &bim_iovec;
+ abfd->flags = flags | BFD_IN_MEMORY;
+ abfd->where = 0;
+ if (buffer != 0)
+ abfd->direction = read_direction;
+ else
+ abfd->direction = write_direction;
+ BFD_ASSERT (! abfd->cacheable);
+ return TRUE;
+}
+
+
/* bfd_openw -- open for writing.
Returns a pointer to a freshly-allocated BFD on success, or NULL.
@@ -593,12 +772,7 @@ bfd_close (bfd *abfd)
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
return FALSE;
- /* FIXME: cagney/2004-02-15: Need to implement a BFD_IN_MEMORY io
- vector. */
- if (!(abfd->flags & BFD_IN_MEMORY))
- ret = abfd->iovec->bclose (abfd);
- else
- ret = 0;
+ ret = abfd->iovec->bclose (abfd);
/* If the file was open for writing and is now executable,
make it so. */
@@ -735,15 +909,9 @@ bfd_make_writable (bfd *abfd)
return FALSE;
}
- bim = bfd_malloc (sizeof (struct bfd_in_memory));
- abfd->iostream = bim;
- /* bfd_bwrite will grow these as needed. */
- bim->size = 0;
- bim->buffer = 0;
-
- abfd->flags |= BFD_IN_MEMORY;
- abfd->direction = write_direction;
- abfd->where = 0;
+ /* bfd_bwrite will grow this as needed. */
+ if (!_bfd_in_memory (abfd, abfd->flags, NULL, 0))
+ return FALSE;
return TRUE;
}
Index: xcofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/xcofflink.c,v
retrieving revision 1.33
diff -p -u -r1.33 xcofflink.c
--- xcofflink.c 2 Dec 2003 22:59:59 -0000 1.33
+++ xcofflink.c 30 Apr 2004 21:38:41 -0000
@@ -3230,22 +3230,11 @@ bfd_xcoff_link_generate_rtinit (abfd, in
const char *fini;
bfd_boolean rtld;
{
- struct bfd_in_memory *bim;
-
- bim = ((struct bfd_in_memory *)
- bfd_malloc ((bfd_size_type) sizeof (struct bfd_in_memory)));
- if (bim == NULL)
+ if (!_bfd_in_memory (abfd, 0, NULL, 0))
return FALSE;
- bim->size = 0;
- bim->buffer = 0;
-
abfd->link_next = 0;
abfd->format = bfd_object;
- abfd->iostream = (PTR) bim;
- abfd->flags = BFD_IN_MEMORY;
- abfd->direction = write_direction;
- abfd->where = 0;
if (! bfd_xcoff_generate_rtinit (abfd, init, fini, rtld))
return FALSE;