This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

[2/17] refcount BFDs everywhere


The general approach to sharing taken by this patch is to first share
BFDs, then attach other shared data to the BFD.

Sharing BFDs seems fundamental: one file on disk, one representation in
GDB.  Attaching data to the BFDs is just convenient; but also nice
because it synchronizes the data's lifetime with the BFD's.  Also, I
tried other approaches to sharing and the patches quickly got out of
control.

This patch lays some groundwork for this by making us reference count
BFDs everywhere.  GDB already does this to a small extent, this just
makes it universal.

Tom

>From 887f5abb1d9e5c85f542705b66d529312757008d Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Mon, 5 Dec 2011 08:11:48 -0700
Subject: [PATCH 02/18] change gdb to refcount bfd everywhere

	* cli/cli-dump.c: Include gdb_bfd.h.
	(bfd_openw_with_cleanup): Use gdb_bfd_ref.
	(bfd_openr_with_cleanup): Likewise.
	* windows-nat.c (windows_make_so): Use gdb_bfd_ref,
	gdb_bfd_unref.
	* utils.c: Include gdb_bfd.h.
	(do_bfd_close_cleanup): Use gdb_bfd_unref.
	* symfile.c: Include gdb_bfd.h.
	(separate_debug_file_exists): Use gdb_bfd_unref.
	(bfd_open_maybe_remote): Use gdb_bfd_ref.
	(symfile_bfd_open): Use gdb_bfd_ref, gdb_bfd_unref.
	(generic_load): Use gdb_bfd_ref.
	(reread_symbols): Use gdb_bfd_unref.
	* symfile-mem.c: Include gdb_bfd.h.
	(symbol_file_add_from_memory): Use make_cleanup_bfd_close.
	* spu-linux-nat.c (spu_bfd_open): Use gdb_bfd_ref, gdb_bfd_unref.
	* solib.c: Include gdb_bfd.h.
	(solib_bfd_fopen): Use gdb_bfd_ref.
	(solib_bfd_open): Use gdb_bfd_unref.
	(free_so_symbols): Use gdb_bfd_unref.
	(reload_shared_libraries_1): Use gdb_bfd_unref.
	* solib-spu.c: Include gdb_bfd.h.
	(spu_bfd_fopen): Use gdb_bfd_ref, gdb_bfd_unref.
	* solib-pa64.c (pa64_solib_create_inferior_hook): Use gdb_bfd_ref,
	gdb_bfd_unref.
	* solib-frv.c: Include gdb_bfd.h.
	(enable_break2): Use gdb_bfd_unref.
	* solib-dsbt.c: Include gdb_bfd.h.
	(enable_break2): Use gdb_bfd_unref.
	* solib-darwin.c: Include gdb_bfd.h.
	(darwin_solib_get_all_image_info_addr_at_init): Use gdb_bfd_ref,
	gdb_bfd_unref.
	(darwin_bfd_open): Use gdb_bfd_unref.
	* rs6000-nat.c (add_vmap): Use gdb_bfd_ref, gdb_bfd_unref.
	* remote-mips.c: Include gdb_bfd.h.
	(mips_load_srec): Use gdb_bfd_ref.
	(pmon_load_fast): Use gdb_bfd_ref.
	* remote-m32r-sdi.c: Include gdb_bfd.h.
	(m32r_load): Use gdb_bfd_ref.
	* record.c: Include gdb_bfd.h.
	(record_save_cleanups): Use gdb_bfd_unref.
	(cmd_record_save): Use gdb_bfd_unref.
	* procfs.c (insert_dbx_link_bpt_in_file): Use gdb_bfd_ref,
	gdb_bfd_unref.
	* objfiles.h (gdb_bfd_close_or_warn): Remove.
	(gdb_bfd_ref, gdb_bfd_unref): Move to gdb_bfd.h.
	* objfiles.c: Include gdb_bfd.h.
	(free_objfile): Use gdb_bfd_unref.
	(gdb_bfd_close_or_warn, gdb_bfd_ref, gdb_bfd_unref): Move to
	gdb_bfd.c.
	* machoread.c (macho_add_oso_symfile): Use gdb_bfd_unref.
	(macho_symfile_read_all_oso): Use gdb_bfd_ref, gdb_bfd_unref.
	(macho_check_dsym): Likewise.
	* m32r-rom.c: Include gdb_bfd.h.
	(m32r_load): Use gdb_bfd_ref.
	(m32r_upload_command): Use gdb_bfd_ref.
	* jit.c: Include gdb_bfd.h.
	(jit_bfd_try_read_symtab): Use gdb_bfd_ref, gdb_bfd_unref.
	* gdb_bfd.h: New file.
	* gdb_bfd.c: New file.
	* gcore.c: Include gdb_bfd.h.
	(create_gcore_bfd): Use gdb_bfd_ref.
	(do_bfd_delete_cleanup): Use gdb_bfd_unref.
	(gcore_command): Use gdb_bfd_unref.
	* exec.c: Include gdb_bfd.h.
	(exec_close): Use gdb_bfd_unref.
	(exec_close_1): Use gdb_bfd_unref.
	(exec_file_attach): Use gdb_bfd_ref.
	* elfread.c: Include gdb_bfd.h.
	(build_id_verify): Use gdb_bfd_unref.
	* dsrec.c: Include gdb_bfd.h.
	(load_srec): Use gdb_bfd_ref.
	* corelow.c: Include gdb_bfd.h.
	(core_close): Use gdb_bfd_unref.
	(core_open): Use gdb_bfd_ref.
	* bfd-target.c: Include gdb_bfd.h.
	(target_bfd_xclose): Use gdb_bfd_unref.
	(target_bfd_reopen): Use gdb_bfd_ref.
	* Makefile.in (SFILES): Add gdb_bfd.c.
	(HFILES_NO_SRCDIR): Add gdb_bfd.h.
	(COMMON_OBS): Add gdb_bfd.o.
---
 gdb/Makefile.in       |    6 ++--
 gdb/bfd-target.c      |    5 ++-
 gdb/cli/cli-dump.c    |    5 ++-
 gdb/corelow.c         |    9 +++--
 gdb/dsrec.c           |    3 +-
 gdb/elfread.c         |    3 +-
 gdb/exec.c            |   12 +++---
 gdb/gcore.c           |    7 ++--
 gdb/gdb_bfd.c         |   90 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb_bfd.h         |   33 ++++++++++++++++++
 gdb/jit.c             |    4 ++-
 gdb/m32r-rom.c        |    5 ++-
 gdb/machoread.c       |   32 +++++++++--------
 gdb/objfiles.c        |   74 ++--------------------------------------
 gdb/objfiles.h        |    3 --
 gdb/procfs.c          |   10 +++---
 gdb/record.c          |    5 ++-
 gdb/remote-m32r-sdi.c |    3 +-
 gdb/remote-mips.c     |    5 ++-
 gdb/rs6000-nat.c      |   13 ++++---
 gdb/solib-darwin.c    |    9 +++--
 gdb/solib-dsbt.c      |    7 ++--
 gdb/solib-frv.c       |   13 ++++---
 gdb/solib-pa64.c      |    6 ++--
 gdb/solib-spu.c       |   11 +++---
 gdb/solib.c           |   11 +++---
 gdb/spu-linux-nat.c   |    3 +-
 gdb/symfile-mem.c     |    7 ++--
 gdb/symfile.c         |   37 +++++++-------------
 gdb/utils.c           |    3 +-
 gdb/windows-nat.c     |    6 ++--
 31 files changed, 251 insertions(+), 189 deletions(-)
 create mode 100644 gdb/gdb_bfd.c
 create mode 100644 gdb/gdb_bfd.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b71db33..213695d 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -708,7 +708,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	exceptions.c expprint.c \
 	f-exp.y f-lang.c f-typeprint.c f-valprint.c filesystem.c \
 	findcmd.c findvar.c frame.c frame-base.c frame-unwind.c \
-	gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
+	gdbarch.c gdb_bfd.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
 	inf-loop.c \
 	infcall.c \
 	infcmd.c inflow.c infrun.c \
@@ -830,7 +830,7 @@ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \
 gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \
 gnulib/stddef.in.h inline-frame.h skip.h \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h gdb-dlfcn.h
+common/linux-osdata.h gdb-dlfcn.h gdb_bfd.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -879,7 +879,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	macrotab.o macrocmd.o macroexp.o macroscope.o \
 	mi-common.o \
 	event-loop.o event-top.o inf-loop.o completer.o \
-	gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o \
+	gdbarch.o arch-utils.o gdbtypes.o gdb_bfd.o osabi.o copying.o \
 	memattr.o mem-break.o target.o parse.o language.o buildsym.o \
 	findcmd.o \
 	std-regs.o \
diff --git a/gdb/bfd-target.c b/gdb/bfd-target.c
index cfeb0b1..91b2bdb 100644
--- a/gdb/bfd-target.c
+++ b/gdb/bfd-target.c
@@ -22,6 +22,7 @@
 #include "target.h"
 #include "bfd-target.h"
 #include "exec.h"
+#include "gdb_bfd.h"
 
 /* The object that is stored in the target_ops->to_data field has this
    type.  */
@@ -71,7 +72,7 @@ target_bfd_xclose (struct target_ops *t, int quitting)
 {
   struct target_bfd_data *data = t->to_data;
 
-  bfd_close (data->bfd);
+  gdb_bfd_unref (data->bfd);
   xfree (data->table.sections);
   xfree (data);
   xfree (t);
@@ -84,7 +85,7 @@ target_bfd_reopen (struct bfd *bfd)
   struct target_bfd_data *data;
 
   data = XZALLOC (struct target_bfd_data);
-  data->bfd = bfd;
+  data->bfd = gdb_bfd_ref (bfd);
   build_section_table (bfd, &data->table.sections, &data->table.sections_end);
 
   t = XZALLOC (struct target_ops);
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 1b2b5d4..a2fd367 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -33,6 +33,7 @@
 #include "readline/readline.h"
 #include "gdbcore.h"
 #include "cli/cli-utils.h"
+#include "gdb_bfd.h"
 
 #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
 
@@ -112,7 +113,7 @@ bfd_openr_with_cleanup (const char *filename, const char *target)
 {
   bfd *ibfd;
 
-  ibfd = bfd_openr (filename, target);
+  ibfd = gdb_bfd_ref (bfd_openr (filename, target));
   if (ibfd == NULL)
     error (_("Failed to open %s: %s."), filename, 
 	   bfd_errmsg (bfd_get_error ()));
@@ -132,7 +133,7 @@ bfd_openw_with_cleanup (const char *filename, const char *target,
 
   if (*mode == 'w')	/* Write: create new file */
     {
-      obfd = bfd_openw (filename, target);
+      obfd = gdb_bfd_ref (bfd_openw (filename, target));
       if (obfd == NULL)
 	error (_("Failed to open %s: %s."), filename, 
 	       bfd_errmsg (bfd_get_error ()));
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 33b96ae..47903d8 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -48,6 +48,7 @@
 #include "progspace.h"
 #include "objfiles.h"
 #include "wrapper.h"
+#include "gdb_bfd.h"
 
 
 #ifndef O_LARGEFILE
@@ -226,7 +227,7 @@ core_close (int quitting)
       core_has_fake_pid = 0;
 
       name = bfd_get_filename (core_bfd);
-      gdb_bfd_close_or_warn (core_bfd);
+      gdb_bfd_unref (core_bfd);
       xfree (name);
       core_bfd = NULL;
     }
@@ -322,9 +323,9 @@ core_open (char *filename, int from_tty)
   if (scratch_chan < 0)
     perror_with_name (filename);
 
-  temp_bfd = bfd_fopen (filename, gnutarget, 
-			write_files ? FOPEN_RUB : FOPEN_RB,
-			scratch_chan);
+  temp_bfd = gdb_bfd_ref (bfd_fopen (filename, gnutarget, 
+				     write_files ? FOPEN_RUB : FOPEN_RB,
+				     scratch_chan));
   if (temp_bfd == NULL)
     perror_with_name (filename);
 
diff --git a/gdb/dsrec.c b/gdb/dsrec.c
index cee2d85..307bdd8 100644
--- a/gdb/dsrec.c
+++ b/gdb/dsrec.c
@@ -23,6 +23,7 @@
 #include <time.h>
 #include "gdb_assert.h"
 #include "gdb_string.h"
+#include "gdb_bfd.h"
 
 extern void report_transfer_performance (unsigned long, time_t, time_t);
 
@@ -59,7 +60,7 @@ load_srec (struct serial *desc, const char *file, bfd_vma load_offset,
 
   srec = (char *) alloca (maxrecsize + 1);
 
-  abfd = bfd_openr (file, 0);
+  abfd = gdb_bfd_ref (bfd_openr (file, 0));
   if (!abfd)
     {
       printf_filtered (_("Unable to open file %s\n"), file);
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 067c77f..9bfba59 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -43,6 +43,7 @@
 #include "infcall.h"
 #include "gdbthread.h"
 #include "regcache.h"
+#include "gdb_bfd.h"
 
 extern void _initialize_elfread (void);
 
@@ -1094,7 +1095,7 @@ build_id_verify (const char *filename, struct build_id *check)
   else
     retval = 1;
 
-  gdb_bfd_close_or_warn (abfd);
+  gdb_bfd_unref (abfd);
 
   xfree (found);
 
diff --git a/gdb/exec.c b/gdb/exec.c
index a2da9d5..37eb018 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -35,6 +35,7 @@
 #include "arch-utils.h"
 #include "gdbthread.h"
 #include "progspace.h"
+#include "gdb_bfd.h"
 
 #include <fcntl.h>
 #include "readline/readline.h"
@@ -102,7 +103,7 @@ exec_close (void)
       bfd *abfd = exec_bfd;
       char *name = bfd_get_filename (abfd);
 
-      gdb_bfd_close_or_warn (abfd);
+      gdb_bfd_unref (abfd);
       xfree (name);
 
       /* Removing target sections may close the exec_ops target.
@@ -139,8 +140,7 @@ exec_close_1 (int quitting)
 	  need_symtab_cleanup = 1;
 	}
       else if (vp->bfd != exec_bfd)
-	/* FIXME-leak: We should be freeing vp->name too, I think.  */
-	gdb_bfd_close_or_warn (vp->bfd);
+	gdb_bfd_unref (vp->bfd);
 
       xfree (vp);
     }
@@ -234,9 +234,9 @@ exec_file_attach (char *filename, int from_tty)
 #endif
       if (scratch_chan < 0)
 	perror_with_name (filename);
-      exec_bfd = bfd_fopen (scratch_pathname, gnutarget,
-			    write_files ? FOPEN_RUB : FOPEN_RB,
-			    scratch_chan);
+      exec_bfd = gdb_bfd_ref (bfd_fopen (scratch_pathname, gnutarget,
+					 write_files ? FOPEN_RUB : FOPEN_RB,
+					 scratch_chan));
 
       if (!exec_bfd)
 	{
diff --git a/gdb/gcore.c b/gdb/gcore.c
index ebb8b0b..0a59567 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -34,6 +34,7 @@
 #include <fcntl.h>
 #include "regcache.h"
 #include "regset.h"
+#include "gdb_bfd.h"
 
 /* The largest amount of memory to read from the target at once.  We
    must throttle it to limit the amount of memory used by GDB during
@@ -51,7 +52,7 @@ static int gcore_memory_sections (bfd *);
 bfd *
 create_gcore_bfd (char *filename)
 {
-  bfd *obfd = bfd_openw (filename, default_gcore_target ());
+  bfd *obfd = gdb_bfd_ref (bfd_openw (filename, default_gcore_target ()));
 
   if (!obfd)
     error (_("Failed to open '%s' for output."), filename);
@@ -109,7 +110,7 @@ do_bfd_delete_cleanup (void *arg)
   bfd *obfd = arg;
   const char *filename = obfd->filename;
 
-  bfd_close (arg);
+  gdb_bfd_unref (arg);
   unlink (filename);
 }
 
@@ -153,7 +154,7 @@ gcore_command (char *args, int from_tty)
   fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
 
   discard_cleanups (old_chain);
-  bfd_close (obfd);
+  gdb_bfd_unref (obfd);
 }
 
 static unsigned long
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
new file mode 100644
index 0000000..160e9e6
--- /dev/null
+++ b/gdb/gdb_bfd.c
@@ -0,0 +1,90 @@
+/* Definitions for BFD wrappers used by GDB.
+
+   Copyright (C) 2011
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdb_bfd.h"
+#include "gdb_assert.h"
+
+/* Close ABFD, and warn if that fails.  */
+
+static int
+gdb_bfd_close_or_warn (struct bfd *abfd)
+{
+  int ret;
+  char *name = bfd_get_filename (abfd);
+
+  ret = bfd_close (abfd);
+
+  if (!ret)
+    warning (_("cannot close \"%s\": %s"),
+	     name, bfd_errmsg (bfd_get_error ()));
+
+  return ret;
+}
+
+/* Add reference to ABFD.  Returns ABFD.  */
+
+struct bfd *
+gdb_bfd_ref (struct bfd *abfd)
+{
+  int *p_refcount;
+
+  if (abfd == NULL)
+    return NULL;
+
+  p_refcount = bfd_usrdata (abfd);
+
+  if (p_refcount != NULL)
+    {
+      *p_refcount += 1;
+      return abfd;
+    }
+
+  p_refcount = xmalloc (sizeof (*p_refcount));
+  *p_refcount = 1;
+  bfd_usrdata (abfd) = p_refcount;
+
+  return abfd;
+}
+
+/* Unreference and possibly close ABFD.  */
+
+void
+gdb_bfd_unref (struct bfd *abfd)
+{
+  int *p_refcount;
+  char *name;
+
+  if (abfd == NULL)
+    return;
+
+  p_refcount = bfd_usrdata (abfd);
+  gdb_assert (*p_refcount >= 1);
+
+  *p_refcount -= 1;
+  if (*p_refcount > 0)
+    return;
+
+  xfree (p_refcount);
+  bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
+
+  name = bfd_get_filename (abfd);
+  gdb_bfd_close_or_warn (abfd);
+}
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
new file mode 100644
index 0000000..2708d01
--- /dev/null
+++ b/gdb/gdb_bfd.h
@@ -0,0 +1,33 @@
+/* Definitions for BFD wrappers used by GDB.
+
+   Copyright (C) 2011
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_BFD_H
+#define GDB_BFD_H
+
+/* Acquire a new reference to ABFD.  Returns ABFD for convenience.  */
+
+struct bfd *gdb_bfd_ref (struct bfd *abfd);
+
+/* Release a reference to ABFD.  If this is the last reference, ABFD
+   will be freed.  */
+
+void gdb_bfd_unref (struct bfd *abfd);
+
+#endif /* GDB_BFD_H */
diff --git a/gdb/jit.c b/gdb/jit.c
index 843c768..a4899ce 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -38,6 +38,7 @@
 #include "gdb-dlfcn.h"
 #include "gdb_stat.h"
 #include "exceptions.h"
+#include "gdb_bfd.h"
 
 static const char *jit_reader_dir = NULL;
 
@@ -799,6 +800,7 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
       puts_unfiltered (_("Error opening JITed symbol file, ignoring it.\n"));
       return;
     }
+  nbfd = gdb_bfd_ref (nbfd);
 
   /* Check the format.  NOTE: This initializes important data that GDB uses!
      We would segfault later without this line.  */
@@ -806,7 +808,7 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
     {
       printf_unfiltered (_("\
 JITed symbol file is not an object file, ignoring it.\n"));
-      bfd_close (nbfd);
+      gdb_bfd_unref (nbfd);
       return;
     }
 
diff --git a/gdb/m32r-rom.c b/gdb/m32r-rom.c
index 4756128..d83f126 100644
--- a/gdb/m32r-rom.c
+++ b/gdb/m32r-rom.c
@@ -40,6 +40,7 @@
 #include "inferior.h"
 #include <ctype.h>
 #include "regcache.h"
+#include "gdb_bfd.h"
 
 /*
  * All this stuff just to get my host computer's IP address!
@@ -129,7 +130,7 @@ m32r_load (char *filename, int from_tty)
   if (filename == NULL || filename[0] == 0)
     filename = get_exec_file (1);
 
-  abfd = bfd_openr (filename, 0);
+  abfd = gdb_bfd_ref (bfd_openr (filename, 0));
   if (!abfd)
     error (_("Unable to open file %s."), filename);
   if (bfd_check_format (abfd, bfd_object) == 0)
@@ -521,7 +522,7 @@ m32r_upload_command (char *args, int from_tty)
     printf_filtered (" -- Ethernet load complete.\n");
 
   gettimeofday (&end_time, NULL);
-  abfd = bfd_openr (args, 0);
+  abfd = gdb_bfd_ref (bfd_openr (args, 0));
   if (abfd != NULL)
     {		/* Download is done -- print section statistics.  */
       if (bfd_check_format (abfd, bfd_object) == 0)
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 46b8842..e32dead 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -466,14 +466,14 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd,
     {
       warning (_("`%s': can't read symbols: %s."), oso->name,
                bfd_errmsg (bfd_get_error ()));
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       return;
     }
 
   if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd))
     {
       warning (_("`%s': file time stamp mismatch."), oso->name);
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       return;
     }
 
@@ -482,7 +482,7 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd,
                               oso->nbr_syms))
     {
       warning (_("`%s': can't create hash table"), oso->name);
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       return;
     }
 
@@ -686,7 +686,7 @@ macho_symfile_read_all_oso (struct objfile *main_objfile, int symfile_flags)
             }
 
 	  /* Open the archive and check the format.  */
-	  archive_bfd = bfd_openr (archive_name, gnutarget);
+	  archive_bfd = gdb_bfd_ref (bfd_openr (archive_name, gnutarget));
 	  if (archive_bfd == NULL)
 	    {
 	      warning (_("Could not open OSO archive file \"%s\""),
@@ -698,17 +698,18 @@ macho_symfile_read_all_oso (struct objfile *main_objfile, int symfile_flags)
 	    {
 	      warning (_("OSO archive file \"%s\" not an archive."),
 		       archive_name);
-	      bfd_close (archive_bfd);
+	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
 	    }
-	  member_bfd = bfd_openr_next_archived_file (archive_bfd, NULL);
+	  member_bfd = gdb_bfd_ref (bfd_openr_next_archived_file (archive_bfd,
+								  NULL));
 
 	  if (member_bfd == NULL)
 	    {
 	      warning (_("Could not read archive members out of "
 			 "OSO archive \"%s\""), archive_name);
-	      bfd_close (archive_bfd);
+	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
 	    }
@@ -738,12 +739,13 @@ macho_symfile_read_all_oso (struct objfile *main_objfile, int symfile_flags)
                 }
 
               prev = member_bfd;
-	      member_bfd = bfd_openr_next_archived_file
-		(archive_bfd, member_bfd);
+	      member_bfd
+		= gdb_bfd_ref (bfd_openr_next_archived_file (archive_bfd,
+							     member_bfd));
 
               /* Free previous member if not referenced by an oso.  */
               if (ix2 >= last_ix)
-                bfd_close (prev);
+                gdb_bfd_unref (prev);
 	    }
           for (ix2 = ix; ix2 < last_ix; ix2++)
             {
@@ -759,7 +761,7 @@ macho_symfile_read_all_oso (struct objfile *main_objfile, int symfile_flags)
 	{
           bfd *abfd;
 
-	  abfd = bfd_openr (oso->name, gnutarget);
+	  abfd = gdb_bfd_ref (bfd_openr (oso->name, gnutarget));
 	  if (!abfd)
             warning (_("`%s': can't open to read symbols: %s."), oso->name,
                      bfd_errmsg (bfd_get_error ()));
@@ -809,7 +811,7 @@ macho_check_dsym (struct objfile *objfile)
       return NULL;
     }
   dsym_filename = xstrdup (dsym_filename);
-  dsym_bfd = bfd_openr (dsym_filename, gnutarget);
+  dsym_bfd = gdb_bfd_ref (bfd_openr (dsym_filename, gnutarget));
   if (dsym_bfd == NULL)
     {
       warning (_("can't open dsym file %s"), dsym_filename);
@@ -819,7 +821,7 @@ macho_check_dsym (struct objfile *objfile)
 
   if (!bfd_check_format (dsym_bfd, bfd_object))
     {
-      bfd_close (dsym_bfd);
+      gdb_bfd_unref (dsym_bfd);
       warning (_("bad dsym file format: %s"), bfd_errmsg (bfd_get_error ()));
       xfree (dsym_filename);
       return NULL;
@@ -829,7 +831,7 @@ macho_check_dsym (struct objfile *objfile)
                                  BFD_MACH_O_LC_UUID, &dsym_uuid) == 0)
     {
       warning (_("can't find UUID in %s"), dsym_filename);
-      bfd_close (dsym_bfd);
+      gdb_bfd_unref (dsym_bfd);
       xfree (dsym_filename);
       return NULL;
     }
@@ -837,7 +839,7 @@ macho_check_dsym (struct objfile *objfile)
               sizeof (main_uuid->command.uuid.uuid)))
     {
       warning (_("dsym file UUID doesn't match the one in %s"), objfile->name);
-      bfd_close (dsym_bfd);
+      gdb_bfd_unref (dsym_bfd);
       xfree (dsym_filename);
       return NULL;
     }
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 34d6422..8afadc3 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -55,6 +55,7 @@
 #include "complaints.h"
 #include "psymtab.h"
 #include "solist.h"
+#include "gdb_bfd.h"
 
 /* Prototypes for local functions */
 
@@ -212,9 +213,9 @@ allocate_objfile (bfd *abfd, int flags)
 
   /* Update the per-objfile information that comes from the bfd, ensuring
      that any data that is reference is saved in the per-objfile data
-     region.  */
+     region.  Note that we steal a reference to ABFD.  */
 
-  objfile->obfd = gdb_bfd_ref (abfd);
+  objfile->obfd = abfd;
   if (abfd != NULL)
     {
       /* Look up the gdbarch associated with the BFD.  */
@@ -1496,75 +1497,6 @@ objfiles_changed (void)
   get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1;
 }
 
-/* Close ABFD, and warn if that fails.  */
-
-int
-gdb_bfd_close_or_warn (struct bfd *abfd)
-{
-  int ret;
-  char *name = bfd_get_filename (abfd);
-
-  ret = bfd_close (abfd);
-
-  if (!ret)
-    warning (_("cannot close \"%s\": %s"),
-	     name, bfd_errmsg (bfd_get_error ()));
-
-  return ret;
-}
-
-/* Add reference to ABFD.  Returns ABFD.  */
-struct bfd *
-gdb_bfd_ref (struct bfd *abfd)
-{
-  int *p_refcount;
-
-  if (abfd == NULL)
-    return NULL;
-
-  p_refcount = bfd_usrdata (abfd);
-
-  if (p_refcount != NULL)
-    {
-      *p_refcount += 1;
-      return abfd;
-    }
-
-  p_refcount = xmalloc (sizeof (*p_refcount));
-  *p_refcount = 1;
-  bfd_usrdata (abfd) = p_refcount;
-
-  return abfd;
-}
-
-/* Unreference and possibly close ABFD.  */
-void
-gdb_bfd_unref (struct bfd *abfd)
-{
-  int *p_refcount;
-  char *name;
-
-  if (abfd == NULL)
-    return;
-
-  p_refcount = bfd_usrdata (abfd);
-
-  /* Valid range for p_refcount: a pointer to int counter, which has a
-     value of 1 (single owner) or 2 (shared).  */
-  gdb_assert (*p_refcount == 1 || *p_refcount == 2);
-
-  *p_refcount -= 1;
-  if (*p_refcount > 0)
-    return;
-
-  xfree (p_refcount);
-  bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
-
-  name = bfd_get_filename (abfd);
-  gdb_bfd_close_or_warn (abfd);
-  xfree (name);
-}
-
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_objfiles;
 
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 742da5d..e502541 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -535,9 +535,6 @@ extern void set_objfile_data (struct objfile *objfile,
 extern void *objfile_data (struct objfile *objfile,
 			   const struct objfile_data *data);
 
-extern struct bfd *gdb_bfd_ref (struct bfd *abfd);
-extern void gdb_bfd_unref (struct bfd *abfd);
-extern int gdb_bfd_close_or_warn (struct bfd *abfd);
 
 
 /* Traverse all object files in the current program space.
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 4df2610..f90f20b 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -3688,7 +3688,7 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
   long storage_needed;
   CORE_ADDR sym_addr;
 
-  abfd = bfd_fdopenr ("unamed", 0, fd);
+  abfd = gdb_bfd_ref (bfd_fdopenr ("unamed", 0, fd));
   if (abfd == NULL)
     {
       warning (_("Failed to create a bfd: %s."), bfd_errmsg (bfd_get_error ()));
@@ -3699,7 +3699,7 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
     {
       /* Not the correct format, so we can not possibly find the dbx_link
 	 symbol in it.	*/
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       return 0;
     }
 
@@ -3713,14 +3713,14 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
       if (dbx_link_bpt == NULL)
 	{
 	  warning (_("Failed to insert dbx_link breakpoint."));
-	  bfd_close (abfd);
+	  gdb_bfd_unref (abfd);
 	  return 0;
 	}
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       return 1;
     }
 
-  bfd_close (abfd);
+  gdb_bfd_unref (abfd);
   return 0;
 }
 
diff --git a/gdb/record.c b/gdb/record.c
index 60de085..7e84e57 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -32,6 +32,7 @@
 #include "gcore.h"
 #include "event-loop.h"
 #include "inf-loop.h"
+#include "gdb_bfd.h"
 
 #include <signal.h>
 
@@ -2543,7 +2544,7 @@ record_save_cleanups (void *data)
   bfd *obfd = data;
   char *pathname = xstrdup (bfd_get_filename (obfd));
 
-  bfd_close (obfd);
+  gdb_bfd_unref (obfd);
   unlink (pathname);
   xfree (pathname);
 }
@@ -2759,7 +2760,7 @@ cmd_record_save (char *args, int from_tty)
     }
 
   do_cleanups (set_cleanups);
-  bfd_close (obfd);
+  gdb_bfd_unref (obfd);
   discard_cleanups (old_cleanups);
 
   /* Succeeded.  */
diff --git a/gdb/remote-m32r-sdi.c b/gdb/remote-m32r-sdi.c
index 70d6dd5..3fb54cc 100644
--- a/gdb/remote-m32r-sdi.c
+++ b/gdb/remote-m32r-sdi.c
@@ -40,6 +40,7 @@
 #include <sys/time.h>
 #include <signal.h>
 #include <time.h>
+#include "gdb_bfd.h"
 
 
 #include "serial.h"
@@ -1262,7 +1263,7 @@ m32r_load (char *args, int from_tty)
   if (!filename)
     filename = get_exec_file (1);
 
-  pbfd = bfd_openr (filename, gnutarget);
+  pbfd = gdb_bfd_ref (bfd_openr (filename, gnutarget));
   if (pbfd == NULL)
     {
       perror_with_name (filename);
diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c
index d544bcb..90490a6 100644
--- a/gdb/remote-mips.c
+++ b/gdb/remote-mips.c
@@ -38,6 +38,7 @@
 #include <ctype.h>
 #include "mips-tdep.h"
 #include "gdbthread.h"
+#include "gdb_bfd.h"
 
 
 /* Breakpoint types.  Values 0, 1, and 2 must agree with the watch
@@ -2791,7 +2792,7 @@ mips_load_srec (char *args)
 
   buffer = alloca (srec_frame * 2 + 256);
 
-  abfd = bfd_openr (args, 0);
+  abfd = gdb_bfd_ref (bfd_openr (args, 0));
   if (!abfd)
     {
       printf_filtered ("Unable to open file %s\n", args);
@@ -3374,7 +3375,7 @@ pmon_load_fast (char *file)
   buffer = (char *) xmalloc (MAXRECSIZE + 1);
   binbuf = (unsigned char *) xmalloc (BINCHUNK);
 
-  abfd = bfd_openr (file, 0);
+  abfd = gdb_bfd_ref (bfd_openr (file, 0));
   if (!abfd)
     {
       printf_filtered ("Unable to open file %s\n", file);
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
index 30e4c15..e471894 100644
--- a/gdb/rs6000-nat.c
+++ b/gdb/rs6000-nat.c
@@ -752,6 +752,7 @@ add_vmap (LdInfo *ldi)
     abfd = bfd_openr (objname, gnutarget);
   else
     abfd = bfd_fdopenr (objname, gnutarget, fd);
+  abfd = gdb_bfd_ref (abfd);
   if (!abfd)
     {
       warning (_("Could not open `%s' as an executable file: %s"),
@@ -768,14 +769,14 @@ add_vmap (LdInfo *ldi)
     {
       last = 0;
       /* FIXME??? am I tossing BFDs?  bfd?  */
-      while ((last = bfd_openr_next_archived_file (abfd, last)))
+      while ((last = gdb_bfd_ref (bfd_openr_next_archived_file (abfd, last))))
 	if (strcmp (mem, last->filename) == 0)
 	  break;
 
       if (!last)
 	{
 	  warning (_("\"%s\": member \"%s\" missing."), objname, mem);
-	  bfd_close (abfd);
+	  gdb_bfd_unref (abfd);
 	  return NULL;
 	}
 
@@ -783,8 +784,8 @@ add_vmap (LdInfo *ldi)
 	{
 	  warning (_("\"%s\": member \"%s\" not in executable format: %s."),
 		   objname, mem, bfd_errmsg (bfd_get_error ()));
-	  bfd_close (last);
-	  bfd_close (abfd);
+	  gdb_bfd_unref (last);
+	  gdb_bfd_unref (abfd);
 	  return NULL;
 	}
 
@@ -794,10 +795,10 @@ add_vmap (LdInfo *ldi)
     {
       warning (_("\"%s\": not in executable format: %s."),
 	       objname, bfd_errmsg (bfd_get_error ()));
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       return NULL;
     }
-  obj = allocate_objfile (vp->bfd, 0);
+  obj = allocate_objfile (gdb_bfd_ref (vp->bfd), 0);
   vp->objfile = obj;
 
   /* Always add symbols for the main objfile.  */
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index d592809..d7b2128 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -28,6 +28,7 @@
 #include "inferior.h"
 #include "regcache.h"
 #include "gdbthread.h"
+#include "gdb_bfd.h"
 
 #include "gdb_assert.h"
 
@@ -313,7 +314,7 @@ darwin_solib_get_all_image_info_addr_at_init (void)
     return;
 
   /* Create a bfd for the interpreter.  */
-  dyld_bfd = bfd_openr (interp_name, gnutarget);
+  dyld_bfd = gdb_bfd_ref (bfd_openr (interp_name, gnutarget));
   if (dyld_bfd)
     {
       bfd *sub;
@@ -324,7 +325,7 @@ darwin_solib_get_all_image_info_addr_at_init (void)
 	dyld_bfd = sub;
       else
 	{
-	  bfd_close (dyld_bfd);
+	  gdb_bfd_unref (dyld_bfd);
 	  dyld_bfd = NULL;
 	}
     }
@@ -341,7 +342,7 @@ darwin_solib_get_all_image_info_addr_at_init (void)
   dyld_all_image_addr =
     lookup_symbol_from_bfd (dyld_bfd, "_dyld_all_image_infos");
 
-  bfd_close (dyld_bfd);
+  gdb_bfd_unref (dyld_bfd);
 
   if (dyld_all_image_addr == 0)
     return;
@@ -451,7 +452,7 @@ darwin_bfd_open (char *pathname)
 				gdbarch_bfd_arch_info (target_gdbarch));
   if (!res)
     {
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       make_cleanup (xfree, found_pathname);
       error (_("`%s': not a shared-library: %s"),
 	     found_pathname, bfd_errmsg (bfd_get_error ()));
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index e7a14d3..40dc3f6 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -30,6 +30,7 @@
 #include "gdbcmd.h"
 #include "elf-bfd.h"
 #include "exceptions.h"
+#include "gdb_bfd.h"
 
 #define GOT_MODULE_OFFSET 4
 
@@ -900,7 +901,7 @@ enable_break2 (void)
 	{
 	  warning (_("Could not find symbol _dl_debug_addr in dynamic linker"));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -949,13 +950,13 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr + 8, 8));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
 
       /* We're done with the temporary bfd.  */
-      bfd_close (tmp_bfd);
+      gdb_bfd_unref (tmp_bfd);
 
       /* We're also done with the loadmap.  */
       xfree (ldm);
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index acb35a2..401efb7 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -32,6 +32,7 @@
 #include "gdbcmd.h"
 #include "elf/frv.h"
 #include "exceptions.h"
+#include "gdb_bfd.h"
 
 /* Flag which indicates whether internal debug messages should be printed.  */
 static int solib_frv_debug;
@@ -575,7 +576,7 @@ enable_break2 (void)
 	{
 	  warning (_("Unable to determine dynamic linker loadmap address."));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -590,7 +591,7 @@ enable_break2 (void)
 	  warning (_("Unable to load dynamic linker loadmap at address %s."),
 	           hex_string_custom (interp_loadmap_addr, 8));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -624,7 +625,7 @@ enable_break2 (void)
 	  warning (_("Could not find symbol _dl_debug_addr "
 		     "in dynamic linker"));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -675,7 +676,7 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr + 8, 8));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
@@ -687,13 +688,13 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr, 8));
 	  enable_break_failure_warning ();
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
 
       /* We're done with the temporary bfd.  */
-      bfd_close (tmp_bfd);
+      gdb_bfd_unref (tmp_bfd);
 
       /* We're also done with the loadmap.  */
       xfree (ldm);
diff --git a/gdb/solib-pa64.c b/gdb/solib-pa64.c
index a9493e4..688e145 100644
--- a/gdb/solib-pa64.c
+++ b/gdb/solib-pa64.c
@@ -363,7 +363,7 @@ manpage for methods to privately map shared library text."));
 	 to find any magic formula to find it for Solaris (appears to
 	 be trivial on GNU/Linux).  Therefore, we have to try an alternate
 	 mechanism to find the dynamic linker's base address.  */
-      tmp_bfd = bfd_openr (buf, gnutarget);
+      tmp_bfd = gdb_bfd_ref (bfd_openr (buf, gnutarget));
       if (tmp_bfd == NULL)
 	return;
 
@@ -372,7 +372,7 @@ manpage for methods to privately map shared library text."));
 	{
 	  warning (_("Unable to grok dynamic linker %s as an object file"),
 		   buf);
-	  bfd_close (tmp_bfd);
+	  gdb_bfd_unref (tmp_bfd);
 	  return;
 	}
 
@@ -402,7 +402,7 @@ manpage for methods to privately map shared library text."));
       }
 
       /* We're done with the temporary bfd.  */
-      bfd_close (tmp_bfd);
+      gdb_bfd_unref (tmp_bfd);
     }
 }
 
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index 1594fbb..6163c41 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -35,6 +35,7 @@
 #include "breakpoint.h"
 #include "gdbthread.h"
 #include "exceptions.h"
+#include "gdb_bfd.h"
 
 #include "spu-tdep.h"
 
@@ -324,16 +325,16 @@ spu_bfd_fopen (char *name, CORE_ADDR addr)
   CORE_ADDR *open_closure = xmalloc (sizeof (CORE_ADDR));
   *open_closure = addr;
 
-  nbfd = bfd_openr_iovec (xstrdup (name), "elf32-spu",
-                          spu_bfd_iovec_open, open_closure,
-                          spu_bfd_iovec_pread, spu_bfd_iovec_close,
-			  spu_bfd_iovec_stat);
+  nbfd = gdb_bfd_ref (bfd_openr_iovec (xstrdup (name), "elf32-spu",
+				       spu_bfd_iovec_open, open_closure,
+				       spu_bfd_iovec_pread, spu_bfd_iovec_close,
+				       spu_bfd_iovec_stat));
   if (!nbfd)
     return NULL;
 
   if (!bfd_check_format (nbfd, bfd_object))
     {
-      bfd_close (nbfd);
+      gdb_bfd_unref (nbfd);
       return NULL;
     }
 
diff --git a/gdb/solib.c b/gdb/solib.c
index 402e9bc..9ef8932 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -48,6 +48,7 @@
 #include "solib.h"
 #include "interps.h"
 #include "filesystem.h"
+#include "gdb_bfd.h"
 
 /* Architecture-specific operations.  */
 
@@ -393,7 +394,7 @@ solib_bfd_fopen (char *pathname, int fd)
 	     pathname, bfd_errmsg (bfd_get_error ()));
     }
 
-  return abfd;
+  return gdb_bfd_ref (abfd);
 }
 
 /* Find shared library PATHNAME and open a BFD for it.  */
@@ -424,7 +425,7 @@ solib_bfd_open (char *pathname)
   /* Check bfd format.  */
   if (!bfd_check_format (abfd, bfd_object))
     {
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
       make_cleanup (xfree, found_pathname);
       error (_("`%s': not in executable format: %s"),
 	     found_pathname, bfd_errmsg (bfd_get_error ()));
@@ -470,7 +471,7 @@ solib_map_sections (struct so_list *so)
     return 0;
 
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
-  so->abfd = gdb_bfd_ref (abfd);
+  so->abfd = abfd;
 
   /* copy full path name into so_name, so that later symbol_file_add
      can find it.  */
@@ -610,7 +611,7 @@ solib_read_symbols (struct so_list *so, int flags)
 
 	  sap = build_section_addr_info_from_section_table (so->sections,
 							    so->sections_end);
-	  so->objfile = symbol_file_add_from_bfd (so->abfd,
+	  so->objfile = symbol_file_add_from_bfd (gdb_bfd_ref (so->abfd),
 						  flags, sap, OBJF_SHARED,
 						  NULL);
 	  so->objfile->addr_low = so->addr_low;
@@ -1231,7 +1232,7 @@ reload_shared_libraries_1 (int from_tty)
 	{
 	  found_pathname = xstrdup (bfd_get_filename (abfd));
 	  make_cleanup (xfree, found_pathname);
-	  gdb_bfd_close_or_warn (abfd);
+	  gdb_bfd_unref (abfd);
 	}
 
       /* If this shared library is no longer associated with its previous
diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c
index a4bcbf7..2e5f3dc 100644
--- a/gdb/spu-linux-nat.c
+++ b/gdb/spu-linux-nat.c
@@ -321,10 +321,11 @@ spu_bfd_open (ULONGEST addr)
 			  spu_bfd_iovec_stat);
   if (!nbfd)
     return NULL;
+  nbfd = gdb_bfd_ref (nbfd);
 
   if (!bfd_check_format (nbfd, bfd_object))
     {
-      bfd_close (nbfd);
+      gdb_bfd_unref (nbfd);
       return NULL;
     }
 
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index c513e0e..0ae35a7 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -55,6 +55,7 @@
 #include "observer.h"
 #include "auxv.h"
 #include "elf/common.h"
+#include "gdb_bfd.h"
 
 
 /* Read inferior memory at ADDR to find the header of a loaded object file
@@ -82,6 +83,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
   if (nbfd == NULL)
     error (_("Failed to read a valid object file image from memory."));
 
+  gdb_bfd_ref (nbfd);
   if (name == NULL)
     nbfd->filename = xstrdup ("shared object read from target memory");
   else
@@ -89,10 +91,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
 
   if (!bfd_check_format (nbfd, bfd_object))
     {
-      /* FIXME: should be checking for errors from bfd_close (for one thing,
-         on error it does not free all the storage associated with the
-         bfd).  */
-      bfd_close (nbfd);
+      make_cleanup_bfd_close (nbfd);
       error (_("Got object file from memory but can't read symbols: %s."),
 	     bfd_errmsg (bfd_get_error ()));
     }
diff --git a/gdb/symfile.c b/gdb/symfile.c
index a4eaad9..314e204 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -57,6 +57,7 @@
 #include "solib.h"
 #include "remote.h"
 #include "stack.h"
+#include "gdb_bfd.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -1390,7 +1391,7 @@ separate_debug_file_exists (const char *name, unsigned long crc,
       if (abfd_stat.st_dev == parent_stat.st_dev
 	  && abfd_stat.st_ino == parent_stat.st_ino)
 	{
-	  bfd_close (abfd);
+	  gdb_bfd_unref (abfd);
 	  return 0;
 	}
       verified_as_different = 1;
@@ -1400,7 +1401,7 @@ separate_debug_file_exists (const char *name, unsigned long crc,
 
   file_crc_p = get_file_crc (abfd, &file_crc);
 
-  bfd_close (abfd);
+  gdb_bfd_unref (abfd);
 
   if (!file_crc_p)
     return 0;
@@ -1652,15 +1653,16 @@ set_initial_language (void)
 }
 
 /* If NAME is a remote name open the file using remote protocol, otherwise
-   open it normally.  */
+   open it normally.  Returns a new reference to the BFD.  On error,
+   returns NULL with the BFD error set.  */
 
 bfd *
 bfd_open_maybe_remote (const char *name)
 {
   if (remote_filename_p (name))
-    return remote_bfd_open (name, gnutarget);
+    return gdb_bfd_ref (remote_bfd_open (name, gnutarget));
   else
-    return bfd_openr (name, gnutarget);
+    return gdb_bfd_ref (bfd_openr (name, gnutarget));
 }
 
 
@@ -1679,7 +1681,7 @@ symfile_bfd_open (char *name)
   if (remote_filename_p (name))
     {
       name = xstrdup (name);
-      sym_bfd = remote_bfd_open (name, gnutarget);
+      sym_bfd = gdb_bfd_ref (remote_bfd_open (name, gnutarget));
       if (!sym_bfd)
 	{
 	  make_cleanup (xfree, name);
@@ -1689,7 +1691,7 @@ symfile_bfd_open (char *name)
 
       if (!bfd_check_format (sym_bfd, bfd_object))
 	{
-	  bfd_close (sym_bfd);
+	  gdb_bfd_unref (sym_bfd);
 	  make_cleanup (xfree, name);
 	  error (_("`%s': can't read symbols: %s."), name,
 		 bfd_errmsg (bfd_get_error ()));
@@ -1724,7 +1726,7 @@ symfile_bfd_open (char *name)
   xfree (name);
   name = absolute_name;
 
-  sym_bfd = bfd_fopen (name, gnutarget, FOPEN_RB, desc);
+  sym_bfd = gdb_bfd_ref (bfd_fopen (name, gnutarget, FOPEN_RB, desc));
   if (!sym_bfd)
     {
       close (desc);
@@ -1736,18 +1738,12 @@ symfile_bfd_open (char *name)
 
   if (!bfd_check_format (sym_bfd, bfd_object))
     {
-      /* FIXME: should be checking for errors from bfd_close (for one
-         thing, on error it does not free all the storage associated
-         with the bfd).  */
-      bfd_close (sym_bfd);	/* This also closes desc.  */
+      make_cleanup_bfd_close (sym_bfd);
       make_cleanup (xfree, name);
       error (_("`%s': can't read symbols: %s."), name,
 	     bfd_errmsg (bfd_get_error ()));
     }
 
-  /* bfd_usrdata exists for applications and libbfd must not touch it.  */
-  gdb_assert (bfd_usrdata (sym_bfd) == NULL);
-
   return sym_bfd;
 }
 
@@ -2072,16 +2068,13 @@ generic_load (char *args, int from_tty)
     }
 
   /* Open the file for loading.  */
-  loadfile_bfd = bfd_openr (filename, gnutarget);
+  loadfile_bfd = gdb_bfd_ref (bfd_openr (filename, gnutarget));
   if (loadfile_bfd == NULL)
     {
       perror_with_name (filename);
       return;
     }
 
-  /* FIXME: should be checking for errors from bfd_close (for one thing,
-     on error it does not free all the storage associated with the
-     bfd).  */
   make_cleanup_bfd_close (loadfile_bfd);
 
   if (!bfd_check_format (loadfile_bfd, bfd_object))
@@ -2452,14 +2445,10 @@ reread_symbols (void)
 	     to close the descriptor but BFD lacks a way of closing the
 	     BFD without closing the descriptor.  */
 	  obfd_filename = bfd_get_filename (objfile->obfd);
-	  if (!bfd_close (objfile->obfd))
-	    error (_("Can't close BFD for %s: %s"), objfile->name,
-		   bfd_errmsg (bfd_get_error ()));
+	  gdb_bfd_unref (objfile->obfd);
 	  objfile->obfd = bfd_open_maybe_remote (obfd_filename);
 	  if (objfile->obfd == NULL)
 	    error (_("Can't open %s to read symbols."), objfile->name);
-	  else
-	    objfile->obfd = gdb_bfd_ref (objfile->obfd);
 	  /* bfd_openr sets cacheable to true, which is what we want.  */
 	  if (!bfd_check_format (objfile->obfd, bfd_object))
 	    error (_("Can't read symbols from %s: %s."), objfile->name,
diff --git a/gdb/utils.c b/gdb/utils.c
index cc93915..01a481f 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -27,6 +27,7 @@
 #include "event-top.h"
 #include "exceptions.h"
 #include "gdbthread.h"
+#include "gdb_bfd.h"
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif /* HAVE_SYS_RESOURCE_H */
@@ -226,7 +227,7 @@ make_cleanup_dyn_string_delete (dyn_string_t arg)
 static void
 do_bfd_close_cleanup (void *arg)
 {
-  bfd_close (arg);
+  gdb_bfd_unref (arg);
 }
 
 struct cleanup *
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 20e3c67..ff34778 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -731,7 +731,7 @@ windows_make_so (const char *name, LPVOID load_addr)
       asection *text = NULL;
       CORE_ADDR text_vma;
 
-      abfd = bfd_openr (so->so_name, "pei-i386");
+      abfd = gdb_bfd_ref (bfd_openr (so->so_name, "pei-i386"));
 
       if (!abfd)
 	return so;
@@ -741,7 +741,7 @@ windows_make_so (const char *name, LPVOID load_addr)
 
       if (!text)
 	{
-	  bfd_close (abfd);
+	  gdb_bfd_unref (abfd);
 	  return so;
 	}
 
@@ -752,7 +752,7 @@ windows_make_so (const char *name, LPVOID load_addr)
 						   load_addr + 0x1000);
       cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
 
-      bfd_close (abfd);
+      gdb_bfd_unref (abfd);
     }
 #endif
 
-- 
1.7.6.4


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