This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[wip] BFD from an arbitrary object; Was: provide pass-through valuein bfd_elf_bfd_from_remote_memory


Hello,

Hi Jim,


Nick, I didn't see anything from you on the following patch:

http://sources.redhat.com/ml/binutils/2003-05/msg00658.html

It's a patch to bfd_elf_bfd_from_remote_memory, which was written by
Roland McGrath; Roland says it's fine with him.


Right, but there was quite a Long discussion between you and Andrew
about several points and I thought that you were going to submit a
revised patch ??

Picking up an old thread.


The attached work-in-progress (GDB works) adds a "struct bfd_file" object to bfd/. It then modifies the "struct bfd" so that an instance of a "bfd_file" is used for I/O.

By doing this it becomes possible to:

- cleanup the existing code
Replacing this:
	if (bfd & BFD_IN_MEMORY)
	  do memory I/O op
	else
	  do file I/O
with this:
	bfd->stream->I/O op (bfd)
along with separate bfd-in-memory and "cache" "struct bfd_file"s.

- let clients implement arbitrary files
In particular, and immediatly, a stream that is backed by the memory found in the inferior that GDB is debugging.


My immediate interest is in opinion (in particular from Nick and Alan) on questions such as:

- is the theory ok?

- given there are N equally effective ways of implementing the "struct bfd_file" object, is the attached reasonable?

- what to do about mmap?
I ignored it as it isn't enabled by default :-/ I personally think that it should be let be until this is in and then BFD and GDB figure out how exactly they both want mmap to work.


- do the changes to cache.c scare anyone (I've not checked them carefully yet :-)?

The other question is of course (and assuming the theory is ok) how should this be integrated?

Andrew

PS: Yes, I know, I "lost" the bfd-in-memory code. I intend moving it to the new file "bim.c".
? diffs
? bim.c
Index: archive.c
===================================================================
RCS file: /cvs/src/src/bfd/archive.c,v
retrieving revision 1.28
diff -u -r1.28 archive.c
--- archive.c	29 Jun 2003 10:06:38 -0000	1.28
+++ archive.c	14 Feb 2004 00:29:38 -0000
@@ -1339,7 +1339,7 @@
   if (member && (member->flags & BFD_IN_MEMORY) != 0)
     {
       /* Assume we just "made" the member, and fake it.  */
-      struct bfd_in_memory *bim = member->iostream;
+      struct bfd_in_memory *bim = member->stream.cookie;
       time (&status.st_mtime);
       status.st_uid = getuid ();
       status.st_gid = getgid ();
Index: bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.71
diff -u -r1.71 bfd-in.h
--- bfd-in.h	11 Feb 2004 23:23:20 -0000	1.71
+++ bfd-in.h	14 Feb 2004 00:29:38 -0000
@@ -703,6 +703,29 @@
 extern bfd_boolean bfd_sparclinux_size_dynamic_sections
   (bfd *, struct bfd_link_info *);
 
+/* Underlying file I/O.  */
+
+struct bfd_file
+{
+  void *cookie;
+  const struct bfd_file_ops *ops;
+};
+
+struct bfd_file_ops
+{
+  file_ptr (*bread) (void *ptr, file_ptr size, file_ptr nmemb,
+		     struct bfd_file *sream);
+  file_ptr (*bwrite) (const void *ptr, file_ptr size, file_ptr nmemb,
+		      struct bfd_file *stream);
+  file_ptr (*btell) (struct bfd_file *stream);
+  int (*bseek) (struct bfd_file *stream, file_ptr offset, int whence);
+  int (*bclose) (struct bfd_file *stream);
+  int (*berror) (struct bfd_file *stream);
+  int (*bflush) (struct bfd_file *stream);
+  int (*bstat) (struct bfd_file *stream, struct stat *sb);
+  // int (*bfileno) (struct bfd_file *stream);
+};
+
 /* mmap hacks */
 
 struct _bfd_window_internal;
Index: bfd.c
===================================================================
RCS file: /cvs/src/src/bfd/bfd.c,v
retrieving revision 1.55
diff -u -r1.55 bfd.c
--- bfd.c	24 Nov 2003 18:06:39 -0000	1.55
+++ bfd.c	14 Feb 2004 00:29:38 -0000
@@ -52,27 +52,12 @@
 .     is the result of an fopen on the filename.  However, if the
 .     BFD_IN_MEMORY flag is set, then iostream is actually a pointer
 .     to a bfd_in_memory struct.  *}
-.  void *iostream;
-.
-.  {* Is the file descriptor being cached?  That is, can it be closed as
-.     needed, and re-opened when accessed later?  *}
-.  bfd_boolean cacheable;
+.  struct bfd_file stream;
 .
 .  {* Marks whether there was a default target specified when the
 .     BFD was opened. This is used to select which matching algorithm
 .     to use to choose the back end.  *}
 .  bfd_boolean target_defaulted;
-.
-.  {* The caching routines use these to maintain a
-.     least-recently-used list of BFDs.  *}
-.  struct bfd *lru_prev, *lru_next;
-.
-.  {* When a file is closed by the caching routines, BFD retains
-.     state information on the file here...  *}
-.  ufile_ptr where;
-.
-.  {* ... and here: (``once'' means at least once).  *}
-.  bfd_boolean opened_once;
 .
 .  {* Set if we have a locally maintained mtime value, rather than
 .     getting it from the file each time.  *}
Index: bfdio.c
===================================================================
RCS file: /cvs/src/src/bfd/bfdio.c,v
retrieving revision 1.5
diff -u -r1.5 bfdio.c
--- bfdio.c	11 Feb 2004 23:23:20 -0000	1.5
+++ bfdio.c	14 Feb 2004 00:29:38 -0000
@@ -38,62 +38,6 @@
 #define S_IXOTH 0001    /* Execute by others.  */
 #endif
 
-file_ptr
-real_ftell (FILE *file)
-{
-#if defined (HAVE_FTELLO64)
-  return ftello64 (file);
-#elif defined (HAVE_FTELLO)
-  return ftello (file);
-#else
-  return ftell (file);
-#endif
-}
-
-int
-real_fseek (FILE *file, file_ptr offset, int whence)
-{
-#if defined (HAVE_FSEEKO64)
-  return fseeko64 (file, offset, whence);
-#elif defined (HAVE_FSEEKO)
-  return fseeko (file, offset, whence);
-#else
-  return fseek (file, offset, whence);
-#endif
-}
-
-/* Note that archive entries don't have streams; they share their parent's.
-   This allows someone to play with the iostream behind BFD's back.
-
-   Also, note that the origin pointer points to the beginning of a file's
-   contents (0 for non-archive elements).  For archive entries this is the
-   first octet in the file, NOT the beginning of the archive header.  */
-
-static size_t
-real_read (void *where, size_t a, size_t b, FILE *file)
-{
-  /* FIXME - this looks like an optimization, but it's really to cover
-     up for a feature of some OSs (not solaris - sigh) that
-     ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
-     internally and tries to link against them.  BFD seems to be smart
-     enough to realize there are no symbol records in the "file" that
-     doesn't exist but attempts to read them anyway.  On Solaris,
-     attempting to read zero bytes from a NULL file results in a core
-     dump, but on other platforms it just returns zero bytes read.
-     This makes it to something reasonable. - DJ */
-  if (a == 0 || b == 0)
-    return 0;
-
-
-#if defined (__VAX) && defined (VMS)
-  /* Apparently fread on Vax VMS does not keep the record length
-     information.  */
-  return read (fileno (file), where, a * b);
-#else
-  return fread (where, a, b, file);
-#endif
-}
-
 /* Return value is amount read.  */
 
 bfd_size_type
@@ -101,29 +45,7 @@
 {
   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 = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
-  if (nread != (size_t) -1)
-    abfd->where += nread;
+  nread = abfd->stream.ops->bread (ptr, 1, (size_t) size, &abfd->stream);
 
   /* Set bfd_error if we did not read as much data as we expected.
 
@@ -134,7 +56,7 @@
      provide something more useful (eg. no_symbols or wrong_format).  */
   if (nread != size)
     {
-      if (ferror (bfd_cache_lookup (abfd)))
+      if (abfd->stream.ops->berror (&abfd->stream))
 	bfd_set_error (bfd_error_system_call);
       else
 	bfd_set_error (bfd_error_file_truncated);
@@ -148,36 +70,7 @@
 {
   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 = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
-  if (nwrote != (size_t) -1)
-    abfd->where += nwrote;
+  nwrote = abfd->stream.ops->bwrite (ptr, 1, (size_t) size, &abfd->stream);
   if (nwrote != size)
     {
 #ifdef ENOSPC
@@ -193,14 +86,9 @@
 {
   file_ptr ptr;
 
-  if ((abfd->flags & BFD_IN_MEMORY) != 0)
-    return abfd->where;
-
-  ptr = real_ftell (bfd_cache_lookup (abfd));
-
+  ptr = abfd->stream.ops->btell (&abfd->stream);
   if (abfd->my_archive)
     ptr -= abfd->origin;
-  abfd->where = ptr;
   return ptr;
 }
 
@@ -209,7 +97,7 @@
 {
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     return 0;
-  return fflush (bfd_cache_lookup(abfd));
+  return abfd->stream.ops->bflush (&abfd->stream);
 }
 
 /* Returns 0 for success, negative value for failure (in which case
@@ -217,19 +105,12 @@
 int
 bfd_stat (bfd *abfd, struct stat *statbuf)
 {
-  FILE *f;
   int result;
 
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     abort ();
 
-  f = bfd_cache_lookup (abfd);
-  if (f == NULL)
-    {
-      bfd_set_error (bfd_error_system_call);
-      return -1;
-    }
-  result = fstat (fileno (f), statbuf);
+  result = abfd->stream.ops->bstat (&abfd->stream, statbuf);
   if (result < 0)
     bfd_set_error (bfd_error_system_call);
   return result;
@@ -242,7 +123,6 @@
 bfd_seek (bfd *abfd, file_ptr position, int direction)
 {
   int result;
-  FILE *f;
   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
@@ -253,112 +133,23 @@
   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
-      /* Explanation for this code: I'm only about 95+% sure that the above
-	 conditions are sufficient and that all i/o calls are properly
-	 adjusting the `where' field.  So this is sort of an `assert'
-	 that the `where' field is correct.  If we can go a while without
-	 tripping the abort, we can probably safely disable this code,
-	 so that the real optimizations happen.  */
-      file_ptr where_am_i_now;
-      where_am_i_now = real_ftell (bfd_cache_lookup (abfd));
-      if (abfd->my_archive)
-	where_am_i_now -= abfd->origin;
-      if (where_am_i_now != abfd->where)
-	abort ();
-#endif
-      if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
-	return 0;
-    }
-  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.  */
-    }
-
-  f = bfd_cache_lookup (abfd);
   file_position = position;
   if (direction == SEEK_SET && abfd->my_archive != NULL)
     file_position += abfd->origin;
 
-  result = real_fseek (f, file_position, direction);
+  result = abfd->stream.ops->bseek (&abfd->stream, file_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)
+      if (errno == EINVAL)
 	bfd_set_error (bfd_error_file_truncated);
       else
 	{
 	  bfd_set_error (bfd_error_system_call);
-	  errno = hold_errno;
+	  errno = errno;
 	}
     }
-  else
-    {
-      /* Adjust `where' field.  */
-      if (direction == SEEK_SET)
-	abfd->where = position;
-      else
-	abfd->where += position;
-    }
   return result;
 }
 
@@ -378,14 +169,12 @@
 long
 bfd_get_mtime (bfd *abfd)
 {
-  FILE *fp;
   struct stat buf;
 
   if (abfd->mtime_set)
     return abfd->mtime;
 
-  fp = bfd_cache_lookup (abfd);
-  if (0 != fstat (fileno (fp), &buf))
+  if (0 != abfd->stream.ops->bstat (&abfd->stream, &buf))
     return 0;
 
   abfd->mtime = buf.st_mtime;		/* Save value in case anyone wants it */
@@ -428,14 +217,12 @@
 long
 bfd_get_size (bfd *abfd)
 {
-  FILE *fp;
   struct stat buf;
 
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
-    return ((struct bfd_in_memory *) abfd->iostream)->size;
+    return ((struct bfd_in_memory *) abfd->stream.cookie)->size;
 
-  fp = bfd_cache_lookup (abfd);
-  if (0 != fstat (fileno (fp), & buf))
+  if (0 != abfd->stream.ops->bstat (&abfd->stream, & buf))
     return 0;
 
   return buf.st_size;
Index: cache.c
===================================================================
RCS file: /cvs/src/src/bfd/cache.c,v
retrieving revision 1.11
diff -u -r1.11 cache.c
--- cache.c	11 Feb 2004 23:23:20 -0000	1.11
+++ cache.c	14 Feb 2004 00:29:38 -0000
@@ -30,11 +30,11 @@
 	regard to the underlying operating system's file descriptor
 	limit (often as low as 20 open files).  The module in
 	<<cache.c>> maintains a least recently used list of
-	<<BFD_CACHE_MAX_OPEN>> files, and exports the name
-	<<bfd_cache_lookup>>, which runs around and makes sure that
-	the required BFD is open. If not, then it chooses a file to
-	close, closes it and opens the one wanted, returning its file
-	handle.
+	<<BFD_CACHE_MAX_OPEN>> files, and exports a <<struct
+	bfd_file>> implementation which runs around and makes sure
+	that the required <<bfd_file>> is open.  If not, then it
+	chooses a file to close, closes it and opens the one wanted,
+	applying the operation to that just opend file.
 
 */
 
@@ -42,122 +42,259 @@
 #include "sysdep.h"
 #include "libbfd.h"
 
-static bfd_boolean bfd_cache_delete (bfd *);
+struct bfd_cache;
+static bfd_boolean bfd_cache_delete (struct bfd_cache *kill);
+static FILE *bfd_cache_lookup (struct bfd_file *stream);
+
+static file_ptr
+real_ftell (FILE *file)
+{
+#if defined (HAVE_FTELLO64)
+  return ftello64 (file);
+#elif defined (HAVE_FTELLO)
+  return ftello (file);
+#else
+  return ftell (file);
+#endif
+}
+
+static int
+real_fseek (FILE *file, file_ptr offset, int whence)
+{
+#if defined (HAVE_FSEEKO64)
+  return fseeko64 (file, offset, whence);
+#elif defined (HAVE_FSEEKO)
+  return fseeko (file, offset, whence);
+#else
+  return fseek (file, offset, whence);
+#endif
+}
+
+static file_ptr
+real_fread (void *where, file_ptr a, file_ptr b, FILE *file)
+{
+  /* FIXME - this looks like an optimization, but it's really to cover
+     up for a feature of some OSs (not solaris - sigh) that
+     ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
+     internally and tries to link against them.  BFD seems to be smart
+     enough to realize there are no symbol records in the "file" that
+     doesn't exist but attempts to read them anyway.  On Solaris,
+     attempting to read zero bytes from a NULL file results in a core
+     dump, but on other platforms it just returns zero bytes read.
+     This makes it to something reasonable. - DJ */
+  if (a == 0 || b == 0)
+    return 0;
+
+#if defined (__VAX) && defined (VMS)
+  /* Apparently fread on Vax VMS does not keep the record length
+     information.  */
+  return read (fileno (file), where, a * b);
+#else
+  return fread (where, a, b, file);
+#endif
+}
+
+static file_ptr
+cache_btell (struct bfd_file *stream)
+{
+  return real_ftell (bfd_cache_lookup (stream));
+}
+
+static int
+cache_bseek (struct bfd_file *stream, file_ptr offset, int whence)
+{
+  return real_fseek (bfd_cache_lookup (stream), offset, whence);
+}
+
+/* Note that archive entries don't have streams; they share their parent's.
+   This allows someone to play with the iostream behind BFD's back.
+
+   Also, note that the origin pointer points to the beginning of a file's
+   contents (0 for non-archive elements).  For archive entries this is the
+   first octet in the file, NOT the beginning of the archive header.  */
+
+static file_ptr
+cache_bread (void *where, file_ptr a, file_ptr b, struct bfd_file *stream)
+{
+  return real_fread (where, a, b, bfd_cache_lookup (stream));
+}
+
+static file_ptr
+cache_bwrite (const void *where, file_ptr a, file_ptr b,
+	     struct bfd_file *stream)
+{
+  return fwrite (where, a, b, bfd_cache_lookup (stream));
+}
+
+static int
+cache_bclose (struct bfd_file *stream)
+{
+  return fclose (bfd_cache_lookup (stream));
+}
+
+static int
+cache_berror (struct bfd_file *stream)
+{
+  return ferror (bfd_cache_lookup (stream));
+}
+
+static int
+cache_bflush (struct bfd_file *stream)
+{
+  return fflush (bfd_cache_lookup (stream));
+}
+
+static int
+cache_bstat (struct bfd_file *stream, struct stat *sb)
+{
+  return fstat (fileno (bfd_cache_lookup (stream)), sb);
+}
+
+static const struct bfd_file_ops cache_bops = {
+  &cache_bread, &cache_bwrite, &cache_btell, &cache_bseek,
+  &cache_bclose, &cache_berror, &cache_bflush, &cache_bstat
+};
 
 /*
 INTERNAL_FUNCTION
-	BFD_CACHE_MAX_OPEN macro
+	bfd_direction_fmode
+
+SYNOPSIS
+        const char * bfd_direction_fmode (enum bfd_direction direction);
 
 DESCRIPTION
-	The maximum number of files which the cache will keep open at
-	one time.
 
-.#define BFD_CACHE_MAX_OPEN 10
+	Return the mode string for opening a file in the specified
+	<<direction>>.
 
 */
 
-/* The number of BFD files we have open.  */
+const char *
+bfd_direction_fmode (enum bfd_direction direction)
+{
+  switch (direction)
+    {
+    case read_direction: return FOPEN_RB;
+    case write_direction: return FOPEN_RUB;
+    case both_direction: return FOPEN_RUB;
+    default: abort ();
+    }
+}
 
-static int open_files;
+struct bfd_cache
+{
+  /* The caching routines use these to maintain a least-recently-used
+     list of file descriptors.  */
+  struct bfd_cache *lru_prev;
+  struct bfd_cache *lru_next;
+
+  /* And of course the open stream.  */
+  FILE *file;
+
+  /* Is the file descriptor being cached?  That is, can it be closed
+     as needed, and re-opened when accessed later?  */
+  bfd_boolean cacheable;
+
+  /* The direction with which the FILE was opened.  */
+  enum bfd_direction direction;
+
+  /* When a file is closed by the caching routines, retains state
+     information on the file here ...  */
+  ufile_ptr where;
+
+  /* ... and here: (``once'' means at least once).  */
+  bfd_boolean opened_once;
+
+  /* ... and here: full path to the file.  */
+  const char *filename;
+};
 
 /*
 INTERNAL_FUNCTION
-	bfd_last_cache
-
-SYNOPSIS
-	extern bfd *bfd_last_cache;
+	BFD_CACHE_MAX_OPEN macro
 
 DESCRIPTION
-	Zero, or a pointer to the topmost BFD on the chain.  This is
-	used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
-	determine when it can avoid a function call.
+	The maximum number of files which the cache will keep open at
+	one time.
+
+.#define BFD_CACHE_MAX_OPEN 10
+
 */
 
-bfd *bfd_last_cache;
+/* The number of BFD files we have open.  */
 
-/*
-  INTERNAL_FUNCTION
-  	bfd_cache_lookup
+static int open_files;
 
-  DESCRIPTION
- 	Check to see if the required BFD is the same as the last one
- 	looked up. If so, then it can use the stream in the BFD with
- 	impunity, since it can't have changed since the last lookup;
- 	otherwise, it has to perform the complicated lookup function.
-
-  .#define bfd_cache_lookup(x) \
-  .    ((x)==bfd_last_cache? \
-  .      (FILE*) (bfd_last_cache->iostream): \
-  .       bfd_cache_lookup_worker(x))
+/* Zero, or a pointer to the topmost bfd_file on the chain.  This is
+   used by <<bfd_cache_lookup>> to determine the most recenty opened
+   file.  */
 
- */
+static struct bfd_cache *bfd_last_cache;
 
-/* Insert a BFD into the cache.  */
+/* Insert a new entry into the cache.  */
 
 static void
-insert (bfd *abfd)
+insert (struct bfd_cache *entry)
 {
   if (bfd_last_cache == NULL)
     {
-      abfd->lru_next = abfd;
-      abfd->lru_prev = abfd;
+      entry->lru_next = entry;
+      entry->lru_prev = entry;
     }
   else
     {
-      abfd->lru_next = bfd_last_cache;
-      abfd->lru_prev = bfd_last_cache->lru_prev;
-      abfd->lru_prev->lru_next = abfd;
-      abfd->lru_next->lru_prev = abfd;
+      entry->lru_next = bfd_last_cache;
+      entry->lru_prev = bfd_last_cache->lru_prev;
+      entry->lru_prev->lru_next = entry;
+      entry->lru_next->lru_prev = entry;
     }
-  bfd_last_cache = abfd;
+  bfd_last_cache = entry;
 }
 
-/* Remove a BFD from the cache.  */
+/* Remove an entry from the cache.  */
 
 static void
-snip (bfd *abfd)
+snip (struct bfd_cache *entry)
 {
-  abfd->lru_prev->lru_next = abfd->lru_next;
-  abfd->lru_next->lru_prev = abfd->lru_prev;
-  if (abfd == bfd_last_cache)
+  entry->lru_prev->lru_next = entry->lru_next;
+  entry->lru_next->lru_prev = entry->lru_prev;
+  if (entry == bfd_last_cache)
     {
-      bfd_last_cache = abfd->lru_next;
-      if (abfd == bfd_last_cache)
+      bfd_last_cache = entry->lru_next;
+      if (entry == bfd_last_cache)
 	bfd_last_cache = NULL;
     }
 }
 
 /* We need to open a new file, and the cache is full.  Find the least
-   recently used cacheable BFD and close it.  */
+   recently used cacheable BFD and close it.  Return non-zero if
+   something was closed.  */
 
 static bfd_boolean
 close_one (void)
 {
-  register bfd *kill;
+  struct bfd_cache *kill;
 
   if (bfd_last_cache == NULL)
-    kill = NULL;
-  else
+    /* There are no open cacheable BFD's.  */
+    return TRUE;
+
+  for (kill = bfd_last_cache->lru_prev;
+       ! kill->cacheable;
+       kill = kill->lru_prev)
     {
-      for (kill = bfd_last_cache->lru_prev;
-	   ! kill->cacheable;
-	   kill = kill->lru_prev)
+      if (kill == bfd_last_cache)
 	{
-	  if (kill == bfd_last_cache)
-	    {
-	      kill = NULL;
-	      break;
-	    }
+	  kill = NULL;
+	  break;
 	}
     }
 
   if (kill == NULL)
-    {
-      /* There are no open cacheable BFD's.  */
-      return TRUE;
-    }
+    /* There are no open cacheable BFD's.  */
+    return TRUE;
 
-  kill->where = real_ftell ((FILE *) kill->iostream);
+  kill->where = real_ftell (kill->file);
 
   return bfd_cache_delete (kill);
 }
@@ -165,11 +302,11 @@
 /* Close a BFD and remove it from the cache.  */
 
 static bfd_boolean
-bfd_cache_delete (bfd *abfd)
+bfd_cache_delete (struct bfd_cache *kill)
 {
   bfd_boolean ret;
 
-  if (fclose ((FILE *) abfd->iostream) == 0)
+  if (fclose (kill->file) == 0)
     ret = TRUE;
   else
     {
@@ -177,35 +314,53 @@
       bfd_set_error (bfd_error_system_call);
     }
 
-  snip (abfd);
+  snip (kill);
 
-  abfd->iostream = NULL;
+  kill->file = NULL;
   --open_files;
 
   return ret;
 }
 
+
 /*
 INTERNAL_FUNCTION
 	bfd_cache_init
 
 SYNOPSIS
-	bfd_boolean bfd_cache_init (bfd *abfd);
+	bfd_boolean bfd_cache_init (struct bfd *nbfd, FILE *file);
 
 DESCRIPTION
-	Add a newly opened BFD to the cache.
+
+	Given an already open <<file>>, add the BFD to the cache.
+
 */
 
 bfd_boolean
-bfd_cache_init (bfd *abfd)
+bfd_cache_init (struct bfd *nbfd, FILE *file)
 {
-  BFD_ASSERT (abfd->iostream != NULL);
+  struct bfd_cache *entry;
+
   if (open_files >= BFD_CACHE_MAX_OPEN)
     {
       if (! close_one ())
 	return FALSE;
     }
-  insert (abfd);
+
+  entry = bfd_zmalloc (sizeof (struct bfd_cache));
+  if (entry == NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return FALSE;
+    }
+
+  /* OK, put everything where it belongs.  */
+  entry->file = file;
+  entry->filename = nbfd->filename;
+  entry->direction = nbfd->direction;
+  nbfd->stream.ops = &cache_bops;
+  nbfd->stream.cookie = entry;
+  insert (entry);
   ++open_files;
   return TRUE;
 }
@@ -215,25 +370,23 @@
 	bfd_cache_close
 
 SYNOPSIS
-	bfd_boolean bfd_cache_close (bfd *abfd);
+	bfd_boolean bfd_cache_close (bfd *entry);
 
 DESCRIPTION
-	Remove the BFD @var{abfd} from the cache. If the attached file is open,
-	then close it too.
+	Remove the BFD @var{entry} from the cache. If the attached
+	file is open, then close it too.
 
 RETURNS
 	<<FALSE>> is returned if closing the file fails, <<TRUE>> is
-	returned if all is well.
-*/
+	returned if all is well.  */
 
 bfd_boolean
 bfd_cache_close (bfd *abfd)
 {
-  if (abfd->iostream == NULL
-      || (abfd->flags & BFD_IN_MEMORY) != 0)
+  if (abfd->stream.ops != &cache_bops)
     return TRUE;
 
-  return bfd_cache_delete (abfd);
+  return bfd_cache_delete (abfd->stream.cookie);
 }
 
 /*
@@ -241,20 +394,43 @@
 	bfd_open_file
 
 SYNOPSIS
-	FILE* bfd_open_file (bfd *abfd);
+	bfd_boolean bfd_open_file (bfd *entry);
 
 DESCRIPTION
-	Call the OS to open a file for @var{abfd}.  Return the <<FILE *>>
-	(possibly <<NULL>>) that results from this operation.  Set up the
-	BFD so that future accesses know the file is open. If the <<FILE *>>
-	returned is <<NULL>>, then it won't have been put in the
-	cache, so it won't have to be removed from it.
+
+	Call the OS to open a file for @var{entry}.  Return the <<FILE
+	*>> (possibly <<NULL>>) that results from this operation.  Set
+	up the BFD so that future accesses know the file is open.  If
+	the <<FILE *>> returned is <<NULL>>, then it won't have been
+	put in the cache, so it won't have to be removed from it.
+
 */
 
-FILE *
-bfd_open_file (bfd *abfd)
+bfd_boolean
+bfd_open_file (struct bfd *nbfd)
 {
-  abfd->cacheable = TRUE;	/* Allow it to be closed later.  */
+  FILE *file;
+
+  file = fopen (nbfd->filename, bfd_direction_fmode (nbfd->direction));
+  if (file == NULL)
+    return FALSE;
+
+  if (!bfd_cache_init (nbfd, file))
+    {
+      /* File didn't exist, or some such.  */
+      fclose (file);
+      return FALSE;
+    }
+  return TRUE;
+
+#if 0
+  struct bfd_cache *entry;
+
+  BFD_ASSERT (abfd->stream.ops == &cache_bops);
+  entry = abfd->stream.cookie;
+
+  /* Allow it to be closed later.  */
+  entry->cacheable = TRUE;
 
   if (open_files >= BFD_CACHE_MAX_OPEN)
     {
@@ -262,19 +438,19 @@
 	return NULL;
     }
 
-  switch (abfd->direction)
+  switch (entry->direction)
     {
     case read_direction:
     case no_direction:
-      abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
+      entry->file = fopen (entry->filename, FOPEN_RB);
       break;
     case both_direction:
     case write_direction:
-      if (abfd->opened_once)
+      if (entry->opened_once)
 	{
-	  abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
-	  if (abfd->iostream == NULL)
-	    abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
+	  entry->file = fopen (entry->filename, FOPEN_RUB);
+	  if (entry->file == NULL)
+	    entry->file = fopen (entry->filename, FOPEN_WUB);
 	}
       else
 	{
@@ -301,66 +477,52 @@
 	     the --info option.  */
 	  struct stat s;
 
-	  if (stat (abfd->filename, &s) == 0 && s.st_size != 0)
-	    unlink (abfd->filename);
+	  if (stat (entry->filename, &s) == 0 && s.st_size != 0)
+	    unlink (entry->filename);
 #endif
-	  abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
-	  abfd->opened_once = TRUE;
+	  entry->file = fopen (entry->filename, FOPEN_WUB);
+	  entry->opened_once = TRUE;
 	}
       break;
     }
 
-  if (abfd->iostream != NULL)
+  if (entry->file != NULL)
     {
-      if (! bfd_cache_init (abfd))
+      if (! bfd_cache_init (entry))
 	return NULL;
     }
 
-  return (FILE *) abfd->iostream;
+  return entry->file;
+#endif
 }
 
-/*
-INTERNAL_FUNCTION
-	bfd_cache_lookup_worker
-
-SYNOPSIS
-	FILE *bfd_cache_lookup_worker (bfd *abfd);
-
-DESCRIPTION
-	Called when the macro <<bfd_cache_lookup>> fails to find a
-	quick answer.  Find a file descriptor for @var{abfd}.  If
-	necessary, it open it.  If there are already more than
-	<<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
-	avoid running out of file descriptors.
-*/
+/* Find a file descriptor for @var{stream}.  If necessary, open it.
+   If there are already more than <<BFD_CACHE_MAX_OPEN>> files open,
+   it tries to close one first, to avoid running out of file
+   descriptors.  */
 
-FILE *
-bfd_cache_lookup_worker (bfd *abfd)
+static FILE *
+bfd_cache_lookup (struct bfd_file *stream)
 {
-  if ((abfd->flags & BFD_IN_MEMORY) != 0)
-    abort ();
-
-  if (abfd->my_archive)
-    abfd = abfd->my_archive;
-
-  if (abfd->iostream != NULL)
+  struct bfd_cache *entry = stream->cookie;
+  if (entry->file != NULL)
     {
       /* Move the file to the start of the cache.  */
-      if (abfd != bfd_last_cache)
+      if (entry != bfd_last_cache)
 	{
-	  snip (abfd);
-	  insert (abfd);
+	  snip (entry);
+	  insert (entry);
 	}
     }
   else
     {
-      if (bfd_open_file (abfd) == NULL)
-	return NULL;
-      if (abfd->where != (unsigned long) abfd->where)
+      entry->file = fopen (entry->filename,
+			   bfd_direction_fmode (entry->direction));
+      if (entry->file == NULL)
 	return NULL;
-      if (real_fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0)
+      if (real_fseek (entry->file, entry->where, SEEK_SET) != 0)
 	return NULL;
     }
 
-  return (FILE *) abfd->iostream;
+  return entry->file;
 }
Index: elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.50
diff -u -r1.50 elfcode.h
--- elfcode.h	16 Oct 2003 04:11:06 -0000	1.50
+++ elfcode.h	14 Feb 2004 00:29:38 -0000
@@ -1725,7 +1725,7 @@
   nbfd->xvec = templ->xvec;
   bim->size = contents_size;
   bim->buffer = contents;
-  nbfd->iostream = bim;
+  nbfd->stream.cookie = bim;
   nbfd->flags = BFD_IN_MEMORY;
   nbfd->direction = read_direction;
   nbfd->mtime = time (NULL);
Index: libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.31
diff -u -r1.31 libbfd-in.h
--- libbfd-in.h	11 Feb 2004 23:23:20 -0000	1.31
+++ libbfd-in.h	14 Feb 2004 00:29:38 -0000
@@ -595,16 +595,6 @@
 #undef abort
 #define abort() _bfd_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
 
-/* Manipulate a system FILE but using BFD's "file_ptr", rather than
-   the system "off_t" or "off64_t", as the offset.  */
-extern file_ptr real_ftell (FILE *file);
-extern int real_fseek (FILE *file, file_ptr offset, int whence);
-
-FILE *	bfd_cache_lookup_worker
-  (bfd *);
-
-extern bfd *bfd_last_cache;
-
 /* List of supported target vectors, and the default vector (if
    bfd_default_vector[0] is NULL, there is no default).  */
 extern const bfd_target * const *bfd_target_vector;
Index: opncls.c
===================================================================
RCS file: /cvs/src/src/bfd/opncls.c,v
retrieving revision 1.21
diff -u -r1.21 opncls.c
--- opncls.c	21 Jan 2004 11:17:53 -0000	1.21
+++ opncls.c	14 Feb 2004 00:29:39 -0000
@@ -68,8 +68,6 @@
   nbfd->arch_info = &bfd_default_arch_struct;
 
   nbfd->direction = no_direction;
-  nbfd->iostream = NULL;
-  nbfd->where = 0;
   if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc,
 			      251))
     {
@@ -81,11 +79,9 @@
   nbfd->format = bfd_unknown;
   nbfd->my_archive = NULL;
   nbfd->origin = 0;
-  nbfd->opened_once = FALSE;
   nbfd->output_has_begun = FALSE;
   nbfd->section_count = 0;
   nbfd->usrdata = NULL;
-  nbfd->cacheable = FALSE;
   nbfd->flags = BFD_NO_FLAGS;
   nbfd->mtime_set = FALSE;
 
@@ -125,31 +121,15 @@
 
 */
 
-/*
-FUNCTION
-	bfd_openr
-
-SYNOPSIS
-	bfd *bfd_openr (const char *filename, const char *target);
-
-DESCRIPTION
-	Open the file @var{filename} (using <<fopen>>) with the target
-	@var{target}.  Return a pointer to the created BFD.
-
-	Calls <<bfd_find_target>>, so @var{target} is interpreted as by
-	that function.
-
-	If <<NULL>> is returned then an error has occured.   Possible errors
-	are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or
-	<<system_call>> error.
-*/
-
-bfd *
-bfd_openr (const char *filename, const char *target)
+static struct bfd *
+bfd_fopen (const char *filename, const char *target,
+	   enum bfd_direction direction)
 {
   bfd *nbfd;
   const bfd_target *target_vec;
 
+  /* nbfd has to point to head of malloc'ed block so that bfd_close may
+     reclaim it correctly.  */
   nbfd = _bfd_new_bfd ();
   if (nbfd == NULL)
     return NULL;
@@ -162,19 +142,46 @@
     }
 
   nbfd->filename = filename;
-  nbfd->direction = read_direction;
+  nbfd->direction = direction;
 
+  /* FIXME: Refactor bfd_open_file into this function?  */
   if (bfd_open_file (nbfd) == NULL)
     {
-      /* File didn't exist, or some such.  */
+      /* File not writeable, etc.  */
       bfd_set_error (bfd_error_system_call);
       _bfd_delete_bfd (nbfd);
       return NULL;
-    }
+  }
 
   return nbfd;
 }
 
+
+/*
+FUNCTION
+	bfd_openr
+
+SYNOPSIS
+	bfd *bfd_openr (const char *filename, const char *target);
+
+DESCRIPTION
+	Open the file @var{filename} (using <<fopen>>) with the target
+	@var{target}.  Return a pointer to the created BFD.
+
+	Calls <<bfd_find_target>>, so @var{target} is interpreted as by
+	that function.
+
+	If <<NULL>> is returned then an error has occured.   Possible errors
+	are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or
+	<<system_call>> error.
+*/
+
+bfd *
+bfd_openr (const char *filename, const char *target)
+{
+  return bfd_fopen (filename, target, read_direction);
+}
+
 /* Don't try to `optimize' this function:
 
    o - We lock using stack space so that interrupting the locking
@@ -214,6 +221,8 @@
   bfd *nbfd;
   const bfd_target *target_vec;
   int fdflags;
+  enum bfd_direction direction;
+  FILE *file;
 
   bfd_set_error (bfd_error_system_call);
 #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
@@ -224,6 +233,15 @@
   if (fdflags == -1)
     return NULL;
 
+  /* (O_ACCMODE) parens are to avoid Ultrix header file bug.  */
+  switch (fdflags & (O_ACCMODE))
+    {
+    case O_RDONLY: direction = read_direction; break;
+    case O_WRONLY: direction = write_direction; break;
+    case O_RDWR:   direction = both_direction; break;
+    default: abort ();
+    }
+
   nbfd = _bfd_new_bfd ();
   if (nbfd == NULL)
     return NULL;
@@ -235,46 +253,27 @@
       return NULL;
     }
 
+  nbfd->filename = filename;
+  nbfd->direction = direction;
+
 #ifndef HAVE_FDOPEN
-  nbfd->iostream = fopen (filename, FOPEN_RB);
+  file = fopen (filename, bfd_direction_fmode (direction));
 #else
   /* (O_ACCMODE) parens are to avoid Ultrix header file bug.  */
-  switch (fdflags & (O_ACCMODE))
-    {
-    case O_RDONLY: nbfd->iostream = fdopen (fd, FOPEN_RB);   break;
-    case O_WRONLY: nbfd->iostream = fdopen (fd, FOPEN_RUB);  break;
-    case O_RDWR:   nbfd->iostream = fdopen (fd, FOPEN_RUB);  break;
-    default: abort ();
-    }
+  file = fdopen (fd, bfd_direction_fmode (direction));
 #endif
 
-  if (nbfd->iostream == NULL)
+  if (file == NULL)
     {
       _bfd_delete_bfd (nbfd);
-      return NULL;
-    }
-
-  /* OK, put everything where it belongs.  */
-  nbfd->filename = filename;
-
-  /* As a special case we allow a FD open for read/write to
-     be written through, although doing so requires that we end
-     the previous clause with a preposition.  */
-  /* (O_ACCMODE) parens are to avoid Ultrix header file bug.  */
-  switch (fdflags & (O_ACCMODE))
-    {
-    case O_RDONLY: nbfd->direction = read_direction; break;
-    case O_WRONLY: nbfd->direction = write_direction; break;
-    case O_RDWR: nbfd->direction = both_direction; break;
-    default: abort ();
+      return FALSE;
     }
 
-  if (! bfd_cache_init (nbfd))
+  if (!bfd_cache_init (nbfd, file))
     {
       _bfd_delete_bfd (nbfd);
       return NULL;
     }
-  nbfd->opened_once = TRUE;
 
   return nbfd;
 }
@@ -310,11 +309,10 @@
       return NULL;
     }
 
-  nbfd->iostream = stream;
   nbfd->filename = filename;
   nbfd->direction = read_direction;
 
-  if (! bfd_cache_init (nbfd))
+  if (! bfd_cache_init (nbfd, stream))
     {
       _bfd_delete_bfd (nbfd);
       return NULL;
@@ -346,34 +344,7 @@
 bfd *
 bfd_openw (const char *filename, const char *target)
 {
-  bfd *nbfd;
-  const bfd_target *target_vec;
-
-  /* nbfd has to point to head of malloc'ed block so that bfd_close may
-     reclaim it correctly.  */
-  nbfd = _bfd_new_bfd ();
-  if (nbfd == NULL)
-    return NULL;
-
-  target_vec = bfd_find_target (target, nbfd);
-  if (target_vec == NULL)
-    {
-      _bfd_delete_bfd (nbfd);
-      return NULL;
-    }
-
-  nbfd->filename = filename;
-  nbfd->direction = write_direction;
-
-  if (bfd_open_file (nbfd) == NULL)
-    {
-      /* File not writeable, etc.  */
-      bfd_set_error (bfd_error_system_call);
-      _bfd_delete_bfd (nbfd);
-      return NULL;
-  }
-
-  return nbfd;
+  return bfd_fopen (filename, target, write_direction);
 }
 
 /*
@@ -522,107 +493,6 @@
   bfd_set_format (nbfd, bfd_object);
 
   return nbfd;
-}
-
-/*
-FUNCTION
-	bfd_make_writable
-
-SYNOPSIS
-	bfd_boolean bfd_make_writable (bfd *abfd);
-
-DESCRIPTION
-	Takes a BFD as created by <<bfd_create>> and converts it
-	into one like as returned by <<bfd_openw>>.  It does this
-	by converting the BFD to BFD_IN_MEMORY.  It's assumed that
-	you will call <<bfd_make_readable>> on this bfd later.
-
-RETURNS
-	<<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
-*/
-
-bfd_boolean
-bfd_make_writable (bfd *abfd)
-{
-  struct bfd_in_memory *bim;
-
-  if (abfd->direction != no_direction)
-    {
-      bfd_set_error (bfd_error_invalid_operation);
-      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;
-
-  return TRUE;
-}
-
-/*
-FUNCTION
-	bfd_make_readable
-
-SYNOPSIS
-	bfd_boolean bfd_make_readable (bfd *abfd);
-
-DESCRIPTION
-	Takes a BFD as created by <<bfd_create>> and
-	<<bfd_make_writable>> and converts it into one like as
-	returned by <<bfd_openr>>.  It does this by writing the
-	contents out to the memory buffer, then reversing the
-	direction.
-
-RETURNS
-	<<TRUE>> is returned if all is ok, otherwise <<FALSE>>.  */
-
-bfd_boolean
-bfd_make_readable (bfd *abfd)
-{
-  if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY))
-    {
-      bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
-    }
-
-  if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
-    return FALSE;
-
-  if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
-    return FALSE;
-
-
-  abfd->arch_info = &bfd_default_arch_struct;
-
-  abfd->where = 0;
-  abfd->format = bfd_unknown;
-  abfd->my_archive = NULL;
-  abfd->origin = 0;
-  abfd->opened_once = FALSE;
-  abfd->output_has_begun = FALSE;
-  abfd->section_count = 0;
-  abfd->usrdata = NULL;
-  abfd->cacheable = FALSE;
-  abfd->flags = BFD_IN_MEMORY;
-  abfd->mtime_set = FALSE;
-
-  abfd->target_defaulted = TRUE;
-  abfd->direction = read_direction;
-  abfd->sections = 0;
-  abfd->symcount = 0;
-  abfd->outsymbols = 0;
-  abfd->tdata.any = 0;
-
-  bfd_section_list_clear (abfd);
-  bfd_check_format (abfd, bfd_object);
-
-  return TRUE;
 }
 
 /*
Index: xcofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/xcofflink.c,v
retrieving revision 1.33
diff -u -r1.33 xcofflink.c
--- xcofflink.c	2 Dec 2003 22:59:59 -0000	1.33
+++ xcofflink.c	14 Feb 2004 00:29:39 -0000
@@ -3242,10 +3242,14 @@
 
   abfd->link_next = 0;
   abfd->format = bfd_object;
-  abfd->iostream = (PTR) bim;
+#if 0
+  abfd->stream.cookie = (PTR) bim;
+#endif
   abfd->flags = BFD_IN_MEMORY;
   abfd->direction = write_direction;
+#if 0
   abfd->where = 0;
+#endif
 
   if (! bfd_xcoff_generate_rtinit (abfd, init, fini, rtld))
     return FALSE;
@@ -3253,7 +3257,9 @@
   /* need to reset to unknown or it will not be read back in correctly */
   abfd->format = bfd_unknown;
   abfd->direction = read_direction;
+#if 0
   abfd->where = 0;
+#endif
 
   return TRUE;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]