public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA 5/8] Add value_freer
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
  2016-11-29  5:06 ` [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 14:24   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 2/8] Use class to manage BFD reference counts Tom Tromey
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds a value_freer class, that records the value mark in the
constructor and then calls value_free_to_mark in the destructor.  It
then updates various spots in gdb to use this class, rather than a
cleanup.

It would be better overall to replace "struct value *" with a
shared_ptr, maybe eliminating the need for this class (watchpoints
would perhaps need some new mechanism as well).  However, that's
difficult to do.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* python/py-value.c (valpy_dereference, valpy_referenced_value)
	(valpy_reference_value, valpy_const_value, valpy_get_address)
	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
	(valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
	(valpy_absolute, valpy_richcompare_throw): Use value_freer.
	* dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
	value_freer.
	* dwarf2-frame.c (execute_stack_op): Use value_freer.
	* value.h (value_freer): New class.
---
 gdb/ChangeLog         | 12 ++++++++++
 gdb/dwarf2-frame.c    |  5 +----
 gdb/dwarf2loc.c       |  8 ++-----
 gdb/python/py-value.c | 62 +++++++++++++++------------------------------------
 gdb/value.h           | 22 ++++++++++++++++++
 5 files changed, 55 insertions(+), 54 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d00862a..6197bfb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* python/py-value.c (valpy_dereference, valpy_referenced_value)
+	(valpy_reference_value, valpy_const_value, valpy_get_address)
+	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
+	(valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
+	(valpy_absolute, valpy_richcompare_throw): Use value_freer.
+	* dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
+	value_freer.
+	* dwarf2-frame.c (execute_stack_op): Use value_freer.
+	* value.h (value_freer): New class.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* dwarf2read.c (dwarf2_build_psymtabs): Use psymtab_discarder.
 	* psympriv.h (make_cleanup_discard_psymtabs): Don't declare.
 	* psymtab.c (discard_psymtabs_upto): Remove.
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index beab304..6e5e4fd 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -403,10 +403,9 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
 		  CORE_ADDR initial, int initial_in_stack_memory)
 {
   CORE_ADDR result;
-  struct cleanup *old_chain;
 
   dwarf_expr_executor ctx;
-  old_chain = make_cleanup_value_free_to_mark (value_mark ());
+  value_freer free_values;
 
   ctx.this_frame = this_frame;
   ctx.gdbarch = get_frame_arch (this_frame);
@@ -430,8 +429,6 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
 Not implemented: computing unwound register using explicit value operator"));
     }
 
-  do_cleanups (old_chain);
-
   return result;
 }
 \f
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 6284e68..0d8a47c 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2840,16 +2840,14 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
 				       struct dwarf2_per_cu_data *per_cu)
 {
   int in_reg;
-  struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
+  value_freer free_values;
+
   symbol_needs_eval_context ctx;
 
   ctx.needs = SYMBOL_NEEDS_NONE;
   ctx.per_cu = per_cu;
-
-  old_chain = make_cleanup_value_free_to_mark (value_mark ());
-
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
@@ -2870,8 +2868,6 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
           in_reg = 1;
     }
 
-  do_cleanups (old_chain);
-
   if (in_reg)
     ctx.needs = SYMBOL_NEEDS_FRAME;
   return ctx.needs;
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index c1f3e16..2afa4e6 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -178,11 +178,10 @@ valpy_dereference (PyObject *self, PyObject *args)
   TRY
     {
       struct value *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       res_val = value_ind (((value_object *) self)->value);
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -209,7 +208,7 @@ valpy_referenced_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val, *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       self_val = ((value_object *) self)->value;
       switch (TYPE_CODE (check_typedef (value_type (self_val))))
@@ -226,7 +225,6 @@ valpy_referenced_value (PyObject *self, PyObject *args)
         }
 
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -247,12 +245,10 @@ valpy_reference_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       self_val = ((value_object *) self)->value;
       result = value_to_value_object (value_ref (self_val));
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -273,13 +269,11 @@ valpy_const_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val, *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       self_val = ((value_object *) self)->value;
       res_val = make_cv_value (1, 0, self_val);
       result = value_to_value_object (res_val);
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -301,12 +295,10 @@ valpy_get_address (PyObject *self, void *closure)
       TRY
 	{
 	  struct value *res_val;
-	  struct cleanup *cleanup
-	    = make_cleanup_value_free_to_mark (value_mark ());
+	  value_freer free_values;
 
 	  res_val = value_addr (val_obj->value);
 	  val_obj->address = value_to_value_object (res_val);
-	  do_cleanups (cleanup);
 	}
       CATCH (except, RETURN_MASK_ALL)
 	{
@@ -354,7 +346,7 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
   TRY
     {
       struct value *val = obj->value;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       type = value_type (val);
       type = check_typedef (type);
@@ -387,8 +379,6 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
 	  /* Re-use object's static type.  */
 	  type = NULL;
 	}
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -428,7 +418,7 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
 	value = value_ind (value);
@@ -436,8 +426,6 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
       str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
 						 user_encoding,
 						 value_type (value));
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -514,7 +502,7 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
     {
       struct value *val = ((value_object *) self)->value;
       struct value *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       if (op == UNOP_DYNAMIC_CAST)
 	res_val = value_dynamic_cast (type, val);
@@ -527,7 +515,6 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
 	}
 
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -737,8 +724,8 @@ valpy_getitem (PyObject *self, PyObject *key)
   TRY
     {
       struct value *tmp = self_value->value;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
       struct value *res_val = NULL;
+      value_freer free_values;
 
       if (field)
 	res_val = value_struct_elt (&tmp, NULL, field.get (), NULL,
@@ -783,7 +770,6 @@ valpy_getitem (PyObject *self, PyObject *key)
 
       if (res_val)
 	result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (ex, RETURN_MASK_ALL)
     {
@@ -861,12 +847,11 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark);
+      value_freer free_values;
       struct value *return_value;
 
       return_value = call_function_by_hand (function, args_count, vargs);
       result = value_to_value_object (return_value);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1014,11 +999,12 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
   PyObject *result = NULL;
 
   struct value *arg1, *arg2;
-  struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
   struct value *res_val = NULL;
   enum exp_opcode op = OP_NULL;
   int handled = 0;
 
+  value_freer free_values;
+
   /* If the gdb.Value object is the second operand, then it will be
      passed to us as the OTHER argument, and SELF will be an entirely
      different kind of object, altogether.  Because of this, we can't
@@ -1026,17 +1012,11 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
      python as well.  */
   arg1 = convert_value_from_python (self);
   if (arg1 == NULL)
-    {
-      do_cleanups (cleanup);
-      return NULL;
-    }
+    return NULL;
 
   arg2 = convert_value_from_python (other);
   if (arg2 == NULL)
-    {
-      do_cleanups (cleanup);
-      return NULL;
-    }
+    return NULL;
 
   switch (opcode)
     {
@@ -1130,7 +1110,6 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
   if (res_val)
     result = value_to_value_object (res_val);
 
-  do_cleanups (cleanup);
   return result;
 }
 
@@ -1209,12 +1188,11 @@ valpy_negative (PyObject *self)
   TRY
     {
       /* Perhaps overkill, but consistency has some virtue.  */
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
       struct value *val;
 
       val = value_neg (((value_object *) self)->value);
       result = value_to_value_object (val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1239,12 +1217,10 @@ valpy_absolute (PyObject *self)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      value_freer free_values;
 
       if (value_less (value, value_zero (value_type (value), not_lval)))
 	isabs = 0;
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1362,15 +1338,14 @@ valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
   int result;
   struct value *value_other;
   struct value *value_self;
-  struct value *mark = value_mark ();
   struct cleanup *cleanup;
 
+  value_freer free_values;
+
   value_other = convert_value_from_python (other);
   if (value_other == NULL)
     return -1;
 
-  cleanup = make_cleanup_value_free_to_mark (mark);
-
   value_self = ((value_object *) self)->value;
 
   switch (op)
@@ -1403,7 +1378,6 @@ valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
       break;
     }
 
-  do_cleanups (cleanup);
   return result;
 }
 
diff --git a/gdb/value.h b/gdb/value.h
index f776323..399bf48 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -714,6 +714,28 @@ extern struct value *value_mark (void);
 
 extern void value_free_to_mark (const struct value *mark);
 
+/* A helper class that uses value_mark at construction time and calls
+   value_free_to_mark in the destructor.  This is used to clear out
+   temporary values created during the lifetime of this object.  */
+class value_freer
+{
+ public:
+
+  value_freer ()
+    : m_value (value_mark ())
+  {
+  }
+
+  ~value_freer ()
+  {
+    value_free_to_mark (m_value);
+  }
+
+ private:
+
+  const struct value *m_value;
+};
+
 extern struct value *value_cstring (const char *ptr, ssize_t len,
 				    struct type *char_type);
 extern struct value *value_string (const char *ptr, ssize_t len,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 4/8] Remove make_cleanup_discard_psymtabs
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
                   ` (3 preceding siblings ...)
  2016-11-29  5:06 ` [RFA 1/8] Add gdb_ref_ptr.h Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 14:21   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 3/8] Introduce and use gdb::unlinker Tom Tromey
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes make_cleanup_discard_psymtabs in favor of a new class.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* dwarf2read.c (dwarf2_build_psymtabs): Use psymtab_discarder.
	* psympriv.h (make_cleanup_discard_psymtabs): Don't declare.
	* psymtab.c (discard_psymtabs_upto): Remove.
	(make_cleanup_discard_psymtabs): Remove.
	(struct psymtab_state): Remove.
---
 gdb/ChangeLog    |  8 ++++++++
 gdb/dwarf2read.c |  5 ++---
 gdb/psympriv.h   | 36 +++++++++++++++++++++++++++++++++++-
 gdb/psymtab.c    | 38 --------------------------------------
 4 files changed, 45 insertions(+), 42 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 18814d3..d00862a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* dwarf2read.c (dwarf2_build_psymtabs): Use psymtab_discarder.
+	* psympriv.h (make_cleanup_discard_psymtabs): Don't declare.
+	* psymtab.c (discard_psymtabs_upto): Remove.
+	(make_cleanup_discard_psymtabs): Remove.
+	(struct psymtab_state): Remove.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* record-full.c (record_full_save_cleanups): Remove.
 	(record_full_save): Use gdb::unlinker.
 	* gcore.c (do_bfd_delete_cleanup): Remove.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index a021aad..0c5d374 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -4268,10 +4268,9 @@ dwarf2_build_psymtabs (struct objfile *objfile)
       /* This isn't really ideal: all the data we allocate on the
 	 objfile's obstack is still uselessly kept around.  However,
 	 freeing it seems unsafe.  */
-      struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile);
-
+      psymtab_discarder psymtabs (objfile);
       dwarf2_build_psymtabs_hard (objfile);
-      discard_cleanups (cleanups);
+      psymtabs.keep ();
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
diff --git a/gdb/psympriv.h b/gdb/psympriv.h
index 915208e..846e970 100644
--- a/gdb/psympriv.h
+++ b/gdb/psympriv.h
@@ -21,6 +21,7 @@
 #define PSYMPRIV_H
 
 #include "psymtab.h"
+#include "objfiles.h"
 
 struct psymbol_allocation_list;
 
@@ -225,7 +226,40 @@ extern struct partial_symtab *allocate_psymtab (const char *,
 
 extern void discard_psymtab (struct objfile *, struct partial_symtab *);
 
-extern struct cleanup *make_cleanup_discard_psymtabs (struct objfile *);
+/* Used when recording partial symbol tables.  On destruction,
+   discards any partial symbol tables that have been built.  However,
+   the tables can be kept by calling the "keep" method.  */
+class psymtab_discarder
+{
+ public:
+
+  psymtab_discarder (struct objfile *objfile)
+    : m_objfile (objfile),
+      m_psymtab (objfile->psymtabs)
+  {
+  }
+
+  ~psymtab_discarder ()
+  {
+    if (m_objfile != NULL)
+      while (m_objfile->psymtabs != m_psymtab)
+	discard_psymtab (m_objfile, m_objfile->psymtabs);
+  }
+
+  /* Keep any partial symbol tables that were built.  */
+  void keep ()
+  {
+    m_objfile = NULL;
+  }
+
+ private:
+
+  /* The objfile.  If NULL this serves as a sentinel to indicate that
+     the psymtabs should be kept.  */
+  struct objfile *m_objfile;
+  /* How far back to free.  */
+  struct partial_symtab *m_psymtab;
+};
 
 /* Traverse all psymtabs in one objfile.  */
 
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 825df77..31731ca 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1836,44 +1836,6 @@ discard_psymtab (struct objfile *objfile, struct partial_symtab *pst)
   objfile->free_psymtabs = pst;
 }
 
-/* An object of this type is passed to discard_psymtabs_upto.  */
-
-struct psymtab_state
-{
-  /* The objfile where psymtabs are discarded.  */
-
-  struct objfile *objfile;
-
-  /* The first psymtab to save.  */
-
-  struct partial_symtab *save;
-};
-
-/* A cleanup function used by make_cleanup_discard_psymtabs.  */
-
-static void
-discard_psymtabs_upto (void *arg)
-{
-  struct psymtab_state *state = (struct psymtab_state *) arg;
-
-  while (state->objfile->psymtabs != state->save)
-    discard_psymtab (state->objfile, state->objfile->psymtabs);
-}
-
-/* Return a new cleanup that discards all psymtabs created in OBJFILE
-   after this function is called.  */
-
-struct cleanup *
-make_cleanup_discard_psymtabs (struct objfile *objfile)
-{
-  struct psymtab_state *state = XNEW (struct psymtab_state);
-
-  state->objfile = objfile;
-  state->save = objfile->psymtabs;
-
-  return make_cleanup_dtor (discard_psymtabs_upto, state, xfree);
-}
-
 \f
 
 /* We need to pass a couple of items to the addrmap_foreach function,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 8/8] Add constructor and destructor to demangle_parse_info
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
                   ` (5 preceding siblings ...)
  2016-11-29  5:06 ` [RFA 3/8] Introduce and use gdb::unlinker Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 15:04   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command Tom Tromey
  7 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds a constructor and destructor to demangle_parse_info, and
then changes all the users to use them.  This removes
make_cleanup_cp_demangled_name_parse_free and its single use.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* python/py-type.c (typy_legacy_template_argument): Update.
	* cp-support.h (struct demangle_parse_info) (demangle_parse_info,
	~demangle_parse_info): Declare new members.
	(cp_demangled_name_to_comp): Return unique_ptr.
	(cp_demangled_name_parse_free)
	(make_cleanup_cp_demangled_name_parse_free)
	(cp_new_demangle_parse_info): Remove.
	* cp-support.c (do_demangled_name_parse_free_cleanup)
	(make_cleanup_cp_demangled_name_parse_free): Remove.
	(inspect_type, cp_canonicalize_string_full)
	(cp_canonicalize_string): Update.
	(mangled_name_to_comp): Change return type.
	(cp_class_name_from_physname, method_name_from_physname)
	(cp_func_name, cp_remove_params): Update.
	* cp-name-parser.y (demangle_parse_info): New constructor, from
	cp_new_demangle_parse_info.
	(~demangle_parse_info): New destructor, from
	cp_demangled_name_parse_free.
	(cp_merge_demangle_parse_infos): Update.
	(cp_demangled_name_to_comp): Change return type.
---
 gdb/ChangeLog        | 23 +++++++++++++++++++++++
 gdb/cp-name-parser.y | 39 ++++++++++-----------------------------
 gdb/cp-support.c     | 52 +++++++++++++---------------------------------------
 gdb/cp-support.h     | 11 +++++------
 gdb/python/py-type.c |  6 +-----
 5 files changed, 52 insertions(+), 79 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d0d2ef6..a117997 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,28 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* python/py-type.c (typy_legacy_template_argument): Update.
+	* cp-support.h (struct demangle_parse_info) (demangle_parse_info,
+	~demangle_parse_info): Declare new members.
+	(cp_demangled_name_to_comp): Return unique_ptr.
+	(cp_demangled_name_parse_free)
+	(make_cleanup_cp_demangled_name_parse_free)
+	(cp_new_demangle_parse_info): Remove.
+	* cp-support.c (do_demangled_name_parse_free_cleanup)
+	(make_cleanup_cp_demangled_name_parse_free): Remove.
+	(inspect_type, cp_canonicalize_string_full)
+	(cp_canonicalize_string): Update.
+	(mangled_name_to_comp): Change return type.
+	(cp_class_name_from_physname, method_name_from_physname)
+	(cp_func_name, cp_remove_params): Update.
+	* cp-name-parser.y (demangle_parse_info): New constructor, from
+	cp_new_demangle_parse_info.
+	(~demangle_parse_info): New destructor, from
+	cp_demangled_name_parse_free.
+	(cp_merge_demangle_parse_infos): Update.
+	(cp_demangled_name_to_comp): Change return type.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* python/python.c (execute_gdb_command): Use unique_xmalloc_ptr.
 
 2016-11-28  Tom Tromey  <tom@tromey.com>
diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index c6a5c34..6f281ab 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -1999,29 +1999,19 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len)
 			       &err);
 }
 
-/* A convenience function to allocate and initialize a new struct
-   demangled_parse_info.  */
+/* Constructor for demangle_parse_info.  */
 
-struct demangle_parse_info *
-cp_new_demangle_parse_info (void)
+demangle_parse_info::demangle_parse_info ()
+: info (NULL),
+  tree (NULL)
 {
-  struct demangle_parse_info *info;
-
-  info = XNEW (struct demangle_parse_info);
-  info->info = NULL;
-  info->tree = NULL;
-  obstack_init (&info->obstack);
-
-  return info;
+  obstack_init (&obstack);
 }
 
-/* Free any memory associated with the given PARSE_INFO.  */
+/* Destructor for demangle_parse_info.  */
 
-void
-cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
+demangle_parse_info::~demangle_parse_info ()
 {
-  struct demangle_info *info = parse_info->info;
-
   /* Free any allocated chunks of memory for the parse.  */
   while (info != NULL)
     {
@@ -2032,15 +2022,11 @@ cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
     }
 
   /* Free any memory allocated during typedef replacement.  */
-  obstack_free (&parse_info->obstack, NULL);
-
-  /* Free the parser info.  */
-  free (parse_info);
+  obstack_free (&obstack, NULL);
 }
 
 /* Merge the two parse trees given by DEST and SRC.  The parse tree
    in SRC is attached to DEST at the node represented by TARGET.
-   SRC is then freed.
 
    NOTE 1: Since there is no API to merge obstacks, this function does
    even attempt to try it.  Fortunately, we do not (yet?) need this ability.
@@ -2067,9 +2053,6 @@ cp_merge_demangle_parse_infos (struct demangle_parse_info *dest,
   /* Clear the (pointer to) SRC's parse data so that it is not freed when
      cp_demangled_parse_info_free is called.  */
   src->info = NULL;
-
-  /* Free SRC.  */
-  cp_demangled_name_parse_free (src);
 }
 
 /* Convert a demangled name to a demangle_component tree.  On success,
@@ -2078,11 +2061,10 @@ cp_merge_demangle_parse_infos (struct demangle_parse_info *dest,
    returned, and an error message will be set in *ERRMSG (which does
    not need to be freed).  */
 
-struct demangle_parse_info *
+struct std::unique_ptr<demangle_parse_info>
 cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 {
   static char errbuf[60];
-  struct demangle_parse_info *result;
 
   prev_lexptr = lexptr = demangled_name;
   error_lexptr = NULL;
@@ -2090,7 +2072,7 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 
   demangle_info = allocate_info ();
 
-  result = cp_new_demangle_parse_info ();
+  std::unique_ptr<demangle_parse_info> result (new demangle_parse_info);
   result->info = demangle_info;
 
   if (yyparse ())
@@ -2102,7 +2084,6 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 	  strcat (errbuf, "'");
 	  *errmsg = errbuf;
 	}
-      cp_demangled_name_parse_free (result);
       return NULL;
     }
 
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index d409b0b..a6edb3c 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -95,24 +95,6 @@ copy_string_to_obstack (struct obstack *obstack, const char *string,
   return (char *) obstack_copy (obstack, string, *len);
 }
 
-/* A cleanup wrapper for cp_demangled_name_parse_free.  */
-
-static void
-do_demangled_name_parse_free_cleanup (void *data)
-{
-  struct demangle_parse_info *info = (struct demangle_parse_info *) data;
-
-  cp_demangled_name_parse_free (info);
-}
-
-/* Create a cleanup for C++ name parsing.  */
-
-struct cleanup *
-make_cleanup_cp_demangled_name_parse_free (struct demangle_parse_info *info)
-{
-  return make_cleanup (do_demangled_name_parse_free_cleanup, info);
-}
-
 /* Return 1 if STRING is clearly already in canonical form.  This
    function is conservative; things which it does not recognize are
    assumed to be non-canonical, and the parser will sort them out
@@ -209,7 +191,7 @@ inspect_type (struct demangle_parse_info *info,
 	  long len;
 	  int is_anon;
 	  struct type *type;
-	  struct demangle_parse_info *i;
+	  std::unique_ptr<demangle_parse_info> i;
 	  struct ui_file *buf;
 
 	  /* Get the real type of the typedef.  */
@@ -272,7 +254,7 @@ inspect_type (struct demangle_parse_info *info,
 	  if (i != NULL)
 	    {
 	      /* Merge the two trees.  */
-	      cp_merge_demangle_parse_infos (info, ret_comp, i);
+	      cp_merge_demangle_parse_infos (info, ret_comp, i.get ());
 
 	      /* Replace any newly introduced typedefs -- but not
 		 if the type is anonymous (that would lead to infinite
@@ -540,22 +522,19 @@ cp_canonicalize_string_full (const char *string,
 {
   std::string ret;
   unsigned int estimated_len;
-  struct demangle_parse_info *info;
+  std::unique_ptr<demangle_parse_info> info;
 
   estimated_len = strlen (string) * 2;
   info = cp_demangled_name_to_comp (string, NULL);
   if (info != NULL)
     {
       /* Replace all the typedefs in the tree.  */
-      replace_typedefs (info, info->tree, finder, data);
+      replace_typedefs (info.get (), info->tree, finder, data);
 
       /* Convert the tree back into a string.  */
       ret = cp_comp_to_string (info->tree, estimated_len);
       gdb_assert (!ret.empty ());
 
-      /* Free the parse information.  */
-      cp_demangled_name_parse_free (info);
-
       /* Finally, compare the original string with the computed
 	 name, returning NULL if they are the same.  */
       if (ret == string)
@@ -581,7 +560,7 @@ cp_canonicalize_string_no_typedefs (const char *string)
 std::string
 cp_canonicalize_string (const char *string)
 {
-  struct demangle_parse_info *info;
+  std::unique_ptr<demangle_parse_info> info;
   unsigned int estimated_len;
 
   if (cp_already_canonical (string))
@@ -593,7 +572,6 @@ cp_canonicalize_string (const char *string)
 
   estimated_len = strlen (string) * 2;
   std::string ret = cp_comp_to_string (info->tree, estimated_len);
-  cp_demangled_name_parse_free (info);
 
   if (ret.empty ())
     {
@@ -614,12 +592,11 @@ cp_canonicalize_string (const char *string)
    freed when finished with the tree, or NULL if none was needed.
    OPTIONS will be passed to the demangler.  */
 
-static struct demangle_parse_info *
+static std::unique_ptr<demangle_parse_info>
 mangled_name_to_comp (const char *mangled_name, int options,
 		      void **memory, char **demangled_p)
 {
   char *demangled_name;
-  struct demangle_parse_info *info;
 
   /* If it looks like a v3 mangled name, then try to go directly
      to trees.  */
@@ -631,7 +608,7 @@ mangled_name_to_comp (const char *mangled_name, int options,
 					  options, memory);
       if (ret)
 	{
-	  info = cp_new_demangle_parse_info ();
+	  std::unique_ptr<demangle_parse_info> info (new demangle_parse_info);
 	  info->tree = ret;
 	  *demangled_p = NULL;
 	  return info;
@@ -646,7 +623,8 @@ mangled_name_to_comp (const char *mangled_name, int options,
   
   /* If we could demangle the name, parse it to build the component
      tree.  */
-  info = cp_demangled_name_to_comp (demangled_name, NULL);
+  std::unique_ptr<demangle_parse_info> info
+    (cp_demangled_name_to_comp (demangled_name, NULL));
 
   if (info == NULL)
     {
@@ -666,7 +644,7 @@ cp_class_name_from_physname (const char *physname)
   void *storage = NULL;
   char *demangled_name = NULL, *ret;
   struct demangle_component *ret_comp, *prev_comp, *cur_comp;
-  struct demangle_parse_info *info;
+  std::unique_ptr<demangle_parse_info> info;
   int done;
 
   info = mangled_name_to_comp (physname, DMGL_ANSI,
@@ -745,7 +723,6 @@ cp_class_name_from_physname (const char *physname)
 
   xfree (storage);
   xfree (demangled_name);
-  cp_demangled_name_parse_free (info);
   return ret;
 }
 
@@ -815,7 +792,7 @@ method_name_from_physname (const char *physname)
   void *storage = NULL;
   char *demangled_name = NULL, *ret;
   struct demangle_component *ret_comp;
-  struct demangle_parse_info *info;
+  std::unique_ptr<demangle_parse_info> info;
 
   info = mangled_name_to_comp (physname, DMGL_ANSI,
 			       &storage, &demangled_name);
@@ -832,7 +809,6 @@ method_name_from_physname (const char *physname)
 
   xfree (storage);
   xfree (demangled_name);
-  cp_demangled_name_parse_free (info);
   return ret;
 }
 
@@ -847,7 +823,7 @@ cp_func_name (const char *full_name)
 {
   char *ret;
   struct demangle_component *ret_comp;
-  struct demangle_parse_info *info;
+  std::unique_ptr<demangle_parse_info> info;
 
   info = cp_demangled_name_to_comp (full_name, NULL);
   if (!info)
@@ -859,7 +835,6 @@ cp_func_name (const char *full_name)
   if (ret_comp != NULL)
     ret = cp_comp_to_string (ret_comp, 10);
 
-  cp_demangled_name_parse_free (info);
   return ret;
 }
 
@@ -872,7 +847,7 @@ cp_remove_params (const char *demangled_name)
 {
   int done = 0;
   struct demangle_component *ret_comp;
-  struct demangle_parse_info *info;
+  std::unique_ptr<demangle_parse_info> info;
   char *ret = NULL;
 
   if (demangled_name == NULL)
@@ -905,7 +880,6 @@ cp_remove_params (const char *demangled_name)
   if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
     ret = cp_comp_to_string (d_left (ret_comp), 10);
 
-  cp_demangled_name_parse_free (info);
   return ret;
 }
 
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index ca7a7d4..ffccded 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -58,6 +58,10 @@ struct demangle_parse_info
 
   /* Any temporary memory used during typedef replacement.  */
   struct obstack obstack;
+
+  demangle_parse_info ();
+
+  ~demangle_parse_info ();
 };
 
 
@@ -135,21 +139,16 @@ struct type *cp_find_type_baseclass_by_name (struct type *parent_type,
 
 /* Functions from cp-name-parser.y.  */
 
-extern struct demangle_parse_info *cp_demangled_name_to_comp
+extern std::unique_ptr<demangle_parse_info> cp_demangled_name_to_comp
      (const char *demangled_name, const char **errmsg);
 
 extern char *cp_comp_to_string (struct demangle_component *result,
 				int estimated_len);
 
-extern void cp_demangled_name_parse_free (struct demangle_parse_info *);
-extern struct cleanup *make_cleanup_cp_demangled_name_parse_free
-     (struct demangle_parse_info *);
 extern void cp_merge_demangle_parse_infos (struct demangle_parse_info *,
 					   struct demangle_component *,
 					   struct demangle_parse_info *);
 
-extern struct demangle_parse_info *cp_new_demangle_parse_info (void);
-
 /* The list of "maint cplus" commands.  */
 
 extern struct cmd_list_element *maint_cplus_cmd_list;
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 5139c92..64b59f1 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -832,7 +832,7 @@ typy_legacy_template_argument (struct type *type, const struct block *block,
 {
   int i;
   struct demangle_component *demangled;
-  struct demangle_parse_info *info = NULL;
+  std::unique_ptr<demangle_parse_info> info;
   const char *err;
   struct type *argtype;
   struct cleanup *cleanup;
@@ -860,7 +860,6 @@ typy_legacy_template_argument (struct type *type, const struct block *block,
       return NULL;
     }
   demangled = info->tree;
-  cleanup = make_cleanup_cp_demangled_name_parse_free (info);
 
   /* Strip off component names.  */
   while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME
@@ -869,7 +868,6 @@ typy_legacy_template_argument (struct type *type, const struct block *block,
 
   if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
     {
-      do_cleanups (cleanup);
       PyErr_SetString (PyExc_RuntimeError, _("Type is not a template."));
       return NULL;
     }
@@ -882,14 +880,12 @@ typy_legacy_template_argument (struct type *type, const struct block *block,
 
   if (! demangled)
     {
-      do_cleanups (cleanup);
       PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."),
 		    argno);
       return NULL;
     }
 
   argtype = typy_lookup_type (demangled->u.s_binary.left, block);
-  do_cleanups (cleanup);
   if (! argtype)
     return NULL;
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 14:45   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 5/8] Add value_freer Tom Tromey
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf2_evaluate_loc_desc_full to use value_freer.

Note that this function previously called do_cleanup using the same
cleanup multiple times.  I had thought this was buggy, but re-reading
make_my_cleanup2 indicates that it is not.  Nevertheless it is
surprising, and at least one of the calls (the one that is completely
removed in this patch) seems to have been done under the assumption
that it would still have some effect.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* value.h (value_freer::~value_freer): Call release.
	(value_freer::release): New method.
	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use value_freer.
---
 gdb/ChangeLog   |  6 ++++++
 gdb/dwarf2loc.c | 27 +++++++++++++--------------
 gdb/value.h     | 12 +++++++++++-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6197bfb..cf61306 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* value.h (value_freer::~value_freer): Call release.
+	(value_freer::release): New method.
+	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use value_freer.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* python/py-value.c (valpy_dereference, valpy_referenced_value)
 	(valpy_reference_value, valpy_const_value, valpy_get_address)
 	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 0d8a47c..43c95b8 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2321,7 +2321,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 			       LONGEST byte_offset)
 {
   struct value *retval;
-  struct cleanup *value_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
   if (byte_offset < 0)
@@ -2335,7 +2334,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
   ctx.per_cu = per_cu;
   ctx.obj_address = 0;
 
-  value_chain = make_cleanup_value_free_to_mark (value_mark ());
+  value_freer free_values;
 
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
@@ -2350,7 +2349,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
     {
       if (ex.error == NOT_AVAILABLE_ERROR)
 	{
-	  do_cleanups (value_chain);
+	  free_values.release ();
 	  retval = allocate_value (type);
 	  mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type));
 	  return retval;
@@ -2359,7 +2358,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	{
 	  if (entry_values_debug)
 	    exception_print (gdb_stdout, ex);
-	  do_cleanups (value_chain);
+	  free_values.release ();
 	  return allocate_optimized_out_value (type);
 	}
       else
@@ -2382,7 +2381,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 				  ctx.addr_size, frame);
       /* We must clean up the value chain after creating the piece
 	 closure but before allocating the result.  */
-      do_cleanups (value_chain);
+      free_values.release ();
       retval = allocate_computed_value (type, &pieced_value_funcs, c);
       set_value_offset (retval, byte_offset);
     }
@@ -2399,7 +2398,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
 	    if (byte_offset != 0)
 	      error (_("cannot use offset on synthetic pointer to register"));
-	    do_cleanups (value_chain);
+	    free_values.release ();
 	    retval = value_from_register (type, gdb_regnum, frame);
 	    if (value_optimized_out (retval))
 	      {
@@ -2411,7 +2410,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 		   inspecting a register ($pc, $sp, etc.), return a
 		   generic optimized out value instead, so that we show
 		   <optimized out> instead of <not saved>.  */
-		do_cleanups (value_chain);
 		tmp = allocate_value (type);
 		value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type));
 		retval = tmp;
@@ -2445,7 +2443,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	      }
 	    address = value_as_address (value_from_pointer (ptr_type, address));
 
-	    do_cleanups (value_chain);
+	    free_values.release ();
 	    retval = value_at_lazy (type, address + byte_offset);
 	    if (in_stack_memory)
 	      set_value_stack (retval, 1);
@@ -2458,6 +2456,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	    gdb_byte *contents;
 	    const gdb_byte *val_bytes;
 	    size_t n = TYPE_LENGTH (value_type (value));
+	    struct cleanup *cleanup;
 
 	    if (byte_offset + TYPE_LENGTH (type) > n)
 	      invalid_synthetic_pointer ();
@@ -2470,8 +2469,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	       to the mark, but we still need the value contents
 	       below.  */
 	    value_incref (value);
-	    do_cleanups (value_chain);
-	    make_cleanup_value_free (value);
+	    free_values.release ();
+	    cleanup = make_cleanup_value_free (value);
 
 	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
@@ -2484,6 +2483,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 		n = TYPE_LENGTH (type);
 	      }
 	    memcpy (contents, val_bytes, n);
+
+	    do_cleanups (cleanup);
 	  }
 	  break;
 
@@ -2496,7 +2497,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	    if (byte_offset + TYPE_LENGTH (type) > n)
 	      invalid_synthetic_pointer ();
 
-	    do_cleanups (value_chain);
+	    free_values.release ();
 	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
 
@@ -2516,7 +2517,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	  break;
 
 	case DWARF_VALUE_OPTIMIZED_OUT:
-	  do_cleanups (value_chain);
+	  free_values.release ();
 	  retval = allocate_optimized_out_value (type);
 	  break;
 
@@ -2532,8 +2533,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
   set_value_initialized (retval, ctx.initialized);
 
-  do_cleanups (value_chain);
-
   return retval;
 }
 
diff --git a/gdb/value.h b/gdb/value.h
index 399bf48..43dfe14 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -728,7 +728,17 @@ class value_freer
 
   ~value_freer ()
   {
-    value_free_to_mark (m_value);
+    release ();
+  }
+
+  /* Free the values currently on the value stack.  */
+  void release ()
+  {
+    if (m_value != NULL)
+      {
+	value_free_to_mark (m_value);
+	m_value = NULL;
+      }
   }
 
  private:
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
                   ` (6 preceding siblings ...)
  2016-11-29  5:06 ` [RFA 8/8] Add constructor and destructor to demangle_parse_info Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-11-29  5:22   ` Tom Tromey
  2016-12-02 14:49   ` Pedro Alves
  7 siblings, 2 replies; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This replaces a cleanup in execute_gdb_command with an instance of
unique_xmalloc_ptr.  std::string was not used because execute_command
and execute_command_to_string don't accept a "const char *" (in fact
the reason for copying the string at all).

2016-11-28  Tom Tromey  <tom@tromey.com>

	* python/python.c (execute_gdb_command): Use unique_xmalloc_ptr.
---
 gdb/ChangeLog       | 4 ++++
 gdb/python/python.c | 8 +++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cf61306..d0d2ef6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* python/python.c (execute_gdb_command): Use unique_xmalloc_ptr.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* value.h (value_freer::~value_freer): Call release.
 	(value_freer::release): New method.
 	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use value_freer.
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 83b9805..83894a1 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -601,8 +601,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
   TRY
     {
       /* Copy the argument text in case the command modifies it.  */
-      char *copy = xstrdup (arg);
-      struct cleanup *cleanup = make_cleanup (xfree, copy);
+      gdb::unique_xmalloc_ptr<char> copy (xstrdup (arg));
       struct interp *interp;
 
       scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
@@ -616,10 +615,9 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
 
       prevent_dont_repeat ();
       if (to_string)
-	to_string_res = execute_command_to_string (copy, from_tty);
+	to_string_res = execute_command_to_string (copy.get (), from_tty);
       else
-	execute_command (copy, from_tty);
-      do_cleanups (cleanup);
+	execute_command (copy.get (), from_tty);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 0/8] C++-ification series #5
@ 2016-11-29  5:06 Tom Tromey
  2016-11-29  5:06 ` [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full Tom Tromey
                   ` (7 more replies)
  0 siblings, 8 replies; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches

This series holds a few more C++-ification changes:

* Generalizes gdbpy_ref to an "externally refcounted" smart pointer,
  with the behavior controlled by a policy class.  This is then used
  to convert BFD refcounting.

* Adds a class to optionally unlink a file in the destructor.

* Adds a class to call value_free_to_mark in the destructor.

* Adds a class to optionally discard psymtabs in the destructor.

* Fix up one more cleanup in the Python code that I missed.

* Change demangle_parse_info to have a constructor and destructor and
  use unique_ptr for managing these.

gdb is getting relatively close to no cleanups in the Python layer
after this series (25 hits for "make_cleanup").

Please review.  I'm running this through the buildbot and will comment
when that is done.

Note that the BFD refcounting change is a bit tricky.  It probably
should have extra testing -- I tested it locally, and there's the
buildbot, and additionally I built it locally using the mingw32 cross
toolchain; but even so it's possible that there are paths that weren't
updated.  These will manifest as build failures on some other
host.

One thing that would be nice is if there were a way to build gdb such
that all the nat* code were built.  This would at least catch compiler
errors.  I think it could be done by having stub implementations of
any platform-specific APIs that are used (just a #define for each
would probably suffice), and by arranging for only the real nat*.c
file's initialization function to be called at startup.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 3/8] Introduce and use gdb::unlinker
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
                   ` (4 preceding siblings ...)
  2016-11-29  5:06 ` [RFA 4/8] Remove make_cleanup_discard_psymtabs Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 13:17   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 8/8] Add constructor and destructor to demangle_parse_info Tom Tromey
  2016-11-29  5:06 ` [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command Tom Tromey
  7 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This introduces a new class, gdb::unlinker, that unlinks a file in the
destructor.  The user of this class has the option to preserve the
file instead, by calling the "keep" method.

This patch then changes the spots in gdb that use unlink in a cleanup
to use this class instead.  In one spot I went ahead and removed all
the cleanups from the function.

This fixes one latent bug -- do_bfd_delete_cleanup could refer to
freed memory, by decref'ing the BFD before using its filename.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* record-full.c (record_full_save_cleanups): Remove.
	(record_full_save): Use gdb::unlinker.
	* gcore.c (do_bfd_delete_cleanup): Remove.
	(gcore_command): Use gdb::unlinker, unique_xmalloc_ptr.  Remove
	cleanups.
	* dwarf2read.c (unlink_if_set): Remove.
	(write_psymtabs_to_index): Use gdb::unlinker.
	* common/gdb_unlinker.h: New file.
---
 gdb/ChangeLog             | 11 +++++++++
 gdb/common/gdb_unlinker.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2read.c          | 21 ++++-------------
 gdb/gcore.c               | 38 ++++++++++--------------------
 gdb/record-full.c         | 54 +++++++++++++++++-------------------------
 5 files changed, 110 insertions(+), 74 deletions(-)
 create mode 100644 gdb/common/gdb_unlinker.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ce21840..18814d3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,16 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* record-full.c (record_full_save_cleanups): Remove.
+	(record_full_save): Use gdb::unlinker.
+	* gcore.c (do_bfd_delete_cleanup): Remove.
+	(gcore_command): Use gdb::unlinker, unique_xmalloc_ptr.  Remove
+	cleanups.
+	* dwarf2read.c (unlink_if_set): Remove.
+	(write_psymtabs_to_index): Use gdb::unlinker.
+	* common/gdb_unlinker.h: New file.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* windows-tdep.c (windows_xfer_shared_library): Update.
 	* windows-nat.c (windows_make_so): Update.
 	* utils.h (make_cleanup_bfd_unref): Remove.
diff --git a/gdb/common/gdb_unlinker.h b/gdb/common/gdb_unlinker.h
new file mode 100644
index 0000000..0f3b98a
--- /dev/null
+++ b/gdb/common/gdb_unlinker.h
@@ -0,0 +1,60 @@
+/* Unlinking class
+
+   Copyright (C) 2016 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_UNLINKER_H
+#define GDB_UNLINKER_H
+
+namespace gdb
+{
+
+/* An object of this class holds a filename and, when the object goes
+   of scope, the file is removed using unlink.
+
+   A user of this class can request that the file be preserved using
+   the "keep" method.  */
+class unlinker
+{
+ public:
+
+  unlinker (const char *filename) ATTRIBUTE_NONNULL (1)
+    : m_filename (filename)
+  {
+    gdb_assert (filename != NULL);
+  }
+
+  ~unlinker ()
+  {
+    if (m_filename != NULL)
+      unlink (m_filename);
+  }
+
+  /* Keep the file, rather than unlink it.  */
+  void keep ()
+  {
+    m_filename = NULL;
+  }
+
+ private:
+
+  const char *m_filename;
+};
+
+}
+
+#endif /* GDB_UNLINKER_H */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 0780ae0..a021aad 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -69,6 +69,7 @@
 #include "filestuff.h"
 #include "build-id.h"
 #include "namespace.h"
+#include "common/gdb_unlinker.h"
 
 #include <fcntl.h>
 #include <sys/types.h>
@@ -23156,16 +23157,6 @@ write_obstack (FILE *file, struct obstack *obstack)
     error (_("couldn't data write to file"));
 }
 
-/* Unlink a file if the argument is not NULL.  */
-
-static void
-unlink_if_set (void *p)
-{
-  char **filename = (char **) p;
-  if (*filename)
-    unlink (*filename);
-}
-
 /* A helper struct used when iterating over debug_types.  */
 struct signatured_type_index_data
 {
@@ -23250,7 +23241,7 @@ static void
 write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 {
   struct cleanup *cleanup;
-  char *filename, *cleanup_filename;
+  char *filename;
   struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
   struct obstack cu_list, types_cu_list;
   int i;
@@ -23280,8 +23271,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
   if (!out_file)
     error (_("Can't open `%s' for writing"), filename);
 
-  cleanup_filename = filename;
-  make_cleanup (unlink_if_set, &cleanup_filename);
+  gdb::unlinker unlink_file (filename);
 
   symtab = create_mapped_symtab ();
   make_cleanup (cleanup_mapped_symtab, symtab);
@@ -23420,9 +23410,8 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 
   fclose (out_file);
 
-  /* We want to keep the file, so we set cleanup_filename to NULL
-     here.  See unlink_if_set.  */
-  cleanup_filename = NULL;
+  /* We want to keep the file.  */
+  unlink_file.keep ();
 
   do_cleanups (cleanup);
 }
diff --git a/gdb/gcore.c b/gdb/gcore.c
index 0b05cf9..ed89cc9 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -35,6 +35,7 @@
 #include "gdb_bfd.h"
 #include "readline/tilde.h"
 #include <algorithm>
+#include "common/gdb_unlinker.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
@@ -135,59 +136,44 @@ write_gcore_file (bfd *obfd)
     throw_exception (except);
 }
 
-static void
-do_bfd_delete_cleanup (void *arg)
-{
-  bfd *obfd = (bfd *) arg;
-  const char *filename = obfd->filename;
-
-  gdb_bfd_unref ((bfd *) arg);
-  unlink (filename);
-}
-
 /* gcore_command -- implements the 'gcore' command.
    Generate a core file from the inferior process.  */
 
 static void
 gcore_command (char *args, int from_tty)
 {
-  struct cleanup *filename_chain;
-  struct cleanup *bfd_chain;
-  char *corefilename;
-  bfd *obfd;
+  gdb::unique_xmalloc_ptr<char> corefilename;
 
   /* No use generating a corefile without a target process.  */
   if (!target_has_execution)
     noprocess ();
 
   if (args && *args)
-    corefilename = tilde_expand (args);
+    corefilename.reset (tilde_expand (args));
   else
     {
       /* Default corefile name is "core.PID".  */
-      corefilename = xstrprintf ("core.%d", ptid_get_pid (inferior_ptid));
+      corefilename.reset (xstrprintf ("core.%d", ptid_get_pid (inferior_ptid)));
     }
-  filename_chain = make_cleanup (xfree, corefilename);
 
   if (info_verbose)
     fprintf_filtered (gdb_stdout,
-		      "Opening corefile '%s' for output.\n", corefilename);
+		      "Opening corefile '%s' for output.\n",
+		      corefilename.get ());
 
   /* Open the output file.  */
-  obfd = create_gcore_bfd (corefilename).release ();
+  gdb_bfd_ref_ptr obfd (create_gcore_bfd (corefilename.get ()));
 
-  /* Need a cleanup that will close and delete the file.  */
-  bfd_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
+  /* Arrange to unlink the file on failure.  */
+  gdb::unlinker unlink_file (corefilename.get ());
 
   /* Call worker function.  */
-  write_gcore_file (obfd);
+  write_gcore_file (obfd.get ());
 
   /* Succeeded.  */
-  discard_cleanups (bfd_chain);
-  gdb_bfd_unref (obfd);
+  unlink_file.keep ();
 
-  fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
-  do_cleanups (filename_chain);
+  fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename.get ());
 }
 
 static unsigned long
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 7ab394b..7499760 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -35,6 +35,7 @@
 #include "gdb_bfd.h"
 #include "observer.h"
 #include "infrun.h"
+#include "common/gdb_unlinker.h"
 
 #include <signal.h>
 
@@ -2537,17 +2538,6 @@ cmd_record_full_restore (char *args, int from_tty)
   record_full_open (args, from_tty);
 }
 
-static void
-record_full_save_cleanups (void *data)
-{
-  bfd *obfd = (bfd *) data;
-  char *pathname = xstrdup (bfd_get_filename (obfd));
-
-  gdb_bfd_unref (obfd);
-  unlink (pathname);
-  xfree (pathname);
-}
-
 /* Save the execution log to a file.  We use a modified elf corefile
    format, with an extra section for our data.  */
 
@@ -2558,9 +2548,7 @@ record_full_save (struct target_ops *self, const char *recfilename)
   uint32_t magic;
   struct regcache *regcache;
   struct gdbarch *gdbarch;
-  struct cleanup *old_cleanups;
   struct cleanup *set_cleanups;
-  bfd *obfd;
   int save_size = 0;
   asection *osec = NULL;
   int bfd_offset = 0;
@@ -2571,8 +2559,10 @@ record_full_save (struct target_ops *self, const char *recfilename)
 			recfilename);
 
   /* Open the output file.  */
-  obfd = create_gcore_bfd (recfilename).release ();
-  old_cleanups = make_cleanup (record_full_save_cleanups, obfd);
+  gdb_bfd_ref_ptr obfd (create_gcore_bfd (recfilename));
+
+  /* Arrange to remove the output file on failure.  */
+  gdb::unlinker unlink_file (recfilename);
 
   /* Save the current record entry to "cur_record_full_list".  */
   cur_record_full_list = record_full_list;
@@ -2615,20 +2605,20 @@ record_full_save (struct target_ops *self, const char *recfilename)
       }
 
   /* Make the new bfd section.  */
-  osec = bfd_make_section_anyway_with_flags (obfd, "precord",
+  osec = bfd_make_section_anyway_with_flags (obfd.get (), "precord",
                                              SEC_HAS_CONTENTS
                                              | SEC_READONLY);
   if (osec == NULL)
     error (_("Failed to create 'precord' section for corefile %s: %s"),
 	   recfilename,
            bfd_errmsg (bfd_get_error ()));
-  bfd_set_section_size (obfd, osec, save_size);
-  bfd_set_section_vma (obfd, osec, 0);
-  bfd_set_section_alignment (obfd, osec, 0);
-  bfd_section_lma (obfd, osec) = 0;
+  bfd_set_section_size (obfd.get (), osec, save_size);
+  bfd_set_section_vma (obfd.get (), osec, 0);
+  bfd_set_section_alignment (obfd.get (), osec, 0);
+  bfd_section_lma (obfd.get (), osec) = 0;
 
   /* Save corefile state.  */
-  write_gcore_file (obfd);
+  write_gcore_file (obfd.get ());
 
   /* Write out the record log.  */
   /* Write the magic code.  */
@@ -2638,7 +2628,7 @@ record_full_save (struct target_ops *self, const char *recfilename)
 			"  Writing 4-byte magic cookie "
 			"RECORD_FULL_FILE_MAGIC (0x%s)\n",
 		      phex_nz (magic, 4));
-  bfdcore_write (obfd, osec, &magic, sizeof (magic), &bfd_offset);
+  bfdcore_write (obfd.get (), osec, &magic, sizeof (magic), &bfd_offset);
 
   /* Save the entries to recfd and forward execute to the end of
      record list.  */
@@ -2653,7 +2643,7 @@ record_full_save (struct target_ops *self, const char *recfilename)
           uint64_t addr;
 
 	  type = record_full_list->type;
-          bfdcore_write (obfd, osec, &type, sizeof (type), &bfd_offset);
+          bfdcore_write (obfd.get (), osec, &type, sizeof (type), &bfd_offset);
 
           switch (record_full_list->type)
             {
@@ -2668,11 +2658,11 @@ record_full_save (struct target_ops *self, const char *recfilename)
 
               /* Write regnum.  */
               regnum = netorder32 (record_full_list->u.reg.num);
-              bfdcore_write (obfd, osec, &regnum,
+              bfdcore_write (obfd.get (), osec, &regnum,
 			     sizeof (regnum), &bfd_offset);
 
               /* Write regval.  */
-              bfdcore_write (obfd, osec,
+              bfdcore_write (obfd.get (), osec,
 			     record_full_get_loc (record_full_list),
 			     record_full_list->u.reg.len, &bfd_offset);
               break;
@@ -2690,15 +2680,16 @@ record_full_save (struct target_ops *self, const char *recfilename)
 
 	      /* Write memlen.  */
 	      len = netorder32 (record_full_list->u.mem.len);
-	      bfdcore_write (obfd, osec, &len, sizeof (len), &bfd_offset);
+	      bfdcore_write (obfd.get (), osec, &len, sizeof (len),
+			     &bfd_offset);
 
 	      /* Write memaddr.  */
 	      addr = netorder64 (record_full_list->u.mem.addr);
-	      bfdcore_write (obfd, osec, &addr, 
+	      bfdcore_write (obfd.get (), osec, &addr, 
 			     sizeof (addr), &bfd_offset);
 
 	      /* Write memval.  */
-	      bfdcore_write (obfd, osec,
+	      bfdcore_write (obfd.get (), osec,
 			     record_full_get_loc (record_full_list),
 			     record_full_list->u.mem.len, &bfd_offset);
               break;
@@ -2712,12 +2703,12 @@ record_full_save (struct target_ops *self, const char *recfilename)
 				      (unsigned long) sizeof (count));
 		/* Write signal value.  */
 		signal = netorder32 (record_full_list->u.end.sigval);
-		bfdcore_write (obfd, osec, &signal,
+		bfdcore_write (obfd.get (), osec, &signal,
 			       sizeof (signal), &bfd_offset);
 
 		/* Write insn count.  */
 		count = netorder32 (record_full_list->u.end.insn_num);
-		bfdcore_write (obfd, osec, &count,
+		bfdcore_write (obfd.get (), osec, &count,
 			       sizeof (count), &bfd_offset);
                 break;
             }
@@ -2746,8 +2737,7 @@ record_full_save (struct target_ops *self, const char *recfilename)
     }
 
   do_cleanups (set_cleanups);
-  gdb_bfd_unref (obfd);
-  discard_cleanups (old_cleanups);
+  unlink_file.keep ();
 
   /* Succeeded.  */
   printf_filtered (_("Saved core file %s with execution log.\n"),
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 2/8] Use class to manage BFD reference counts
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
  2016-11-29  5:06 ` [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full Tom Tromey
  2016-11-29  5:06 ` [RFA 5/8] Add value_freer Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 13:05   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 1/8] Add gdb_ref_ptr.h Tom Tromey
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This introduces a new specialization of gdb::ref_ptr that can be used
to manage BFD reference counts.  Then it changes most places in gdb to
use this new class, rather than explicit reference-counting or
cleanups.  This patch removes make_cleanup_bfd_unref.

If you look you will see a couple of spots using "release" where a use
of gdb_bfd_ref_ptr would be cleaner.  These will be fixed in the next
patch.

I think this patch fixes some latent bugs.  For example, it seems to
me that previously objfpy_add_separate_debug_file leaked a BFD.

I'm not 100% certain that the macho_symfile_read_all_oso change is
correct.  The existing code here is hard for me to follow.  One goal
of this sort of automated reference counting, though, is to make it
more difficult to make logic errors; so hopefully the code is clear
now.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* windows-tdep.c (windows_xfer_shared_library): Update.
	* windows-nat.c (windows_make_so): Update.
	* utils.h (make_cleanup_bfd_unref): Remove.
	* utils.c (do_bfd_close_cleanup, make_cleanup_bfd_unref): Remove.
	* symfile.h (symfile_bfd_open)
	(find_separate_debug_file_in_section): Return gdb_bfd_ref_ptr.
	* symfile.c (read_symbols, symbol_file_add)
	(separate_debug_file_exists): Update.
	(symfile_bfd_open): Return gdb_bfd_ref_ptr.
	(generic_load, reread_symbols): Update.
	* symfile-mem.c (symbol_file_add_from_memory): Update.
	* spu-linux-nat.c (spu_bfd_open): Return gdb_bfd_ref_ptr.
	(spu_symbol_file_add_from_memory): Update.
	* solist.h (struct target_so_ops) <bfd_open>: Return
	gdb_bfd_ref_ptr.
	(solib_bfd_fopen, solib_bfd_open): Return gdb_bfd_ref_ptr.
	* solib.c (solib_bfd_fopen, solib_bfd_open): Return
	gdb_bfd_ref_ptr.
	(solib_map_sections, reload_shared_libraries_1): Update.
	* solib-svr4.c (enable_break): Update.
	* solib-spu.c (spu_bfd_fopen): Return gdb_bfd_ref_ptr.
	* solib-frv.c (enable_break2): Update.
	* solib-dsbt.c (enable_break): Update.
	* solib-darwin.c (gdb_bfd_mach_o_fat_extract): Return
	gdb_bfd_ref_ptr.
	(darwin_solib_get_all_image_info_addr_at_init): Update.
	(darwin_bfd_open): Return gdb_bfd_ref_ptr.
	* solib-aix.c (solib_aix_bfd_open): Return gdb_bfd_ref_ptr.
	* record-full.c (record_full_save): Update.
	* python/py-objfile.c (objfpy_add_separate_debug_file): Update.
	* procfs.c (insert_dbx_link_bpt_in_file): Update.
	* minidebug.c (find_separate_debug_file_in_section): Return
	gdb_bfd_ref_ptr.
	* machoread.c (macho_add_oso_symfile): Change abfd to
	gdb_bfd_ref_ptr.
	(macho_symfile_read_all_oso): Update.
	(macho_check_dsym): Return gdb_bfd_ref_ptr.
	(macho_symfile_read): Update.
	* jit.c (bfd_open_from_target_memory): Return gdb_bfd_ref_ptr.
	(jit_bfd_try_read_symtab): Update.
	* gdb_bfd.h (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
	(gdb_bfd_openw, gdb_bfd_openr_iovec)
	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
	gdb_bfd_ref_ptr.
	(gdb_bfd_ref_policy): New struct.
	(gdb_bfd_ref_ptr): New typedef.
	* gdb_bfd.c (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
	(gdb_bfd_openw, gdb_bfd_openr_iovec)
	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
	gdb_bfd_ref_ptr.
	* gcore.h (create_gcore_bfd): Return gdb_bfd_ref_ptr.
	* gcore.c (create_gcore_bfd): Return gdb_bfd_ref_ptr.
	(gcore_command): Update.
	* exec.c (exec_file_attach): Update.
	* elfread.c (elf_symfile_read): Update.
	* dwarf2read.c (dwarf2_get_dwz_file): Update.
	(try_open_dwop_file, open_dwo_file): Return gdb_bfd_ref_ptr.
	(open_and_init_dwo_file): Update.
	(open_dwp_file): Return gdb_bfd_ref_ptr.
	(open_and_init_dwp_file): Update.
	* corelow.c (core_open): Update.
	* compile/compile-object-load.c (compile_object_load): Update.
	* common/gdb_ref_ptr.h (ref_ptr::operator->): New operator.
	* coffread.c (coff_symfile_read): Update.
	* cli/cli-dump.c (bfd_openr_or_error, bfd_openw_or_error): Return
	gdb_bfd_ref_ptr.  Rename.
	(dump_bfd_file, restore_command): Update.
	* build-id.h (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
	* build-id.c (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
	(find_separate_debug_file_by_buildid): Update.
---
 gdb/ChangeLog                     | 73 ++++++++++++++++++++++++++++++++
 gdb/build-id.c                    | 30 +++++--------
 gdb/build-id.h                    |  6 ++-
 gdb/cli/cli-dump.c                | 55 +++++++++++-------------
 gdb/coffread.c                    |  6 +--
 gdb/common/gdb_ref_ptr.h          |  6 +++
 gdb/compile/compile-object-load.c | 20 ++++-----
 gdb/corelow.c                     | 14 +++----
 gdb/dwarf2read.c                  | 77 +++++++++++++++-------------------
 gdb/elfread.c                     | 17 ++++----
 gdb/exec.c                        | 12 ++++--
 gdb/gcore.c                       | 12 +++---
 gdb/gcore.h                       |  4 +-
 gdb/gdb_bfd.c                     | 34 +++++++--------
 gdb/gdb_bfd.h                     | 81 +++++++++++++++++++++--------------
 gdb/jit.c                         | 30 ++++++-------
 gdb/machoread.c                   | 88 +++++++++++++++------------------------
 gdb/minidebug.c                   | 16 ++++---
 gdb/procfs.c                      | 11 ++---
 gdb/python/py-objfile.c           |  4 +-
 gdb/record-full.c                 |  2 +-
 gdb/solib-aix.c                   | 74 +++++++++++++-------------------
 gdb/solib-darwin.c                | 67 +++++++++++------------------
 gdb/solib-dsbt.c                  | 23 +++++-----
 gdb/solib-frv.c                   | 28 +++++--------
 gdb/solib-spu.c                   | 37 ++++++++--------
 gdb/solib-svr4.c                  | 31 +++++++-------
 gdb/solib.c                       | 50 ++++++++++------------
 gdb/solist.h                      |  7 ++--
 gdb/spu-linux-nat.c               | 40 ++++++++----------
 gdb/symfile-mem.c                 |  7 ++--
 gdb/symfile.c                     | 81 +++++++++++++----------------------
 gdb/symfile.h                     |  5 ++-
 gdb/utils.c                       | 12 ------
 gdb/utils.h                       |  2 -
 gdb/windows-nat.c                 | 19 ++++-----
 gdb/windows-tdep.c                |  6 +--
 37 files changed, 516 insertions(+), 571 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f455f7f..ce21840 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,78 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* windows-tdep.c (windows_xfer_shared_library): Update.
+	* windows-nat.c (windows_make_so): Update.
+	* utils.h (make_cleanup_bfd_unref): Remove.
+	* utils.c (do_bfd_close_cleanup, make_cleanup_bfd_unref): Remove.
+	* symfile.h (symfile_bfd_open)
+	(find_separate_debug_file_in_section): Return gdb_bfd_ref_ptr.
+	* symfile.c (read_symbols, symbol_file_add)
+	(separate_debug_file_exists): Update.
+	(symfile_bfd_open): Return gdb_bfd_ref_ptr.
+	(generic_load, reread_symbols): Update.
+	* symfile-mem.c (symbol_file_add_from_memory): Update.
+	* spu-linux-nat.c (spu_bfd_open): Return gdb_bfd_ref_ptr.
+	(spu_symbol_file_add_from_memory): Update.
+	* solist.h (struct target_so_ops) <bfd_open>: Return
+	gdb_bfd_ref_ptr.
+	(solib_bfd_fopen, solib_bfd_open): Return gdb_bfd_ref_ptr.
+	* solib.c (solib_bfd_fopen, solib_bfd_open): Return
+	gdb_bfd_ref_ptr.
+	(solib_map_sections, reload_shared_libraries_1): Update.
+	* solib-svr4.c (enable_break): Update.
+	* solib-spu.c (spu_bfd_fopen): Return gdb_bfd_ref_ptr.
+	* solib-frv.c (enable_break2): Update.
+	* solib-dsbt.c (enable_break): Update.
+	* solib-darwin.c (gdb_bfd_mach_o_fat_extract): Return
+	gdb_bfd_ref_ptr.
+	(darwin_solib_get_all_image_info_addr_at_init): Update.
+	(darwin_bfd_open): Return gdb_bfd_ref_ptr.
+	* solib-aix.c (solib_aix_bfd_open): Return gdb_bfd_ref_ptr.
+	* record-full.c (record_full_save): Update.
+	* python/py-objfile.c (objfpy_add_separate_debug_file): Update.
+	* procfs.c (insert_dbx_link_bpt_in_file): Update.
+	* minidebug.c (find_separate_debug_file_in_section): Return
+	gdb_bfd_ref_ptr.
+	* machoread.c (macho_add_oso_symfile): Change abfd to
+	gdb_bfd_ref_ptr.
+	(macho_symfile_read_all_oso): Update.
+	(macho_check_dsym): Return gdb_bfd_ref_ptr.
+	(macho_symfile_read): Update.
+	* jit.c (bfd_open_from_target_memory): Return gdb_bfd_ref_ptr.
+	(jit_bfd_try_read_symtab): Update.
+	* gdb_bfd.h (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
+	(gdb_bfd_openw, gdb_bfd_openr_iovec)
+	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
+	gdb_bfd_ref_ptr.
+	(gdb_bfd_ref_policy): New struct.
+	(gdb_bfd_ref_ptr): New typedef.
+	* gdb_bfd.c (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
+	(gdb_bfd_openw, gdb_bfd_openr_iovec)
+	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
+	gdb_bfd_ref_ptr.
+	* gcore.h (create_gcore_bfd): Return gdb_bfd_ref_ptr.
+	* gcore.c (create_gcore_bfd): Return gdb_bfd_ref_ptr.
+	(gcore_command): Update.
+	* exec.c (exec_file_attach): Update.
+	* elfread.c (elf_symfile_read): Update.
+	* dwarf2read.c (dwarf2_get_dwz_file): Update.
+	(try_open_dwop_file, open_dwo_file): Return gdb_bfd_ref_ptr.
+	(open_and_init_dwo_file): Update.
+	(open_dwp_file): Return gdb_bfd_ref_ptr.
+	(open_and_init_dwp_file): Update.
+	* corelow.c (core_open): Update.
+	* compile/compile-object-load.c (compile_object_load): Update.
+	* common/gdb_ref_ptr.h (ref_ptr::operator->): New operator.
+	* coffread.c (coff_symfile_read): Update.
+	* cli/cli-dump.c (bfd_openr_or_error, bfd_openw_or_error): Return
+	gdb_bfd_ref_ptr.  Rename.
+	(dump_bfd_file, restore_command): Update.
+	* build-id.h (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
+	* build-id.c (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
+	(find_separate_debug_file_by_buildid): Update.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* common/gdb_ref_ptr.h: New file.
 	* python/py-ref.h (struct gdbpy_ref_policy): New.
 	(gdbpy_ref): Now a typedef.
diff --git a/gdb/build-id.c b/gdb/build-id.c
index 886f2d7..029cb4d 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -67,14 +67,14 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
 
 /* See build-id.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 {
   char *link, *debugdir;
   VEC (char_ptr) *debugdir_vec;
   struct cleanup *back_to;
   int ix;
-  bfd *abfd = NULL;
+  gdb_bfd_ref_ptr abfd;
   int alloc_len;
 
   /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
@@ -127,11 +127,10 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
       if (abfd == NULL)
 	continue;
 
-      if (build_id_verify (abfd, build_id_len, build_id))
+      if (build_id_verify (abfd.get(), build_id_len, build_id))
 	break;
 
-      gdb_bfd_unref (abfd);
-      abfd = NULL;
+      abfd.release ();
     }
 
   do_cleanups (back_to);
@@ -148,25 +147,16 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
   build_id = build_id_bfd_get (objfile->obfd);
   if (build_id != NULL)
     {
-      bfd *abfd;
-
-      abfd = build_id_to_debug_bfd (build_id->size, build_id->data);
+      gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
+						   build_id->data));
       /* Prevent looping on a stripped .debug file.  */
       if (abfd != NULL
-	  && filename_cmp (bfd_get_filename (abfd),
+	  && filename_cmp (bfd_get_filename (abfd.get ()),
 			   objfile_name (objfile)) == 0)
-        {
-	  warning (_("\"%s\": separate debug info file has no debug info"),
-		   bfd_get_filename (abfd));
-	  gdb_bfd_unref (abfd);
-	}
+	warning (_("\"%s\": separate debug info file has no debug info"),
+		 bfd_get_filename (abfd.get ()));
       else if (abfd != NULL)
-	{
-	  char *result = xstrdup (bfd_get_filename (abfd));
-
-	  gdb_bfd_unref (abfd);
-	  return result;
-	}
+	return xstrdup (bfd_get_filename (abfd.get ()));
     }
   return NULL;
 }
diff --git a/gdb/build-id.h b/gdb/build-id.h
index ddf0765..6c37dee 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -20,6 +20,8 @@
 #ifndef BUILD_ID_H
 #define BUILD_ID_H
 
+#include "gdb_bfd.h"
+
 /* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
 
 extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
@@ -35,8 +37,8 @@ extern int build_id_verify (bfd *abfd,
    return NULL.  The returned reference to the BFD must be released by
    the caller.  */
 
-extern bfd *build_id_to_debug_bfd (size_t build_id_len,
-				   const bfd_byte *build_id);
+extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
+					      const bfd_byte *build_id);
 
 /* Find the separate debug file for OBJFILE, by using the build-id
    associated with OBJFILE's BFD.  If successful, returns a malloc'd
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 781c638..ace721a 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -103,45 +103,40 @@ fopen_with_cleanup (const char *filename, const char *mode)
   return file;
 }
 
-static bfd *
-bfd_openr_with_cleanup (const char *filename, const char *target)
+static gdb_bfd_ref_ptr
+bfd_openr_or_error (const char *filename, const char *target)
 {
-  bfd *ibfd;
-
-  ibfd = gdb_bfd_openr (filename, target);
+  gdb_bfd_ref_ptr ibfd (gdb_bfd_openr (filename, target));
   if (ibfd == NULL)
-    error (_("Failed to open %s: %s."), filename, 
+    error (_("Failed to open %s: %s."), filename,
 	   bfd_errmsg (bfd_get_error ()));
 
-  make_cleanup_bfd_unref (ibfd);
-  if (!bfd_check_format (ibfd, bfd_object))
+  if (!bfd_check_format (ibfd.get (), bfd_object))
     error (_("'%s' is not a recognized file format."), filename);
 
   return ibfd;
 }
 
-static bfd *
-bfd_openw_with_cleanup (const char *filename, const char *target,
-			const char *mode)
+static gdb_bfd_ref_ptr
+bfd_openw_or_error (const char *filename, const char *target, const char *mode)
 {
-  bfd *obfd;
+  gdb_bfd_ref_ptr obfd;
 
   if (*mode == 'w')	/* Write: create new file */
     {
       obfd = gdb_bfd_openw (filename, target);
       if (obfd == NULL)
-	error (_("Failed to open %s: %s."), filename, 
+	error (_("Failed to open %s: %s."), filename,
 	       bfd_errmsg (bfd_get_error ()));
-      make_cleanup_bfd_unref (obfd);
-      if (!bfd_set_format (obfd, bfd_object))
-	error (_("bfd_openw_with_cleanup: %s."), bfd_errmsg (bfd_get_error ()));
+      if (!bfd_set_format (obfd.get (), bfd_object))
+	error (_("bfd_openw_or_error: %s."), bfd_errmsg (bfd_get_error ()));
     }
   else if (*mode == 'a')	/* Append to existing file.  */
     {	/* FIXME -- doesn't work...  */
       error (_("bfd_openw does not work with append."));
     }
   else
-    error (_("bfd_openw_with_cleanup: unknown mode %s."), mode);
+    error (_("bfd_openw_or_error: unknown mode %s."), mode);
 
   return obfd;
 }
@@ -187,20 +182,19 @@ dump_bfd_file (const char *filename, const char *mode,
 	       const char *target, CORE_ADDR vaddr, 
 	       const bfd_byte *buf, ULONGEST len)
 {
-  bfd *obfd;
   asection *osection;
 
-  obfd = bfd_openw_with_cleanup (filename, target, mode);
-  osection = bfd_make_section_anyway (obfd, ".newsec");
-  bfd_set_section_size (obfd, osection, len);
-  bfd_set_section_vma (obfd, osection, vaddr);
-  bfd_set_section_alignment (obfd, osection, 0);
-  bfd_set_section_flags (obfd, osection, (SEC_HAS_CONTENTS
-					  | SEC_ALLOC
-					  | SEC_LOAD));
+  gdb_bfd_ref_ptr obfd (bfd_openw_or_error (filename, target, mode));
+  osection = bfd_make_section_anyway (obfd.get (), ".newsec");
+  bfd_set_section_size (obfd.get (), osection, len);
+  bfd_set_section_vma (obfd.get (), osection, vaddr);
+  bfd_set_section_alignment (obfd.get (), osection, 0);
+  bfd_set_section_flags (obfd.get (), osection, (SEC_HAS_CONTENTS
+						 | SEC_ALLOC
+						 | SEC_LOAD));
   osection->entsize = 0;
-  if (!bfd_set_section_contents (obfd, osection, buf, 0, len))
-    warning (_("writing dump file '%s' (%s)"), filename, 
+  if (!bfd_set_section_contents (obfd.get (), osection, buf, 0, len))
+    warning (_("writing dump file '%s' (%s)"), filename,
 	     bfd_errmsg (bfd_get_error ()));
 }
 
@@ -624,12 +618,11 @@ restore_command (char *args_in, int from_tty)
   else
     {
       /* Open the file for loading.  */
-      ibfd = bfd_openr_with_cleanup (filename, NULL);
+      gdb_bfd_ref_ptr ibfd (bfd_openr_or_error (filename, NULL));
 
       /* Process the sections.  */
-      bfd_map_over_sections (ibfd, restore_section_callback, &data);
+      bfd_map_over_sections (ibfd.get (), restore_section_callback, &data);
     }
-  return;
 }
 
 static void
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 501e901..db32a92 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -742,10 +742,10 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 
       if (debugfile)
 	{
-	  bfd *abfd = symfile_bfd_open (debugfile);
+	  gdb_bfd_ref_ptr abfd (symfile_bfd_open (debugfile));
 
-	  make_cleanup_bfd_unref (abfd);
-	  symbol_file_add_separate (abfd, debugfile, symfile_flags, objfile);
+	  symbol_file_add_separate (abfd.get (), debugfile, symfile_flags,
+				    objfile);
 	}
     }
 
diff --git a/gdb/common/gdb_ref_ptr.h b/gdb/common/gdb_ref_ptr.h
index cc8ba94..989af97 100644
--- a/gdb/common/gdb_ref_ptr.h
+++ b/gdb/common/gdb_ref_ptr.h
@@ -137,6 +137,12 @@ class ref_ptr
     return result;
   }
 
+  /* Let users refer to members of the underlying pointer.  */
+  T *operator-> () const
+  {
+    return m_obj;
+  }
+
  private:
 
   T *m_obj;
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index c08aa2b..7351148 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -612,7 +612,6 @@ compile_object_load (const compile_file_names &file_names,
 		     enum compile_i_scope_types scope, void *scope_data)
 {
   struct cleanup *cleanups, *cleanups_free_objfile;
-  bfd *abfd;
   struct setup_sections_data setup_sections_data;
   CORE_ADDR addr, regs_addr, out_value_addr = 0;
   struct symbol *func_sym;
@@ -634,17 +633,16 @@ compile_object_load (const compile_file_names &file_names,
   filename = tilde_expand (file_names.object_file ());
   cleanups = make_cleanup (xfree, filename);
 
-  abfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (filename, gnutarget, -1));
   if (abfd == NULL)
     error (_("\"%s\": could not open as compiled module: %s"),
           filename, bfd_errmsg (bfd_get_error ()));
-  make_cleanup_bfd_unref (abfd);
 
-  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
+  if (!bfd_check_format_matches (abfd.get (), bfd_object, &matching))
     error (_("\"%s\": not in loadable format: %s"),
           filename, gdb_bfd_errmsg (bfd_get_error (), matching));
 
-  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0)
+  if ((bfd_get_file_flags (abfd.get ()) & (EXEC_P | DYNAMIC)) != 0)
     error (_("\"%s\": not in object format."), filename);
 
   setup_sections_data.last_size = 0;
@@ -653,17 +651,17 @@ compile_object_load (const compile_file_names &file_names,
   setup_sections_data.last_max_alignment = 1;
   setup_sections_data.munmap_list_headp = &munmap_list_head;
   make_cleanup (munmap_listp_free_cleanup, &munmap_list_head);
-  bfd_map_over_sections (abfd, setup_sections, &setup_sections_data);
-  setup_sections (abfd, NULL, &setup_sections_data);
+  bfd_map_over_sections (abfd.get (), setup_sections, &setup_sections_data);
+  setup_sections (abfd.get (), NULL, &setup_sections_data);
 
-  storage_needed = bfd_get_symtab_upper_bound (abfd);
+  storage_needed = bfd_get_symtab_upper_bound (abfd.get ());
   if (storage_needed < 0)
     error (_("Cannot read symbols of compiled module \"%s\": %s"),
           filename, bfd_errmsg (bfd_get_error ()));
 
   /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in
      "Reading symbols from ..." message for automatically generated file.  */
-  objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL);
+  objfile = symbol_file_add_from_bfd (abfd.get (), filename, 0, NULL, 0, NULL);
   cleanups_free_objfile = make_cleanup_free_objfile (objfile);
 
   func_sym = lookup_global_symbol_from_objfile (objfile,
@@ -712,7 +710,7 @@ compile_object_load (const compile_file_names &file_names,
      called from default_symfile_relocate.  */
   symbol_table = (asymbol **) obstack_alloc (&objfile->objfile_obstack,
 					     storage_needed);
-  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+  number_of_symbols = bfd_canonicalize_symtab (abfd.get (), symbol_table);
   if (number_of_symbols < 0)
     error (_("Cannot parse symbols of compiled module \"%s\": %s"),
           filename, bfd_errmsg (bfd_get_error ()));
@@ -771,7 +769,7 @@ compile_object_load (const compile_file_names &file_names,
   if (missing_symbols)
     error (_("%ld symbols were missing, cannot continue."), missing_symbols);
 
-  bfd_map_over_sections (abfd, copy_sections, symbol_table);
+  bfd_map_over_sections (abfd.get (), copy_sections, symbol_table);
 
   regs_type = get_regs_type (func_sym, objfile);
   if (regs_type == NULL)
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 376b7c9..04d2b87 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -275,7 +275,6 @@ core_open (const char *arg, int from_tty)
   int siggy;
   struct cleanup *old_chain;
   char *temp;
-  bfd *temp_bfd;
   int scratch_chan;
   int flags;
   char *filename;
@@ -310,20 +309,19 @@ core_open (const char *arg, int from_tty)
   if (scratch_chan < 0)
     perror_with_name (filename);
 
-  temp_bfd = gdb_bfd_fopen (filename, gnutarget, 
-			    write_files ? FOPEN_RUB : FOPEN_RB,
-			    scratch_chan);
+  gdb_bfd_ref_ptr temp_bfd (gdb_bfd_fopen (filename, gnutarget, 
+					   write_files ? FOPEN_RUB : FOPEN_RB,
+					   scratch_chan));
   if (temp_bfd == NULL)
     perror_with_name (filename);
 
-  if (!bfd_check_format (temp_bfd, bfd_core)
-      && !gdb_check_format (temp_bfd))
+  if (!bfd_check_format (temp_bfd.get (), bfd_core)
+      && !gdb_check_format (temp_bfd.get ()))
     {
       /* Do it after the err msg */
       /* 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_unref (temp_bfd);
       error (_("\"%s\" is not a core dump: %s"),
 	     filename, bfd_errmsg (bfd_get_error ()));
     }
@@ -333,7 +331,7 @@ core_open (const char *arg, int from_tty)
 
   do_cleanups (old_chain);
   unpush_target (&core_ops);
-  core_bfd = temp_bfd;
+  core_bfd = temp_bfd.release ();
   old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/);
 
   core_gdbarch = gdbarch_from_bfd (core_bfd);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index b088dea..0780ae0 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2476,7 +2476,6 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
 static struct dwz_file *
 dwarf2_get_dwz_file (void)
 {
-  bfd *dwz_bfd;
   char *data;
   struct cleanup *cleanup;
   const char *filename;
@@ -2520,14 +2519,11 @@ dwarf2_get_dwz_file (void)
 
   /* First try the file name given in the section.  If that doesn't
      work, try to use the build-id instead.  */
-  dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget, -1));
   if (dwz_bfd != NULL)
     {
-      if (!build_id_verify (dwz_bfd, buildid_len, buildid))
-	{
-	  gdb_bfd_unref (dwz_bfd);
-	  dwz_bfd = NULL;
-	}
+      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+	dwz_bfd.release ();
     }
 
   if (dwz_bfd == NULL)
@@ -2539,13 +2535,13 @@ dwarf2_get_dwz_file (void)
 
   result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
 			   struct dwz_file);
-  result->dwz_bfd = dwz_bfd;
+  result->dwz_bfd = dwz_bfd.release ();
 
-  bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result);
+  bfd_map_over_sections (result->dwz_bfd, locate_dwz_sections, result);
 
   do_cleanups (cleanup);
 
-  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, result->dwz_bfd);
   dwarf2_per_objfile->dwz_file = result;
   return result;
 }
@@ -10448,10 +10444,9 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir,
    If unable to find/open the file, return NULL.
    NOTE: This function is derived from symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
 {
-  bfd *sym_bfd;
   int desc, flags;
   char *absolute_name;
   /* Blech.  OPF_TRY_CWD_FIRST also disables searching the path list if
@@ -10478,25 +10473,22 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
 		O_RDONLY | O_BINARY, &absolute_name);
   xfree (search_path);
   if (desc < 0)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
-  sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc));
   xfree (absolute_name);
   if (sym_bfd == NULL)
-    return NULL;
-  bfd_set_cacheable (sym_bfd, 1);
+    return gdb_bfd_ref_ptr ();
+  bfd_set_cacheable (sym_bfd.get (), 1);
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
-    {
-      gdb_bfd_unref (sym_bfd); /* This also closes desc.  */
-      return NULL;
-    }
+  if (!bfd_check_format (sym_bfd.get (), bfd_object))
+    return gdb_bfd_ref_ptr ();
 
   /* Success.  Record the bfd as having been included by the objfile's bfd.
      This is important because things like demangled_names_hash lives in the
      objfile's per_bfd space and may have references to things like symbol
      names that live in the DWO/DWP file's per_bfd space.  PR 16426.  */
-  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd.get ());
 
   return sym_bfd;
 }
@@ -10508,11 +10500,9 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
    Upon success, the canonicalized path of the file is stored in the bfd,
    same as symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 open_dwo_file (const char *file_name, const char *comp_dir)
 {
-  bfd *abfd;
-
   if (IS_ABSOLUTE_PATH (file_name))
     return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/);
 
@@ -10525,7 +10515,8 @@ open_dwo_file (const char *file_name, const char *comp_dir)
 
       /* NOTE: If comp_dir is a relative path, this will also try the
 	 search path, which seems useful.  */
-      abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/);
+      gdb_bfd_ref_ptr abfd (try_open_dwop_file (path_to_try, 0 /*is_dwp*/,
+						1 /*search_cwd*/));
       xfree (path_to_try);
       if (abfd != NULL)
 	return abfd;
@@ -10535,7 +10526,7 @@ open_dwo_file (const char *file_name, const char *comp_dir)
      is a list of paths.  */
 
   if (*debug_file_directory == '\0')
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
   return try_open_dwop_file (file_name, 0 /*is_dwp*/, 1 /*search_cwd*/);
 }
@@ -10611,10 +10602,9 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwo_file *dwo_file;
-  bfd *dbfd;
   struct cleanup *cleanups;
 
-  dbfd = open_dwo_file (dwo_name, comp_dir);
+  gdb_bfd_ref_ptr dbfd (open_dwo_file (dwo_name, comp_dir));
   if (dbfd == NULL)
     {
       if (dwarf_read_debug)
@@ -10624,11 +10614,12 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
   dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
   dwo_file->dwo_name = dwo_name;
   dwo_file->comp_dir = comp_dir;
-  dwo_file->dbfd = dbfd;
+  dwo_file->dbfd = dbfd.release ();
 
   cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
 
-  bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections);
+  bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
+			 &dwo_file->sections);
 
   dwo_file->cu = create_dwo_cu (dwo_file);
 
@@ -10780,12 +10771,11 @@ allocate_dwp_loaded_cutus_table (struct objfile *objfile)
    Upon success, the canonicalized path of the file is stored in the bfd,
    same as symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 open_dwp_file (const char *file_name)
 {
-  bfd *abfd;
-
-  abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/);
+  gdb_bfd_ref_ptr abfd (try_open_dwop_file (file_name, 1 /*is_dwp*/,
+					    1 /*search_cwd*/));
   if (abfd != NULL)
     return abfd;
 
@@ -10806,7 +10796,7 @@ open_dwp_file (const char *file_name)
 				 0 /*search_cwd*/);
     }
 
-  return NULL;
+  return gdb_bfd_ref_ptr ();
 }
 
 /* Initialize the use of the DWP file for the current objfile.
@@ -10819,7 +10809,6 @@ open_and_init_dwp_file (void)
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwp_file *dwp_file;
   char *dwp_name;
-  bfd *dbfd;
   struct cleanup *cleanups = make_cleanup (null_cleanup, 0);
 
   /* Try to find first .dwp for the binary file before any symbolic links
@@ -10841,7 +10830,7 @@ open_and_init_dwp_file (void)
     dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
   make_cleanup (xfree, dwp_name);
 
-  dbfd = open_dwp_file (dwp_name);
+  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name));
   if (dbfd == NULL
       && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
     {
@@ -10859,17 +10848,18 @@ open_and_init_dwp_file (void)
       return NULL;
     }
   dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
-  dwp_file->name = bfd_get_filename (dbfd);
-  dwp_file->dbfd = dbfd;
+  dwp_file->name = bfd_get_filename (dbfd.get ());
+  dwp_file->dbfd = dbfd.release ();
   do_cleanups (cleanups);
 
   /* +1: section 0 is unused */
-  dwp_file->num_sections = bfd_count_sections (dbfd) + 1;
+  dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1;
   dwp_file->elf_sections =
     OBSTACK_CALLOC (&objfile->objfile_obstack,
 		    dwp_file->num_sections, asection *);
 
-  bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
+  bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_common_dwp_sections,
+			 dwp_file);
 
   dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
 
@@ -10889,7 +10879,8 @@ open_and_init_dwp_file (void)
   dwp_file->version = dwp_file->cus->version;
 
   if (dwp_file->version == 2)
-    bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
+    bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_v2_dwp_sections,
+			   dwp_file);
 
   dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
   dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
diff --git a/gdb/elfread.c b/gdb/elfread.c
index c6d0fdb..7e2358b 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1265,21 +1265,18 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 	   && objfile->separate_debug_objfile == NULL
 	   && objfile->separate_debug_objfile_backlink == NULL)
     {
-      char *debugfile;
-
-      debugfile = find_separate_debug_file_by_buildid (objfile);
+      gdb::unique_xmalloc_ptr<char> debugfile
+	(find_separate_debug_file_by_buildid (objfile));
 
       if (debugfile == NULL)
-	debugfile = find_separate_debug_file_by_debuglink (objfile);
+	debugfile.reset (find_separate_debug_file_by_debuglink (objfile));
 
-      if (debugfile)
+      if (debugfile != NULL)
 	{
-	  struct cleanup *cleanup = make_cleanup (xfree, debugfile);
-	  bfd *abfd = symfile_bfd_open (debugfile);
+	  gdb_bfd_ref_ptr abfd (symfile_bfd_open (debugfile.get ()));
 
-	  make_cleanup_bfd_unref (abfd);
-	  symbol_file_add_separate (abfd, debugfile, symfile_flags, objfile);
-	  do_cleanups (cleanup);
+	  symbol_file_add_separate (abfd.get (), debugfile.get (),
+				    symfile_flags, objfile);
 	}
     }
 }
diff --git a/gdb/exec.c b/gdb/exec.c
index eeca005..875a675 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -258,7 +258,9 @@ exec_file_attach (const char *filename, int from_tty)
      this at the end of the function; but acquiring it now lets the
      BFD cache return it if this call refers to the same file.  */
   gdb_bfd_ref (exec_bfd);
-  cleanups = make_cleanup_bfd_unref (exec_bfd);
+  gdb_bfd_ref_ptr exec_bfd_holder (exec_bfd);
+
+  cleanups = make_cleanup (null_cleanup, NULL);
 
   /* Remove any previous exec file.  */
   exec_close ();
@@ -333,11 +335,13 @@ exec_file_attach (const char *filename, int from_tty)
 	  make_cleanup (xfree, canonical_pathname);
 	}
 
+      gdb_bfd_ref_ptr temp;
       if (write_files && !load_via_target)
-	exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget,
-				  FOPEN_RUB, scratch_chan);
+	temp = gdb_bfd_fopen (canonical_pathname, gnutarget,
+			      FOPEN_RUB, scratch_chan);
       else
-	exec_bfd = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
+	temp = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
+      exec_bfd = temp.release ();
 
       if (!exec_bfd)
 	{
diff --git a/gdb/gcore.c b/gdb/gcore.c
index cb4d703..0b05cf9 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -49,15 +49,15 @@ static int gcore_memory_sections (bfd *);
 /* create_gcore_bfd -- helper for gcore_command (exported).
    Open a new bfd core file for output, and return the handle.  */
 
-bfd *
+gdb_bfd_ref_ptr
 create_gcore_bfd (const char *filename)
 {
-  bfd *obfd = gdb_bfd_openw (filename, default_gcore_target ());
+  gdb_bfd_ref_ptr obfd (gdb_bfd_openw (filename, default_gcore_target ()));
 
-  if (!obfd)
+  if (obfd == NULL)
     error (_("Failed to open '%s' for output."), filename);
-  bfd_set_format (obfd, bfd_core);
-  bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ());
+  bfd_set_format (obfd.get (), bfd_core);
+  bfd_set_arch_mach (obfd.get (), default_gcore_arch (), default_gcore_mach ());
   return obfd;
 }
 
@@ -174,7 +174,7 @@ gcore_command (char *args, int from_tty)
 		      "Opening corefile '%s' for output.\n", corefilename);
 
   /* Open the output file.  */
-  obfd = create_gcore_bfd (corefilename);
+  obfd = create_gcore_bfd (corefilename).release ();
 
   /* Need a cleanup that will close and delete the file.  */
   bfd_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
diff --git a/gdb/gcore.h b/gdb/gcore.h
index 91107e0..f4f0545 100644
--- a/gdb/gcore.h
+++ b/gdb/gcore.h
@@ -20,7 +20,9 @@
 #if !defined (GCORE_H)
 #define GCORE_H 1
 
-extern bfd *create_gcore_bfd (const char *filename);
+#include "gdb_bfd.h"
+
+extern gdb_bfd_ref_ptr create_gcore_bfd (const char *filename);
 extern void write_gcore_file (bfd *obfd);
 extern bfd *load_corefile (char *filename, int from_tty);
 extern int objfile_find_memory_regions (struct target_ops *self,
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index df00f87..d483177 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -356,7 +356,7 @@ gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream,
 
 /* See gdb_bfd.h.  */
 
-struct bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_open (const char *name, const char *target, int fd)
 {
   hashval_t hash;
@@ -392,7 +392,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
       if (fd == -1)
 	{
 	  bfd_set_error (bfd_error_system_call);
-	  return NULL;
+	  return gdb_bfd_ref_ptr ();
 	}
     }
 
@@ -428,12 +428,12 @@ gdb_bfd_open (const char *name, const char *target, int fd)
 			    bfd_get_filename (abfd));
       close (fd);
       gdb_bfd_ref (abfd);
-      return abfd;
+      return gdb_bfd_ref_ptr (abfd);
     }
 
   abfd = bfd_fopen (name, target, FOPEN_RB, fd);
   if (abfd == NULL)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
   if (debug_bfd_cache)
     fprintf_unfiltered (gdb_stdlog,
@@ -449,7 +449,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
     }
 
   gdb_bfd_ref (abfd);
-  return abfd;
+  return gdb_bfd_ref_ptr (abfd);
 }
 
 /* A helper function that releases any section data attached to the
@@ -772,7 +772,7 @@ gdb_bfd_crc (struct bfd *abfd, unsigned long *crc_out)
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
 	       int fd)
 {
@@ -781,12 +781,12 @@ gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openr (const char *filename, const char *target)
 {
   bfd *result = bfd_openr (filename, target);
@@ -794,12 +794,12 @@ gdb_bfd_openr (const char *filename, const char *target)
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openw (const char *filename, const char *target)
 {
   bfd *result = bfd_openw (filename, target);
@@ -807,12 +807,12 @@ gdb_bfd_openw (const char *filename, const char *target)
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openr_iovec (const char *filename, const char *target,
 		     void *(*open_func) (struct bfd *nbfd,
 					 void *open_closure),
@@ -835,7 +835,7 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
@@ -861,7 +861,7 @@ gdb_bfd_mark_parent (bfd *child, bfd *parent)
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
 {
   bfd *result = bfd_openr_next_archived_file (archive, previous);
@@ -869,7 +869,7 @@ gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
   if (result)
     gdb_bfd_mark_parent (result, archive);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
@@ -886,7 +886,7 @@ gdb_bfd_record_inclusion (bfd *includer, bfd *includee)
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
 {
   bfd *result = bfd_fdopenr (filename, target, fd);
@@ -894,7 +894,7 @@ gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 \f
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index a5b5ee9..8c4a60a 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -21,6 +21,7 @@
 #define GDB_BFD_H
 
 #include "registry.h"
+#include "common/gdb_ref_ptr.h"
 
 DECLARE_REGISTRY (bfd);
 
@@ -39,6 +40,34 @@ int is_target_filename (const char *name);
 
 int gdb_bfd_has_target_filename (struct bfd *abfd);
 
+/* Increment the reference count of ABFD.  It is fine for ABFD to be
+   NULL; in this case the function does nothing.  */
+
+void gdb_bfd_ref (struct bfd *abfd);
+
+/* Decrement the reference count of ABFD.  If this is the last
+   reference, ABFD will be freed.  If ABFD is NULL, this function does
+   nothing.  */
+
+void gdb_bfd_unref (struct bfd *abfd);
+
+/* A policy class for gdb::ref_ptr for BFD reference counting.  */
+struct gdb_bfd_ref_policy
+{
+  static void incref (struct bfd *abfd)
+  {
+    gdb_bfd_ref (abfd);
+  }
+
+  static void decref (struct bfd *abfd)
+  {
+    gdb_bfd_unref (abfd);
+  }
+};
+
+/* A gdb::ref_ptr that has been specialized for BFD objects.  */
+typedef gdb::ref_ptr<struct bfd, gdb_bfd_ref_policy> gdb_bfd_ref_ptr;
+
 /* Open a read-only (FOPEN_RB) BFD given arguments like bfd_fopen.
    If NAME starts with TARGET_SYSROOT_PREFIX then the BFD will be
    opened using target fileio operations if necessary.  Returns NULL
@@ -51,18 +80,7 @@ int gdb_bfd_has_target_filename (struct bfd *abfd);
    not be exactly NAME but rather NAME with TARGET_SYSROOT_PREFIX
    stripped.  */
 
-struct bfd *gdb_bfd_open (const char *name, const char *target, int fd);
-
-/* Increment the reference count of ABFD.  It is fine for ABFD to be
-   NULL; in this case the function does nothing.  */
-
-void gdb_bfd_ref (struct bfd *abfd);
-
-/* Decrement the reference count of ABFD.  If this is the last
-   reference, ABFD will be freed.  If ABFD is NULL, this function does
-   nothing.  */
-
-void gdb_bfd_unref (struct bfd *abfd);
+gdb_bfd_ref_ptr gdb_bfd_open (const char *name, const char *target, int fd);
 
 /* Mark the CHILD BFD as being a member of PARENT.  Also, increment
    the reference count of CHILD.  Calling this function ensures that
@@ -110,45 +128,46 @@ int gdb_bfd_crc (struct bfd *abfd, unsigned long *crc_out);
 /* A wrapper for bfd_fopen that initializes the gdb-specific reference
    count.  */
 
-bfd *gdb_bfd_fopen (const char *, const char *, const char *, int);
+gdb_bfd_ref_ptr gdb_bfd_fopen (const char *, const char *, const char *, int);
 
 /* A wrapper for bfd_openr that initializes the gdb-specific reference
    count.  */
 
-bfd *gdb_bfd_openr (const char *, const char *);
+gdb_bfd_ref_ptr gdb_bfd_openr (const char *, const char *);
 
 /* A wrapper for bfd_openw that initializes the gdb-specific reference
    count.  */
 
-bfd *gdb_bfd_openw (const char *, const char *);
+gdb_bfd_ref_ptr gdb_bfd_openw (const char *, const char *);
 
 /* A wrapper for bfd_openr_iovec that initializes the gdb-specific
    reference count.  */
 
-bfd *gdb_bfd_openr_iovec (const char *filename, const char *target,
-			  void *(*open_func) (struct bfd *nbfd,
-					      void *open_closure),
-			  void *open_closure,
-			  file_ptr (*pread_func) (struct bfd *nbfd,
-						  void *stream,
-						  void *buf,
-						  file_ptr nbytes,
-						  file_ptr offset),
-			  int (*close_func) (struct bfd *nbfd,
-					     void *stream),
-			  int (*stat_func) (struct bfd *abfd,
-					    void *stream,
-					    struct stat *sb));
+gdb_bfd_ref_ptr gdb_bfd_openr_iovec (const char *filename, const char *target,
+				     void *(*open_func) (struct bfd *nbfd,
+							 void *open_closure),
+				     void *open_closure,
+				     file_ptr (*pread_func) (struct bfd *nbfd,
+							     void *stream,
+							     void *buf,
+							     file_ptr nbytes,
+							     file_ptr offset),
+				     int (*close_func) (struct bfd *nbfd,
+							void *stream),
+				     int (*stat_func) (struct bfd *abfd,
+						       void *stream,
+						       struct stat *sb));
 
 /* A wrapper for bfd_openr_next_archived_file that initializes the
    gdb-specific reference count.  */
 
-bfd *gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous);
+gdb_bfd_ref_ptr gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous);
 
 /* A wrapper for bfd_fdopenr that initializes the gdb-specific
    reference count.  */
 
-bfd *gdb_bfd_fdopenr (const char *filename, const char *target, int fd);
+gdb_bfd_ref_ptr gdb_bfd_fdopenr (const char *filename, const char *target,
+				 int fd);
 
 \f
 
diff --git a/gdb/jit.c b/gdb/jit.c
index 03b6bd8..2101115 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -136,7 +136,7 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
 
 /* Open a BFD from the target's memory.  */
 
-static struct bfd *
+static gdb_bfd_ref_ptr
 bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
 {
   struct target_buffer *buffer = XNEW (struct target_buffer);
@@ -892,7 +892,6 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
                          CORE_ADDR entry_addr,
                          struct gdbarch *gdbarch)
 {
-  bfd *nbfd;
   struct section_addr_info *sai;
   struct bfd_section *sec;
   struct objfile *objfile;
@@ -907,8 +906,9 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
 			paddress (gdbarch, code_entry->symfile_addr),
 			pulongest (code_entry->symfile_size));
 
-  nbfd = bfd_open_from_target_memory (code_entry->symfile_addr,
-                                      code_entry->symfile_size, gnutarget);
+  gdb_bfd_ref_ptr nbfd (bfd_open_from_target_memory (code_entry->symfile_addr,
+						     code_entry->symfile_size,
+						     gnutarget));
   if (nbfd == NULL)
     {
       puts_unfiltered (_("Error opening JITed symbol file, ignoring it.\n"));
@@ -917,42 +917,42 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
 
   /* Check the format.  NOTE: This initializes important data that GDB uses!
      We would segfault later without this line.  */
-  if (!bfd_check_format (nbfd, bfd_object))
+  if (!bfd_check_format (nbfd.get (), bfd_object))
     {
       printf_unfiltered (_("\
 JITed symbol file is not an object file, ignoring it.\n"));
-      gdb_bfd_unref (nbfd);
       return;
     }
 
   /* Check bfd arch.  */
   b = gdbarch_bfd_arch_info (gdbarch);
-  if (b->compatible (b, bfd_get_arch_info (nbfd)) != b)
+  if (b->compatible (b, bfd_get_arch_info (nbfd.get ())) != b)
     warning (_("JITed object file architecture %s is not compatible "
-               "with target architecture %s."), bfd_get_arch_info
-             (nbfd)->printable_name, b->printable_name);
+               "with target architecture %s."),
+	     bfd_get_arch_info (nbfd.get ())->printable_name,
+	     b->printable_name);
 
   /* Read the section address information out of the symbol file.  Since the
      file is generated by the JIT at runtime, it should all of the absolute
      addresses that we care about.  */
-  sai = alloc_section_addr_info (bfd_count_sections (nbfd));
+  sai = alloc_section_addr_info (bfd_count_sections (nbfd.get ()));
   old_cleanups = make_cleanup_free_section_addr_info (sai);
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
-    if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
+    if ((bfd_get_section_flags (nbfd.get (), sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
         /* We assume that these virtual addresses are absolute, and do not
            treat them as offsets.  */
-        sai->other[i].addr = bfd_get_section_vma (nbfd, sec);
-        sai->other[i].name = xstrdup (bfd_get_section_name (nbfd, sec));
+        sai->other[i].addr = bfd_get_section_vma (nbfd.get (), sec);
+        sai->other[i].name = xstrdup (bfd_get_section_name (nbfd.get (), sec));
         sai->other[i].sectindex = sec->index;
         ++i;
       }
   sai->num_sections = i;
 
   /* This call does not take ownership of SAI.  */
-  make_cleanup_bfd_unref (nbfd);
-  objfile = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd), 0, sai,
+  objfile = symbol_file_add_from_bfd (nbfd.get (),
+				      bfd_get_filename (nbfd.get ()), 0, sai,
 				      OBJF_SHARED | OBJF_NOT_FILENAME, NULL);
 
   do_cleanups (old_cleanups);
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 00f25a4..4f0313e 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -429,7 +429,8 @@ macho_resolve_oso_sym_with_minsym (struct objfile *main_objfile, asymbol *sym)
 /* Add oso file OSO/ABFD as a symbol file.  */
 
 static void
-macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
+macho_add_oso_symfile (oso_el *oso, const gdb_bfd_ref_ptr &abfd,
+		       const char *name,
                        struct objfile *main_objfile,
 		       symfile_add_flags symfile_flags)
 {
@@ -439,7 +440,6 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
   asymbol **symp;
   struct bfd_hash_table table;
   int nbr_sections;
-  struct cleanup *cleanup;
 
   /* Per section flag to mark which section have been rebased.  */
   unsigned char *sections_rebased;
@@ -448,18 +448,16 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
     printf_unfiltered
       (_("Loading debugging symbols from oso: %s\n"), oso->name);
 
-  if (!bfd_check_format (abfd, bfd_object))
+  if (!bfd_check_format (abfd.get (), bfd_object))
     {
       warning (_("`%s': can't read symbols: %s."), oso->name,
                bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (abfd);
       return;
     }
 
-  if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd))
+  if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd.get ()))
     {
       warning (_("`%s': file time stamp mismatch."), oso->name);
-      gdb_bfd_unref (abfd);
       return;
     }
 
@@ -468,19 +466,18 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
                               oso->nbr_syms))
     {
       warning (_("`%s': can't create hash table"), oso->name);
-      gdb_bfd_unref (abfd);
       return;
     }
 
-  bfd_set_cacheable (abfd, 1);
+  bfd_set_cacheable (abfd.get (), 1);
 
   /* Read symbols table.  */
-  storage = bfd_get_symtab_upper_bound (abfd);
+  storage = bfd_get_symtab_upper_bound (abfd.get ());
   symbol_table = (asymbol **) xmalloc (storage);
-  bfd_canonicalize_symtab (abfd, symbol_table);
+  bfd_canonicalize_symtab (abfd.get (), symbol_table);
 
   /* Init section flags.  */
-  nbr_sections = bfd_count_sections (abfd);
+  nbr_sections = bfd_count_sections (abfd.get ());
   sections_rebased = (unsigned char *) alloca (nbr_sections);
   for (i = 0; i < nbr_sections; i++)
     sections_rebased[i] = 0;
@@ -601,7 +598,7 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
                          sec->name, sym->name,
                          paddress (arch, res));
                     }
-                  bfd_set_section_vma (abfd, sec, res);
+                  bfd_set_section_vma (abfd.get (), sec, res);
                   sections_rebased[sec->index] = 1;
                 }
             }
@@ -617,13 +614,12 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
 
   /* We need to clear SYMFILE_MAINLINE to avoid interractive question
      from symfile.c:symbol_file_add_with_addrs_or_offsets.  */
-  cleanup = make_cleanup_bfd_unref (abfd);
   symbol_file_add_from_bfd
-    (abfd, name, symfile_flags & ~(SYMFILE_MAINLINE | SYMFILE_VERBOSE), NULL,
+    (abfd.get (), name, symfile_flags & ~(SYMFILE_MAINLINE | SYMFILE_VERBOSE),
+     NULL,
      main_objfile->flags & (OBJF_REORDERED | OBJF_SHARED
 			    | OBJF_READNOW | OBJF_USERLOADED),
      main_objfile);
-  do_cleanups (cleanup);
 }
 
 /* Read symbols from the vector of oso files.
@@ -651,8 +647,6 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
       pfx_len = get_archive_prefix_len (oso->name);
       if (pfx_len > 0)
 	{
-	  bfd *archive_bfd;
-	  bfd *member_bfd;
           int last_ix;
           oso_el *oso2;
           int ix2;
@@ -668,7 +662,8 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
             }
 
 	  /* Open the archive and check the format.  */
-	  archive_bfd = gdb_bfd_open (archive_name.c_str (), gnutarget, -1);
+	  gdb_bfd_ref_ptr archive_bfd (gdb_bfd_open (archive_name.c_str (),
+						     gnutarget, -1));
 	  if (archive_bfd == NULL)
 	    {
 	      warning (_("Could not open OSO archive file \"%s\""),
@@ -676,22 +671,21 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
               ix = last_ix;
 	      continue;
 	    }
-	  if (!bfd_check_format (archive_bfd, bfd_archive))
+	  if (!bfd_check_format (archive_bfd.get (), bfd_archive))
 	    {
 	      warning (_("OSO archive file \"%s\" not an archive."),
 		       archive_name.c_str ());
-	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
 	    }
 
-	  member_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
+	  gdb_bfd_ref_ptr member_bfd
+	    (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
 
 	  if (member_bfd == NULL)
 	    {
 	      warning (_("Could not read archive members out of "
 			 "OSO archive \"%s\""), archive_name.c_str ());
-	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
 	    }
@@ -699,7 +693,6 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
           /* Load all oso in this library.  */
 	  while (member_bfd != NULL)
 	    {
-	      bfd *prev;
 	      const char *member_name = member_bfd->filename;
               int member_len = strlen (member_name);
 
@@ -721,13 +714,8 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
                     }
                 }
 
-              prev = member_bfd;
-	      member_bfd = gdb_bfd_openr_next_archived_file (archive_bfd,
-							     member_bfd);
-
-              /* Free previous member if not referenced by an oso.  */
-              if (ix2 >= last_ix)
-                gdb_bfd_unref (prev);
+	      member_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
+							     member_bfd.get ());
 	    }
           for (ix2 = ix; ix2 < last_ix; ix2++)
             {
@@ -741,10 +729,8 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
 	}
       else
 	{
-          bfd *abfd;
-
-	  abfd = gdb_bfd_open (oso->name, gnutarget, -1);
-	  if (!abfd)
+	  gdb_bfd_ref_ptr abfd (gdb_bfd_open (oso->name, gnutarget, -1));
+	  if (abfd == NULL)
             warning (_("`%s': can't open to read symbols: %s."), oso->name,
                      bfd_errmsg (bfd_get_error ()));
           else
@@ -768,7 +754,7 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
    Return NULL if no valid dsym file is found (FILENAMEP is not used in
    such case).  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 macho_check_dsym (struct objfile *objfile, char **filenamep)
 {
   size_t name_len = strlen (objfile_name (objfile));
@@ -776,7 +762,6 @@ macho_check_dsym (struct objfile *objfile, char **filenamep)
   const char *base_name = lbasename (objfile_name (objfile));
   size_t base_len = strlen (base_name);
   char *dsym_filename = (char *) alloca (name_len + dsym_len + base_len + 1);
-  bfd *dsym_bfd;
   bfd_mach_o_load_command *main_uuid;
   bfd_mach_o_load_command *dsym_uuid;
 
@@ -785,42 +770,39 @@ macho_check_dsym (struct objfile *objfile, char **filenamep)
   strcpy (dsym_filename + name_len + dsym_len, base_name);
 
   if (access (dsym_filename, R_OK) != 0)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
   if (bfd_mach_o_lookup_command (objfile->obfd,
                                  BFD_MACH_O_LC_UUID, &main_uuid) == 0)
     {
       warning (_("can't find UUID in %s"), objfile_name (objfile));
-      return NULL;
+      return gdb_bfd_ref_ptr ();
     }
-  dsym_bfd = gdb_bfd_openr (dsym_filename, gnutarget);
+  gdb_bfd_ref_ptr dsym_bfd (gdb_bfd_openr (dsym_filename, gnutarget));
   if (dsym_bfd == NULL)
     {
       warning (_("can't open dsym file %s"), dsym_filename);
-      return NULL;
+      return gdb_bfd_ref_ptr ();
     }
 
-  if (!bfd_check_format (dsym_bfd, bfd_object))
+  if (!bfd_check_format (dsym_bfd.get (), bfd_object))
     {
-      gdb_bfd_unref (dsym_bfd);
       warning (_("bad dsym file format: %s"), bfd_errmsg (bfd_get_error ()));
-      return NULL;
+      return gdb_bfd_ref_ptr ();
     }
 
-  if (bfd_mach_o_lookup_command (dsym_bfd,
+  if (bfd_mach_o_lookup_command (dsym_bfd.get (),
                                  BFD_MACH_O_LC_UUID, &dsym_uuid) == 0)
     {
       warning (_("can't find UUID in %s"), dsym_filename);
-      gdb_bfd_unref (dsym_bfd);
-      return NULL;
+      return gdb_bfd_ref_ptr ();
     }
   if (memcmp (dsym_uuid->command.uuid.uuid, main_uuid->command.uuid.uuid,
               sizeof (main_uuid->command.uuid.uuid)))
     {
       warning (_("dsym file UUID doesn't match the one in %s"),
 	       objfile_name (objfile));
-      gdb_bfd_unref (dsym_bfd);
-      return NULL;
+      return gdb_bfd_ref_ptr ();
     }
   *filenamep = xstrdup (dsym_filename);
   return dsym_bfd;
@@ -831,7 +813,6 @@ macho_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 {
   bfd *abfd = objfile->obfd;
   long storage_needed;
-  bfd *dsym_bfd;
   VEC (oso_el) *oso_vector = NULL;
   struct cleanup *old_chain = make_cleanup (VEC_cleanup (oso_el), &oso_vector);
 
@@ -879,7 +860,7 @@ macho_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
       dwarf2_build_frame_info (objfile);
 
       /* Check for DSYM file.  */
-      dsym_bfd = macho_check_dsym (objfile, &dsym_filename);
+      gdb_bfd_ref_ptr dsym_bfd (macho_check_dsym (objfile, &dsym_filename));
       if (dsym_bfd != NULL)
 	{
           struct bfd_section *asect, *dsect;
@@ -896,14 +877,13 @@ macho_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
             {
               if (strcmp (asect->name, dsect->name) != 0)
                 break;
-              bfd_set_section_size (dsym_bfd, dsect,
+              bfd_set_section_size (dsym_bfd.get (), dsect,
                                     bfd_get_section_size (asect));
             }
 
 	  /* Add the dsym file as a separate file.  */
-	  make_cleanup_bfd_unref (dsym_bfd);
-          symbol_file_add_separate (dsym_bfd, dsym_filename, symfile_flags,
-				    objfile);
+          symbol_file_add_separate (dsym_bfd.get (), dsym_filename,
+				    symfile_flags, objfile);
 
 	  /* Don't try to read dwarf2 from main file or shared libraries.  */
 	  do_cleanups (old_chain);
diff --git a/gdb/minidebug.c b/gdb/minidebug.c
index 4323294..f54f0cc 100644
--- a/gdb/minidebug.c
+++ b/gdb/minidebug.c
@@ -256,35 +256,33 @@ lzma_stat (struct bfd *abfd,
    If we find one we create a iovec based bfd that decompresses the
    object data on demand.  If we don't find one, return NULL.  */
 
-bfd *
+gdb_bfd_ref_ptr
 find_separate_debug_file_in_section (struct objfile *objfile)
 {
   asection *section;
-  bfd *abfd;
+  gdb_bfd_ref_ptr abfd;
 
   if (objfile->obfd == NULL)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
   section = bfd_get_section_by_name (objfile->obfd, ".gnu_debugdata");
   if (section == NULL)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
 #ifdef HAVE_LIBLZMA
   abfd = gdb_bfd_openr_iovec (objfile_name (objfile), gnutarget, lzma_open,
 			      section, lzma_pread, lzma_close, lzma_stat);
   if (abfd == NULL)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
-  if (!bfd_check_format (abfd, bfd_object))
+  if (!bfd_check_format (abfd.get (), bfd_object))
     {
       warning (_("Cannot parse .gnu_debugdata section; not a BFD object"));
-      gdb_bfd_unref (abfd);
-      return NULL;
+      return gdb_bfd_ref_ptr ();
     }
 #else
   warning (_("Cannot parse .gnu_debugdata section; LZMA support was "
 	     "disabled at compile time"));
-  abfd = NULL;
 #endif /* !HAVE_LIBLZMA */
 
   return abfd;
diff --git a/gdb/procfs.c b/gdb/procfs.c
index ff814ba..f8fd487 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -3413,26 +3413,24 @@ dbx_link_addr (bfd *abfd)
 static int
 insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
 {
-  bfd *abfd;
   long storage_needed;
   CORE_ADDR sym_addr;
 
-  abfd = gdb_bfd_fdopenr ("unamed", 0, fd);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_fdopenr ("unamed", 0, fd));
   if (abfd == NULL)
     {
       warning (_("Failed to create a bfd: %s."), bfd_errmsg (bfd_get_error ()));
       return 0;
     }
 
-  if (!bfd_check_format (abfd, bfd_object))
+  if (!bfd_check_format (abfd.get (), bfd_object))
     {
       /* Not the correct format, so we can not possibly find the dbx_link
 	 symbol in it.	*/
-      gdb_bfd_unref (abfd);
       return 0;
     }
 
-  sym_addr = dbx_link_addr (abfd);
+  sym_addr = dbx_link_addr (abfd.get ());
   if (sym_addr != 0)
     {
       struct breakpoint *dbx_link_bpt;
@@ -3444,14 +3442,11 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
       if (dbx_link_bpt == NULL)
 	{
 	  warning (_("Failed to insert dbx_link breakpoint."));
-	  gdb_bfd_unref (abfd);
 	  return 0;
 	}
-      gdb_bfd_unref (abfd);
       return 1;
     }
 
-  gdb_bfd_unref (abfd);
   return 0;
 }
 
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 497d0ba..42e26b7 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -445,9 +445,9 @@ objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
 
   TRY
     {
-      bfd *abfd = symfile_bfd_open (file_name);
+      gdb_bfd_ref_ptr abfd (symfile_bfd_open (file_name));
 
-      symbol_file_add_separate (abfd, file_name, 0, obj->objfile);
+      symbol_file_add_separate (abfd.get (), file_name, 0, obj->objfile);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 603a9ba..7ab394b 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -2571,7 +2571,7 @@ record_full_save (struct target_ops *self, const char *recfilename)
 			recfilename);
 
   /* Open the output file.  */
-  obfd = create_gcore_bfd (recfilename);
+  obfd = create_gcore_bfd (recfilename).release ();
   old_cleanups = make_cleanup (record_full_save_cleanups, obfd);
 
   /* Save the current record entry to "cur_record_full_list".  */
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index 75634df..96aa83e 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -624,7 +624,7 @@ solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
 
 /* Implement the "bfd_open" target_so_ops method.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 solib_aix_bfd_open (char *pathname)
 {
   /* The pathname is actually a synthetic filename with the following
@@ -635,11 +635,7 @@ solib_aix_bfd_open (char *pathname)
      to the solib's lm_info here?  */
   const int path_len = strlen (pathname);
   char *sep;
-  char *filename;
   int filename_len;
-  char *member_name;
-  bfd *archive_bfd, *object_bfd;
-  struct cleanup *cleanup;
   int found_file;
   char *found_pathname;
 
@@ -658,82 +654,70 @@ solib_aix_bfd_open (char *pathname)
     }
   filename_len = sep - pathname;
 
-  filename = xstrprintf ("%.*s", filename_len, pathname);
-  cleanup = make_cleanup (xfree, filename);
-  member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
-  make_cleanup (xfree, member_name);
+  gdb::unique_xmalloc_ptr<char> filename
+    (xstrprintf ("%.*s", filename_len, pathname));
+  gdb::unique_xmalloc_ptr<char> member_name
+    (xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1));
 
   /* Calling solib_find makes certain that sysroot path is set properly
      if program has a dependency on .a archive and sysroot is set via
      set sysroot command.  */
-  found_pathname = solib_find (filename, &found_file);
+  found_pathname = solib_find (filename.get (), &found_file);
   if (found_pathname == NULL)
       perror_with_name (pathname);
-  archive_bfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname, found_file));
   if (archive_bfd == NULL)
     {
       warning (_("Could not open `%s' as an executable file: %s"),
-	       filename, bfd_errmsg (bfd_get_error ()));
-      do_cleanups (cleanup);
-      return NULL;
+	       filename.get (), bfd_errmsg (bfd_get_error ()));
+      return gdb_bfd_ref_ptr ();
     }
 
-  if (bfd_check_format (archive_bfd, bfd_object))
-    {
-      do_cleanups (cleanup);
-      return archive_bfd;
-    }
+  if (bfd_check_format (archive_bfd.get (), bfd_object))
+    return archive_bfd;
 
-  if (! bfd_check_format (archive_bfd, bfd_archive))
+  if (! bfd_check_format (archive_bfd.get (), bfd_archive))
     {
       warning (_("\"%s\": not in executable format: %s."),
-	       filename, bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (archive_bfd);
-      do_cleanups (cleanup);
-      return NULL;
+	       filename.get (), bfd_errmsg (bfd_get_error ()));
+      return gdb_bfd_ref_ptr ();
     }
 
-  object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
+  gdb_bfd_ref_ptr object_bfd
+    (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
   while (object_bfd != NULL)
     {
-      bfd *next;
-
-      if (strcmp (member_name, object_bfd->filename) == 0)
+      if (strcmp (member_name.get (), object_bfd->filename) == 0)
 	break;
 
-      next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
-      gdb_bfd_unref (object_bfd);
-      object_bfd = next;
+      object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
+						     object_bfd.get ());
     }
 
   if (object_bfd == NULL)
     {
-      warning (_("\"%s\": member \"%s\" missing."), filename, member_name);
-      gdb_bfd_unref (archive_bfd);
-      do_cleanups (cleanup);
-      return NULL;
+      warning (_("\"%s\": member \"%s\" missing."), filename.get (),
+	       member_name.get ());
+      return gdb_bfd_ref_ptr ();
     }
 
-  if (! bfd_check_format (object_bfd, bfd_object))
+  if (! bfd_check_format (object_bfd.get (), bfd_object))
     {
       warning (_("%s(%s): not in object format: %s."),
-	       filename, member_name, bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (archive_bfd);
-      gdb_bfd_unref (object_bfd);
-      do_cleanups (cleanup);
-      return NULL;
+	       filename.get (), member_name.get (),
+	       bfd_errmsg (bfd_get_error ()));
+      return gdb_bfd_ref_ptr ();
     }
 
   /* Override the returned bfd's name with the name returned from solib_find
      along with appended parenthesized member name in order to allow commands
      listing all shared libraries to display.  Otherwise, we would only be
      displaying the name of the archive member object.  */
-  xfree (bfd_get_filename (object_bfd));
+  xfree (bfd_get_filename (object_bfd.get ()));
   object_bfd->filename = xstrprintf ("%s%s",
-                                     bfd_get_filename (archive_bfd), sep);
+                                     bfd_get_filename (archive_bfd.get ()),
+				     sep);
 
-  gdb_bfd_unref (archive_bfd);
-  do_cleanups (cleanup);
   return object_bfd;
 }
 
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 24cf848..6a8f2da 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -427,21 +427,21 @@ darwin_in_dynsym_resolve_code (CORE_ADDR pc)
    counting properly.  This will either return NULL, or return a new
    reference to a BFD.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format,
 			    const bfd_arch_info_type *arch)
 {
   bfd *result = bfd_mach_o_fat_extract (abfd, format, arch);
 
   if (result == NULL)
-    return NULL;
+    return gdb_bfd_ref_ptr ();
 
   if (result == abfd)
     gdb_bfd_ref (result);
   else
     gdb_bfd_mark_parent (result, abfd);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* Extract dyld_all_image_addr when the process was just created, assuming the
@@ -452,8 +452,6 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info)
 {
   char *interp_name;
   CORE_ADDR load_addr = 0;
-  bfd *dyld_bfd = NULL;
-  struct cleanup *cleanup;
 
   /* This method doesn't work with an attached process.  */
   if (current_inferior ()->attach_flag)
@@ -464,42 +462,30 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info)
   if (!interp_name)
     return;
 
-  cleanup = make_cleanup (null_cleanup, NULL);
-
   /* Create a bfd for the interpreter.  */
-  dyld_bfd = gdb_bfd_open (interp_name, gnutarget, -1);
-  if (dyld_bfd)
+  gdb_bfd_ref_ptr dyld_bfd (gdb_bfd_open (interp_name, gnutarget, -1));
+  if (dyld_bfd != NULL)
     {
-      bfd *sub;
-
-      make_cleanup_bfd_unref (dyld_bfd);
-      sub = gdb_bfd_mach_o_fat_extract
-	(dyld_bfd, bfd_object, gdbarch_bfd_arch_info (target_gdbarch ()));
-      if (sub)
-	{
-	  dyld_bfd = sub;
-	  make_cleanup_bfd_unref (sub);
-	}
+      gdb_bfd_ref_ptr sub
+	(gdb_bfd_mach_o_fat_extract (dyld_bfd.get (), bfd_object,
+				     gdbarch_bfd_arch_info (target_gdbarch ())));
+      if (sub != NULL)
+	dyld_bfd = sub;
       else
-	dyld_bfd = NULL;
-    }
-  if (!dyld_bfd)
-    {
-      do_cleanups (cleanup);
-      return;
+	dyld_bfd.release ();
     }
+  if (dyld_bfd == NULL)
+    return;
 
   /* We find the dynamic linker's base address by examining
      the current pc (which should point at the entry point for the
      dynamic linker) and subtracting the offset of the entry point.  */
   load_addr = (regcache_read_pc (get_current_regcache ())
-               - bfd_get_start_address (dyld_bfd));
+               - bfd_get_start_address (dyld_bfd.get ()));
 
   /* Now try to set a breakpoint in the dynamic linker.  */
   info->all_image_addr =
-    lookup_symbol_from_bfd (dyld_bfd, "_dyld_all_image_infos");
-
-  do_cleanups (cleanup);
+    lookup_symbol_from_bfd (dyld_bfd.get (), "_dyld_all_image_infos");
 
   if (info->all_image_addr == 0)
     return;
@@ -634,13 +620,11 @@ darwin_lookup_lib_symbol (struct objfile *objfile,
   return (struct block_symbol) {NULL, NULL};
 }
 
-static bfd *
+static gdb_bfd_ref_ptr
 darwin_bfd_open (char *pathname)
 {
   char *found_pathname;
   int found_file;
-  bfd *abfd;
-  bfd *res;
 
   /* Search for shared library file.  */
   found_pathname = solib_find (pathname, &found_file);
@@ -648,24 +632,21 @@ darwin_bfd_open (char *pathname)
     perror_with_name (pathname);
 
   /* Open bfd for shared library.  */
-  abfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref_ptr abfd (solib_bfd_fopen (found_pathname, found_file));
 
-  res = gdb_bfd_mach_o_fat_extract (abfd, bfd_object,
-				    gdbarch_bfd_arch_info (target_gdbarch ()));
-  if (!res)
-    {
-      make_cleanup_bfd_unref (abfd);
-      error (_("`%s': not a shared-library: %s"),
-	     bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
-    }
+  gdb_bfd_ref_ptr res
+    (gdb_bfd_mach_o_fat_extract (abfd.get (), bfd_object,
+				 gdbarch_bfd_arch_info (target_gdbarch ())));
+  if (res == NULL)
+    error (_("`%s': not a shared-library: %s"),
+	   bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
 
   /* The current filename for fat-binary BFDs is a name generated
      by BFD, usually a string containing the name of the architecture.
      Reset its value to the actual filename.  */
-  xfree (bfd_get_filename (res));
+  xfree (bfd_get_filename (res.get ()));
   res->filename = xstrdup (pathname);
 
-  gdb_bfd_unref (abfd);
   return res;
 }
 
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index d66fe5d..14cab05 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -816,7 +816,6 @@ enable_break (void)
     {
       unsigned int interp_sect_size;
       char *buf;
-      bfd *tmp_bfd = NULL;
       CORE_ADDR addr;
       struct int_elf32_dsbt_loadmap *ldm;
       int ret;
@@ -832,6 +831,7 @@ enable_break (void)
 	 loaded so that we can load its symbols and place a breakpoint
 	 in the dynamic linker itself.  */
 
+      gdb_bfd_ref_ptr tmp_bfd;
       TRY
 	{
 	  tmp_bfd = solib_bfd_open (buf);
@@ -852,29 +852,31 @@ enable_break (void)
 
       /* Record the relocated start and end address of the dynamic linker
 	 text and plt section for dsbt_in_dynsym_resolve_code.  */
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
 	{
 	  info->interp_text_sect_low
-	    = bfd_section_vma (tmp_bfd, interp_sect);
+	    = bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  info->interp_text_sect_low
 	    += displacement_from_map (ldm, info->interp_text_sect_low);
 	  info->interp_text_sect_high
 	    = info->interp_text_sect_low
-	    + bfd_section_size (tmp_bfd, interp_sect);
+	    + bfd_section_size (tmp_bfd.get (), interp_sect);
 	}
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
 	{
 	  info->interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect);
+	    bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  info->interp_plt_sect_low
 	    += displacement_from_map (ldm, info->interp_plt_sect_low);
 	  info->interp_plt_sect_high =
-	    info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+	    info->interp_plt_sect_low + bfd_section_size (tmp_bfd.get (),
+							  interp_sect);
 	}
 
-      addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_state");
+      addr = gdb_bfd_lookup_symbol (tmp_bfd.get (), cmp_name,
+				    "_dl_debug_state");
       if (addr != 0)
 	{
 	  if (solib_dsbt_debug)
@@ -901,10 +903,7 @@ enable_break (void)
 	  ret = 0;
 	}
 
-      /* We're done with the temporary bfd.  */
-      gdb_bfd_unref (tmp_bfd);
-
-      /* We're also done with the loadmap.  */
+      /* We're done with the loadmap.  */
       xfree (ldm);
 
       return ret;
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index 61a4ed0..0387b44 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -532,7 +532,6 @@ enable_break2 (void)
     {
       unsigned int interp_sect_size;
       char *buf;
-      bfd *tmp_bfd = NULL;
       int status;
       CORE_ADDR addr, interp_loadmap_addr;
       gdb_byte addr_buf[FRV_PTR_SIZE];
@@ -554,6 +553,7 @@ enable_break2 (void)
          be trivial on GNU/Linux).  Therefore, we have to try an alternate
          mechanism to find the dynamic linker's base address.  */
 
+      gdb_bfd_ref_ptr tmp_bfd;
       TRY
         {
           tmp_bfd = solib_bfd_open (buf);
@@ -575,7 +575,6 @@ enable_break2 (void)
 	{
 	  warning (_("Unable to determine dynamic linker loadmap address."));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -590,41 +589,41 @@ enable_break2 (void)
 	  warning (_("Unable to load dynamic linker loadmap at address %s."),
 	           hex_string_custom (interp_loadmap_addr, 8));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
 	{
 	  interp_text_sect_low
-	    = bfd_section_vma (tmp_bfd, interp_sect);
+	    = bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  interp_text_sect_low
 	    += displacement_from_map (ldm, interp_text_sect_low);
 	  interp_text_sect_high
-	    = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+	    = interp_text_sect_low + bfd_section_size (tmp_bfd.get (),
+						       interp_sect);
 	}
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
 	{
 	  interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect);
+	    bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  interp_plt_sect_low
 	    += displacement_from_map (ldm, interp_plt_sect_low);
 	  interp_plt_sect_high =
-	    interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+	    interp_plt_sect_low + bfd_section_size (tmp_bfd.get (),
+						    interp_sect);
 	}
 
-      addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr");
+      addr = gdb_bfd_lookup_symbol (tmp_bfd.get (), cmp_name, "_dl_debug_addr");
 
       if (addr == 0)
 	{
 	  warning (_("Could not find symbol _dl_debug_addr "
 		     "in dynamic linker"));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -675,7 +674,6 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr + 8, 8));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
@@ -687,15 +685,11 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr, 8));
 	  enable_break_failure_warning ();
-	  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.  */
-      gdb_bfd_unref (tmp_bfd);
-
-      /* We're also done with the loadmap.  */
+      /* We're done with the loadmap.  */
       xfree (ldm);
 
       /* Remove all the solib event breakpoints.  Their addresses
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index fa2977e..117398d 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -319,36 +319,32 @@ spu_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb)
   return 0;
 }
 
-static bfd *
+static gdb_bfd_ref_ptr
 spu_bfd_fopen (char *name, CORE_ADDR addr)
 {
-  bfd *nbfd;
   CORE_ADDR *open_closure = XNEW (CORE_ADDR);
 
   *open_closure = addr;
 
-  nbfd = gdb_bfd_openr_iovec (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;
+  gdb_bfd_ref_ptr nbfd (gdb_bfd_openr_iovec (name, "elf32-spu",
+					     spu_bfd_iovec_open, open_closure,
+					     spu_bfd_iovec_pread,
+					     spu_bfd_iovec_close,
+					     spu_bfd_iovec_stat));
+  if (nbfd == NULL)
+    return gdb_bfd_ref_ptr ();
 
-  if (!bfd_check_format (nbfd, bfd_object))
-    {
-      gdb_bfd_unref (nbfd);
-      return NULL;
-    }
+  if (!bfd_check_format (nbfd.get (), bfd_object))
+    return gdb_bfd_ref_ptr ();
 
   return nbfd;
 }
 
 /* Open shared library BFD.  */
-static bfd *
+static gdb_bfd_ref_ptr
 spu_bfd_open (char *pathname)
 {
   char *original_name = strrchr (pathname, '@');
-  bfd *abfd;
   asection *spu_name;
   unsigned long long addr;
   int fd;
@@ -362,22 +358,23 @@ spu_bfd_open (char *pathname)
     internal_error (__FILE__, __LINE__, "bad object ID");
 
   /* Open BFD representing SPE executable.  */
-  abfd = spu_bfd_fopen (original_name, (CORE_ADDR) addr);
-  if (!abfd)
+  gdb_bfd_ref_ptr abfd (spu_bfd_fopen (original_name, (CORE_ADDR) addr));
+  if (abfd == NULL)
     error (_("Cannot read SPE executable at %s"), original_name);
 
   /* Retrieve SPU name note.  */
-  spu_name = bfd_get_section_by_name (abfd, ".note.spu_name");
+  spu_name = bfd_get_section_by_name (abfd.get (), ".note.spu_name");
   if (spu_name)
     {
-      int sect_size = bfd_section_size (abfd, spu_name);
+      int sect_size = bfd_section_size (abfd.get (), spu_name);
 
       if (sect_size > 20)
 	{
 	  char *buf
 	    = (char *) alloca (sect_size - 20 + strlen (original_name) + 1);
 
-	  bfd_get_section_contents (abfd, spu_name, buf, 20, sect_size - 20);
+	  bfd_get_section_contents (abfd.get (), spu_name, buf, 20,
+				    sect_size - 20);
 	  buf[sect_size - 20] = '\0';
 
 	  strcat (buf, original_name);
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 0e18292..b801364 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2355,7 +2355,6 @@ enable_break (struct svr4_info *info, int from_tty)
       int load_addr_found = 0;
       int loader_found_in_list = 0;
       struct so_list *so;
-      bfd *tmp_bfd = NULL;
       struct target_ops *tmp_bfd_target;
 
       sym_addr = 0;
@@ -2369,6 +2368,7 @@ enable_break (struct svr4_info *info, int from_tty)
          be trivial on GNU/Linux).  Therefore, we have to try an alternate
          mechanism to find the dynamic linker's base address.  */
 
+      gdb_bfd_ref_ptr tmp_bfd;
       TRY
         {
 	  tmp_bfd = solib_bfd_open (interp_name);
@@ -2382,11 +2382,9 @@ enable_break (struct svr4_info *info, int from_tty)
 	goto bkpt_at_symbol;
 
       /* Now convert the TMP_BFD into a target.  That way target, as
-         well as BFD operations can be used.  */
-      tmp_bfd_target = target_bfd_reopen (tmp_bfd);
-      /* target_bfd_reopen acquired its own reference, so we can
-         release ours now.  */
-      gdb_bfd_unref (tmp_bfd);
+         well as BFD operations can be used.  target_bfd_reopen
+         acquires its own reference.  */
+      tmp_bfd_target = target_bfd_reopen (tmp_bfd.get ());
 
       /* On a running target, we can get the dynamic linker's base
          address from the shared library table.  */
@@ -2397,7 +2395,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	    {
 	      load_addr_found = 1;
 	      loader_found_in_list = 1;
-	      load_addr = lm_addr_check (so, tmp_bfd);
+	      load_addr = lm_addr_check (so, tmp_bfd.get ());
 	      break;
 	    }
 	  so = so->next;
@@ -2418,7 +2416,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	    if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
 	      {
 		CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
-		CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd,
+		CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd.get (),
 							      tmp_bfd_target);
 
 		gdb_assert (load_addr < space_size);
@@ -2447,7 +2445,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	    = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
 
 	  load_addr = (regcache_read_pc (regcache)
-		       - exec_entry_point (tmp_bfd, tmp_bfd_target));
+		       - exec_entry_point (tmp_bfd.get (), tmp_bfd_target));
 	}
 
       if (!loader_found_in_list)
@@ -2460,29 +2458,30 @@ enable_break (struct svr4_info *info, int from_tty)
 
       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
 	{
 	  info->interp_text_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+	    bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
 	  info->interp_text_sect_high =
 	    info->interp_text_sect_low
-	    + bfd_section_size (tmp_bfd, interp_sect);
+	    + bfd_section_size (tmp_bfd.get (), interp_sect);
 	}
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
 	{
 	  info->interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+	    bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
 	  info->interp_plt_sect_high =
 	    info->interp_plt_sect_low
-	    + bfd_section_size (tmp_bfd, interp_sect);
+	    + bfd_section_size (tmp_bfd.get (), interp_sect);
 	}
 
       /* Now try to set a breakpoint in the dynamic linker.  */
       for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
 	{
-	  sym_addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name_and_sec_flags,
+	  sym_addr = gdb_bfd_lookup_symbol (tmp_bfd.get (),
+					    cmp_name_and_sec_flags,
 					    *bkpt_namep);
 	  if (sym_addr != 0)
 	    break;
diff --git a/gdb/solib.c b/gdb/solib.c
index db370e9..44e1396 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -474,15 +474,15 @@ solib_find (char *in_pathname, int *fd)
    function.  If unsuccessful, the FD will be closed (unless FD was
    -1).  */
 
-bfd *
+gdb_bfd_ref_ptr
 solib_bfd_fopen (char *pathname, int fd)
 {
-  bfd *abfd = gdb_bfd_open (pathname, gnutarget, fd);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (pathname, gnutarget, fd));
 
-  if (abfd != NULL && !gdb_bfd_has_target_filename (abfd))
-    bfd_set_cacheable (abfd, 1);
+  if (abfd != NULL && !gdb_bfd_has_target_filename (abfd.get ()))
+    bfd_set_cacheable (abfd.get (), 1);
 
-  if (!abfd)
+  if (abfd == NULL)
     {
       make_cleanup (xfree, pathname);
       error (_("Could not open `%s' as an executable file: %s"),
@@ -496,12 +496,11 @@ solib_bfd_fopen (char *pathname, int fd)
 
 /* Find shared library PATHNAME and open a BFD for it.  */
 
-bfd *
+gdb_bfd_ref_ptr
 solib_bfd_open (char *pathname)
 {
   char *found_pathname;
   int found_file;
-  bfd *abfd;
   const struct bfd_arch_info *b;
 
   /* Search for shared library file.  */
@@ -511,28 +510,26 @@ solib_bfd_open (char *pathname)
       /* Return failure if the file could not be found, so that we can
 	 accumulate messages about missing libraries.  */
       if (errno == ENOENT)
-	return NULL;
+	return gdb_bfd_ref_ptr ();
 
       perror_with_name (pathname);
     }
 
   /* Open bfd for shared library.  */
-  abfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref_ptr abfd (solib_bfd_fopen (found_pathname, found_file));
 
   /* Check bfd format.  */
-  if (!bfd_check_format (abfd, bfd_object))
-    {
-      make_cleanup_bfd_unref (abfd);
-      error (_("`%s': not in executable format: %s"),
-	     bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
-    }
+  if (!bfd_check_format (abfd.get (), bfd_object))
+    error (_("`%s': not in executable format: %s"),
+	   bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
 
   /* Check bfd arch.  */
   b = gdbarch_bfd_arch_info (target_gdbarch ());
-  if (!b->compatible (b, bfd_get_arch_info (abfd)))
+  if (!b->compatible (b, bfd_get_arch_info (abfd.get ())))
     warning (_("`%s': Shared library architecture %s is not compatible "
                "with target architecture %s."), bfd_get_filename (abfd),
-             bfd_get_arch_info (abfd)->printable_name, b->printable_name);
+             bfd_get_arch_info (abfd.get ())->printable_name,
+	     b->printable_name);
 
   return abfd;
 }
@@ -556,18 +553,17 @@ solib_map_sections (struct so_list *so)
   char *filename;
   struct target_section *p;
   struct cleanup *old_chain;
-  bfd *abfd;
 
   filename = tilde_expand (so->so_name);
   old_chain = make_cleanup (xfree, filename);
-  abfd = ops->bfd_open (filename);
+  gdb_bfd_ref_ptr abfd (ops->bfd_open (filename));
   do_cleanups (old_chain);
 
   if (abfd == NULL)
     return 0;
 
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
-  so->abfd = abfd;
+  so->abfd = abfd.release ();
 
   /* Copy the full path name into so_name, allowing symbol_file_add
      to find it later.  This also affects the =library-loaded GDB/MI
@@ -575,14 +571,14 @@ solib_map_sections (struct so_list *so)
      the library's host-side path.  If we let the target dictate
      that objfile's path, and the target is different from the host,
      GDB/MI will not provide the correct host-side path.  */
-  if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE)
+  if (strlen (bfd_get_filename (so->abfd)) >= SO_NAME_MAX_PATH_SIZE)
     error (_("Shared library file name is too long."));
-  strcpy (so->so_name, bfd_get_filename (abfd));
+  strcpy (so->so_name, bfd_get_filename (so->abfd));
 
-  if (build_section_table (abfd, &so->sections, &so->sections_end))
+  if (build_section_table (so->abfd, &so->sections, &so->sections_end))
     {
       error (_("Can't find the file sections in `%s': %s"),
-	     bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+	     bfd_get_filename (so->abfd), bfd_errmsg (bfd_get_error ()));
     }
 
   for (p = so->sections; p < so->sections_end; p++)
@@ -1373,7 +1369,6 @@ reload_shared_libraries_1 (int from_tty)
   for (so = so_list_head; so != NULL; so = so->next)
     {
       char *filename, *found_pathname = NULL;
-      bfd *abfd;
       int was_loaded = so->symbols_loaded;
       symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
 
@@ -1382,12 +1377,11 @@ reload_shared_libraries_1 (int from_tty)
 
       filename = tilde_expand (so->so_original_name);
       make_cleanup (xfree, filename);
-      abfd = solib_bfd_open (filename);
+      gdb_bfd_ref_ptr abfd (solib_bfd_open (filename));
       if (abfd != NULL)
 	{
-	  found_pathname = xstrdup (bfd_get_filename (abfd));
+	  found_pathname = xstrdup (bfd_get_filename (abfd.get ()));
 	  make_cleanup (xfree, found_pathname);
-	  gdb_bfd_unref (abfd);
 	}
 
       /* If this shared library is no longer associated with its previous
diff --git a/gdb/solist.h b/gdb/solist.h
index f709483..ca02051 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -22,6 +22,7 @@
 #define SO_NAME_MAX_PATH_SIZE 512	/* FIXME: Should be dynamic */
 /* For domain_enum domain.  */
 #include "symtab.h"
+#include "gdb_bfd.h"
 
 /* Forward declaration for target specific link map information.  This
    struct is opaque to all but the target specific file.  */
@@ -121,7 +122,7 @@ struct target_so_ops
     int (*in_dynsym_resolve_code) (CORE_ADDR pc);
 
     /* Find and open shared library binary file.  */
-    bfd *(*bfd_open) (char *pathname);
+    gdb_bfd_ref_ptr (*bfd_open) (char *pathname);
 
     /* Optional extra hook for finding and opening a solib.
        If TEMP_PATHNAME is non-NULL: If the file is successfully opened a
@@ -178,10 +179,10 @@ extern char *exec_file_find (char *in_pathname, int *fd);
 extern char *solib_find (char *in_pathname, int *fd);
 
 /* Open BFD for shared library file.  */
-extern bfd *solib_bfd_fopen (char *pathname, int fd);
+extern gdb_bfd_ref_ptr solib_bfd_fopen (char *pathname, int fd);
 
 /* Find solib binary file and open it.  */
-extern bfd *solib_bfd_open (char *in_pathname);
+extern gdb_bfd_ref_ptr solib_bfd_open (char *in_pathname);
 
 /* FIXME: gdbarch needs to control this variable.  */
 extern struct target_so_ops *current_target_so_ops;
diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c
index f1d58ec..75d8868 100644
--- a/gdb/spu-linux-nat.c
+++ b/gdb/spu-linux-nat.c
@@ -318,37 +318,35 @@ spu_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
   return 0;
 }
 
-static bfd *
+static gdb_bfd_ref_ptr
 spu_bfd_open (ULONGEST addr)
 {
-  struct bfd *nbfd;
   asection *spu_name;
 
   ULONGEST *open_closure = XNEW (ULONGEST);
   *open_closure = addr;
 
-  nbfd = gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
-			      spu_bfd_iovec_open, open_closure,
-			      spu_bfd_iovec_pread, spu_bfd_iovec_close,
-			      spu_bfd_iovec_stat);
-  if (!nbfd)
-    return NULL;
+  gdb_bfd_ref_ptr nbfd (gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
+					     spu_bfd_iovec_open, open_closure,
+					     spu_bfd_iovec_pread,
+					     spu_bfd_iovec_close,
+					     spu_bfd_iovec_stat));
+  if (nbfd == NULL)
+    return gdb_bfd_ref_ptr ();
 
-  if (!bfd_check_format (nbfd, bfd_object))
-    {
-      gdb_bfd_unref (nbfd);
-      return NULL;
-    }
+  if (!bfd_check_format (nbfd.get (), bfd_object))
+    return gdb_bfd_ref_ptr ();
 
   /* Retrieve SPU name note and update BFD name.  */
-  spu_name = bfd_get_section_by_name (nbfd, ".note.spu_name");
+  spu_name = bfd_get_section_by_name (nbfd.get (), ".note.spu_name");
   if (spu_name)
     {
-      int sect_size = bfd_section_size (nbfd, spu_name);
+      int sect_size = bfd_section_size (nbfd.get (), spu_name);
       if (sect_size > 20)
 	{
 	  char *buf = (char *)alloca (sect_size - 20 + 1);
-	  bfd_get_section_contents (nbfd, spu_name, buf, 20, sect_size - 20);
+	  bfd_get_section_contents (nbfd.get (), spu_name, buf, 20,
+				    sect_size - 20);
 	  buf[sect_size - 20] = '\0';
 
 	  xfree ((char *)nbfd->filename);
@@ -367,7 +365,6 @@ static void
 spu_symbol_file_add_from_memory (int inferior_fd)
 {
   ULONGEST addr;
-  struct bfd *nbfd;
 
   gdb_byte id[128];
   char annex[32];
@@ -385,15 +382,12 @@ spu_symbol_file_add_from_memory (int inferior_fd)
     return;
 
   /* Open BFD representing SPE executable and read its symbols.  */
-  nbfd = spu_bfd_open (addr);
-  if (nbfd)
+  gdb_bfd_ref_ptr nbfd (spu_bfd_open (addr));
+  if (nbfd != NULL)
     {
-      struct cleanup *cleanup = make_cleanup_bfd_unref (nbfd);
-
-      symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd),
+      symbol_file_add_from_bfd (nbfd.get (), bfd_get_filename (nbfd),
 				SYMFILE_VERBOSE | SYMFILE_MAINLINE,
 				NULL, 0, NULL);
-      do_cleanups (cleanup);
     }
 }
 
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index 58257b9..ec283b2 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -102,20 +102,21 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
     error (_("Failed to read a valid object file image from memory."));
 
   gdb_bfd_ref (nbfd);
+  /* Manage the new reference for the duration of this function.  */
+  gdb_bfd_ref_ptr nbfd_holder (nbfd);
+
   xfree (bfd_get_filename (nbfd));
   if (name == NULL)
     nbfd->filename = xstrdup ("shared object read from target memory");
   else
     nbfd->filename = name;
 
-  cleanup = make_cleanup_bfd_unref (nbfd);
-
   if (!bfd_check_format (nbfd, bfd_object))
     error (_("Got object file from memory but can't read symbols: %s."),
 	   bfd_errmsg (bfd_get_error ()));
 
   sai = alloc_section_addr_info (bfd_count_sections (nbfd));
-  make_cleanup (xfree, sai);
+  cleanup = make_cleanup (xfree, sai);
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 52f99bf..4775d5b 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -876,8 +876,7 @@ read_symbols (struct objfile *objfile, symfile_add_flags add_flags)
       && objfile->separate_debug_objfile == NULL
       && objfile->separate_debug_objfile_backlink == NULL)
     {
-      bfd *abfd = find_separate_debug_file_in_section (objfile);
-      struct cleanup *cleanup = make_cleanup_bfd_unref (abfd);
+      gdb_bfd_ref_ptr abfd (find_separate_debug_file_in_section (objfile));
 
       if (abfd != NULL)
 	{
@@ -885,11 +884,9 @@ read_symbols (struct objfile *objfile, symfile_add_flags add_flags)
 	     virtual section-as-bfd like the bfd filename containing the
 	     section.  Therefore use also non-canonical name form for the same
 	     file containing the section.  */
-	  symbol_file_add_separate (abfd, objfile->original_name, add_flags,
-				    objfile);
+	  symbol_file_add_separate (abfd.get (), objfile->original_name,
+				    add_flags, objfile);
 	}
-
-      do_cleanups (cleanup);
     }
   if ((add_flags & SYMFILE_NO_READ) == 0)
     require_partial_symbols (objfile, 0);
@@ -1287,13 +1284,10 @@ struct objfile *
 symbol_file_add (const char *name, symfile_add_flags add_flags,
 		 struct section_addr_info *addrs, objfile_flags flags)
 {
-  bfd *bfd = symfile_bfd_open (name);
-  struct cleanup *cleanup = make_cleanup_bfd_unref (bfd);
-  struct objfile *objf;
+  gdb_bfd_ref_ptr bfd (symfile_bfd_open (name));
 
-  objf = symbol_file_add_from_bfd (bfd, name, add_flags, addrs, flags, NULL);
-  do_cleanups (cleanup);
-  return objf;
+  return symbol_file_add_from_bfd (bfd.get (), name, add_flags, addrs,
+				   flags, NULL);
 }
 
 /* Call symbol_file_add() with default values and update whatever is
@@ -1354,7 +1348,6 @@ separate_debug_file_exists (const char *name, unsigned long crc,
 {
   unsigned long file_crc;
   int file_crc_p;
-  bfd *abfd;
   struct stat parent_stat, abfd_stat;
   int verified_as_different;
 
@@ -1367,9 +1360,9 @@ separate_debug_file_exists (const char *name, unsigned long crc,
   if (filename_cmp (name, objfile_name (parent_objfile)) == 0)
     return 0;
 
-  abfd = gdb_bfd_open (name, gnutarget, -1);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (name, gnutarget, -1));
 
-  if (!abfd)
+  if (abfd == NULL)
     return 0;
 
   /* Verify symlinks were not the cause of filename_cmp name difference above.
@@ -1383,24 +1376,19 @@ separate_debug_file_exists (const char *name, unsigned long crc,
      numbers will never set st_ino to zero, this is merely an
      optimization, so we do not need to worry about false negatives.  */
 
-  if (bfd_stat (abfd, &abfd_stat) == 0
+  if (bfd_stat (abfd.get (), &abfd_stat) == 0
       && abfd_stat.st_ino != 0
       && bfd_stat (parent_objfile->obfd, &parent_stat) == 0)
     {
       if (abfd_stat.st_dev == parent_stat.st_dev
 	  && abfd_stat.st_ino == parent_stat.st_ino)
-	{
-	  gdb_bfd_unref (abfd);
-	  return 0;
-	}
+	return 0;
       verified_as_different = 1;
     }
   else
     verified_as_different = 0;
 
-  file_crc_p = gdb_bfd_crc (abfd, &file_crc);
-
-  gdb_bfd_unref (abfd);
+  file_crc_p = gdb_bfd_crc (abfd.get (), &file_crc);
 
   if (!file_crc_p)
     return 0;
@@ -1721,10 +1709,9 @@ set_initial_language (void)
    includes a newly malloc'd` copy of NAME (tilde-expanded and made
    absolute).  In case of trouble, error() is called.  */
 
-bfd *
+gdb_bfd_ref_ptr
 symfile_bfd_open (const char *name)
 {
-  bfd *sym_bfd;
   int desc = -1;
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
 
@@ -1760,20 +1747,17 @@ symfile_bfd_open (const char *name)
       name = absolute_name;
     }
 
-  sym_bfd = gdb_bfd_open (name, gnutarget, desc);
-  if (!sym_bfd)
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (name, gnutarget, desc));
+  if (sym_bfd == NULL)
     error (_("`%s': can't open to read symbols: %s."), name,
 	   bfd_errmsg (bfd_get_error ()));
 
-  if (!gdb_bfd_has_target_filename (sym_bfd))
-    bfd_set_cacheable (sym_bfd, 1);
+  if (!gdb_bfd_has_target_filename (sym_bfd.get ()))
+    bfd_set_cacheable (sym_bfd.get (), 1);
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
-    {
-      make_cleanup_bfd_unref (sym_bfd);
-      error (_("`%s': can't read symbols: %s."), name,
-	     bfd_errmsg (bfd_get_error ()));
-    }
+  if (!bfd_check_format (sym_bfd.get (), bfd_object))
+    error (_("`%s': can't read symbols: %s."), name,
+	   bfd_errmsg (bfd_get_error ()));
 
   do_cleanups (back_to);
 
@@ -2073,7 +2057,6 @@ static void print_transfer_performance (struct ui_file *stream,
 void
 generic_load (const char *args, int from_tty)
 {
-  bfd *loadfile_bfd;
   char *filename;
   struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
   struct load_section_data cbdata;
@@ -2114,25 +2097,23 @@ generic_load (const char *args, int from_tty)
     }
 
   /* Open the file for loading.  */
-  loadfile_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr loadfile_bfd (gdb_bfd_open (filename, gnutarget, -1));
   if (loadfile_bfd == NULL)
     {
       perror_with_name (filename);
       return;
     }
 
-  make_cleanup_bfd_unref (loadfile_bfd);
-
-  if (!bfd_check_format (loadfile_bfd, bfd_object))
+  if (!bfd_check_format (loadfile_bfd.get (), bfd_object))
     {
       error (_("\"%s\" is not an object file: %s"), filename,
 	     bfd_errmsg (bfd_get_error ()));
     }
 
-  bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
+  bfd_map_over_sections (loadfile_bfd.get (), add_section_size_callback,
 			 (void *) &total_progress.total_size);
 
-  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+  bfd_map_over_sections (loadfile_bfd.get (), load_section_callback, &cbdata);
 
   using namespace std::chrono;
 
@@ -2144,7 +2125,7 @@ generic_load (const char *args, int from_tty)
 
   steady_clock::time_point end_time = steady_clock::now ();
 
-  entry = bfd_get_start_address (loadfile_bfd);
+  entry = bfd_get_start_address (loadfile_bfd.get ());
   entry = gdbarch_addr_bits_remove (target_gdbarch (), entry);
   ui_out_text (uiout, "Start address ");
   ui_out_field_fmt (uiout, "address", "%s", paddress (target_gdbarch (), entry));
@@ -2568,22 +2549,16 @@ reread_symbols (void)
 
 	  /* Clean up any state BFD has sitting around.  */
 	  {
-	    struct bfd *obfd = objfile->obfd;
+	    gdb_bfd_ref_ptr obfd (objfile->obfd);
 	    char *obfd_filename;
 
 	    obfd_filename = bfd_get_filename (objfile->obfd);
 	    /* Open the new BFD before freeing the old one, so that
 	       the filename remains live.  */
-	    objfile->obfd = gdb_bfd_open (obfd_filename, gnutarget, -1);
+	    gdb_bfd_ref_ptr temp (gdb_bfd_open (obfd_filename, gnutarget, -1));
+	    objfile->obfd = temp.release ();
 	    if (objfile->obfd == NULL)
-	      {
-		/* We have to make a cleanup and error here, rather
-		   than erroring later, because once we unref OBFD,
-		   OBFD_FILENAME will be freed.  */
-		make_cleanup_bfd_unref (obfd);
-		error (_("Can't open %s to read symbols."), obfd_filename);
-	      }
-	    gdb_bfd_unref (obfd);
+	      error (_("Can't open %s to read symbols."), obfd_filename);
 	  }
 
 	  original_name = xstrdup (objfile->original_name);
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 59952cb..7a2e6fb 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -25,6 +25,7 @@
 #include "probe.h"
 #include "symfile-add-flags.h"
 #include "objfile-flags.h"
+#include "gdb_bfd.h"
 
 /* Opaque declarations.  */
 struct target_section;
@@ -499,7 +500,7 @@ extern void set_initial_language (void);
 
 extern void find_lowest_section (bfd *, asection *, void *);
 
-extern bfd *symfile_bfd_open (const char *);
+extern gdb_bfd_ref_ptr symfile_bfd_open (const char *);
 
 extern int get_section_index (struct objfile *, char *);
 
@@ -646,6 +647,6 @@ extern void elfmdebug_build_psymtabs (struct objfile *,
 
 /* From minidebug.c.  */
 
-extern bfd *find_separate_debug_file_in_section (struct objfile *);
+extern gdb_bfd_ref_ptr find_separate_debug_file_in_section (struct objfile *);
 
 #endif /* !defined(SYMFILE_H) */
diff --git a/gdb/utils.c b/gdb/utils.c
index 77c38bf..6ee6fc8 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -151,18 +151,6 @@ make_cleanup_freeargv (char **arg)
   return make_cleanup (do_freeargv, arg);
 }
 
-static void
-do_bfd_close_cleanup (void *arg)
-{
-  gdb_bfd_unref ((bfd *) arg);
-}
-
-struct cleanup *
-make_cleanup_bfd_unref (bfd *abfd)
-{
-  return make_cleanup (do_bfd_close_cleanup, abfd);
-}
-
 /* Helper function which does the work for make_cleanup_fclose.  */
 
 static void
diff --git a/gdb/utils.h b/gdb/utils.h
index 349530e..4407eeb 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -81,8 +81,6 @@ extern struct cleanup *(make_cleanup_free_section_addr_info
 
 extern struct cleanup *make_cleanup_fclose (FILE *file);
 
-extern struct cleanup *make_cleanup_bfd_unref (bfd *abfd);
-
 struct obstack;
 extern struct cleanup *make_cleanup_obstack_free (struct obstack *obstack);
 
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 5b79f34..efccd71 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -669,32 +669,27 @@ windows_make_so (const char *name, LPVOID load_addr)
   p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
   if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
     {
-      bfd *abfd;
       asection *text = NULL;
       CORE_ADDR text_vma;
 
-      abfd = gdb_bfd_open (so->so_name, "pei-i386", -1);
+      gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386", -1));
 
-      if (!abfd)
+      if (abfd == NULL)
 	return so;
 
-      if (bfd_check_format (abfd, bfd_object))
-	text = bfd_get_section_by_name (abfd, ".text");
+      if (bfd_check_format (abfd.get (), bfd_object))
+	text = bfd_get_section_by_name (abfd.get (), ".text");
 
       if (!text)
-	{
-	  gdb_bfd_unref (abfd);
-	  return so;
-	}
+	return so;
 
       /* The symbols in a dll are offset by 0x1000, which is the
 	 offset from 0 of the first byte in an image - because of the
 	 file header and the section alignment.  */
       cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
 						   load_addr + 0x1000);
-      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
-
-      gdb_bfd_unref (abfd);
+      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd.get (),
+							      text);
     }
 #endif
 
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 810607a..2f79d8d 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -372,7 +372,6 @@ windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
 			     struct gdbarch *gdbarch, struct obstack *obstack)
 {
   char *p;
-  struct bfd * dll;
   CORE_ADDR text_offset;
 
   obstack_grow_str (obstack, "<library name=\"");
@@ -380,12 +379,11 @@ windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
   obstack_grow_str (obstack, p);
   xfree (p);
   obstack_grow_str (obstack, "\"><segment address=\"");
-  dll = gdb_bfd_open (so_name, gnutarget, -1);
+  gdb_bfd_ref_ptr dll (gdb_bfd_open (so_name, gnutarget, -1));
   /* The following calls are OK even if dll is NULL.
      The default value 0x1000 is returned by pe_text_section_offset
      in that case.  */
-  text_offset = pe_text_section_offset (dll);
-  gdb_bfd_unref (dll);
+  text_offset = pe_text_section_offset (dll.get ());
   obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset));
   obstack_grow_str (obstack, "\"/></library>");
 }
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [RFA 1/8] Add gdb_ref_ptr.h
  2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
                   ` (2 preceding siblings ...)
  2016-11-29  5:06 ` [RFA 2/8] Use class to manage BFD reference counts Tom Tromey
@ 2016-11-29  5:06 ` Tom Tromey
  2016-12-02 13:08   ` Pedro Alves
  2016-12-03  0:05   ` Pedro Alves
  2016-11-29  5:06 ` [RFA 4/8] Remove make_cleanup_discard_psymtabs Tom Tromey
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:06 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds a new gdb_ref_ptr.h, that implements a reference-counting
smart pointer class, where the user of the class supplies a
reference-counting policy object.

This class will be used in the next patch, which changes most explicit
BFD reference counts to use this new type.  Meanwhile, this patch
changes gdbpy_ref to be a specialization of this new class.

This change required adding new nullptr_t overloads some operators in
gdb_ref_ptr.h.  I suspect this was needed because some Python header
redefines NULL, but I'm not certain.

2016-11-28  Tom Tromey  <tom@tromey.com>

	* common/gdb_ref_ptr.h: New file.
	* python/py-ref.h (struct gdbpy_ref_policy): New.
	(gdbpy_ref): Now a typedef.
---
 gdb/ChangeLog            |   6 ++
 gdb/common/gdb_ref_ptr.h | 209 +++++++++++++++++++++++++++++++++++++++++++++++
 gdb/python/py-ref.h      | 135 ++----------------------------
 3 files changed, 224 insertions(+), 126 deletions(-)
 create mode 100644 gdb/common/gdb_ref_ptr.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8cbe8ad..f455f7f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
 2016-11-28  Tom Tromey  <tom@tromey.com>
 
+	* common/gdb_ref_ptr.h: New file.
+	* python/py-ref.h (struct gdbpy_ref_policy): New.
+	(gdbpy_ref): Now a typedef.
+
+2016-11-28  Tom Tromey  <tom@tromey.com>
+
 	* utils.h (make_cleanup_htab_delete): Don't declare.
 	* utils.c (do_htab_delete_cleanup, make_cleanup_htab_delete):
 	Remove.
diff --git a/gdb/common/gdb_ref_ptr.h b/gdb/common/gdb_ref_ptr.h
new file mode 100644
index 0000000..cc8ba94
--- /dev/null
+++ b/gdb/common/gdb_ref_ptr.h
@@ -0,0 +1,209 @@
+/* Reference-counted smart pointer class
+
+   Copyright (C) 2016 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_REF_PTR_H
+#define GDB_REF_PTR_H
+
+#include <cstddef>
+
+namespace gdb
+{
+
+/* An instance of this class either holds a reference to a
+   reference-counted object or is "NULL".  Reference counting is
+   handled externally by a policy class.  If the object holds a
+   reference, then when the object is destroyed, the reference is
+   decref'd.
+
+   Normally an instance is constructed using a pointer.  This sort of
+   initialization lets this class manage the lifetime of that
+   reference.
+
+   Assignment and copy construction will make a new reference as
+   appropriate.  Assignment from a plain pointer is disallowed to
+   avoid confusion about whether this acquires a new reference;
+   instead use the "reset" method -- which, like the pointer
+   constructor, transfers ownership.
+
+   The policy class must provide two static methods:
+   void incref (T *);
+   void decref (T *);
+*/
+template<typename T, typename POLICY>
+class ref_ptr
+{
+ public:
+
+  /* Create a new NULL instance.  */
+  ref_ptr ()
+    : m_obj (NULL)
+  {
+  }
+
+  /* Create a new instance.  OBJ is a reference, management of which
+     is now transferred to this class.  */
+  explicit ref_ptr (T *obj)
+    : m_obj (obj)
+  {
+  }
+
+  /* Copy another instance.  */
+  ref_ptr (const ref_ptr &other)
+    : m_obj (other.m_obj)
+  {
+    if (m_obj != NULL)
+      POLICY::incref (m_obj);
+  }
+
+  /* Transfer ownership from OTHER.  */
+  ref_ptr (ref_ptr &&other)
+    : m_obj (other.m_obj)
+  {
+    other.m_obj = NULL;
+  }
+
+  /* Destroy this instance.  */
+  ~ref_ptr ()
+  {
+    if (m_obj != NULL)
+      POLICY::decref (m_obj);
+  }
+
+  /* Copy another instance.  */
+  ref_ptr &operator= (const ref_ptr &other)
+  {
+    /* Do nothing on self-assignment.  */
+    if (this != &other)
+      {
+	reset (other.m_obj);
+	if (m_obj != NULL)
+	  POLICY::incref (m_obj);
+      }
+    return *this;
+  }
+
+  /* Transfer ownership from OTHER.  */
+  ref_ptr &operator= (ref_ptr &&other)
+  {
+    /* Do nothing on self-assignment.  */
+    if (this != &other)
+      {
+	reset (other.m_obj);
+	other.m_obj = NULL;
+      }
+    return *this;
+  }
+
+  /* Change this instance's referent.  OBJ is a reference, management
+     of which is now transferred to this class.  */
+  void reset (T *obj)
+  {
+    if (m_obj != NULL)
+      POLICY::decref (m_obj);
+    m_obj = obj;
+  }
+
+  /* Return this instance's referent without changing the state of
+     this class.  */
+  T *get () const
+  {
+    return m_obj;
+  }
+
+  /* Return this instance's referent, and stop managing this
+     reference.  The caller is now responsible for the ownership of
+     the reference.  */
+  T *release ()
+  {
+    T *result = m_obj;
+
+    m_obj = NULL;
+    return result;
+  }
+
+ private:
+
+  T *m_obj;
+};
+
+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self,
+			const ref_ptr<T, POLICY> &other)
+{
+  return self.get () == other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self, const T *other)
+{
+  return self.get () == other;
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self, const std::nullptr_t)
+{
+  return self.get () == nullptr;
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const T *self, const ref_ptr<T, POLICY> &other)
+{
+  return self == other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const std::nullptr_t, const ref_ptr<T, POLICY> &other)
+{
+  return nullptr == other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const ref_ptr<T, POLICY> &self,
+			const ref_ptr<T, POLICY> &other)
+{
+  return self.get () != other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const ref_ptr<T, POLICY> &self, const T *other)
+{
+  return self.get () != other;
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const ref_ptr<T, POLICY> &self, const std::nullptr_t)
+{
+  return self.get () != nullptr;
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const T *self, const ref_ptr<T, POLICY> &other)
+{
+  return self != other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const std::nullptr_t, const ref_ptr<T, POLICY> &other)
+{
+  return nullptr != other.get ();
+}
+
+}
+
+#endif /* GDB_REF_PTR_H */
diff --git a/gdb/python/py-ref.h b/gdb/python/py-ref.h
index f0e4aae..b2479bf 100644
--- a/gdb/python/py-ref.h
+++ b/gdb/python/py-ref.h
@@ -20,140 +20,23 @@
 #ifndef GDB_PYTHON_REF_H
 #define GDB_PYTHON_REF_H
 
-/* An instance of this class either holds a reference to a PyObject,
-   or is "NULL".  If it holds a reference, then when the object is
-   destroyed, the PyObject is decref'd.
+#include "common/gdb_ref_ptr.h"
 
-   Normally an instance is constructed using a PyObject*.  This sort
-   of initialization lets this class manage the lifetime of that
-   reference.
-
-   Assignment and copy construction will make a new reference as
-   appropriate.  Assignment from a plain PyObject* is disallowed to
-   avoid confusion about whether this acquires a new reference;
-   instead use the "reset" method -- which, like the PyObject*
-   constructor, transfers ownership.
-*/
-class gdbpy_ref
+/* A policy class for gdb::ref_ptr for Python reference counting.  */
+struct gdbpy_ref_policy
 {
- public:
-
-  /* Create a new NULL instance.  */
-  gdbpy_ref ()
-    : m_obj (NULL)
-  {
-  }
-
-  /* Create a new instance.  OBJ is a reference, management of which
-     is now transferred to this class.  */
-  explicit gdbpy_ref (PyObject *obj)
-    : m_obj (obj)
-  {
-  }
-
-  /* Copy another instance.  */
-  gdbpy_ref (const gdbpy_ref &other)
-    : m_obj (other.m_obj)
-  {
-    Py_XINCREF (m_obj);
-  }
-
-  /* Transfer ownership from OTHER.  */
-  gdbpy_ref (gdbpy_ref &&other)
-    : m_obj (other.m_obj)
-  {
-    other.m_obj = NULL;
-  }
-
-  /* Destroy this instance.  */
-  ~gdbpy_ref ()
-  {
-    Py_XDECREF (m_obj);
-  }
-
-  /* Copy another instance.  */
-  gdbpy_ref &operator= (const gdbpy_ref &other)
-  {
-    /* Do nothing on self-assignment.  */
-    if (this != &other)
-      {
-	reset (other.m_obj);
-	Py_XINCREF (m_obj);
-      }
-    return *this;
-  }
-
-  /* Transfer ownership from OTHER.  */
-  gdbpy_ref &operator= (gdbpy_ref &&other)
+  static void incref (PyObject *ptr)
   {
-    /* Do nothing on self-assignment.  */
-    if (this != &other)
-      {
-	reset (other.m_obj);
-	other.m_obj = NULL;
-      }
-    return *this;
+    Py_INCREF (ptr);
   }
 
-  /* Change this instance's referent.  OBJ is a reference, management
-     of which is now transferred to this class.  */
-  void reset (PyObject *obj)
+  static void decref (PyObject *ptr)
   {
-    Py_XDECREF (m_obj);
-    m_obj = obj;
+    Py_DECREF (ptr);
   }
-
-  /* Return this instance's referent.  In Python terms this is a
-     borrowed pointer.  */
-  PyObject *get () const
-  {
-    return m_obj;
-  }
-
-  /* Return this instance's referent, and stop managing this
-     reference.  The caller is now responsible for the ownership of
-     the reference.  */
-  PyObject *release ()
-  {
-    PyObject *result = m_obj;
-
-    m_obj = NULL;
-    return result;
-  }
-
- private:
-
-  PyObject *m_obj;
 };
 
-inline bool operator== (const gdbpy_ref &self, const gdbpy_ref &other)
-{
-  return self.get () == other.get ();
-}
-
-inline bool operator== (const gdbpy_ref &self, const PyObject *other)
-{
-  return self.get () == other;
-}
-
-inline bool operator== (const PyObject *self, const gdbpy_ref &other)
-{
-  return self == other.get ();
-}
-
-inline bool operator!= (const gdbpy_ref &self, const gdbpy_ref &other)
-{
-  return self.get () != other.get ();
-}
-
-inline bool operator!= (const gdbpy_ref &self, const PyObject *other)
-{
-  return self.get () != other;
-}
-
-inline bool operator!= (const PyObject *self, const gdbpy_ref &other)
-{
-  return self != other.get ();
-}
+/* A gdb::ref_ptr that has been specialized for Python objects.  */
+typedef gdb::ref_ptr<PyObject, gdbpy_ref_policy> gdbpy_ref;
 
 #endif /* GDB_PYTHON_REF_H */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-11-29  5:06 ` [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command Tom Tromey
@ 2016-11-29  5:22   ` Tom Tromey
  2016-12-15  3:49     ` Tom Tromey
  2016-12-02 14:49   ` Pedro Alves
  1 sibling, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-11-29  5:22 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> This replaces a cleanup in execute_gdb_command with an instance of
Tom> unique_xmalloc_ptr.  std::string was not used because execute_command
Tom> and execute_command_to_string don't accept a "const char *" (in fact
Tom> the reason for copying the string at all).

To my surprise, this patch is broken.
I must not have re-run the python tests locally after writing it :(

The problem is that prevent_dont_repeat returns a cleanup, which is then
left dangling after this patch.

I'm looking into a fix.  Meanwhile I think the rest of the series can
still be considered.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 2/8] Use class to manage BFD reference counts
  2016-11-29  5:06 ` [RFA 2/8] Use class to manage BFD reference counts Tom Tromey
@ 2016-12-02 13:05   ` Pedro Alves
  2016-12-13 13:26     ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 13:05 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches


> @@ -10535,7 +10526,7 @@ open_dwo_file (const char *file_name, const char *comp_dir)
>       is a list of paths.  */
>  
>    if (*debug_file_directory == '\0')
> -    return NULL;
> +    return gdb_bfd_ref_ptr ();

This provides a good reason to have an implicit construction from nullptr_t.
You had it in the original gdbpy_reference submission, but I had asked
to remove it.  If we add it back, these cases could be more clearly
written as "return NULL/nullptr".  Could you do that, and then drop all
the hunks like:

 > -    return NULL;
 > +    return gdb_bfd_ref_ptr ();

?

> @@ -658,82 +654,70 @@ solib_aix_bfd_open (char *pathname)
>      }
>    filename_len = sep - pathname;
>  
> -  filename = xstrprintf ("%.*s", filename_len, pathname);
> -  cleanup = make_cleanup (xfree, filename);
> -  member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
> -  make_cleanup (xfree, member_name);
> +  gdb::unique_xmalloc_ptr<char> filename
> +    (xstrprintf ("%.*s", filename_len, pathname));
> +  gdb::unique_xmalloc_ptr<char> member_name
> +    (xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1));

I think these could be:

    std::string filename
      = string_printf ("%.*s", filename_len, pathname);
    std::string member_name
      = string_printf ("%.*s", path_len - filename_len - 2, sep + 1));

>  
>    /* Calling solib_find makes certain that sysroot path is set properly
>       if program has a dependency on .a archive and sysroot is set via
>       set sysroot command.  */
> -  found_pathname = solib_find (filename, &found_file);
> +  found_pathname = solib_find (filename.get (), &found_file);
>    if (found_pathname == NULL)
>        perror_with_name (pathname);
> -  archive_bfd = solib_bfd_fopen (found_pathname, found_file);
> +  gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname, found_file));
>    if (archive_bfd == NULL)
>      {
>        warning (_("Could not open `%s' as an executable file: %s"),
> -	       filename, bfd_errmsg (bfd_get_error ()));
> -      do_cleanups (cleanup);
> -      return NULL;
> +	       filename.get (), bfd_errmsg (bfd_get_error ()));
> +      return gdb_bfd_ref_ptr ();
>      }
>  
> -  if (bfd_check_format (archive_bfd, bfd_object))
> -    {
> -      do_cleanups (cleanup);
> -      return archive_bfd;
> -    }
> +  if (bfd_check_format (archive_bfd.get (), bfd_object))
> +    return archive_bfd;
>  
> -  if (! bfd_check_format (archive_bfd, bfd_archive))
> +  if (! bfd_check_format (archive_bfd.get (), bfd_archive))
>      {
>        warning (_("\"%s\": not in executable format: %s."),
> -	       filename, bfd_errmsg (bfd_get_error ()));
> -      gdb_bfd_unref (archive_bfd);
> -      do_cleanups (cleanup);
> -      return NULL;
> +	       filename.get (), bfd_errmsg (bfd_get_error ()));
> +      return gdb_bfd_ref_ptr ();
>      }
>  
> -  object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
> +  gdb_bfd_ref_ptr object_bfd
> +    (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
>    while (object_bfd != NULL)
>      {
> -      bfd *next;
> -
> -      if (strcmp (member_name, object_bfd->filename) == 0)
> +      if (strcmp (member_name.get (), object_bfd->filename) == 0)
>  	break;

Then here:

    member_name == object_bfd->filename

>  
> -      next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
> -      gdb_bfd_unref (object_bfd);
> -      object_bfd = next;
> +      object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
> +						     object_bfd.get ());
>      }
>  

Otherwise LGTM.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-11-29  5:06 ` [RFA 1/8] Add gdb_ref_ptr.h Tom Tromey
@ 2016-12-02 13:08   ` Pedro Alves
  2016-12-02 17:46     ` Tom Tromey
  2016-12-03  0:05   ` Pedro Alves
  1 sibling, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 13:08 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This adds a new gdb_ref_ptr.h, that implements a reference-counting
> smart pointer class, where the user of the class supplies a
> reference-counting policy object.
> 
> This class will be used in the next patch, which changes most explicit
> BFD reference counts to use this new type.  Meanwhile, this patch
> changes gdbpy_ref to be a specialization of this new class.
> 
> This change required adding new nullptr_t overloads some operators in
> gdb_ref_ptr.h.  I suspect this was needed because some Python header
> redefines NULL, but I'm not certain.

Can you please remove them and see what breaks?  Odd that this would be
something about Python, given the class is being used in Python code
today?

BTW, it's worth noting that there's a proposal to add (an oddly named)
policy-based intrusive ref counting smart pointer to the standard:

 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0468r0.html

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 3/8] Introduce and use gdb::unlinker
  2016-11-29  5:06 ` [RFA 3/8] Introduce and use gdb::unlinker Tom Tromey
@ 2016-12-02 13:17   ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 13:17 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This introduces a new class, gdb::unlinker, that unlinks a file in the
> destructor.  The user of this class has the option to preserve the
> file instead, by calling the "keep" method.

Thanks.

> 
> This patch then changes the spots in gdb that use unlink in a cleanup
> to use this class instead.  In one spot I went ahead and removed all
> the cleanups from the function.
> 
> This fixes one latent bug -- do_bfd_delete_cleanup could refer to
> freed memory, by decref'ing the BFD before using its filename.

LGTM.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 4/8] Remove make_cleanup_discard_psymtabs
  2016-11-29  5:06 ` [RFA 4/8] Remove make_cleanup_discard_psymtabs Tom Tromey
@ 2016-12-02 14:21   ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 14:21 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This removes make_cleanup_discard_psymtabs in favor of a new class.
> 
> 2016-11-28  Tom Tromey  <tom@tromey.com>
> 
> 	* dwarf2read.c (dwarf2_build_psymtabs): Use psymtab_discarder.
> 	* psympriv.h (make_cleanup_discard_psymtabs): Don't declare.
> 	* psymtab.c (discard_psymtabs_upto): Remove.
> 	(make_cleanup_discard_psymtabs): Remove.
> 	(struct psymtab_state): Remove.

OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 5/8] Add value_freer
  2016-11-29  5:06 ` [RFA 5/8] Add value_freer Tom Tromey
@ 2016-12-02 14:24   ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 14:24 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This adds a value_freer class, that records the value mark in the
> constructor and then calls value_free_to_mark in the destructor.  It
> then updates various spots in gdb to use this class, rather than a
> cleanup.
> 
> It would be better overall to replace "struct value *" with a
> shared_ptr, maybe eliminating the need for this class (watchpoints
> would perhaps need some new mechanism as well).  However, that's
> difficult to do.
> 
> 2016-11-28  Tom Tromey  <tom@tromey.com>
> 
> 	* python/py-value.c (valpy_dereference, valpy_referenced_value)
> 	(valpy_reference_value, valpy_const_value, valpy_get_address)
> 	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
> 	(valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
> 	(valpy_absolute, valpy_richcompare_throw): Use value_freer.
> 	* dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
> 	value_freer.
> 	* dwarf2-frame.c (execute_stack_op): Use value_freer.
> 	* value.h (value_freer): New class.

OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-11-29  5:06 ` [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full Tom Tromey
@ 2016-12-02 14:45   ` Pedro Alves
  2016-12-13 13:29     ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 14:45 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This changes dwarf2_evaluate_loc_desc_full to use value_freer.
> 
> Note that this function previously called do_cleanup using the same
> cleanup multiple times.  I had thought this was buggy, but re-reading
> make_my_cleanup2 indicates that it is not.  Nevertheless it is
> surprising, and at least one of the calls (the one that is completely
> removed in this patch) seems to have been done under the assumption
> that it would still have some effect.
> 
> 2016-11-28  Tom Tromey  <tom@tromey.com>
> 
> 	* value.h (value_freer::~value_freer): Call release.
> 	(value_freer::release): New method.
> 	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use value_freer.
> ---
>  gdb/ChangeLog   |  6 ++++++
>  gdb/dwarf2loc.c | 27 +++++++++++++--------------
>  gdb/value.h     | 12 +++++++++++-
>  3 files changed, 30 insertions(+), 15 deletions(-)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 6197bfb..cf61306 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,11 @@
>  2016-11-28  Tom Tromey  <tom@tromey.com>
>  
> +	* value.h (value_freer::~value_freer): Call release.
> +	(value_freer::release): New method.
> +	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use value_freer.
> +
> +2016-11-28  Tom Tromey  <tom@tromey.com>
> +
>  	* python/py-value.c (valpy_dereference, valpy_referenced_value)
>  	(valpy_reference_value, valpy_const_value, valpy_get_address)
>  	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
> diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> index 0d8a47c..43c95b8 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -2321,7 +2321,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
>  			       LONGEST byte_offset)
>  {
>    struct value *retval;
> -  struct cleanup *value_chain;
>    struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
>  
>    if (byte_offset < 0)
> @@ -2335,7 +2334,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
>    ctx.per_cu = per_cu;
>    ctx.obj_address = 0;
>  
> -  value_chain = make_cleanup_value_free_to_mark (value_mark ());
> +  value_freer free_values;
>  
>    ctx.gdbarch = get_objfile_arch (objfile);
>    ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
> @@ -2350,7 +2349,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
>      {
>        if (ex.error == NOT_AVAILABLE_ERROR)
>  	{
> -	  do_cleanups (value_chain);
> +	  free_values.release ();

"release ()" looks potentially confusing to me, if you're in an
"unique_ptr" mindset, where release means the opposite -- to stop
managing.  Can we call that something else?

Maybe "free", since the class is called value_freer?

Or "reset ()", following the naming used in the standard smart pointers?

The latter could be naturally extended to support

  free_values.reset (value_mark ());

later too, if we need it.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-11-29  5:06 ` [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command Tom Tromey
  2016-11-29  5:22   ` Tom Tromey
@ 2016-12-02 14:49   ` Pedro Alves
  2016-12-13 13:30     ` Tom Tromey
  1 sibling, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 14:49 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This replaces a cleanup in execute_gdb_command with an instance of
> unique_xmalloc_ptr.  std::string was not used because execute_command
> and execute_command_to_string don't accept a "const char *" (in fact
> the reason for copying the string at all).

You can do:

 std::string copy (arg);
 ...
 to_string_res = execute_command_to_string (&copy[0], from_tty);

That's fine in C++11.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 8/8] Add constructor and destructor to demangle_parse_info
  2016-11-29  5:06 ` [RFA 8/8] Add constructor and destructor to demangle_parse_info Tom Tromey
@ 2016-12-02 15:04   ` Pedro Alves
  2016-12-13 13:50     ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 15:04 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:

> @@ -646,7 +623,8 @@ mangled_name_to_comp (const char *mangled_name, int options,
>    
>    /* If we could demangle the name, parse it to build the component
>       tree.  */
> -  info = cp_demangled_name_to_comp (demangled_name, NULL);
> +  std::unique_ptr<demangle_parse_info> info
> +    (cp_demangled_name_to_comp (demangled_name, NULL));

Style question:

When initializing a unique_ptr from a function that returns a
unique_ptr already, IMO, using = reads a little better
over ()s, like:

  std::unique_ptr<demangle_parse_info> info
    = cp_demangled_name_to_comp (demangled_name, NULL);

I.e., kind of like how you'd call make_unique with '=' instead
of

 unique_ptr<T> foo (make_unique<T>());

which I've never seen.

I wonder whether that's just me?

> diff --git a/gdb/cp-support.h b/gdb/cp-support.h
> index ca7a7d4..ffccded 100644
> --- a/gdb/cp-support.h
> +++ b/gdb/cp-support.h
> @@ -58,6 +58,10 @@ struct demangle_parse_info
>  
>    /* Any temporary memory used during typedef replacement.  */
>    struct obstack obstack;
> +
> +  demangle_parse_info ();
> +
> +  ~demangle_parse_info ();

Put these before the data fields.

Otherwise LGTM.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-12-02 13:08   ` Pedro Alves
@ 2016-12-02 17:46     ` Tom Tromey
  2016-12-02 18:11       ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-02 17:46 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Can you please remove them and see what breaks?  Odd that this would be
Pedro> something about Python, given the class is being used in Python code
Pedro> today?

Yes, it's odd.  If I comment out the nullptr_t overloads, I get build
failures like:

../../binutils-gdb/gdb/python/py-exitedevent.c:31:20: error: no match for ‘operator==’ (operand types are ‘gdbpy_ref {aka gdb::ref_ptr<_object, gdbpy_ref_policy>}’ and ‘long int’)
   if (exited_event == NULL)
                    ^
../../binutils-gdb/gdb/common/gdb_ref_ptr.h:183:13: note:   template argument deduction/substitution failed:
In file included from ../../binutils-gdb/gdb/python/py-ref.h:23:0,
                 from ../../binutils-gdb/gdb/python/py-event.h:27,
                 from ../../binutils-gdb/gdb/python/py-event.c:21:
../../binutils-gdb/gdb/common/gdb_ref_ptr.h:171:13: note: candidate: template<class T, class POLICY> bool gdb::operator==(const T*, const gdb::ref_ptr<T, POLICY>&)
 inline bool operator== (const T *self, const ref_ptr<T, POLICY> &other)
             ^~~~~~~~


I don't understand why it picks this particular candidate, but
re-reading it now I think my earlier theory is wrong.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-12-02 17:46     ` Tom Tromey
@ 2016-12-02 18:11       ` Pedro Alves
  2016-12-02 19:52         ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 18:11 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/02/2016 05:46 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> Can you please remove them and see what breaks?  Odd that this would be
> Pedro> something about Python, given the class is being used in Python code
> Pedro> today?
> 
> Yes, it's odd.  If I comment out the nullptr_t overloads, I get build
> failures like:
> 
> ../../binutils-gdb/gdb/python/py-exitedevent.c:31:20: error: no match for ‘operator==’ (operand types are ‘gdbpy_ref {aka gdb::ref_ptr<_object, gdbpy_ref_policy>}’ and ‘long int’)
>    if (exited_event == NULL)
>                     ^
> ../../binutils-gdb/gdb/common/gdb_ref_ptr.h:183:13: note:   template argument deduction/substitution failed:
> In file included from ../../binutils-gdb/gdb/python/py-ref.h:23:0,
>                  from ../../binutils-gdb/gdb/python/py-event.h:27,
>                  from ../../binutils-gdb/gdb/python/py-event.c:21:
> ../../binutils-gdb/gdb/common/gdb_ref_ptr.h:171:13: note: candidate: template<class T, class POLICY> bool gdb::operator==(const T*, const gdb::ref_ptr<T, POLICY>&)
>  inline bool operator== (const T *self, const ref_ptr<T, POLICY> &other)
>              ^~~~~~~~
> 
> 
> I don't understand why it picks this particular candidate, but

I think gcc will list you all candidates, mentioning why each one
can't work.  I.e., it likely tells you more further below?

> re-reading it now I think my earlier theory is wrong.

Does it still happen if you remove the cstddef include?

Do you have your code in some branch?  It seems none of the
gdbpy_ref stuff is in master yet.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-12-02 18:11       ` Pedro Alves
@ 2016-12-02 19:52         ` Tom Tromey
  2016-12-02 23:45           ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-02 19:52 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> I think gcc will list you all candidates, mentioning why each one
Pedro> can't work.  I.e., it likely tells you more further below?

Yeah, it does, I missed that.

Pedro> Does it still happen if you remove the cstddef include?

Yes.

Pedro> Do you have your code in some branch?  It seems none of the
Pedro> gdbpy_ref stuff is in master yet.

I pushed it to py-cxx-changes on my github account.
I haven't pushed anything in since I have one giant branch and there
were some issues with a couple individual patches.  The final two
patches on that branch aren't submitted yet, they are the fixes I need
to fold in and resubmit.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-12-02 19:52         ` Tom Tromey
@ 2016-12-02 23:45           ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-02 23:45 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/02/2016 07:52 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> I think gcc will list you all candidates, mentioning why each one
> Pedro> can't work.  I.e., it likely tells you more further below?
> 
> Yeah, it does, I missed that.

Ah, trying locally and getting at the compile log helped.  The overload
we'd expect to work, doesn't:

..../src/gdb/solib-darwin.c: In function ‘void darwin_solib_get_all_image_info_addr_at_init(darwin_info*)’:
..../src/gdb/solib-darwin.c:467:16: error: no match for ‘operator!=’ (operand types are ‘gdb_bfd_ref_ptr {aka gdb::ref_ptr<bfd, gdb_bfd_ref_policy>}’ and ‘long int’)
   if (dyld_bfd != NULL)
                ^
[...]
..../src/gdb/common/gdb_ref_ptr.h:212:13: note: candidate: template<class T, class POLICY> bool gdb::operator!=(const gdb::ref_ptr<T, POLICY>&, const T*)
 inline bool operator!= (const ref_ptr<T, POLICY> &self, const T *other)
             ^
..../src/gdb/common/gdb_ref_ptr.h:212:13: note:   template argument deduction/substitution failed:
..../src/gdb/solib-darwin.c:467:19: note:   mismatched types ‘const T*’ and ‘long int’
   if (dyld_bfd != NULL)
                   ^
[...]

That's simply because template type deduction, which happens
before overload resolution, does not consider implicit conversions.
And then there's no overload in the overload set that satisfied
the operation.

Before the gdb_ref_ptr.h patch (this email thread), gdbpy_ref
is not a template, so:

  inline bool operator!= (const gdbpy_ref &self, const PyObject *other);

is left in the overload set, at which point implicit conversions can
apply.

I was a bit mystified about why my gdb_unique_ptr shim had == NULL
working without nullptr_t overloads, but I remember now.  It was
because it was using the safe bool idiom to make it work.  I.e.,
adding this to ref_ptr would make operator==/operator!= work without
the nullptr_t overloads too:

  /* "explicit operator bool ()" emulation using the safe bool
     idiom.  */
private:
  typedef void (ref_ptr::*explicit_operator_bool) () const;
  void this_type_does_not_support_comparisons () const {}

public:
  operator explicit_operator_bool () const
  {
    return (m_obj != NULL
           ? &ref_ptr::this_type_does_not_support_comparisons
           : 0);
  }

With this, despite the fact that no operator== candidate template
matches, the compile still manages to call the built-in, non-template:

 bool operator==(member function ptr, long);

> Pedro> Do you have your code in some branch?  It seems none of the
> Pedro> gdbpy_ref stuff is in master yet.
> 
> I pushed it to py-cxx-changes on my github account.

Thanks, that helped.

So the conclusion is that the nullptr_t overloads are necessary because
ref_ptr is now a template.

BTW, notice that both retain_ptr (that proposal I linked to), and unique_ptr
have these same overloads.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-11-29  5:06 ` [RFA 1/8] Add gdb_ref_ptr.h Tom Tromey
  2016-12-02 13:08   ` Pedro Alves
@ 2016-12-03  0:05   ` Pedro Alves
  2016-12-13 13:13     ` Tom Tromey
  1 sibling, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-03  0:05 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 11/29/2016 05:05 AM, Tom Tromey wrote:
> This adds a new gdb_ref_ptr.h, that implements a reference-counting
> smart pointer class, where the user of the class supplies a
> reference-counting policy object.
> 
> This class will be used in the next patch, which changes most explicit
> BFD reference counts to use this new type.  Meanwhile, this patch
> changes gdbpy_ref to be a specialization of this new class.
> 
> This change required adding new nullptr_t overloads some operators in
> gdb_ref_ptr.h.  I suspect this was needed because some Python header
> redefines NULL, but I'm not certain.
> 
> 2016-11-28  Tom Tromey  <tom@tromey.com>
> 
> 	* common/gdb_ref_ptr.h: New file.
> 	* python/py-ref.h (struct gdbpy_ref_policy): New.
> 	(gdbpy_ref): Now a typedef.
> ---
>  gdb/ChangeLog            |   6 ++
>  gdb/common/gdb_ref_ptr.h | 209 +++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/python/py-ref.h      | 135 ++----------------------------
>  3 files changed, 224 insertions(+), 126 deletions(-)
>  create mode 100644 gdb/common/gdb_ref_ptr.h
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 8cbe8ad..f455f7f 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,11 @@
>  2016-11-28  Tom Tromey  <tom@tromey.com>
>  
> +	* common/gdb_ref_ptr.h: New file.
> +	* python/py-ref.h (struct gdbpy_ref_policy): New.
> +	(gdbpy_ref): Now a typedef.
> +
> +2016-11-28  Tom Tromey  <tom@tromey.com>
> +
>  	* utils.h (make_cleanup_htab_delete): Don't declare.
>  	* utils.c (do_htab_delete_cleanup, make_cleanup_htab_delete):
>  	Remove.
> diff --git a/gdb/common/gdb_ref_ptr.h b/gdb/common/gdb_ref_ptr.h
> new file mode 100644
> index 0000000..cc8ba94
> --- /dev/null
> +++ b/gdb/common/gdb_ref_ptr.h
> @@ -0,0 +1,209 @@
> +/* Reference-counted smart pointer class
> +
> +   Copyright (C) 2016 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_REF_PTR_H
> +#define GDB_REF_PTR_H
> +
> +#include <cstddef>
> +
> +namespace gdb
> +{
> +
> +/* An instance of this class either holds a reference to a
> +   reference-counted object or is "NULL".  Reference counting is
> +   handled externally by a policy class.  If the object holds a
> +   reference, then when the object is destroyed, the reference is
> +   decref'd.
> +
> +   Normally an instance is constructed using a pointer.  This sort of
> +   initialization lets this class manage the lifetime of that
> +   reference.
> +
> +   Assignment and copy construction will make a new reference as
> +   appropriate.  Assignment from a plain pointer is disallowed to
> +   avoid confusion about whether this acquires a new reference;
> +   instead use the "reset" method -- which, like the pointer
> +   constructor, transfers ownership.
> +
> +   The policy class must provide two static methods:
> +   void incref (T *);
> +   void decref (T *);
> +*/
> +template<typename T, typename POLICY>
> +class ref_ptr

BTW, I noticed today that the GCC standards say:

 "Template parameter names should use CamelCase, following the C++
  Standard."

and they do seem to follow it.  I think it's a good idea.
Would you mind adjusting accordingly?

I also noticed the "self/other" naming in the global operators:

+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self,
+			const ref_ptr<T, POLICY> &other)
+{

I'd find it pedantically more correct to write lhs/rhs, since
there's no actual this/self here.  Could you tweak that too?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 1/8] Add gdb_ref_ptr.h
  2016-12-03  0:05   ` Pedro Alves
@ 2016-12-13 13:13     ` Tom Tromey
  0 siblings, 0 replies; 50+ messages in thread
From: Tom Tromey @ 2016-12-13 13:13 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> BTW, I noticed today that the GCC standards say:
Pedro>  "Template parameter names should use CamelCase, following the C++
Pedro>   Standard."
Pedro> and they do seem to follow it.  I think it's a good idea.
Pedro> Would you mind adjusting accordingly?

No problem, I did that.
FWIW my personal style is also to use CamelCase for macro arguments.

Pedro> I also noticed the "self/other" naming in the global operators:
Pedro> +template<typename T, typename POLICY>
Pedro> +inline bool operator== (const ref_ptr<T, POLICY> &self,
Pedro> +			const ref_ptr<T, POLICY> &other)
Pedro> +{
Pedro> I'd find it pedantically more correct to write lhs/rhs, since
Pedro> there's no actual this/self here.  Could you tweak that too?

I did this too.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 2/8] Use class to manage BFD reference counts
  2016-12-02 13:05   ` Pedro Alves
@ 2016-12-13 13:26     ` Tom Tromey
  2016-12-15  4:12       ` Tom Tromey
  2016-12-20 17:19       ` [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts) Pedro Alves
  0 siblings, 2 replies; 50+ messages in thread
From: Tom Tromey @ 2016-12-13 13:26 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> -    return NULL;
>> +    return gdb_bfd_ref_ptr ();

Pedro> This provides a good reason to have an implicit construction from
Pedro> nullptr_t.  You had it in the original gdbpy_reference
Pedro> submission, but I had asked to remove it.  If we add it back,
Pedro> these cases could be more clearly written as "return
Pedro> NULL/nullptr".  Could you do that, and then drop all the hunks
Pedro> like:

>> -    return NULL;
>> +    return gdb_bfd_ref_ptr ();

Pedro> ?

I did this.

Pedro> I think these could be:
Pedro>     std::string filename
Pedro>       = string_printf ("%.*s", filename_len, pathname);
Pedro>     std::string member_name
Pedro>       = string_printf ("%.*s", path_len - filename_len - 2, sep + 1));

I did this, but it's a bit ugly as solib_find isn't const-correct.

I'll send a new patch soon.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-02 14:45   ` Pedro Alves
@ 2016-12-13 13:29     ` Tom Tromey
  2016-12-20 14:49       ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-13 13:29 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Or "reset ()", following the naming used in the standard smart pointers?

I went with reset since I think "free" can be a macro sometimes.
Or at least it could in C... not actually sure if C++ removed this
possibility.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-02 14:49   ` Pedro Alves
@ 2016-12-13 13:30     ` Tom Tromey
  0 siblings, 0 replies; 50+ messages in thread
From: Tom Tromey @ 2016-12-13 13:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> You can do:
Pedro>  std::string copy (arg);
Pedro>  ...
Pedro>  to_string_res = execute_command_to_string (&copy[0], from_tty);

Thanks, I made this change.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 8/8] Add constructor and destructor to demangle_parse_info
  2016-12-02 15:04   ` Pedro Alves
@ 2016-12-13 13:50     ` Tom Tromey
  0 siblings, 0 replies; 50+ messages in thread
From: Tom Tromey @ 2016-12-13 13:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> When initializing a unique_ptr from a function that returns a
Pedro> unique_ptr already, IMO, using = reads a little better
Pedro> over ()s, like:
Pedro>   std::unique_ptr<demangle_parse_info> info
Pedro>     = cp_demangled_name_to_comp (demangled_name, NULL);
Pedro> I.e., kind of like how you'd call make_unique with '=' instead
Pedro> of
Pedro>  unique_ptr<T> foo (make_unique<T>());
Pedro> which I've never seen.

Pedro> I wonder whether that's just me?

I don't really have a preference either way.
I made this change.

>> +  demangle_parse_info ();
>> +
>> +  ~demangle_parse_info ();

Pedro> Put these before the data fields.

Done.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-11-29  5:22   ` Tom Tromey
@ 2016-12-15  3:49     ` Tom Tromey
  2016-12-20 17:48       ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-15  3:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> To my surprise, this patch is broken.
Tom> I must not have re-run the python tests locally after writing it :(

Tom> The problem is that prevent_dont_repeat returns a cleanup, which is then
Tom> left dangling after this patch.

Here's the updated patch.
I ran this one through the buildbot.

Tom

commit 1a638a680bae42954d4ebc896cb5828a9e27709b
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Nov 28 21:11:53 2016 -0700

    Remove cleanups from execute_gdb_command
    
    This replaces a cleanup in execute_gdb_command with an instance of
    std::string.
    
    Testing showed that this originally missed a cleanup that was returned
    by prevent_dont_repeat.  This version of the patch changes
    prevent_dont_repeat to be a class, avoiding a cleanup.
    
    2016-12-14  Tom Tromey  <tom@tromey.com>
    
    	* top.c (prevent_dont_repeat): Now a constructor.
    	* python/python.c (execute_gdb_command): Use std::string.
    	Update.
    	* guile/guile.c (gdbscm_execute_gdb_command): Update.
    	* command.h (prevent_dont_repeat): Now a class, not a function.
    	* breakpoint.c (bpstat_do_actions_1): Update.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 023c112..576270d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2016-12-14  Tom Tromey  <tom@tromey.com>
+
+	* top.c (prevent_dont_repeat): Now a constructor.
+	* python/python.c (execute_gdb_command): Use std::string.
+	Update.
+	* guile/guile.c (gdbscm_execute_gdb_command): Update.
+	* command.h (prevent_dont_repeat): Now a class, not a function.
+	* breakpoint.c (bpstat_do_actions_1): Update.
+
 2016-12-13  Tom Tromey  <tom@tromey.com>
 
 	* value.h (value_freer::~value_freer): Call reset.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 92aac3a..5af1dfa 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4685,7 +4685,7 @@ bpstat_do_actions_1 (bpstat *bsp)
   executing_breakpoint_commands = 1;
   old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
 
-  prevent_dont_repeat ();
+  prevent_dont_repeat preventer ();
 
   /* This pointer will iterate over the list of bpstat's.  */
   bs = *bsp;
diff --git a/gdb/command.h b/gdb/command.h
index 965d91f..38ff38a 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -408,7 +408,17 @@ extern void error_no_arg (const char *) ATTRIBUTE_NORETURN;
 
 extern void dont_repeat (void);
 
-extern struct cleanup *prevent_dont_repeat (void);
+/* Prevent dont_repeat from doing anything.  */
+class prevent_dont_repeat
+{
+ public:
+
+  prevent_dont_repeat ();
+
+ private:
+
+  scoped_restore_tmpl<int> m_save_suppress;
+};
 
 /* Used to mark commands that don't do anything.  If we just leave the
    function field NULL, the command is interpreted as a help topic, or
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index 9a126a1..599896b 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -332,7 +332,7 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
       inner_cleanups = make_cleanup_restore_integer (&current_ui->async);
       current_ui->async = 0;
 
-      prevent_dont_repeat ();
+      prevent_dont_repeat preventer ();
       if (to_string)
 	to_string_res = execute_command_to_string (command, from_tty);
       else
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 83b9805..cf9502d 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -601,8 +601,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
   TRY
     {
       /* Copy the argument text in case the command modifies it.  */
-      char *copy = xstrdup (arg);
-      struct cleanup *cleanup = make_cleanup (xfree, copy);
+      std::string copy (arg);
       struct interp *interp;
 
       scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
@@ -614,12 +613,11 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
       interp = interp_lookup (current_ui, "console");
       current_uiout = interp_ui_out (interp);
 
-      prevent_dont_repeat ();
+      prevent_dont_repeat preventer ();
       if (to_string)
-	to_string_res = execute_command_to_string (copy, from_tty);
+	to_string_res = execute_command_to_string (&copy[0], from_tty);
       else
-	execute_command (copy, from_tty);
-      do_cleanups (cleanup);
+	execute_command (&copy[0], from_tty);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/top.c b/gdb/top.c
index 7d8b6e8..1aa926b 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -757,13 +757,9 @@ dont_repeat (void)
 /* Prevent dont_repeat from working, and return a cleanup that
    restores the previous state.  */
 
-struct cleanup *
-prevent_dont_repeat (void)
+prevent_dont_repeat::prevent_dont_repeat ()
+: m_save_suppress (&suppress_dont_repeat, 1)
 {
-  struct cleanup *result = make_cleanup_restore_integer (&suppress_dont_repeat);
-
-  suppress_dont_repeat = 1;
-  return result;
 }
 
 \f

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 2/8] Use class to manage BFD reference counts
  2016-12-13 13:26     ` Tom Tromey
@ 2016-12-15  4:12       ` Tom Tromey
  2016-12-20 18:18         ` Pedro Alves
  2016-12-20 17:19       ` [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts) Pedro Alves
  1 sibling, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-15  4:12 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> I'll send a new patch soon.

Here it is.
This was part of the series I sent through buildbot.

Tom

commit 01194fdb20215d47306a30814000a5663afa5fa1
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Nov 21 11:12:23 2016 -0700

    Use class to manage BFD reference counts
    
    This introduces a new specialization of gdb::ref_ptr that can be used
    to manage BFD reference counts.  Then it changes most places in gdb to
    use this new class, rather than explicit reference-counting or
    cleanups.  This patch removes make_cleanup_bfd_unref.
    
    If you look you will see a couple of spots using "release" where a use
    of gdb_bfd_ref_ptr would be cleaner.  These will be fixed in the next
    patch.
    
    I think this patch fixes some latent bugs.  For example, it seems to
    me that previously objfpy_add_separate_debug_file leaked a BFD.
    
    I'm not 100% certain that the macho_symfile_read_all_oso change is
    correct.  The existing code here is hard for me to follow.  One goal
    of this sort of automated reference counting, though, is to make it
    more difficult to make logic errors; so hopefully the code is clear
    now.
    
    2016-12-13  Tom Tromey  <tom@tromey.com>
    
    	* windows-tdep.c (windows_xfer_shared_library): Update.
    	* windows-nat.c (windows_make_so): Update.
    	* utils.h (make_cleanup_bfd_unref): Remove.
    	* utils.c (do_bfd_close_cleanup, make_cleanup_bfd_unref): Remove.
    	* symfile.h (symfile_bfd_open)
    	(find_separate_debug_file_in_section): Return gdb_bfd_ref_ptr.
    	* symfile.c (read_symbols, symbol_file_add)
    	(separate_debug_file_exists): Update.
    	(symfile_bfd_open): Return gdb_bfd_ref_ptr.
    	(generic_load, reread_symbols): Update.
    	* symfile-mem.c (symbol_file_add_from_memory): Update.
    	* spu-linux-nat.c (spu_bfd_open): Return gdb_bfd_ref_ptr.
    	(spu_symbol_file_add_from_memory): Update.
    	* solist.h (struct target_so_ops) <bfd_open>: Return
    	gdb_bfd_ref_ptr.
    	(solib_bfd_fopen, solib_bfd_open): Return gdb_bfd_ref_ptr.
    	* solib.c (solib_bfd_fopen, solib_bfd_open): Return
    	gdb_bfd_ref_ptr.
    	(solib_map_sections, reload_shared_libraries_1): Update.
    	* solib-svr4.c (enable_break): Update.
    	* solib-spu.c (spu_bfd_fopen): Return gdb_bfd_ref_ptr.
    	* solib-frv.c (enable_break2): Update.
    	* solib-dsbt.c (enable_break): Update.
    	* solib-darwin.c (gdb_bfd_mach_o_fat_extract): Return
    	gdb_bfd_ref_ptr.
    	(darwin_solib_get_all_image_info_addr_at_init): Update.
    	(darwin_bfd_open): Return gdb_bfd_ref_ptr.
    	* solib-aix.c (solib_aix_bfd_open): Return gdb_bfd_ref_ptr.
    	* record-full.c (record_full_save): Update.
    	* python/py-objfile.c (objfpy_add_separate_debug_file): Update.
    	* procfs.c (insert_dbx_link_bpt_in_file): Update.
    	* minidebug.c (find_separate_debug_file_in_section): Return
    	gdb_bfd_ref_ptr.
    	* machoread.c (macho_add_oso_symfile): Change abfd to
    	gdb_bfd_ref_ptr.
    	(macho_symfile_read_all_oso): Update.
    	(macho_check_dsym): Return gdb_bfd_ref_ptr.
    	(macho_symfile_read): Update.
    	* jit.c (bfd_open_from_target_memory): Return gdb_bfd_ref_ptr.
    	(jit_bfd_try_read_symtab): Update.
    	* gdb_bfd.h (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
    	(gdb_bfd_openw, gdb_bfd_openr_iovec)
    	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
    	gdb_bfd_ref_ptr.
    	(gdb_bfd_ref_policy): New struct.
    	(gdb_bfd_ref_ptr): New typedef.
    	* gdb_bfd.c (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
    	(gdb_bfd_openw, gdb_bfd_openr_iovec)
    	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
    	gdb_bfd_ref_ptr.
    	* gcore.h (create_gcore_bfd): Return gdb_bfd_ref_ptr.
    	* gcore.c (create_gcore_bfd): Return gdb_bfd_ref_ptr.
    	(gcore_command): Update.
    	* exec.c (exec_file_attach): Update.
    	* elfread.c (elf_symfile_read): Update.
    	* dwarf2read.c (dwarf2_get_dwz_file): Update.
    	(try_open_dwop_file, open_dwo_file): Return gdb_bfd_ref_ptr.
    	(open_and_init_dwo_file): Update.
    	(open_dwp_file): Return gdb_bfd_ref_ptr.
    	(open_and_init_dwp_file): Update.
    	* corelow.c (core_open): Update.
    	* compile/compile-object-load.c (compile_object_load): Update.
    	* common/gdb_ref_ptr.h (ref_ptr::operator->): New operator.
    	* coffread.c (coff_symfile_read): Update.
    	* cli/cli-dump.c (bfd_openr_or_error, bfd_openw_or_error): Return
    	gdb_bfd_ref_ptr.  Rename.
    	(dump_bfd_file, restore_command): Update.
    	* build-id.h (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
    	* build-id.c (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
    	(find_separate_debug_file_by_buildid): Update.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4377e12..f2a89f5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,78 @@
 2016-12-13  Tom Tromey  <tom@tromey.com>
 
+	* windows-tdep.c (windows_xfer_shared_library): Update.
+	* windows-nat.c (windows_make_so): Update.
+	* utils.h (make_cleanup_bfd_unref): Remove.
+	* utils.c (do_bfd_close_cleanup, make_cleanup_bfd_unref): Remove.
+	* symfile.h (symfile_bfd_open)
+	(find_separate_debug_file_in_section): Return gdb_bfd_ref_ptr.
+	* symfile.c (read_symbols, symbol_file_add)
+	(separate_debug_file_exists): Update.
+	(symfile_bfd_open): Return gdb_bfd_ref_ptr.
+	(generic_load, reread_symbols): Update.
+	* symfile-mem.c (symbol_file_add_from_memory): Update.
+	* spu-linux-nat.c (spu_bfd_open): Return gdb_bfd_ref_ptr.
+	(spu_symbol_file_add_from_memory): Update.
+	* solist.h (struct target_so_ops) <bfd_open>: Return
+	gdb_bfd_ref_ptr.
+	(solib_bfd_fopen, solib_bfd_open): Return gdb_bfd_ref_ptr.
+	* solib.c (solib_bfd_fopen, solib_bfd_open): Return
+	gdb_bfd_ref_ptr.
+	(solib_map_sections, reload_shared_libraries_1): Update.
+	* solib-svr4.c (enable_break): Update.
+	* solib-spu.c (spu_bfd_fopen): Return gdb_bfd_ref_ptr.
+	* solib-frv.c (enable_break2): Update.
+	* solib-dsbt.c (enable_break): Update.
+	* solib-darwin.c (gdb_bfd_mach_o_fat_extract): Return
+	gdb_bfd_ref_ptr.
+	(darwin_solib_get_all_image_info_addr_at_init): Update.
+	(darwin_bfd_open): Return gdb_bfd_ref_ptr.
+	* solib-aix.c (solib_aix_bfd_open): Return gdb_bfd_ref_ptr.
+	* record-full.c (record_full_save): Update.
+	* python/py-objfile.c (objfpy_add_separate_debug_file): Update.
+	* procfs.c (insert_dbx_link_bpt_in_file): Update.
+	* minidebug.c (find_separate_debug_file_in_section): Return
+	gdb_bfd_ref_ptr.
+	* machoread.c (macho_add_oso_symfile): Change abfd to
+	gdb_bfd_ref_ptr.
+	(macho_symfile_read_all_oso): Update.
+	(macho_check_dsym): Return gdb_bfd_ref_ptr.
+	(macho_symfile_read): Update.
+	* jit.c (bfd_open_from_target_memory): Return gdb_bfd_ref_ptr.
+	(jit_bfd_try_read_symtab): Update.
+	* gdb_bfd.h (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
+	(gdb_bfd_openw, gdb_bfd_openr_iovec)
+	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
+	gdb_bfd_ref_ptr.
+	(gdb_bfd_ref_policy): New struct.
+	(gdb_bfd_ref_ptr): New typedef.
+	* gdb_bfd.c (gdb_bfd_open, gdb_bfd_fopen, gdb_bfd_openr)
+	(gdb_bfd_openw, gdb_bfd_openr_iovec)
+	(gdb_bfd_openr_next_archived_file, gdb_bfd_fdopenr): Return
+	gdb_bfd_ref_ptr.
+	* gcore.h (create_gcore_bfd): Return gdb_bfd_ref_ptr.
+	* gcore.c (create_gcore_bfd): Return gdb_bfd_ref_ptr.
+	(gcore_command): Update.
+	* exec.c (exec_file_attach): Update.
+	* elfread.c (elf_symfile_read): Update.
+	* dwarf2read.c (dwarf2_get_dwz_file): Update.
+	(try_open_dwop_file, open_dwo_file): Return gdb_bfd_ref_ptr.
+	(open_and_init_dwo_file): Update.
+	(open_dwp_file): Return gdb_bfd_ref_ptr.
+	(open_and_init_dwp_file): Update.
+	* corelow.c (core_open): Update.
+	* compile/compile-object-load.c (compile_object_load): Update.
+	* common/gdb_ref_ptr.h (ref_ptr::operator->): New operator.
+	* coffread.c (coff_symfile_read): Update.
+	* cli/cli-dump.c (bfd_openr_or_error, bfd_openw_or_error): Return
+	gdb_bfd_ref_ptr.  Rename.
+	(dump_bfd_file, restore_command): Update.
+	* build-id.h (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
+	* build-id.c (build_id_to_debug_bfd): Return gdb_bfd_ref_ptr.
+	(find_separate_debug_file_by_buildid): Update.
+
+2016-12-13  Tom Tromey  <tom@tromey.com>
+
 	* common/gdb_ref_ptr.h: New file.
 	* python/py-ref.h (struct gdbpy_ref_policy): New.
 	(gdbpy_ref): Now a typedef.
diff --git a/gdb/build-id.c b/gdb/build-id.c
index 886f2d7..029cb4d 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -67,14 +67,14 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
 
 /* See build-id.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 {
   char *link, *debugdir;
   VEC (char_ptr) *debugdir_vec;
   struct cleanup *back_to;
   int ix;
-  bfd *abfd = NULL;
+  gdb_bfd_ref_ptr abfd;
   int alloc_len;
 
   /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
@@ -127,11 +127,10 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
       if (abfd == NULL)
 	continue;
 
-      if (build_id_verify (abfd, build_id_len, build_id))
+      if (build_id_verify (abfd.get(), build_id_len, build_id))
 	break;
 
-      gdb_bfd_unref (abfd);
-      abfd = NULL;
+      abfd.release ();
     }
 
   do_cleanups (back_to);
@@ -148,25 +147,16 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
   build_id = build_id_bfd_get (objfile->obfd);
   if (build_id != NULL)
     {
-      bfd *abfd;
-
-      abfd = build_id_to_debug_bfd (build_id->size, build_id->data);
+      gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
+						   build_id->data));
       /* Prevent looping on a stripped .debug file.  */
       if (abfd != NULL
-	  && filename_cmp (bfd_get_filename (abfd),
+	  && filename_cmp (bfd_get_filename (abfd.get ()),
 			   objfile_name (objfile)) == 0)
-        {
-	  warning (_("\"%s\": separate debug info file has no debug info"),
-		   bfd_get_filename (abfd));
-	  gdb_bfd_unref (abfd);
-	}
+	warning (_("\"%s\": separate debug info file has no debug info"),
+		 bfd_get_filename (abfd.get ()));
       else if (abfd != NULL)
-	{
-	  char *result = xstrdup (bfd_get_filename (abfd));
-
-	  gdb_bfd_unref (abfd);
-	  return result;
-	}
+	return xstrdup (bfd_get_filename (abfd.get ()));
     }
   return NULL;
 }
diff --git a/gdb/build-id.h b/gdb/build-id.h
index ddf0765..6c37dee 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -20,6 +20,8 @@
 #ifndef BUILD_ID_H
 #define BUILD_ID_H
 
+#include "gdb_bfd.h"
+
 /* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
 
 extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
@@ -35,8 +37,8 @@ extern int build_id_verify (bfd *abfd,
    return NULL.  The returned reference to the BFD must be released by
    the caller.  */
 
-extern bfd *build_id_to_debug_bfd (size_t build_id_len,
-				   const bfd_byte *build_id);
+extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
+					      const bfd_byte *build_id);
 
 /* Find the separate debug file for OBJFILE, by using the build-id
    associated with OBJFILE's BFD.  If successful, returns a malloc'd
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 781c638..ace721a 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -103,45 +103,40 @@ fopen_with_cleanup (const char *filename, const char *mode)
   return file;
 }
 
-static bfd *
-bfd_openr_with_cleanup (const char *filename, const char *target)
+static gdb_bfd_ref_ptr
+bfd_openr_or_error (const char *filename, const char *target)
 {
-  bfd *ibfd;
-
-  ibfd = gdb_bfd_openr (filename, target);
+  gdb_bfd_ref_ptr ibfd (gdb_bfd_openr (filename, target));
   if (ibfd == NULL)
-    error (_("Failed to open %s: %s."), filename, 
+    error (_("Failed to open %s: %s."), filename,
 	   bfd_errmsg (bfd_get_error ()));
 
-  make_cleanup_bfd_unref (ibfd);
-  if (!bfd_check_format (ibfd, bfd_object))
+  if (!bfd_check_format (ibfd.get (), bfd_object))
     error (_("'%s' is not a recognized file format."), filename);
 
   return ibfd;
 }
 
-static bfd *
-bfd_openw_with_cleanup (const char *filename, const char *target,
-			const char *mode)
+static gdb_bfd_ref_ptr
+bfd_openw_or_error (const char *filename, const char *target, const char *mode)
 {
-  bfd *obfd;
+  gdb_bfd_ref_ptr obfd;
 
   if (*mode == 'w')	/* Write: create new file */
     {
       obfd = gdb_bfd_openw (filename, target);
       if (obfd == NULL)
-	error (_("Failed to open %s: %s."), filename, 
+	error (_("Failed to open %s: %s."), filename,
 	       bfd_errmsg (bfd_get_error ()));
-      make_cleanup_bfd_unref (obfd);
-      if (!bfd_set_format (obfd, bfd_object))
-	error (_("bfd_openw_with_cleanup: %s."), bfd_errmsg (bfd_get_error ()));
+      if (!bfd_set_format (obfd.get (), bfd_object))
+	error (_("bfd_openw_or_error: %s."), bfd_errmsg (bfd_get_error ()));
     }
   else if (*mode == 'a')	/* Append to existing file.  */
     {	/* FIXME -- doesn't work...  */
       error (_("bfd_openw does not work with append."));
     }
   else
-    error (_("bfd_openw_with_cleanup: unknown mode %s."), mode);
+    error (_("bfd_openw_or_error: unknown mode %s."), mode);
 
   return obfd;
 }
@@ -187,20 +182,19 @@ dump_bfd_file (const char *filename, const char *mode,
 	       const char *target, CORE_ADDR vaddr, 
 	       const bfd_byte *buf, ULONGEST len)
 {
-  bfd *obfd;
   asection *osection;
 
-  obfd = bfd_openw_with_cleanup (filename, target, mode);
-  osection = bfd_make_section_anyway (obfd, ".newsec");
-  bfd_set_section_size (obfd, osection, len);
-  bfd_set_section_vma (obfd, osection, vaddr);
-  bfd_set_section_alignment (obfd, osection, 0);
-  bfd_set_section_flags (obfd, osection, (SEC_HAS_CONTENTS
-					  | SEC_ALLOC
-					  | SEC_LOAD));
+  gdb_bfd_ref_ptr obfd (bfd_openw_or_error (filename, target, mode));
+  osection = bfd_make_section_anyway (obfd.get (), ".newsec");
+  bfd_set_section_size (obfd.get (), osection, len);
+  bfd_set_section_vma (obfd.get (), osection, vaddr);
+  bfd_set_section_alignment (obfd.get (), osection, 0);
+  bfd_set_section_flags (obfd.get (), osection, (SEC_HAS_CONTENTS
+						 | SEC_ALLOC
+						 | SEC_LOAD));
   osection->entsize = 0;
-  if (!bfd_set_section_contents (obfd, osection, buf, 0, len))
-    warning (_("writing dump file '%s' (%s)"), filename, 
+  if (!bfd_set_section_contents (obfd.get (), osection, buf, 0, len))
+    warning (_("writing dump file '%s' (%s)"), filename,
 	     bfd_errmsg (bfd_get_error ()));
 }
 
@@ -624,12 +618,11 @@ restore_command (char *args_in, int from_tty)
   else
     {
       /* Open the file for loading.  */
-      ibfd = bfd_openr_with_cleanup (filename, NULL);
+      gdb_bfd_ref_ptr ibfd (bfd_openr_or_error (filename, NULL));
 
       /* Process the sections.  */
-      bfd_map_over_sections (ibfd, restore_section_callback, &data);
+      bfd_map_over_sections (ibfd.get (), restore_section_callback, &data);
     }
-  return;
 }
 
 static void
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 501e901..db32a92 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -742,10 +742,10 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 
       if (debugfile)
 	{
-	  bfd *abfd = symfile_bfd_open (debugfile);
+	  gdb_bfd_ref_ptr abfd (symfile_bfd_open (debugfile));
 
-	  make_cleanup_bfd_unref (abfd);
-	  symbol_file_add_separate (abfd, debugfile, symfile_flags, objfile);
+	  symbol_file_add_separate (abfd.get (), debugfile, symfile_flags,
+				    objfile);
 	}
     }
 
diff --git a/gdb/common/gdb_ref_ptr.h b/gdb/common/gdb_ref_ptr.h
index fbf4688..0bb77ec 100644
--- a/gdb/common/gdb_ref_ptr.h
+++ b/gdb/common/gdb_ref_ptr.h
@@ -143,6 +143,12 @@ class ref_ptr
     return result;
   }
 
+  /* Let users refer to members of the underlying pointer.  */
+  T *operator-> () const
+  {
+    return m_obj;
+  }
+
  private:
 
   T *m_obj;
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index c08aa2b..7351148 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -612,7 +612,6 @@ compile_object_load (const compile_file_names &file_names,
 		     enum compile_i_scope_types scope, void *scope_data)
 {
   struct cleanup *cleanups, *cleanups_free_objfile;
-  bfd *abfd;
   struct setup_sections_data setup_sections_data;
   CORE_ADDR addr, regs_addr, out_value_addr = 0;
   struct symbol *func_sym;
@@ -634,17 +633,16 @@ compile_object_load (const compile_file_names &file_names,
   filename = tilde_expand (file_names.object_file ());
   cleanups = make_cleanup (xfree, filename);
 
-  abfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (filename, gnutarget, -1));
   if (abfd == NULL)
     error (_("\"%s\": could not open as compiled module: %s"),
           filename, bfd_errmsg (bfd_get_error ()));
-  make_cleanup_bfd_unref (abfd);
 
-  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
+  if (!bfd_check_format_matches (abfd.get (), bfd_object, &matching))
     error (_("\"%s\": not in loadable format: %s"),
           filename, gdb_bfd_errmsg (bfd_get_error (), matching));
 
-  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0)
+  if ((bfd_get_file_flags (abfd.get ()) & (EXEC_P | DYNAMIC)) != 0)
     error (_("\"%s\": not in object format."), filename);
 
   setup_sections_data.last_size = 0;
@@ -653,17 +651,17 @@ compile_object_load (const compile_file_names &file_names,
   setup_sections_data.last_max_alignment = 1;
   setup_sections_data.munmap_list_headp = &munmap_list_head;
   make_cleanup (munmap_listp_free_cleanup, &munmap_list_head);
-  bfd_map_over_sections (abfd, setup_sections, &setup_sections_data);
-  setup_sections (abfd, NULL, &setup_sections_data);
+  bfd_map_over_sections (abfd.get (), setup_sections, &setup_sections_data);
+  setup_sections (abfd.get (), NULL, &setup_sections_data);
 
-  storage_needed = bfd_get_symtab_upper_bound (abfd);
+  storage_needed = bfd_get_symtab_upper_bound (abfd.get ());
   if (storage_needed < 0)
     error (_("Cannot read symbols of compiled module \"%s\": %s"),
           filename, bfd_errmsg (bfd_get_error ()));
 
   /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in
      "Reading symbols from ..." message for automatically generated file.  */
-  objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL);
+  objfile = symbol_file_add_from_bfd (abfd.get (), filename, 0, NULL, 0, NULL);
   cleanups_free_objfile = make_cleanup_free_objfile (objfile);
 
   func_sym = lookup_global_symbol_from_objfile (objfile,
@@ -712,7 +710,7 @@ compile_object_load (const compile_file_names &file_names,
      called from default_symfile_relocate.  */
   symbol_table = (asymbol **) obstack_alloc (&objfile->objfile_obstack,
 					     storage_needed);
-  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+  number_of_symbols = bfd_canonicalize_symtab (abfd.get (), symbol_table);
   if (number_of_symbols < 0)
     error (_("Cannot parse symbols of compiled module \"%s\": %s"),
           filename, bfd_errmsg (bfd_get_error ()));
@@ -771,7 +769,7 @@ compile_object_load (const compile_file_names &file_names,
   if (missing_symbols)
     error (_("%ld symbols were missing, cannot continue."), missing_symbols);
 
-  bfd_map_over_sections (abfd, copy_sections, symbol_table);
+  bfd_map_over_sections (abfd.get (), copy_sections, symbol_table);
 
   regs_type = get_regs_type (func_sym, objfile);
   if (regs_type == NULL)
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 376b7c9..04d2b87 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -275,7 +275,6 @@ core_open (const char *arg, int from_tty)
   int siggy;
   struct cleanup *old_chain;
   char *temp;
-  bfd *temp_bfd;
   int scratch_chan;
   int flags;
   char *filename;
@@ -310,20 +309,19 @@ core_open (const char *arg, int from_tty)
   if (scratch_chan < 0)
     perror_with_name (filename);
 
-  temp_bfd = gdb_bfd_fopen (filename, gnutarget, 
-			    write_files ? FOPEN_RUB : FOPEN_RB,
-			    scratch_chan);
+  gdb_bfd_ref_ptr temp_bfd (gdb_bfd_fopen (filename, gnutarget, 
+					   write_files ? FOPEN_RUB : FOPEN_RB,
+					   scratch_chan));
   if (temp_bfd == NULL)
     perror_with_name (filename);
 
-  if (!bfd_check_format (temp_bfd, bfd_core)
-      && !gdb_check_format (temp_bfd))
+  if (!bfd_check_format (temp_bfd.get (), bfd_core)
+      && !gdb_check_format (temp_bfd.get ()))
     {
       /* Do it after the err msg */
       /* 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_unref (temp_bfd);
       error (_("\"%s\" is not a core dump: %s"),
 	     filename, bfd_errmsg (bfd_get_error ()));
     }
@@ -333,7 +331,7 @@ core_open (const char *arg, int from_tty)
 
   do_cleanups (old_chain);
   unpush_target (&core_ops);
-  core_bfd = temp_bfd;
+  core_bfd = temp_bfd.release ();
   old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/);
 
   core_gdbarch = gdbarch_from_bfd (core_bfd);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 9676d59..8748f7c 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2479,7 +2479,6 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
 static struct dwz_file *
 dwarf2_get_dwz_file (void)
 {
-  bfd *dwz_bfd;
   char *data;
   struct cleanup *cleanup;
   const char *filename;
@@ -2523,14 +2522,11 @@ dwarf2_get_dwz_file (void)
 
   /* First try the file name given in the section.  If that doesn't
      work, try to use the build-id instead.  */
-  dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget, -1));
   if (dwz_bfd != NULL)
     {
-      if (!build_id_verify (dwz_bfd, buildid_len, buildid))
-	{
-	  gdb_bfd_unref (dwz_bfd);
-	  dwz_bfd = NULL;
-	}
+      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+	dwz_bfd.release ();
     }
 
   if (dwz_bfd == NULL)
@@ -2542,13 +2538,13 @@ dwarf2_get_dwz_file (void)
 
   result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
 			   struct dwz_file);
-  result->dwz_bfd = dwz_bfd;
+  result->dwz_bfd = dwz_bfd.release ();
 
-  bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result);
+  bfd_map_over_sections (result->dwz_bfd, locate_dwz_sections, result);
 
   do_cleanups (cleanup);
 
-  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, result->dwz_bfd);
   dwarf2_per_objfile->dwz_file = result;
   return result;
 }
@@ -10454,10 +10450,9 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir,
    If unable to find/open the file, return NULL.
    NOTE: This function is derived from symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
 {
-  bfd *sym_bfd;
   int desc, flags;
   char *absolute_name;
   /* Blech.  OPF_TRY_CWD_FIRST also disables searching the path list if
@@ -10486,23 +10481,20 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
   if (desc < 0)
     return NULL;
 
-  sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc));
   xfree (absolute_name);
   if (sym_bfd == NULL)
     return NULL;
-  bfd_set_cacheable (sym_bfd, 1);
+  bfd_set_cacheable (sym_bfd.get (), 1);
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
-    {
-      gdb_bfd_unref (sym_bfd); /* This also closes desc.  */
-      return NULL;
-    }
+  if (!bfd_check_format (sym_bfd.get (), bfd_object))
+    return NULL;
 
   /* Success.  Record the bfd as having been included by the objfile's bfd.
      This is important because things like demangled_names_hash lives in the
      objfile's per_bfd space and may have references to things like symbol
      names that live in the DWO/DWP file's per_bfd space.  PR 16426.  */
-  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd.get ());
 
   return sym_bfd;
 }
@@ -10514,11 +10506,9 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
    Upon success, the canonicalized path of the file is stored in the bfd,
    same as symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 open_dwo_file (const char *file_name, const char *comp_dir)
 {
-  bfd *abfd;
-
   if (IS_ABSOLUTE_PATH (file_name))
     return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/);
 
@@ -10531,7 +10521,8 @@ open_dwo_file (const char *file_name, const char *comp_dir)
 
       /* NOTE: If comp_dir is a relative path, this will also try the
 	 search path, which seems useful.  */
-      abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/);
+      gdb_bfd_ref_ptr abfd (try_open_dwop_file (path_to_try, 0 /*is_dwp*/,
+						1 /*search_cwd*/));
       xfree (path_to_try);
       if (abfd != NULL)
 	return abfd;
@@ -10617,10 +10608,9 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwo_file *dwo_file;
-  bfd *dbfd;
   struct cleanup *cleanups;
 
-  dbfd = open_dwo_file (dwo_name, comp_dir);
+  gdb_bfd_ref_ptr dbfd (open_dwo_file (dwo_name, comp_dir));
   if (dbfd == NULL)
     {
       if (dwarf_read_debug)
@@ -10630,11 +10620,12 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
   dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
   dwo_file->dwo_name = dwo_name;
   dwo_file->comp_dir = comp_dir;
-  dwo_file->dbfd = dbfd;
+  dwo_file->dbfd = dbfd.release ();
 
   cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
 
-  bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections);
+  bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
+			 &dwo_file->sections);
 
   dwo_file->cu = create_dwo_cu (dwo_file);
 
@@ -10786,12 +10777,11 @@ allocate_dwp_loaded_cutus_table (struct objfile *objfile)
    Upon success, the canonicalized path of the file is stored in the bfd,
    same as symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 open_dwp_file (const char *file_name)
 {
-  bfd *abfd;
-
-  abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/);
+  gdb_bfd_ref_ptr abfd (try_open_dwop_file (file_name, 1 /*is_dwp*/,
+					    1 /*search_cwd*/));
   if (abfd != NULL)
     return abfd;
 
@@ -10825,7 +10815,6 @@ open_and_init_dwp_file (void)
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwp_file *dwp_file;
   char *dwp_name;
-  bfd *dbfd;
   struct cleanup *cleanups = make_cleanup (null_cleanup, 0);
 
   /* Try to find first .dwp for the binary file before any symbolic links
@@ -10847,7 +10836,7 @@ open_and_init_dwp_file (void)
     dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
   make_cleanup (xfree, dwp_name);
 
-  dbfd = open_dwp_file (dwp_name);
+  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name));
   if (dbfd == NULL
       && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
     {
@@ -10865,17 +10854,18 @@ open_and_init_dwp_file (void)
       return NULL;
     }
   dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
-  dwp_file->name = bfd_get_filename (dbfd);
-  dwp_file->dbfd = dbfd;
+  dwp_file->name = bfd_get_filename (dbfd.get ());
+  dwp_file->dbfd = dbfd.release ();
   do_cleanups (cleanups);
 
   /* +1: section 0 is unused */
-  dwp_file->num_sections = bfd_count_sections (dbfd) + 1;
+  dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1;
   dwp_file->elf_sections =
     OBSTACK_CALLOC (&objfile->objfile_obstack,
 		    dwp_file->num_sections, asection *);
 
-  bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
+  bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_common_dwp_sections,
+			 dwp_file);
 
   dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
 
@@ -10895,7 +10885,8 @@ open_and_init_dwp_file (void)
   dwp_file->version = dwp_file->cus->version;
 
   if (dwp_file->version == 2)
-    bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
+    bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_v2_dwp_sections,
+			   dwp_file);
 
   dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
   dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
diff --git a/gdb/elfread.c b/gdb/elfread.c
index c6d0fdb..7e2358b 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1265,21 +1265,18 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 	   && objfile->separate_debug_objfile == NULL
 	   && objfile->separate_debug_objfile_backlink == NULL)
     {
-      char *debugfile;
-
-      debugfile = find_separate_debug_file_by_buildid (objfile);
+      gdb::unique_xmalloc_ptr<char> debugfile
+	(find_separate_debug_file_by_buildid (objfile));
 
       if (debugfile == NULL)
-	debugfile = find_separate_debug_file_by_debuglink (objfile);
+	debugfile.reset (find_separate_debug_file_by_debuglink (objfile));
 
-      if (debugfile)
+      if (debugfile != NULL)
 	{
-	  struct cleanup *cleanup = make_cleanup (xfree, debugfile);
-	  bfd *abfd = symfile_bfd_open (debugfile);
+	  gdb_bfd_ref_ptr abfd (symfile_bfd_open (debugfile.get ()));
 
-	  make_cleanup_bfd_unref (abfd);
-	  symbol_file_add_separate (abfd, debugfile, symfile_flags, objfile);
-	  do_cleanups (cleanup);
+	  symbol_file_add_separate (abfd.get (), debugfile.get (),
+				    symfile_flags, objfile);
 	}
     }
 }
diff --git a/gdb/exec.c b/gdb/exec.c
index eeca005..875a675 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -258,7 +258,9 @@ exec_file_attach (const char *filename, int from_tty)
      this at the end of the function; but acquiring it now lets the
      BFD cache return it if this call refers to the same file.  */
   gdb_bfd_ref (exec_bfd);
-  cleanups = make_cleanup_bfd_unref (exec_bfd);
+  gdb_bfd_ref_ptr exec_bfd_holder (exec_bfd);
+
+  cleanups = make_cleanup (null_cleanup, NULL);
 
   /* Remove any previous exec file.  */
   exec_close ();
@@ -333,11 +335,13 @@ exec_file_attach (const char *filename, int from_tty)
 	  make_cleanup (xfree, canonical_pathname);
 	}
 
+      gdb_bfd_ref_ptr temp;
       if (write_files && !load_via_target)
-	exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget,
-				  FOPEN_RUB, scratch_chan);
+	temp = gdb_bfd_fopen (canonical_pathname, gnutarget,
+			      FOPEN_RUB, scratch_chan);
       else
-	exec_bfd = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
+	temp = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
+      exec_bfd = temp.release ();
 
       if (!exec_bfd)
 	{
diff --git a/gdb/gcore.c b/gdb/gcore.c
index cb4d703..0b05cf9 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -49,15 +49,15 @@ static int gcore_memory_sections (bfd *);
 /* create_gcore_bfd -- helper for gcore_command (exported).
    Open a new bfd core file for output, and return the handle.  */
 
-bfd *
+gdb_bfd_ref_ptr
 create_gcore_bfd (const char *filename)
 {
-  bfd *obfd = gdb_bfd_openw (filename, default_gcore_target ());
+  gdb_bfd_ref_ptr obfd (gdb_bfd_openw (filename, default_gcore_target ()));
 
-  if (!obfd)
+  if (obfd == NULL)
     error (_("Failed to open '%s' for output."), filename);
-  bfd_set_format (obfd, bfd_core);
-  bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ());
+  bfd_set_format (obfd.get (), bfd_core);
+  bfd_set_arch_mach (obfd.get (), default_gcore_arch (), default_gcore_mach ());
   return obfd;
 }
 
@@ -174,7 +174,7 @@ gcore_command (char *args, int from_tty)
 		      "Opening corefile '%s' for output.\n", corefilename);
 
   /* Open the output file.  */
-  obfd = create_gcore_bfd (corefilename);
+  obfd = create_gcore_bfd (corefilename).release ();
 
   /* Need a cleanup that will close and delete the file.  */
   bfd_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
diff --git a/gdb/gcore.h b/gdb/gcore.h
index 91107e0..f4f0545 100644
--- a/gdb/gcore.h
+++ b/gdb/gcore.h
@@ -20,7 +20,9 @@
 #if !defined (GCORE_H)
 #define GCORE_H 1
 
-extern bfd *create_gcore_bfd (const char *filename);
+#include "gdb_bfd.h"
+
+extern gdb_bfd_ref_ptr create_gcore_bfd (const char *filename);
 extern void write_gcore_file (bfd *obfd);
 extern bfd *load_corefile (char *filename, int from_tty);
 extern int objfile_find_memory_regions (struct target_ops *self,
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index df00f87..c7f02b9 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -356,7 +356,7 @@ gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream,
 
 /* See gdb_bfd.h.  */
 
-struct bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_open (const char *name, const char *target, int fd)
 {
   hashval_t hash;
@@ -428,7 +428,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
 			    bfd_get_filename (abfd));
       close (fd);
       gdb_bfd_ref (abfd);
-      return abfd;
+      return gdb_bfd_ref_ptr (abfd);
     }
 
   abfd = bfd_fopen (name, target, FOPEN_RB, fd);
@@ -449,7 +449,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
     }
 
   gdb_bfd_ref (abfd);
-  return abfd;
+  return gdb_bfd_ref_ptr (abfd);
 }
 
 /* A helper function that releases any section data attached to the
@@ -772,7 +772,7 @@ gdb_bfd_crc (struct bfd *abfd, unsigned long *crc_out)
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
 	       int fd)
 {
@@ -781,12 +781,12 @@ gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openr (const char *filename, const char *target)
 {
   bfd *result = bfd_openr (filename, target);
@@ -794,12 +794,12 @@ gdb_bfd_openr (const char *filename, const char *target)
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openw (const char *filename, const char *target)
 {
   bfd *result = bfd_openw (filename, target);
@@ -807,12 +807,12 @@ gdb_bfd_openw (const char *filename, const char *target)
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openr_iovec (const char *filename, const char *target,
 		     void *(*open_func) (struct bfd *nbfd,
 					 void *open_closure),
@@ -835,7 +835,7 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
@@ -861,7 +861,7 @@ gdb_bfd_mark_parent (bfd *child, bfd *parent)
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
 {
   bfd *result = bfd_openr_next_archived_file (archive, previous);
@@ -869,7 +869,7 @@ gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
   if (result)
     gdb_bfd_mark_parent (result, archive);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* See gdb_bfd.h.  */
@@ -886,7 +886,7 @@ gdb_bfd_record_inclusion (bfd *includer, bfd *includee)
 
 /* See gdb_bfd.h.  */
 
-bfd *
+gdb_bfd_ref_ptr
 gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
 {
   bfd *result = bfd_fdopenr (filename, target, fd);
@@ -894,7 +894,7 @@ gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
   if (result)
     gdb_bfd_ref (result);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 \f
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index a5b5ee9..8c4a60a 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -21,6 +21,7 @@
 #define GDB_BFD_H
 
 #include "registry.h"
+#include "common/gdb_ref_ptr.h"
 
 DECLARE_REGISTRY (bfd);
 
@@ -39,6 +40,34 @@ int is_target_filename (const char *name);
 
 int gdb_bfd_has_target_filename (struct bfd *abfd);
 
+/* Increment the reference count of ABFD.  It is fine for ABFD to be
+   NULL; in this case the function does nothing.  */
+
+void gdb_bfd_ref (struct bfd *abfd);
+
+/* Decrement the reference count of ABFD.  If this is the last
+   reference, ABFD will be freed.  If ABFD is NULL, this function does
+   nothing.  */
+
+void gdb_bfd_unref (struct bfd *abfd);
+
+/* A policy class for gdb::ref_ptr for BFD reference counting.  */
+struct gdb_bfd_ref_policy
+{
+  static void incref (struct bfd *abfd)
+  {
+    gdb_bfd_ref (abfd);
+  }
+
+  static void decref (struct bfd *abfd)
+  {
+    gdb_bfd_unref (abfd);
+  }
+};
+
+/* A gdb::ref_ptr that has been specialized for BFD objects.  */
+typedef gdb::ref_ptr<struct bfd, gdb_bfd_ref_policy> gdb_bfd_ref_ptr;
+
 /* Open a read-only (FOPEN_RB) BFD given arguments like bfd_fopen.
    If NAME starts with TARGET_SYSROOT_PREFIX then the BFD will be
    opened using target fileio operations if necessary.  Returns NULL
@@ -51,18 +80,7 @@ int gdb_bfd_has_target_filename (struct bfd *abfd);
    not be exactly NAME but rather NAME with TARGET_SYSROOT_PREFIX
    stripped.  */
 
-struct bfd *gdb_bfd_open (const char *name, const char *target, int fd);
-
-/* Increment the reference count of ABFD.  It is fine for ABFD to be
-   NULL; in this case the function does nothing.  */
-
-void gdb_bfd_ref (struct bfd *abfd);
-
-/* Decrement the reference count of ABFD.  If this is the last
-   reference, ABFD will be freed.  If ABFD is NULL, this function does
-   nothing.  */
-
-void gdb_bfd_unref (struct bfd *abfd);
+gdb_bfd_ref_ptr gdb_bfd_open (const char *name, const char *target, int fd);
 
 /* Mark the CHILD BFD as being a member of PARENT.  Also, increment
    the reference count of CHILD.  Calling this function ensures that
@@ -110,45 +128,46 @@ int gdb_bfd_crc (struct bfd *abfd, unsigned long *crc_out);
 /* A wrapper for bfd_fopen that initializes the gdb-specific reference
    count.  */
 
-bfd *gdb_bfd_fopen (const char *, const char *, const char *, int);
+gdb_bfd_ref_ptr gdb_bfd_fopen (const char *, const char *, const char *, int);
 
 /* A wrapper for bfd_openr that initializes the gdb-specific reference
    count.  */
 
-bfd *gdb_bfd_openr (const char *, const char *);
+gdb_bfd_ref_ptr gdb_bfd_openr (const char *, const char *);
 
 /* A wrapper for bfd_openw that initializes the gdb-specific reference
    count.  */
 
-bfd *gdb_bfd_openw (const char *, const char *);
+gdb_bfd_ref_ptr gdb_bfd_openw (const char *, const char *);
 
 /* A wrapper for bfd_openr_iovec that initializes the gdb-specific
    reference count.  */
 
-bfd *gdb_bfd_openr_iovec (const char *filename, const char *target,
-			  void *(*open_func) (struct bfd *nbfd,
-					      void *open_closure),
-			  void *open_closure,
-			  file_ptr (*pread_func) (struct bfd *nbfd,
-						  void *stream,
-						  void *buf,
-						  file_ptr nbytes,
-						  file_ptr offset),
-			  int (*close_func) (struct bfd *nbfd,
-					     void *stream),
-			  int (*stat_func) (struct bfd *abfd,
-					    void *stream,
-					    struct stat *sb));
+gdb_bfd_ref_ptr gdb_bfd_openr_iovec (const char *filename, const char *target,
+				     void *(*open_func) (struct bfd *nbfd,
+							 void *open_closure),
+				     void *open_closure,
+				     file_ptr (*pread_func) (struct bfd *nbfd,
+							     void *stream,
+							     void *buf,
+							     file_ptr nbytes,
+							     file_ptr offset),
+				     int (*close_func) (struct bfd *nbfd,
+							void *stream),
+				     int (*stat_func) (struct bfd *abfd,
+						       void *stream,
+						       struct stat *sb));
 
 /* A wrapper for bfd_openr_next_archived_file that initializes the
    gdb-specific reference count.  */
 
-bfd *gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous);
+gdb_bfd_ref_ptr gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous);
 
 /* A wrapper for bfd_fdopenr that initializes the gdb-specific
    reference count.  */
 
-bfd *gdb_bfd_fdopenr (const char *filename, const char *target, int fd);
+gdb_bfd_ref_ptr gdb_bfd_fdopenr (const char *filename, const char *target,
+				 int fd);
 
 \f
 
diff --git a/gdb/jit.c b/gdb/jit.c
index 03b6bd8..2101115 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -136,7 +136,7 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
 
 /* Open a BFD from the target's memory.  */
 
-static struct bfd *
+static gdb_bfd_ref_ptr
 bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
 {
   struct target_buffer *buffer = XNEW (struct target_buffer);
@@ -892,7 +892,6 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
                          CORE_ADDR entry_addr,
                          struct gdbarch *gdbarch)
 {
-  bfd *nbfd;
   struct section_addr_info *sai;
   struct bfd_section *sec;
   struct objfile *objfile;
@@ -907,8 +906,9 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
 			paddress (gdbarch, code_entry->symfile_addr),
 			pulongest (code_entry->symfile_size));
 
-  nbfd = bfd_open_from_target_memory (code_entry->symfile_addr,
-                                      code_entry->symfile_size, gnutarget);
+  gdb_bfd_ref_ptr nbfd (bfd_open_from_target_memory (code_entry->symfile_addr,
+						     code_entry->symfile_size,
+						     gnutarget));
   if (nbfd == NULL)
     {
       puts_unfiltered (_("Error opening JITed symbol file, ignoring it.\n"));
@@ -917,42 +917,42 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
 
   /* Check the format.  NOTE: This initializes important data that GDB uses!
      We would segfault later without this line.  */
-  if (!bfd_check_format (nbfd, bfd_object))
+  if (!bfd_check_format (nbfd.get (), bfd_object))
     {
       printf_unfiltered (_("\
 JITed symbol file is not an object file, ignoring it.\n"));
-      gdb_bfd_unref (nbfd);
       return;
     }
 
   /* Check bfd arch.  */
   b = gdbarch_bfd_arch_info (gdbarch);
-  if (b->compatible (b, bfd_get_arch_info (nbfd)) != b)
+  if (b->compatible (b, bfd_get_arch_info (nbfd.get ())) != b)
     warning (_("JITed object file architecture %s is not compatible "
-               "with target architecture %s."), bfd_get_arch_info
-             (nbfd)->printable_name, b->printable_name);
+               "with target architecture %s."),
+	     bfd_get_arch_info (nbfd.get ())->printable_name,
+	     b->printable_name);
 
   /* Read the section address information out of the symbol file.  Since the
      file is generated by the JIT at runtime, it should all of the absolute
      addresses that we care about.  */
-  sai = alloc_section_addr_info (bfd_count_sections (nbfd));
+  sai = alloc_section_addr_info (bfd_count_sections (nbfd.get ()));
   old_cleanups = make_cleanup_free_section_addr_info (sai);
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
-    if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
+    if ((bfd_get_section_flags (nbfd.get (), sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
         /* We assume that these virtual addresses are absolute, and do not
            treat them as offsets.  */
-        sai->other[i].addr = bfd_get_section_vma (nbfd, sec);
-        sai->other[i].name = xstrdup (bfd_get_section_name (nbfd, sec));
+        sai->other[i].addr = bfd_get_section_vma (nbfd.get (), sec);
+        sai->other[i].name = xstrdup (bfd_get_section_name (nbfd.get (), sec));
         sai->other[i].sectindex = sec->index;
         ++i;
       }
   sai->num_sections = i;
 
   /* This call does not take ownership of SAI.  */
-  make_cleanup_bfd_unref (nbfd);
-  objfile = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd), 0, sai,
+  objfile = symbol_file_add_from_bfd (nbfd.get (),
+				      bfd_get_filename (nbfd.get ()), 0, sai,
 				      OBJF_SHARED | OBJF_NOT_FILENAME, NULL);
 
   do_cleanups (old_cleanups);
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 00f25a4..dd99eb7 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -429,7 +429,8 @@ macho_resolve_oso_sym_with_minsym (struct objfile *main_objfile, asymbol *sym)
 /* Add oso file OSO/ABFD as a symbol file.  */
 
 static void
-macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
+macho_add_oso_symfile (oso_el *oso, const gdb_bfd_ref_ptr &abfd,
+		       const char *name,
                        struct objfile *main_objfile,
 		       symfile_add_flags symfile_flags)
 {
@@ -439,7 +440,6 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
   asymbol **symp;
   struct bfd_hash_table table;
   int nbr_sections;
-  struct cleanup *cleanup;
 
   /* Per section flag to mark which section have been rebased.  */
   unsigned char *sections_rebased;
@@ -448,18 +448,16 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
     printf_unfiltered
       (_("Loading debugging symbols from oso: %s\n"), oso->name);
 
-  if (!bfd_check_format (abfd, bfd_object))
+  if (!bfd_check_format (abfd.get (), bfd_object))
     {
       warning (_("`%s': can't read symbols: %s."), oso->name,
                bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (abfd);
       return;
     }
 
-  if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd))
+  if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd.get ()))
     {
       warning (_("`%s': file time stamp mismatch."), oso->name);
-      gdb_bfd_unref (abfd);
       return;
     }
 
@@ -468,19 +466,18 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
                               oso->nbr_syms))
     {
       warning (_("`%s': can't create hash table"), oso->name);
-      gdb_bfd_unref (abfd);
       return;
     }
 
-  bfd_set_cacheable (abfd, 1);
+  bfd_set_cacheable (abfd.get (), 1);
 
   /* Read symbols table.  */
-  storage = bfd_get_symtab_upper_bound (abfd);
+  storage = bfd_get_symtab_upper_bound (abfd.get ());
   symbol_table = (asymbol **) xmalloc (storage);
-  bfd_canonicalize_symtab (abfd, symbol_table);
+  bfd_canonicalize_symtab (abfd.get (), symbol_table);
 
   /* Init section flags.  */
-  nbr_sections = bfd_count_sections (abfd);
+  nbr_sections = bfd_count_sections (abfd.get ());
   sections_rebased = (unsigned char *) alloca (nbr_sections);
   for (i = 0; i < nbr_sections; i++)
     sections_rebased[i] = 0;
@@ -601,7 +598,7 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
                          sec->name, sym->name,
                          paddress (arch, res));
                     }
-                  bfd_set_section_vma (abfd, sec, res);
+                  bfd_set_section_vma (abfd.get (), sec, res);
                   sections_rebased[sec->index] = 1;
                 }
             }
@@ -617,13 +614,12 @@ macho_add_oso_symfile (oso_el *oso, bfd *abfd, const char *name,
 
   /* We need to clear SYMFILE_MAINLINE to avoid interractive question
      from symfile.c:symbol_file_add_with_addrs_or_offsets.  */
-  cleanup = make_cleanup_bfd_unref (abfd);
   symbol_file_add_from_bfd
-    (abfd, name, symfile_flags & ~(SYMFILE_MAINLINE | SYMFILE_VERBOSE), NULL,
+    (abfd.get (), name, symfile_flags & ~(SYMFILE_MAINLINE | SYMFILE_VERBOSE),
+     NULL,
      main_objfile->flags & (OBJF_REORDERED | OBJF_SHARED
 			    | OBJF_READNOW | OBJF_USERLOADED),
      main_objfile);
-  do_cleanups (cleanup);
 }
 
 /* Read symbols from the vector of oso files.
@@ -651,8 +647,6 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
       pfx_len = get_archive_prefix_len (oso->name);
       if (pfx_len > 0)
 	{
-	  bfd *archive_bfd;
-	  bfd *member_bfd;
           int last_ix;
           oso_el *oso2;
           int ix2;
@@ -668,7 +662,8 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
             }
 
 	  /* Open the archive and check the format.  */
-	  archive_bfd = gdb_bfd_open (archive_name.c_str (), gnutarget, -1);
+	  gdb_bfd_ref_ptr archive_bfd (gdb_bfd_open (archive_name.c_str (),
+						     gnutarget, -1));
 	  if (archive_bfd == NULL)
 	    {
 	      warning (_("Could not open OSO archive file \"%s\""),
@@ -676,22 +671,21 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
               ix = last_ix;
 	      continue;
 	    }
-	  if (!bfd_check_format (archive_bfd, bfd_archive))
+	  if (!bfd_check_format (archive_bfd.get (), bfd_archive))
 	    {
 	      warning (_("OSO archive file \"%s\" not an archive."),
 		       archive_name.c_str ());
-	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
 	    }
 
-	  member_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
+	  gdb_bfd_ref_ptr member_bfd
+	    (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
 
 	  if (member_bfd == NULL)
 	    {
 	      warning (_("Could not read archive members out of "
 			 "OSO archive \"%s\""), archive_name.c_str ());
-	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
 	    }
@@ -699,7 +693,6 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
           /* Load all oso in this library.  */
 	  while (member_bfd != NULL)
 	    {
-	      bfd *prev;
 	      const char *member_name = member_bfd->filename;
               int member_len = strlen (member_name);
 
@@ -721,13 +714,8 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
                     }
                 }
 
-              prev = member_bfd;
-	      member_bfd = gdb_bfd_openr_next_archived_file (archive_bfd,
-							     member_bfd);
-
-              /* Free previous member if not referenced by an oso.  */
-              if (ix2 >= last_ix)
-                gdb_bfd_unref (prev);
+	      member_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
+							     member_bfd.get ());
 	    }
           for (ix2 = ix; ix2 < last_ix; ix2++)
             {
@@ -741,10 +729,8 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
 	}
       else
 	{
-          bfd *abfd;
-
-	  abfd = gdb_bfd_open (oso->name, gnutarget, -1);
-	  if (!abfd)
+	  gdb_bfd_ref_ptr abfd (gdb_bfd_open (oso->name, gnutarget, -1));
+	  if (abfd == NULL)
             warning (_("`%s': can't open to read symbols: %s."), oso->name,
                      bfd_errmsg (bfd_get_error ()));
           else
@@ -768,7 +754,7 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
    Return NULL if no valid dsym file is found (FILENAMEP is not used in
    such case).  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 macho_check_dsym (struct objfile *objfile, char **filenamep)
 {
   size_t name_len = strlen (objfile_name (objfile));
@@ -776,7 +762,6 @@ macho_check_dsym (struct objfile *objfile, char **filenamep)
   const char *base_name = lbasename (objfile_name (objfile));
   size_t base_len = strlen (base_name);
   char *dsym_filename = (char *) alloca (name_len + dsym_len + base_len + 1);
-  bfd *dsym_bfd;
   bfd_mach_o_load_command *main_uuid;
   bfd_mach_o_load_command *dsym_uuid;
 
@@ -793,25 +778,23 @@ macho_check_dsym (struct objfile *objfile, char **filenamep)
       warning (_("can't find UUID in %s"), objfile_name (objfile));
       return NULL;
     }
-  dsym_bfd = gdb_bfd_openr (dsym_filename, gnutarget);
+  gdb_bfd_ref_ptr dsym_bfd (gdb_bfd_openr (dsym_filename, gnutarget));
   if (dsym_bfd == NULL)
     {
       warning (_("can't open dsym file %s"), dsym_filename);
       return NULL;
     }
 
-  if (!bfd_check_format (dsym_bfd, bfd_object))
+  if (!bfd_check_format (dsym_bfd.get (), bfd_object))
     {
-      gdb_bfd_unref (dsym_bfd);
       warning (_("bad dsym file format: %s"), bfd_errmsg (bfd_get_error ()));
       return NULL;
     }
 
-  if (bfd_mach_o_lookup_command (dsym_bfd,
+  if (bfd_mach_o_lookup_command (dsym_bfd.get (),
                                  BFD_MACH_O_LC_UUID, &dsym_uuid) == 0)
     {
       warning (_("can't find UUID in %s"), dsym_filename);
-      gdb_bfd_unref (dsym_bfd);
       return NULL;
     }
   if (memcmp (dsym_uuid->command.uuid.uuid, main_uuid->command.uuid.uuid,
@@ -819,7 +802,6 @@ macho_check_dsym (struct objfile *objfile, char **filenamep)
     {
       warning (_("dsym file UUID doesn't match the one in %s"),
 	       objfile_name (objfile));
-      gdb_bfd_unref (dsym_bfd);
       return NULL;
     }
   *filenamep = xstrdup (dsym_filename);
@@ -831,7 +813,6 @@ macho_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 {
   bfd *abfd = objfile->obfd;
   long storage_needed;
-  bfd *dsym_bfd;
   VEC (oso_el) *oso_vector = NULL;
   struct cleanup *old_chain = make_cleanup (VEC_cleanup (oso_el), &oso_vector);
 
@@ -879,7 +860,7 @@ macho_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
       dwarf2_build_frame_info (objfile);
 
       /* Check for DSYM file.  */
-      dsym_bfd = macho_check_dsym (objfile, &dsym_filename);
+      gdb_bfd_ref_ptr dsym_bfd (macho_check_dsym (objfile, &dsym_filename));
       if (dsym_bfd != NULL)
 	{
           struct bfd_section *asect, *dsect;
@@ -896,14 +877,13 @@ macho_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
             {
               if (strcmp (asect->name, dsect->name) != 0)
                 break;
-              bfd_set_section_size (dsym_bfd, dsect,
+              bfd_set_section_size (dsym_bfd.get (), dsect,
                                     bfd_get_section_size (asect));
             }
 
 	  /* Add the dsym file as a separate file.  */
-	  make_cleanup_bfd_unref (dsym_bfd);
-          symbol_file_add_separate (dsym_bfd, dsym_filename, symfile_flags,
-				    objfile);
+          symbol_file_add_separate (dsym_bfd.get (), dsym_filename,
+				    symfile_flags, objfile);
 
 	  /* Don't try to read dwarf2 from main file or shared libraries.  */
 	  do_cleanups (old_chain);
diff --git a/gdb/minidebug.c b/gdb/minidebug.c
index 4323294..61a3971 100644
--- a/gdb/minidebug.c
+++ b/gdb/minidebug.c
@@ -256,11 +256,11 @@ lzma_stat (struct bfd *abfd,
    If we find one we create a iovec based bfd that decompresses the
    object data on demand.  If we don't find one, return NULL.  */
 
-bfd *
+gdb_bfd_ref_ptr
 find_separate_debug_file_in_section (struct objfile *objfile)
 {
   asection *section;
-  bfd *abfd;
+  gdb_bfd_ref_ptr abfd;
 
   if (objfile->obfd == NULL)
     return NULL;
@@ -275,16 +275,14 @@ find_separate_debug_file_in_section (struct objfile *objfile)
   if (abfd == NULL)
     return NULL;
 
-  if (!bfd_check_format (abfd, bfd_object))
+  if (!bfd_check_format (abfd.get (), bfd_object))
     {
       warning (_("Cannot parse .gnu_debugdata section; not a BFD object"));
-      gdb_bfd_unref (abfd);
       return NULL;
     }
 #else
   warning (_("Cannot parse .gnu_debugdata section; LZMA support was "
 	     "disabled at compile time"));
-  abfd = NULL;
 #endif /* !HAVE_LIBLZMA */
 
   return abfd;
diff --git a/gdb/procfs.c b/gdb/procfs.c
index ff814ba..f8fd487 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -3413,26 +3413,24 @@ dbx_link_addr (bfd *abfd)
 static int
 insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
 {
-  bfd *abfd;
   long storage_needed;
   CORE_ADDR sym_addr;
 
-  abfd = gdb_bfd_fdopenr ("unamed", 0, fd);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_fdopenr ("unamed", 0, fd));
   if (abfd == NULL)
     {
       warning (_("Failed to create a bfd: %s."), bfd_errmsg (bfd_get_error ()));
       return 0;
     }
 
-  if (!bfd_check_format (abfd, bfd_object))
+  if (!bfd_check_format (abfd.get (), bfd_object))
     {
       /* Not the correct format, so we can not possibly find the dbx_link
 	 symbol in it.	*/
-      gdb_bfd_unref (abfd);
       return 0;
     }
 
-  sym_addr = dbx_link_addr (abfd);
+  sym_addr = dbx_link_addr (abfd.get ());
   if (sym_addr != 0)
     {
       struct breakpoint *dbx_link_bpt;
@@ -3444,14 +3442,11 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
       if (dbx_link_bpt == NULL)
 	{
 	  warning (_("Failed to insert dbx_link breakpoint."));
-	  gdb_bfd_unref (abfd);
 	  return 0;
 	}
-      gdb_bfd_unref (abfd);
       return 1;
     }
 
-  gdb_bfd_unref (abfd);
   return 0;
 }
 
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 497d0ba..42e26b7 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -445,9 +445,9 @@ objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
 
   TRY
     {
-      bfd *abfd = symfile_bfd_open (file_name);
+      gdb_bfd_ref_ptr abfd (symfile_bfd_open (file_name));
 
-      symbol_file_add_separate (abfd, file_name, 0, obj->objfile);
+      symbol_file_add_separate (abfd.get (), file_name, 0, obj->objfile);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 5608e70..707cb63 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -2571,7 +2571,7 @@ record_full_save (struct target_ops *self, const char *recfilename)
 			recfilename);
 
   /* Open the output file.  */
-  obfd = create_gcore_bfd (recfilename);
+  obfd = create_gcore_bfd (recfilename).release ();
   old_cleanups = make_cleanup (record_full_save_cleanups, obfd);
 
   /* Save the current record entry to "cur_record_full_list".  */
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index 75634df..6612f20 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -624,7 +624,7 @@ solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
 
 /* Implement the "bfd_open" target_so_ops method.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 solib_aix_bfd_open (char *pathname)
 {
   /* The pathname is actually a synthetic filename with the following
@@ -635,11 +635,7 @@ solib_aix_bfd_open (char *pathname)
      to the solib's lm_info here?  */
   const int path_len = strlen (pathname);
   char *sep;
-  char *filename;
   int filename_len;
-  char *member_name;
-  bfd *archive_bfd, *object_bfd;
-  struct cleanup *cleanup;
   int found_file;
   char *found_pathname;
 
@@ -658,69 +654,57 @@ solib_aix_bfd_open (char *pathname)
     }
   filename_len = sep - pathname;
 
-  filename = xstrprintf ("%.*s", filename_len, pathname);
-  cleanup = make_cleanup (xfree, filename);
-  member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
-  make_cleanup (xfree, member_name);
+  std::string filename (string_printf ("%.*s", filename_len, pathname));
+  std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
+					  sep + 1));
 
   /* Calling solib_find makes certain that sysroot path is set properly
      if program has a dependency on .a archive and sysroot is set via
      set sysroot command.  */
-  found_pathname = solib_find (filename, &found_file);
+  found_pathname = solib_find (&filename[0], &found_file);
   if (found_pathname == NULL)
       perror_with_name (pathname);
-  archive_bfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname, found_file));
   if (archive_bfd == NULL)
     {
       warning (_("Could not open `%s' as an executable file: %s"),
-	       filename, bfd_errmsg (bfd_get_error ()));
-      do_cleanups (cleanup);
+	       filename.c_str (), bfd_errmsg (bfd_get_error ()));
       return NULL;
     }
 
-  if (bfd_check_format (archive_bfd, bfd_object))
-    {
-      do_cleanups (cleanup);
-      return archive_bfd;
-    }
+  if (bfd_check_format (archive_bfd.get (), bfd_object))
+    return archive_bfd;
 
-  if (! bfd_check_format (archive_bfd, bfd_archive))
+  if (! bfd_check_format (archive_bfd.get (), bfd_archive))
     {
       warning (_("\"%s\": not in executable format: %s."),
-	       filename, bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (archive_bfd);
-      do_cleanups (cleanup);
+	       filename.c_str (), bfd_errmsg (bfd_get_error ()));
       return NULL;
     }
 
-  object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
+  gdb_bfd_ref_ptr object_bfd
+    (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
   while (object_bfd != NULL)
     {
-      bfd *next;
-
-      if (strcmp (member_name, object_bfd->filename) == 0)
+      if (member_name == object_bfd->filename)
 	break;
 
-      next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
-      gdb_bfd_unref (object_bfd);
-      object_bfd = next;
+      object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
+						     object_bfd.get ());
     }
 
   if (object_bfd == NULL)
     {
-      warning (_("\"%s\": member \"%s\" missing."), filename, member_name);
-      gdb_bfd_unref (archive_bfd);
-      do_cleanups (cleanup);
+      warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
+	       member_name.c_str ());
       return NULL;
     }
 
-  if (! bfd_check_format (object_bfd, bfd_object))
+  if (! bfd_check_format (object_bfd.get (), bfd_object))
     {
       warning (_("%s(%s): not in object format: %s."),
-	       filename, member_name, bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (archive_bfd);
-      gdb_bfd_unref (object_bfd);
-      do_cleanups (cleanup);
+	       filename.c_str (), member_name.c_str (),
+	       bfd_errmsg (bfd_get_error ()));
       return NULL;
     }
 
@@ -728,12 +712,11 @@ solib_aix_bfd_open (char *pathname)
      along with appended parenthesized member name in order to allow commands
      listing all shared libraries to display.  Otherwise, we would only be
      displaying the name of the archive member object.  */
-  xfree (bfd_get_filename (object_bfd));
+  xfree (bfd_get_filename (object_bfd.get ()));
   object_bfd->filename = xstrprintf ("%s%s",
-                                     bfd_get_filename (archive_bfd), sep);
+                                     bfd_get_filename (archive_bfd.get ()),
+				     sep);
 
-  gdb_bfd_unref (archive_bfd);
-  do_cleanups (cleanup);
   return object_bfd;
 }
 
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 24cf848..51d42c7 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -427,7 +427,7 @@ darwin_in_dynsym_resolve_code (CORE_ADDR pc)
    counting properly.  This will either return NULL, or return a new
    reference to a BFD.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format,
 			    const bfd_arch_info_type *arch)
 {
@@ -441,7 +441,7 @@ gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format,
   else
     gdb_bfd_mark_parent (result, abfd);
 
-  return result;
+  return gdb_bfd_ref_ptr (result);
 }
 
 /* Extract dyld_all_image_addr when the process was just created, assuming the
@@ -452,8 +452,6 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info)
 {
   char *interp_name;
   CORE_ADDR load_addr = 0;
-  bfd *dyld_bfd = NULL;
-  struct cleanup *cleanup;
 
   /* This method doesn't work with an attached process.  */
   if (current_inferior ()->attach_flag)
@@ -464,42 +462,30 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info)
   if (!interp_name)
     return;
 
-  cleanup = make_cleanup (null_cleanup, NULL);
-
   /* Create a bfd for the interpreter.  */
-  dyld_bfd = gdb_bfd_open (interp_name, gnutarget, -1);
-  if (dyld_bfd)
+  gdb_bfd_ref_ptr dyld_bfd (gdb_bfd_open (interp_name, gnutarget, -1));
+  if (dyld_bfd != NULL)
     {
-      bfd *sub;
-
-      make_cleanup_bfd_unref (dyld_bfd);
-      sub = gdb_bfd_mach_o_fat_extract
-	(dyld_bfd, bfd_object, gdbarch_bfd_arch_info (target_gdbarch ()));
-      if (sub)
-	{
-	  dyld_bfd = sub;
-	  make_cleanup_bfd_unref (sub);
-	}
+      gdb_bfd_ref_ptr sub
+	(gdb_bfd_mach_o_fat_extract (dyld_bfd.get (), bfd_object,
+				     gdbarch_bfd_arch_info (target_gdbarch ())));
+      if (sub != NULL)
+	dyld_bfd = sub;
       else
-	dyld_bfd = NULL;
-    }
-  if (!dyld_bfd)
-    {
-      do_cleanups (cleanup);
-      return;
+	dyld_bfd.release ();
     }
+  if (dyld_bfd == NULL)
+    return;
 
   /* We find the dynamic linker's base address by examining
      the current pc (which should point at the entry point for the
      dynamic linker) and subtracting the offset of the entry point.  */
   load_addr = (regcache_read_pc (get_current_regcache ())
-               - bfd_get_start_address (dyld_bfd));
+               - bfd_get_start_address (dyld_bfd.get ()));
 
   /* Now try to set a breakpoint in the dynamic linker.  */
   info->all_image_addr =
-    lookup_symbol_from_bfd (dyld_bfd, "_dyld_all_image_infos");
-
-  do_cleanups (cleanup);
+    lookup_symbol_from_bfd (dyld_bfd.get (), "_dyld_all_image_infos");
 
   if (info->all_image_addr == 0)
     return;
@@ -634,13 +620,11 @@ darwin_lookup_lib_symbol (struct objfile *objfile,
   return (struct block_symbol) {NULL, NULL};
 }
 
-static bfd *
+static gdb_bfd_ref_ptr
 darwin_bfd_open (char *pathname)
 {
   char *found_pathname;
   int found_file;
-  bfd *abfd;
-  bfd *res;
 
   /* Search for shared library file.  */
   found_pathname = solib_find (pathname, &found_file);
@@ -648,24 +632,21 @@ darwin_bfd_open (char *pathname)
     perror_with_name (pathname);
 
   /* Open bfd for shared library.  */
-  abfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref_ptr abfd (solib_bfd_fopen (found_pathname, found_file));
 
-  res = gdb_bfd_mach_o_fat_extract (abfd, bfd_object,
-				    gdbarch_bfd_arch_info (target_gdbarch ()));
-  if (!res)
-    {
-      make_cleanup_bfd_unref (abfd);
-      error (_("`%s': not a shared-library: %s"),
-	     bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
-    }
+  gdb_bfd_ref_ptr res
+    (gdb_bfd_mach_o_fat_extract (abfd.get (), bfd_object,
+				 gdbarch_bfd_arch_info (target_gdbarch ())));
+  if (res == NULL)
+    error (_("`%s': not a shared-library: %s"),
+	   bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
 
   /* The current filename for fat-binary BFDs is a name generated
      by BFD, usually a string containing the name of the architecture.
      Reset its value to the actual filename.  */
-  xfree (bfd_get_filename (res));
+  xfree (bfd_get_filename (res.get ()));
   res->filename = xstrdup (pathname);
 
-  gdb_bfd_unref (abfd);
   return res;
 }
 
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index d66fe5d..14cab05 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -816,7 +816,6 @@ enable_break (void)
     {
       unsigned int interp_sect_size;
       char *buf;
-      bfd *tmp_bfd = NULL;
       CORE_ADDR addr;
       struct int_elf32_dsbt_loadmap *ldm;
       int ret;
@@ -832,6 +831,7 @@ enable_break (void)
 	 loaded so that we can load its symbols and place a breakpoint
 	 in the dynamic linker itself.  */
 
+      gdb_bfd_ref_ptr tmp_bfd;
       TRY
 	{
 	  tmp_bfd = solib_bfd_open (buf);
@@ -852,29 +852,31 @@ enable_break (void)
 
       /* Record the relocated start and end address of the dynamic linker
 	 text and plt section for dsbt_in_dynsym_resolve_code.  */
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
 	{
 	  info->interp_text_sect_low
-	    = bfd_section_vma (tmp_bfd, interp_sect);
+	    = bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  info->interp_text_sect_low
 	    += displacement_from_map (ldm, info->interp_text_sect_low);
 	  info->interp_text_sect_high
 	    = info->interp_text_sect_low
-	    + bfd_section_size (tmp_bfd, interp_sect);
+	    + bfd_section_size (tmp_bfd.get (), interp_sect);
 	}
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
 	{
 	  info->interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect);
+	    bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  info->interp_plt_sect_low
 	    += displacement_from_map (ldm, info->interp_plt_sect_low);
 	  info->interp_plt_sect_high =
-	    info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+	    info->interp_plt_sect_low + bfd_section_size (tmp_bfd.get (),
+							  interp_sect);
 	}
 
-      addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_state");
+      addr = gdb_bfd_lookup_symbol (tmp_bfd.get (), cmp_name,
+				    "_dl_debug_state");
       if (addr != 0)
 	{
 	  if (solib_dsbt_debug)
@@ -901,10 +903,7 @@ enable_break (void)
 	  ret = 0;
 	}
 
-      /* We're done with the temporary bfd.  */
-      gdb_bfd_unref (tmp_bfd);
-
-      /* We're also done with the loadmap.  */
+      /* We're done with the loadmap.  */
       xfree (ldm);
 
       return ret;
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index 61a4ed0..0387b44 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -532,7 +532,6 @@ enable_break2 (void)
     {
       unsigned int interp_sect_size;
       char *buf;
-      bfd *tmp_bfd = NULL;
       int status;
       CORE_ADDR addr, interp_loadmap_addr;
       gdb_byte addr_buf[FRV_PTR_SIZE];
@@ -554,6 +553,7 @@ enable_break2 (void)
          be trivial on GNU/Linux).  Therefore, we have to try an alternate
          mechanism to find the dynamic linker's base address.  */
 
+      gdb_bfd_ref_ptr tmp_bfd;
       TRY
         {
           tmp_bfd = solib_bfd_open (buf);
@@ -575,7 +575,6 @@ enable_break2 (void)
 	{
 	  warning (_("Unable to determine dynamic linker loadmap address."));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -590,41 +589,41 @@ enable_break2 (void)
 	  warning (_("Unable to load dynamic linker loadmap at address %s."),
 	           hex_string_custom (interp_loadmap_addr, 8));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
 	{
 	  interp_text_sect_low
-	    = bfd_section_vma (tmp_bfd, interp_sect);
+	    = bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  interp_text_sect_low
 	    += displacement_from_map (ldm, interp_text_sect_low);
 	  interp_text_sect_high
-	    = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+	    = interp_text_sect_low + bfd_section_size (tmp_bfd.get (),
+						       interp_sect);
 	}
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
 	{
 	  interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect);
+	    bfd_section_vma (tmp_bfd.get (), interp_sect);
 	  interp_plt_sect_low
 	    += displacement_from_map (ldm, interp_plt_sect_low);
 	  interp_plt_sect_high =
-	    interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+	    interp_plt_sect_low + bfd_section_size (tmp_bfd.get (),
+						    interp_sect);
 	}
 
-      addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr");
+      addr = gdb_bfd_lookup_symbol (tmp_bfd.get (), cmp_name, "_dl_debug_addr");
 
       if (addr == 0)
 	{
 	  warning (_("Could not find symbol _dl_debug_addr "
 		     "in dynamic linker"));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
 
@@ -675,7 +674,6 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr + 8, 8));
 	  enable_break_failure_warning ();
-	  gdb_bfd_unref (tmp_bfd);
 	  return 0;
 	}
       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
@@ -687,15 +685,11 @@ enable_break2 (void)
 		     "(at address %s) from dynamic linker"),
 	           hex_string_custom (addr, 8));
 	  enable_break_failure_warning ();
-	  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.  */
-      gdb_bfd_unref (tmp_bfd);
-
-      /* We're also done with the loadmap.  */
+      /* We're done with the loadmap.  */
       xfree (ldm);
 
       /* Remove all the solib event breakpoints.  Their addresses
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index fa2977e..ab98656 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -319,36 +319,32 @@ spu_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb)
   return 0;
 }
 
-static bfd *
+static gdb_bfd_ref_ptr
 spu_bfd_fopen (char *name, CORE_ADDR addr)
 {
-  bfd *nbfd;
   CORE_ADDR *open_closure = XNEW (CORE_ADDR);
 
   *open_closure = addr;
 
-  nbfd = gdb_bfd_openr_iovec (name, "elf32-spu",
-			      spu_bfd_iovec_open, open_closure,
-			      spu_bfd_iovec_pread, spu_bfd_iovec_close,
-			      spu_bfd_iovec_stat);
-  if (!nbfd)
+  gdb_bfd_ref_ptr nbfd (gdb_bfd_openr_iovec (name, "elf32-spu",
+					     spu_bfd_iovec_open, open_closure,
+					     spu_bfd_iovec_pread,
+					     spu_bfd_iovec_close,
+					     spu_bfd_iovec_stat));
+  if (nbfd == NULL)
     return NULL;
 
-  if (!bfd_check_format (nbfd, bfd_object))
-    {
-      gdb_bfd_unref (nbfd);
-      return NULL;
-    }
+  if (!bfd_check_format (nbfd.get (), bfd_object))
+    return NULL;
 
   return nbfd;
 }
 
 /* Open shared library BFD.  */
-static bfd *
+static gdb_bfd_ref_ptr
 spu_bfd_open (char *pathname)
 {
   char *original_name = strrchr (pathname, '@');
-  bfd *abfd;
   asection *spu_name;
   unsigned long long addr;
   int fd;
@@ -362,22 +358,23 @@ spu_bfd_open (char *pathname)
     internal_error (__FILE__, __LINE__, "bad object ID");
 
   /* Open BFD representing SPE executable.  */
-  abfd = spu_bfd_fopen (original_name, (CORE_ADDR) addr);
-  if (!abfd)
+  gdb_bfd_ref_ptr abfd (spu_bfd_fopen (original_name, (CORE_ADDR) addr));
+  if (abfd == NULL)
     error (_("Cannot read SPE executable at %s"), original_name);
 
   /* Retrieve SPU name note.  */
-  spu_name = bfd_get_section_by_name (abfd, ".note.spu_name");
+  spu_name = bfd_get_section_by_name (abfd.get (), ".note.spu_name");
   if (spu_name)
     {
-      int sect_size = bfd_section_size (abfd, spu_name);
+      int sect_size = bfd_section_size (abfd.get (), spu_name);
 
       if (sect_size > 20)
 	{
 	  char *buf
 	    = (char *) alloca (sect_size - 20 + strlen (original_name) + 1);
 
-	  bfd_get_section_contents (abfd, spu_name, buf, 20, sect_size - 20);
+	  bfd_get_section_contents (abfd.get (), spu_name, buf, 20,
+				    sect_size - 20);
 	  buf[sect_size - 20] = '\0';
 
 	  strcat (buf, original_name);
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 0e18292..b801364 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2355,7 +2355,6 @@ enable_break (struct svr4_info *info, int from_tty)
       int load_addr_found = 0;
       int loader_found_in_list = 0;
       struct so_list *so;
-      bfd *tmp_bfd = NULL;
       struct target_ops *tmp_bfd_target;
 
       sym_addr = 0;
@@ -2369,6 +2368,7 @@ enable_break (struct svr4_info *info, int from_tty)
          be trivial on GNU/Linux).  Therefore, we have to try an alternate
          mechanism to find the dynamic linker's base address.  */
 
+      gdb_bfd_ref_ptr tmp_bfd;
       TRY
         {
 	  tmp_bfd = solib_bfd_open (interp_name);
@@ -2382,11 +2382,9 @@ enable_break (struct svr4_info *info, int from_tty)
 	goto bkpt_at_symbol;
 
       /* Now convert the TMP_BFD into a target.  That way target, as
-         well as BFD operations can be used.  */
-      tmp_bfd_target = target_bfd_reopen (tmp_bfd);
-      /* target_bfd_reopen acquired its own reference, so we can
-         release ours now.  */
-      gdb_bfd_unref (tmp_bfd);
+         well as BFD operations can be used.  target_bfd_reopen
+         acquires its own reference.  */
+      tmp_bfd_target = target_bfd_reopen (tmp_bfd.get ());
 
       /* On a running target, we can get the dynamic linker's base
          address from the shared library table.  */
@@ -2397,7 +2395,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	    {
 	      load_addr_found = 1;
 	      loader_found_in_list = 1;
-	      load_addr = lm_addr_check (so, tmp_bfd);
+	      load_addr = lm_addr_check (so, tmp_bfd.get ());
 	      break;
 	    }
 	  so = so->next;
@@ -2418,7 +2416,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	    if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
 	      {
 		CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
-		CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd,
+		CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd.get (),
 							      tmp_bfd_target);
 
 		gdb_assert (load_addr < space_size);
@@ -2447,7 +2445,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	    = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
 
 	  load_addr = (regcache_read_pc (regcache)
-		       - exec_entry_point (tmp_bfd, tmp_bfd_target));
+		       - exec_entry_point (tmp_bfd.get (), tmp_bfd_target));
 	}
 
       if (!loader_found_in_list)
@@ -2460,29 +2458,30 @@ enable_break (struct svr4_info *info, int from_tty)
 
       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
 	{
 	  info->interp_text_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+	    bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
 	  info->interp_text_sect_high =
 	    info->interp_text_sect_low
-	    + bfd_section_size (tmp_bfd, interp_sect);
+	    + bfd_section_size (tmp_bfd.get (), interp_sect);
 	}
-      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+      interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
 	{
 	  info->interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+	    bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
 	  info->interp_plt_sect_high =
 	    info->interp_plt_sect_low
-	    + bfd_section_size (tmp_bfd, interp_sect);
+	    + bfd_section_size (tmp_bfd.get (), interp_sect);
 	}
 
       /* Now try to set a breakpoint in the dynamic linker.  */
       for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
 	{
-	  sym_addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name_and_sec_flags,
+	  sym_addr = gdb_bfd_lookup_symbol (tmp_bfd.get (),
+					    cmp_name_and_sec_flags,
 					    *bkpt_namep);
 	  if (sym_addr != 0)
 	    break;
diff --git a/gdb/solib.c b/gdb/solib.c
index c4b2cdc..7fc4463 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -474,15 +474,15 @@ solib_find (char *in_pathname, int *fd)
    function.  If unsuccessful, the FD will be closed (unless FD was
    -1).  */
 
-bfd *
+gdb_bfd_ref_ptr
 solib_bfd_fopen (char *pathname, int fd)
 {
-  bfd *abfd = gdb_bfd_open (pathname, gnutarget, fd);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (pathname, gnutarget, fd));
 
-  if (abfd != NULL && !gdb_bfd_has_target_filename (abfd))
-    bfd_set_cacheable (abfd, 1);
+  if (abfd != NULL && !gdb_bfd_has_target_filename (abfd.get ()))
+    bfd_set_cacheable (abfd.get (), 1);
 
-  if (!abfd)
+  if (abfd == NULL)
     {
       make_cleanup (xfree, pathname);
       error (_("Could not open `%s' as an executable file: %s"),
@@ -496,12 +496,11 @@ solib_bfd_fopen (char *pathname, int fd)
 
 /* Find shared library PATHNAME and open a BFD for it.  */
 
-bfd *
+gdb_bfd_ref_ptr
 solib_bfd_open (char *pathname)
 {
   char *found_pathname;
   int found_file;
-  bfd *abfd;
   const struct bfd_arch_info *b;
 
   /* Search for shared library file.  */
@@ -517,22 +516,20 @@ solib_bfd_open (char *pathname)
     }
 
   /* Open bfd for shared library.  */
-  abfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref_ptr abfd (solib_bfd_fopen (found_pathname, found_file));
 
   /* Check bfd format.  */
-  if (!bfd_check_format (abfd, bfd_object))
-    {
-      make_cleanup_bfd_unref (abfd);
-      error (_("`%s': not in executable format: %s"),
-	     bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
-    }
+  if (!bfd_check_format (abfd.get (), bfd_object))
+    error (_("`%s': not in executable format: %s"),
+	   bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
 
   /* Check bfd arch.  */
   b = gdbarch_bfd_arch_info (target_gdbarch ());
-  if (!b->compatible (b, bfd_get_arch_info (abfd)))
+  if (!b->compatible (b, bfd_get_arch_info (abfd.get ())))
     warning (_("`%s': Shared library architecture %s is not compatible "
                "with target architecture %s."), bfd_get_filename (abfd),
-             bfd_get_arch_info (abfd)->printable_name, b->printable_name);
+             bfd_get_arch_info (abfd.get ())->printable_name,
+	     b->printable_name);
 
   return abfd;
 }
@@ -556,18 +553,17 @@ solib_map_sections (struct so_list *so)
   char *filename;
   struct target_section *p;
   struct cleanup *old_chain;
-  bfd *abfd;
 
   filename = tilde_expand (so->so_name);
   old_chain = make_cleanup (xfree, filename);
-  abfd = ops->bfd_open (filename);
+  gdb_bfd_ref_ptr abfd (ops->bfd_open (filename));
   do_cleanups (old_chain);
 
   if (abfd == NULL)
     return 0;
 
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
-  so->abfd = abfd;
+  so->abfd = abfd.release ();
 
   /* Copy the full path name into so_name, allowing symbol_file_add
      to find it later.  This also affects the =library-loaded GDB/MI
@@ -575,14 +571,14 @@ solib_map_sections (struct so_list *so)
      the library's host-side path.  If we let the target dictate
      that objfile's path, and the target is different from the host,
      GDB/MI will not provide the correct host-side path.  */
-  if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE)
+  if (strlen (bfd_get_filename (so->abfd)) >= SO_NAME_MAX_PATH_SIZE)
     error (_("Shared library file name is too long."));
-  strcpy (so->so_name, bfd_get_filename (abfd));
+  strcpy (so->so_name, bfd_get_filename (so->abfd));
 
-  if (build_section_table (abfd, &so->sections, &so->sections_end))
+  if (build_section_table (so->abfd, &so->sections, &so->sections_end))
     {
       error (_("Can't find the file sections in `%s': %s"),
-	     bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+	     bfd_get_filename (so->abfd), bfd_errmsg (bfd_get_error ()));
     }
 
   for (p = so->sections; p < so->sections_end; p++)
@@ -1351,7 +1347,6 @@ reload_shared_libraries_1 (int from_tty)
   for (so = so_list_head; so != NULL; so = so->next)
     {
       char *filename, *found_pathname = NULL;
-      bfd *abfd;
       int was_loaded = so->symbols_loaded;
       symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
 
@@ -1360,12 +1355,11 @@ reload_shared_libraries_1 (int from_tty)
 
       filename = tilde_expand (so->so_original_name);
       make_cleanup (xfree, filename);
-      abfd = solib_bfd_open (filename);
+      gdb_bfd_ref_ptr abfd (solib_bfd_open (filename));
       if (abfd != NULL)
 	{
-	  found_pathname = xstrdup (bfd_get_filename (abfd));
+	  found_pathname = xstrdup (bfd_get_filename (abfd.get ()));
 	  make_cleanup (xfree, found_pathname);
-	  gdb_bfd_unref (abfd);
 	}
 
       /* If this shared library is no longer associated with its previous
diff --git a/gdb/solist.h b/gdb/solist.h
index f709483..ca02051 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -22,6 +22,7 @@
 #define SO_NAME_MAX_PATH_SIZE 512	/* FIXME: Should be dynamic */
 /* For domain_enum domain.  */
 #include "symtab.h"
+#include "gdb_bfd.h"
 
 /* Forward declaration for target specific link map information.  This
    struct is opaque to all but the target specific file.  */
@@ -121,7 +122,7 @@ struct target_so_ops
     int (*in_dynsym_resolve_code) (CORE_ADDR pc);
 
     /* Find and open shared library binary file.  */
-    bfd *(*bfd_open) (char *pathname);
+    gdb_bfd_ref_ptr (*bfd_open) (char *pathname);
 
     /* Optional extra hook for finding and opening a solib.
        If TEMP_PATHNAME is non-NULL: If the file is successfully opened a
@@ -178,10 +179,10 @@ extern char *exec_file_find (char *in_pathname, int *fd);
 extern char *solib_find (char *in_pathname, int *fd);
 
 /* Open BFD for shared library file.  */
-extern bfd *solib_bfd_fopen (char *pathname, int fd);
+extern gdb_bfd_ref_ptr solib_bfd_fopen (char *pathname, int fd);
 
 /* Find solib binary file and open it.  */
-extern bfd *solib_bfd_open (char *in_pathname);
+extern gdb_bfd_ref_ptr solib_bfd_open (char *in_pathname);
 
 /* FIXME: gdbarch needs to control this variable.  */
 extern struct target_so_ops *current_target_so_ops;
diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c
index f1d58ec..9d333b8 100644
--- a/gdb/spu-linux-nat.c
+++ b/gdb/spu-linux-nat.c
@@ -318,37 +318,35 @@ spu_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
   return 0;
 }
 
-static bfd *
+static gdb_bfd_ref_ptr
 spu_bfd_open (ULONGEST addr)
 {
-  struct bfd *nbfd;
   asection *spu_name;
 
   ULONGEST *open_closure = XNEW (ULONGEST);
   *open_closure = addr;
 
-  nbfd = gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
-			      spu_bfd_iovec_open, open_closure,
-			      spu_bfd_iovec_pread, spu_bfd_iovec_close,
-			      spu_bfd_iovec_stat);
-  if (!nbfd)
+  gdb_bfd_ref_ptr nbfd (gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
+					     spu_bfd_iovec_open, open_closure,
+					     spu_bfd_iovec_pread,
+					     spu_bfd_iovec_close,
+					     spu_bfd_iovec_stat));
+  if (nbfd == NULL)
     return NULL;
 
-  if (!bfd_check_format (nbfd, bfd_object))
-    {
-      gdb_bfd_unref (nbfd);
-      return NULL;
-    }
+  if (!bfd_check_format (nbfd.get (), bfd_object))
+    return NULL;
 
   /* Retrieve SPU name note and update BFD name.  */
-  spu_name = bfd_get_section_by_name (nbfd, ".note.spu_name");
+  spu_name = bfd_get_section_by_name (nbfd.get (), ".note.spu_name");
   if (spu_name)
     {
-      int sect_size = bfd_section_size (nbfd, spu_name);
+      int sect_size = bfd_section_size (nbfd.get (), spu_name);
       if (sect_size > 20)
 	{
 	  char *buf = (char *)alloca (sect_size - 20 + 1);
-	  bfd_get_section_contents (nbfd, spu_name, buf, 20, sect_size - 20);
+	  bfd_get_section_contents (nbfd.get (), spu_name, buf, 20,
+				    sect_size - 20);
 	  buf[sect_size - 20] = '\0';
 
 	  xfree ((char *)nbfd->filename);
@@ -367,7 +365,6 @@ static void
 spu_symbol_file_add_from_memory (int inferior_fd)
 {
   ULONGEST addr;
-  struct bfd *nbfd;
 
   gdb_byte id[128];
   char annex[32];
@@ -385,15 +382,12 @@ spu_symbol_file_add_from_memory (int inferior_fd)
     return;
 
   /* Open BFD representing SPE executable and read its symbols.  */
-  nbfd = spu_bfd_open (addr);
-  if (nbfd)
+  gdb_bfd_ref_ptr nbfd (spu_bfd_open (addr));
+  if (nbfd != NULL)
     {
-      struct cleanup *cleanup = make_cleanup_bfd_unref (nbfd);
-
-      symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd),
+      symbol_file_add_from_bfd (nbfd.get (), bfd_get_filename (nbfd),
 				SYMFILE_VERBOSE | SYMFILE_MAINLINE,
 				NULL, 0, NULL);
-      do_cleanups (cleanup);
     }
 }
 
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index 58257b9..ec283b2 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -102,20 +102,21 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
     error (_("Failed to read a valid object file image from memory."));
 
   gdb_bfd_ref (nbfd);
+  /* Manage the new reference for the duration of this function.  */
+  gdb_bfd_ref_ptr nbfd_holder (nbfd);
+
   xfree (bfd_get_filename (nbfd));
   if (name == NULL)
     nbfd->filename = xstrdup ("shared object read from target memory");
   else
     nbfd->filename = name;
 
-  cleanup = make_cleanup_bfd_unref (nbfd);
-
   if (!bfd_check_format (nbfd, bfd_object))
     error (_("Got object file from memory but can't read symbols: %s."),
 	   bfd_errmsg (bfd_get_error ()));
 
   sai = alloc_section_addr_info (bfd_count_sections (nbfd));
-  make_cleanup (xfree, sai);
+  cleanup = make_cleanup (xfree, sai);
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 52f99bf..4775d5b 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -876,8 +876,7 @@ read_symbols (struct objfile *objfile, symfile_add_flags add_flags)
       && objfile->separate_debug_objfile == NULL
       && objfile->separate_debug_objfile_backlink == NULL)
     {
-      bfd *abfd = find_separate_debug_file_in_section (objfile);
-      struct cleanup *cleanup = make_cleanup_bfd_unref (abfd);
+      gdb_bfd_ref_ptr abfd (find_separate_debug_file_in_section (objfile));
 
       if (abfd != NULL)
 	{
@@ -885,11 +884,9 @@ read_symbols (struct objfile *objfile, symfile_add_flags add_flags)
 	     virtual section-as-bfd like the bfd filename containing the
 	     section.  Therefore use also non-canonical name form for the same
 	     file containing the section.  */
-	  symbol_file_add_separate (abfd, objfile->original_name, add_flags,
-				    objfile);
+	  symbol_file_add_separate (abfd.get (), objfile->original_name,
+				    add_flags, objfile);
 	}
-
-      do_cleanups (cleanup);
     }
   if ((add_flags & SYMFILE_NO_READ) == 0)
     require_partial_symbols (objfile, 0);
@@ -1287,13 +1284,10 @@ struct objfile *
 symbol_file_add (const char *name, symfile_add_flags add_flags,
 		 struct section_addr_info *addrs, objfile_flags flags)
 {
-  bfd *bfd = symfile_bfd_open (name);
-  struct cleanup *cleanup = make_cleanup_bfd_unref (bfd);
-  struct objfile *objf;
+  gdb_bfd_ref_ptr bfd (symfile_bfd_open (name));
 
-  objf = symbol_file_add_from_bfd (bfd, name, add_flags, addrs, flags, NULL);
-  do_cleanups (cleanup);
-  return objf;
+  return symbol_file_add_from_bfd (bfd.get (), name, add_flags, addrs,
+				   flags, NULL);
 }
 
 /* Call symbol_file_add() with default values and update whatever is
@@ -1354,7 +1348,6 @@ separate_debug_file_exists (const char *name, unsigned long crc,
 {
   unsigned long file_crc;
   int file_crc_p;
-  bfd *abfd;
   struct stat parent_stat, abfd_stat;
   int verified_as_different;
 
@@ -1367,9 +1360,9 @@ separate_debug_file_exists (const char *name, unsigned long crc,
   if (filename_cmp (name, objfile_name (parent_objfile)) == 0)
     return 0;
 
-  abfd = gdb_bfd_open (name, gnutarget, -1);
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (name, gnutarget, -1));
 
-  if (!abfd)
+  if (abfd == NULL)
     return 0;
 
   /* Verify symlinks were not the cause of filename_cmp name difference above.
@@ -1383,24 +1376,19 @@ separate_debug_file_exists (const char *name, unsigned long crc,
      numbers will never set st_ino to zero, this is merely an
      optimization, so we do not need to worry about false negatives.  */
 
-  if (bfd_stat (abfd, &abfd_stat) == 0
+  if (bfd_stat (abfd.get (), &abfd_stat) == 0
       && abfd_stat.st_ino != 0
       && bfd_stat (parent_objfile->obfd, &parent_stat) == 0)
     {
       if (abfd_stat.st_dev == parent_stat.st_dev
 	  && abfd_stat.st_ino == parent_stat.st_ino)
-	{
-	  gdb_bfd_unref (abfd);
-	  return 0;
-	}
+	return 0;
       verified_as_different = 1;
     }
   else
     verified_as_different = 0;
 
-  file_crc_p = gdb_bfd_crc (abfd, &file_crc);
-
-  gdb_bfd_unref (abfd);
+  file_crc_p = gdb_bfd_crc (abfd.get (), &file_crc);
 
   if (!file_crc_p)
     return 0;
@@ -1721,10 +1709,9 @@ set_initial_language (void)
    includes a newly malloc'd` copy of NAME (tilde-expanded and made
    absolute).  In case of trouble, error() is called.  */
 
-bfd *
+gdb_bfd_ref_ptr
 symfile_bfd_open (const char *name)
 {
-  bfd *sym_bfd;
   int desc = -1;
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
 
@@ -1760,20 +1747,17 @@ symfile_bfd_open (const char *name)
       name = absolute_name;
     }
 
-  sym_bfd = gdb_bfd_open (name, gnutarget, desc);
-  if (!sym_bfd)
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (name, gnutarget, desc));
+  if (sym_bfd == NULL)
     error (_("`%s': can't open to read symbols: %s."), name,
 	   bfd_errmsg (bfd_get_error ()));
 
-  if (!gdb_bfd_has_target_filename (sym_bfd))
-    bfd_set_cacheable (sym_bfd, 1);
+  if (!gdb_bfd_has_target_filename (sym_bfd.get ()))
+    bfd_set_cacheable (sym_bfd.get (), 1);
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
-    {
-      make_cleanup_bfd_unref (sym_bfd);
-      error (_("`%s': can't read symbols: %s."), name,
-	     bfd_errmsg (bfd_get_error ()));
-    }
+  if (!bfd_check_format (sym_bfd.get (), bfd_object))
+    error (_("`%s': can't read symbols: %s."), name,
+	   bfd_errmsg (bfd_get_error ()));
 
   do_cleanups (back_to);
 
@@ -2073,7 +2057,6 @@ static void print_transfer_performance (struct ui_file *stream,
 void
 generic_load (const char *args, int from_tty)
 {
-  bfd *loadfile_bfd;
   char *filename;
   struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
   struct load_section_data cbdata;
@@ -2114,25 +2097,23 @@ generic_load (const char *args, int from_tty)
     }
 
   /* Open the file for loading.  */
-  loadfile_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr loadfile_bfd (gdb_bfd_open (filename, gnutarget, -1));
   if (loadfile_bfd == NULL)
     {
       perror_with_name (filename);
       return;
     }
 
-  make_cleanup_bfd_unref (loadfile_bfd);
-
-  if (!bfd_check_format (loadfile_bfd, bfd_object))
+  if (!bfd_check_format (loadfile_bfd.get (), bfd_object))
     {
       error (_("\"%s\" is not an object file: %s"), filename,
 	     bfd_errmsg (bfd_get_error ()));
     }
 
-  bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
+  bfd_map_over_sections (loadfile_bfd.get (), add_section_size_callback,
 			 (void *) &total_progress.total_size);
 
-  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+  bfd_map_over_sections (loadfile_bfd.get (), load_section_callback, &cbdata);
 
   using namespace std::chrono;
 
@@ -2144,7 +2125,7 @@ generic_load (const char *args, int from_tty)
 
   steady_clock::time_point end_time = steady_clock::now ();
 
-  entry = bfd_get_start_address (loadfile_bfd);
+  entry = bfd_get_start_address (loadfile_bfd.get ());
   entry = gdbarch_addr_bits_remove (target_gdbarch (), entry);
   ui_out_text (uiout, "Start address ");
   ui_out_field_fmt (uiout, "address", "%s", paddress (target_gdbarch (), entry));
@@ -2568,22 +2549,16 @@ reread_symbols (void)
 
 	  /* Clean up any state BFD has sitting around.  */
 	  {
-	    struct bfd *obfd = objfile->obfd;
+	    gdb_bfd_ref_ptr obfd (objfile->obfd);
 	    char *obfd_filename;
 
 	    obfd_filename = bfd_get_filename (objfile->obfd);
 	    /* Open the new BFD before freeing the old one, so that
 	       the filename remains live.  */
-	    objfile->obfd = gdb_bfd_open (obfd_filename, gnutarget, -1);
+	    gdb_bfd_ref_ptr temp (gdb_bfd_open (obfd_filename, gnutarget, -1));
+	    objfile->obfd = temp.release ();
 	    if (objfile->obfd == NULL)
-	      {
-		/* We have to make a cleanup and error here, rather
-		   than erroring later, because once we unref OBFD,
-		   OBFD_FILENAME will be freed.  */
-		make_cleanup_bfd_unref (obfd);
-		error (_("Can't open %s to read symbols."), obfd_filename);
-	      }
-	    gdb_bfd_unref (obfd);
+	      error (_("Can't open %s to read symbols."), obfd_filename);
 	  }
 
 	  original_name = xstrdup (objfile->original_name);
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 59952cb..7a2e6fb 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -25,6 +25,7 @@
 #include "probe.h"
 #include "symfile-add-flags.h"
 #include "objfile-flags.h"
+#include "gdb_bfd.h"
 
 /* Opaque declarations.  */
 struct target_section;
@@ -499,7 +500,7 @@ extern void set_initial_language (void);
 
 extern void find_lowest_section (bfd *, asection *, void *);
 
-extern bfd *symfile_bfd_open (const char *);
+extern gdb_bfd_ref_ptr symfile_bfd_open (const char *);
 
 extern int get_section_index (struct objfile *, char *);
 
@@ -646,6 +647,6 @@ extern void elfmdebug_build_psymtabs (struct objfile *,
 
 /* From minidebug.c.  */
 
-extern bfd *find_separate_debug_file_in_section (struct objfile *);
+extern gdb_bfd_ref_ptr find_separate_debug_file_in_section (struct objfile *);
 
 #endif /* !defined(SYMFILE_H) */
diff --git a/gdb/utils.c b/gdb/utils.c
index 77c38bf..6ee6fc8 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -151,18 +151,6 @@ make_cleanup_freeargv (char **arg)
   return make_cleanup (do_freeargv, arg);
 }
 
-static void
-do_bfd_close_cleanup (void *arg)
-{
-  gdb_bfd_unref ((bfd *) arg);
-}
-
-struct cleanup *
-make_cleanup_bfd_unref (bfd *abfd)
-{
-  return make_cleanup (do_bfd_close_cleanup, abfd);
-}
-
 /* Helper function which does the work for make_cleanup_fclose.  */
 
 static void
diff --git a/gdb/utils.h b/gdb/utils.h
index 349530e..4407eeb 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -81,8 +81,6 @@ extern struct cleanup *(make_cleanup_free_section_addr_info
 
 extern struct cleanup *make_cleanup_fclose (FILE *file);
 
-extern struct cleanup *make_cleanup_bfd_unref (bfd *abfd);
-
 struct obstack;
 extern struct cleanup *make_cleanup_obstack_free (struct obstack *obstack);
 
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 5b79f34..efccd71 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -669,32 +669,27 @@ windows_make_so (const char *name, LPVOID load_addr)
   p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
   if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
     {
-      bfd *abfd;
       asection *text = NULL;
       CORE_ADDR text_vma;
 
-      abfd = gdb_bfd_open (so->so_name, "pei-i386", -1);
+      gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386", -1));
 
-      if (!abfd)
+      if (abfd == NULL)
 	return so;
 
-      if (bfd_check_format (abfd, bfd_object))
-	text = bfd_get_section_by_name (abfd, ".text");
+      if (bfd_check_format (abfd.get (), bfd_object))
+	text = bfd_get_section_by_name (abfd.get (), ".text");
 
       if (!text)
-	{
-	  gdb_bfd_unref (abfd);
-	  return so;
-	}
+	return so;
 
       /* The symbols in a dll are offset by 0x1000, which is the
 	 offset from 0 of the first byte in an image - because of the
 	 file header and the section alignment.  */
       cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
 						   load_addr + 0x1000);
-      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
-
-      gdb_bfd_unref (abfd);
+      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd.get (),
+							      text);
     }
 #endif
 
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 810607a..2f79d8d 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -372,7 +372,6 @@ windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
 			     struct gdbarch *gdbarch, struct obstack *obstack)
 {
   char *p;
-  struct bfd * dll;
   CORE_ADDR text_offset;
 
   obstack_grow_str (obstack, "<library name=\"");
@@ -380,12 +379,11 @@ windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
   obstack_grow_str (obstack, p);
   xfree (p);
   obstack_grow_str (obstack, "\"><segment address=\"");
-  dll = gdb_bfd_open (so_name, gnutarget, -1);
+  gdb_bfd_ref_ptr dll (gdb_bfd_open (so_name, gnutarget, -1));
   /* The following calls are OK even if dll is NULL.
      The default value 0x1000 is returned by pe_text_section_offset
      in that case.  */
-  text_offset = pe_text_section_offset (dll);
-  gdb_bfd_unref (dll);
+  text_offset = pe_text_section_offset (dll.get ());
   obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset));
   obstack_grow_str (obstack, "\"/></library>");
 }

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-13 13:29     ` Tom Tromey
@ 2016-12-20 14:49       ` Pedro Alves
  2016-12-23 19:05         ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-20 14:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/13/2016 01:28 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> Or "reset ()", following the naming used in the standard smart pointers?
> 
> I went with reset since I think "free" can be a macro sometimes.
> Or at least it could in C... not actually sure if C++ removed this
> possibility.

I always assumed it has, but had never went looking for the specific
wording.  Looking at the C++14 draft N4140, I see:

 17.6.1.2 - Headers:

 5 - Names which are defined as macros in C shall be defined as macros in
 the C ++ standard library, even if C grants license for implementation 
 as functions. [ Note: The names defined as macros in C include the
 following: assert, offsetof, setjmp, va_arg, va_end, and va_start. - end note ]

 6 - Names that are defined as functions in C shall be defined as functions in
 the C ++ standard library." (175)

And then footnote 175 clarifies:

 "175) This disallows the practice, allowed in C, of providing a masking
 macro in addition to the function prototype. The only way to achieve equivalent
 inline behavior in C ++ is to provide a definition as an extern inline function."


So I think the answer is yes, C++ removes that possibility.


BTW, I meanwhile realized that "release" would also be a
naming/concept conflict with release_value / value_release_to_mark
too.  Really best to avoid it here.

In pondering a bit more over this, I wonder whether
adding a "scoped_" to go with scoped_restore etc., would make
it a bit clearer to readers that this is a RAII type.  Then
also considering value_release_to_mark, I wonder would an
API/naming like this:

struct scoped_value_mark
{
   scoped_value_mark () : m_value (value_mark ()) {}
   ~scoped_value_mark () { free_to_mark ()}

   void free_to_mark () { if (m_value) value_free_to_mark (m_value); }
   void release_to_mark () { if (m_value) value_release_to_mark (m_value); }

   /* Get the mark value.  */
   struct value *get () { return m_value; }
};

Uses would look like:

 scoped_value_mark value_mark;
 ...
    value_mark.free_to_mark (); // some path than wants an explicit "free_to_mark".


In eval.c:fetch_subexp_value we'd use it like:

  /* Evaluate the expression.  */
  scoped_value_mark mark;

  [...]
      result = evaluate_subexp (NULL_TYPE, exp, pc, EVAL_NORMAL);
  [...]

  new_mark = value_mark ();
  if (mark.get () == new_mark)
    return;

  /* Make sure it's not lazy, so that after the target stops again we
     have a non-lazy previous value to compare with.  */
  [...]

  if (val_chain)
    {
      /* Return the chain of intermediate values.  We use this to
	 decide which addresses to watch.  */
      *val_chain = new_mark;
      mark.release_to_mark ();
    }
}

Would this result in clearer client code?  IMHO, yes, but WDYT?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts)
  2016-12-13 13:26     ` Tom Tromey
  2016-12-15  4:12       ` Tom Tromey
@ 2016-12-20 17:19       ` Pedro Alves
  2016-12-20 18:05         ` Tom Tromey
  1 sibling, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-20 17:19 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/13/2016 01:25 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> -    return NULL;
>>> +    return gdb_bfd_ref_ptr ();
> 
> Pedro> This provides a good reason to have an implicit construction from
> Pedro> nullptr_t.  You had it in the original gdbpy_reference
> Pedro> submission, but I had asked to remove it.  If we add it back,
> Pedro> these cases could be more clearly written as "return
> Pedro> NULL/nullptr".  Could you do that, and then drop all the hunks
> Pedro> like:
> 
>>> -    return NULL;
>>> +    return gdb_bfd_ref_ptr ();
> 
> Pedro> ?
> 
> I did this.

Thanks!

> Pedro> I think these could be:
> Pedro>     std::string filename
> Pedro>       = string_printf ("%.*s", filename_len, pathname);
> Pedro>     std::string member_name
> Pedro>       = string_printf ("%.*s", path_len - filename_len - 2, sep + 1));
> 
> I did this, but it's a bit ugly as solib_find isn't const-correct.

That doesn't look hard to fix.  I've pushed in the patch below.
What uglification does this allow removing?

From 992f1ddc3be1f5195f18beaa801ac50f284b10c5 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 20 Dec 2016 17:07:19 +0000
Subject: [PATCH] gdb: Constify solib_find

gdb/ChangeLog:
2016-12-20  Pedro Alves  <palves@redhat.com>

	* nto-tdep.c (nto_find_and_open_solib): Constify 'solib'
	parameter.
	* nto-tdep.h (nto_find_and_open_solib): Constify 'solib'
	parameter.
	* solib.c (solib_find_1, exec_file_find, solib_find): Constify
	in_pathname' parameter.
	* solist.h (struct target_so_ops) <find_and_open_solib>: Constify
	'soname' parameter.
	(exec_file_find, solib_find): Constify 'in_pathname' parameter.
---
 gdb/ChangeLog  | 12 ++++++++++++
 gdb/nto-tdep.c |  3 ++-
 gdb/nto-tdep.h |  2 +-
 gdb/solib.c    |  8 ++++----
 gdb/solist.h   |  6 +++---
 5 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5f0e6fe..2041dd5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,4 +1,16 @@
 2016-12-20  Pedro Alves  <palves@redhat.com>
+
+	* nto-tdep.c (nto_find_and_open_solib): Constify 'solib'
+	parameter.
+	* nto-tdep.h (nto_find_and_open_solib): Constify 'solib'
+	parameter.
+	* solib.c (solib_find_1, exec_file_find, solib_find): Constify
+	in_pathname' parameter.
+	* solist.h (struct target_so_ops) <find_and_open_solib>: Constify
+	'soname' parameter.
+	(exec_file_find, solib_find): Constify 'in_pathname' parameter.
+
+2016-12-20  Pedro Alves  <palves@redhat.com>
 	    Yao Qi  <yao.qi@linaro.org>
 
 	PR gdb/20977
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
index 47d8a2b..1b18de1 100644
--- a/gdb/nto-tdep.c
+++ b/gdb/nto-tdep.c
@@ -87,7 +87,8 @@ nto_map_arch_to_cputype (const char *arch)
 }
 
 int
-nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
+nto_find_and_open_solib (const char *solib, unsigned o_flags,
+			 char **temp_pathname)
 {
   char *buf, *arch_path, *nto_root;
   const char *endian;
diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h
index 81ed50c..06a1f9a 100644
--- a/gdb/nto-tdep.h
+++ b/gdb/nto-tdep.h
@@ -164,7 +164,7 @@ void nto_relocate_section_addresses (struct so_list *,
 
 int nto_map_arch_to_cputype (const char *);
 
-int nto_find_and_open_solib (char *, unsigned, char **);
+int nto_find_and_open_solib (const char *, unsigned, char **);
 
 enum gdb_osabi nto_elf_osabi_sniffer (bfd *abfd);
 
diff --git a/gdb/solib.c b/gdb/solib.c
index c4b2cdc..82214d0 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -152,7 +152,7 @@ show_solib_search_path (struct ui_file *file, int from_tty,
 */
 
 static char *
-solib_find_1 (char *in_pathname, int *fd, int is_solib)
+solib_find_1 (const char *in_pathname, int *fd, int is_solib)
 {
   const struct target_so_ops *ops = solib_ops (target_gdbarch ());
   int found_file = -1;
@@ -383,7 +383,7 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
    file handle for the main executable.  */
 
 char *
-exec_file_find (char *in_pathname, int *fd)
+exec_file_find (const char *in_pathname, int *fd)
 {
   char *result;
   const char *fskind = effective_target_file_system_kind ();
@@ -434,7 +434,7 @@ exec_file_find (char *in_pathname, int *fd)
    above.  */
 
 char *
-solib_find (char *in_pathname, int *fd)
+solib_find (const char *in_pathname, int *fd)
 {
   const char *solib_symbols_extension
     = gdbarch_solib_symbols_extension (target_gdbarch ());
@@ -443,7 +443,7 @@ solib_find (char *in_pathname, int *fd)
      extension.  */
   if (solib_symbols_extension != NULL)
     {
-      char *p = in_pathname + strlen (in_pathname);
+      const char *p = in_pathname + strlen (in_pathname);
 
       while (p > in_pathname && *p != '.')
 	p--;
diff --git a/gdb/solist.h b/gdb/solist.h
index f709483..948ad31 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -127,7 +127,7 @@ struct target_so_ops
        If TEMP_PATHNAME is non-NULL: If the file is successfully opened a
        pointer to a malloc'd and realpath'd copy of SONAME is stored there,
        otherwise NULL is stored there.  */
-    int (*find_and_open_solib) (char *soname,
+    int (*find_and_open_solib) (const char *soname,
         unsigned o_flags, char **temp_pathname);
 
     /* Hook for looking up global symbols in a library-specific way.  */
@@ -172,10 +172,10 @@ void free_so (struct so_list *so);
 struct so_list *master_so_list (void);
 
 /* Find main executable binary file.  */
-extern char *exec_file_find (char *in_pathname, int *fd);
+extern char *exec_file_find (const char *in_pathname, int *fd);
 
 /* Find shared library binary file.  */
-extern char *solib_find (char *in_pathname, int *fd);
+extern char *solib_find (const char *in_pathname, int *fd);
 
 /* Open BFD for shared library file.  */
 extern bfd *solib_bfd_fopen (char *pathname, int fd);
-- 
2.5.5


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-15  3:49     ` Tom Tromey
@ 2016-12-20 17:48       ` Pedro Alves
  2016-12-20 18:13         ` Tom Tromey
  2016-12-20 23:31         ` Tom Tromey
  0 siblings, 2 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-20 17:48 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/15/2016 03:48 AM, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
> 
> Tom> To my surprise, this patch is broken.
> Tom> I must not have re-run the python tests locally after writing it :(
> 
> Tom> The problem is that prevent_dont_repeat returns a cleanup, which is then
> Tom> left dangling after this patch.
> 
> Here's the updated patch.
> I ran this one through the buildbot.
> 

In some other local patch that I hadn't posted, I handled a similar
situation of save/restoring some global that we don't want to expose
by making the "make_cleanup_..." function return a scoped_restore, which
avoids having to create a new class.  It seems a bit simpler that
creating a class to me, and maybe a tiny bit more efficient code-space
wise (rtti?)  Did you consider this approach?  In this case, it'd look
like this:

From 3138a3fb72f76d0d1bb5a2e1db57e450c37dd43a Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 20 Dec 2016 17:30:56 +0000
Subject: [PATCH] Return scoped_restore instead of cleanup

---
 gdb/breakpoint.c |  2 +-
 gdb/command.h    |  2 +-
 gdb/top.c        | 16 ++++++----------
 3 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index d737cad..dc72986 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4685,7 +4685,7 @@ bpstat_do_actions_1 (bpstat *bsp)
   executing_breakpoint_commands = 1;
   old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
 
-  prevent_dont_repeat ();
+  scoped_restore save_dont_repeat = prevent_dont_repeat ();
 
   /* This pointer will iterate over the list of bpstat's.  */
   bs = *bsp;
diff --git a/gdb/command.h b/gdb/command.h
index 965d91f..7b87814 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -408,7 +408,7 @@ extern void error_no_arg (const char *) ATTRIBUTE_NORETURN;
 
 extern void dont_repeat (void);
 
-extern struct cleanup *prevent_dont_repeat (void);
+extern scoped_restore_tmpl<bool> prevent_dont_repeat ();
 
 /* Used to mark commands that don't do anything.  If we just leave the
    function field NULL, the command is interpreted as a help topic, or
diff --git a/gdb/top.c b/gdb/top.c
index 7d8b6e8..280af71 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -732,10 +732,10 @@ execute_command_to_string (char *p, int from_tty)
 }
 
 \f
-/* When nonzero, cause dont_repeat to do nothing.  This should only be
+/* When true, cause dont_repeat to do nothing.  This should only be
    set via prevent_dont_repeat.  */
 
-static int suppress_dont_repeat = 0;
+static bool suppress_dont_repeat = false;
 
 /* Commands call this if they do not want to be repeated by null lines.  */
 
@@ -754,16 +754,12 @@ dont_repeat (void)
     *saved_command_line = 0;
 }
 
-/* Prevent dont_repeat from working, and return a cleanup that
+/* Prevent dont_repeat from working, and return a scoped restore that
    restores the previous state.  */
-
-struct cleanup *
-prevent_dont_repeat (void)
+scoped_restore_tmpl<bool>
+prevent_dont_repeat ()
 {
-  struct cleanup *result = make_cleanup_restore_integer (&suppress_dont_repeat);
-
-  suppress_dont_repeat = 1;
-  return result;
+  return make_scoped_restore (&suppress_dont_repeat, true);
 }
 
 \f
-- 
2.5.5


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts)
  2016-12-20 17:19       ` [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts) Pedro Alves
@ 2016-12-20 18:05         ` Tom Tromey
  0 siblings, 0 replies; 50+ messages in thread
From: Tom Tromey @ 2016-12-20 18:05 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Tom> I did this, but it's a bit ugly as solib_find isn't const-correct.

Pedro> That doesn't look hard to fix.  I've pushed in the patch below.
Pedro> What uglification does this allow removing?

Huh.  I had taken a stab at this but I thought I ran into some morass,
so I stopped.  Oh well.

Anyway what this enables is a change from &str[0] to str.c_str().

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-20 17:48       ` Pedro Alves
@ 2016-12-20 18:13         ` Tom Tromey
  2016-12-23 20:01           ` Tom Tromey
  2016-12-20 23:31         ` Tom Tromey
  1 sibling, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-20 18:13 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> In some other local patch that I hadn't posted, I handled a similar
Pedro> situation of save/restoring some global that we don't want to expose
Pedro> by making the "make_cleanup_..." function return a scoped_restore, which
Pedro> avoids having to create a new class.  It seems a bit simpler that
Pedro> creating a class to me, and maybe a tiny bit more efficient code-space
Pedro> wise (rtti?)  Did you consider this approach?

I didn't, but I like it, so I'll make this change.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 2/8] Use class to manage BFD reference counts
  2016-12-15  4:12       ` Tom Tromey
@ 2016-12-20 18:18         ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-20 18:18 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/15/2016 03:49 AM, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
> 
> Tom> I'll send a new patch soon.
> 
> Here it is.
> This was part of the series I sent through buildbot.

Thanks.  This LGTM.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-20 17:48       ` Pedro Alves
  2016-12-20 18:13         ` Tom Tromey
@ 2016-12-20 23:31         ` Tom Tromey
  2016-12-20 23:56           ` Pedro Alves
  1 sibling, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-20 23:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> -extern struct cleanup *prevent_dont_repeat (void);
Pedro> +extern scoped_restore_tmpl<bool> prevent_dont_repeat ();

Probably this should use __attribute__((warn_unused_result)), but that
isn't wrapped in ansidecl.h (yet) and I don't know offhand what version
test to use for it.  Do you?

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-20 23:31         ` Tom Tromey
@ 2016-12-20 23:56           ` Pedro Alves
  2016-12-22 14:50             ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-20 23:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/20/2016 11:27 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> -extern struct cleanup *prevent_dont_repeat (void);
> Pedro> +extern scoped_restore_tmpl<bool> prevent_dont_repeat ();
> 
> Probably this should use __attribute__((warn_unused_result)), but that
> isn't wrapped in ansidecl.h (yet) and I don't know offhand what version
> test to use for it.  Do you?

Good idea.  Looks like it's GCC 3.4.  glibc has:

/* If fortification mode, we warn about unused results of certain
   function calls which can lead to problems.  */
#if __GNUC_PREREQ (3,4)
# define __attribute_warn_unused_result__ \
   __attribute__ ((__warn_unused_result__))
# if __USE_FORTIFY_LEVEL > 0
#  define __wur __attribute_warn_unused_result__
# endif
#else
# define __attribute_warn_unused_result__ /* empty */
#endif
#ifndef __wur
# define __wur /* Ignore */
#endif

Grepping my F23's system headers I see other hits for GCC 3.4:

/usr/include/lzma.h:237:        /* warn_unused_result was added in GCC 3.4. */
/usr/include/llvm/Support/Compiler.h:125:#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0)
/usr/include/llvm/Support/Compiler.h:126:#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__))

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-20 23:56           ` Pedro Alves
@ 2016-12-22 14:50             ` Tom Tromey
  2016-12-22 15:09               ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-22 14:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Tom> Probably this should use __attribute__((warn_unused_result)), but that
Tom> isn't wrapped in ansidecl.h (yet) and I don't know offhand what version
Tom> test to use for it.  Do you?

Pedro> Good idea.  Looks like it's GCC 3.4.

This turns out not to work :(

FWIW in addition to the ATTRIBUTE_WARN_UNUSED_RESULT patch, I also had
to patch gdb's configure script to add -Wunused-result, as -Wunused
turns this off.

The g++ bug is known:

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38172

It looks like the accepted fix upstream to use the C++17 [[nodiscard]]
attribute; not sure if we can use that somehow.

Meanwhile I'm going to drop this part of my patch.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-22 14:50             ` Tom Tromey
@ 2016-12-22 15:09               ` Pedro Alves
  2016-12-22 15:29                 ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2016-12-22 15:09 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/22/2016 02:49 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Tom> Probably this should use __attribute__((warn_unused_result)), but that
> Tom> isn't wrapped in ansidecl.h (yet) and I don't know offhand what version
> Tom> test to use for it.  Do you?
> 
> Pedro> Good idea.  Looks like it's GCC 3.4.
> 
> This turns out not to work :(
> 
> FWIW in addition to the ATTRIBUTE_WARN_UNUSED_RESULT patch, I also had
> to patch gdb's configure script to add -Wunused-result, as -Wunused
> turns this off.
> 

Bummer.  :-(

> The g++ bug is known:
> 
>     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38172
> 

> It looks like the accepted fix upstream to use the C++17 [[nodiscard]]
> attribute; not sure if we can use that somehow.

Can't see why not, if we put it behind some ATTRIBUTE_NODISCARD or
some such define.  Sounds like with that we could put the attribute in
the scoped_restore_impl template itself ('struct [[nodiscard]] foo'),
and get the warning for all similar make_foo_scoped_restore-like
functions for free.

> 
> Meanwhile I'm going to drop this part of my patch.

That's fine, we can always add it later.  Thanks much for experimenting.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-22 15:09               ` Pedro Alves
@ 2016-12-22 15:29                 ` Tom Tromey
  2016-12-22 15:40                   ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-22 15:29 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> It looks like the accepted fix upstream to use the C++17 [[nodiscard]]
>> attribute; not sure if we can use that somehow.

Pedro> Can't see why not, if we put it behind some ATTRIBUTE_NODISCARD or
Pedro> some such define.

It wasn't obvious to me (and as you can tell I'm not doing much research
into this kind of thing lately...) what condition to use.  C++17 isn't
official yet, and presumably even if we had some value for __cplusplus
to check, we'd also have to check for when exactly it was added to g++?

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-22 15:29                 ` Tom Tromey
@ 2016-12-22 15:40                   ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2016-12-22 15:40 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/22/2016 03:29 PM, Tom Tromey wrote:

> C++17 isn't
> official yet, and presumably even if we had some value for __cplusplus
> to check, we'd also have to check for when exactly it was added to g++?

According to:

 https://gcc.gnu.org/projects/cxx-status.html

that could be checked with __has_cpp_attribute(nodiscard).

From that page, seems like G++ 4.8 had an [[gnu::warn_unused_result]]
alternative that perhaps works on C++11 too.  I have no experience
with it though.

But as I said, we can always add this later.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-20 14:49       ` Pedro Alves
@ 2016-12-23 19:05         ` Tom Tromey
  2016-12-23 19:59           ` Tom Tromey
  2016-12-23 19:59           ` Tom Tromey
  0 siblings, 2 replies; 50+ messages in thread
From: Tom Tromey @ 2016-12-23 19:05 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> In pondering a bit more over this, I wonder whether
Pedro> adding a "scoped_" to go with scoped_restore etc., would make
Pedro> it a bit clearer to readers that this is a RAII type.  Then
Pedro> also considering value_release_to_mark, I wonder would an
Pedro> API/naming like this:
[...]
Pedro> Would this result in clearer client code?  IMHO, yes, but WDYT?

It looks good to me.  I've made this change and I'll send the new
patches soon.

FYI I've only implemented the subset of the proposed API that was needed
by the patches I have.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-23 19:05         ` Tom Tromey
  2016-12-23 19:59           ` Tom Tromey
@ 2016-12-23 19:59           ` Tom Tromey
  2017-01-10 17:58             ` Pedro Alves
  1 sibling, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-23 19:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

Tom> It looks good to me.  I've made this change and I'll send the new
Tom> patches soon.

Here's the new version of the patch to use scoped_value_mark in
dwarf2_evaluate_loc_desc_full.

Tom

commit 63b869373e8dff9fd8648c00712459dd18a9798b
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Nov 21 21:04:59 2016 -0700

    Use scoped_value_mark in dwarf2_evaluate_loc_desc_full
    
    This changes dwarf2_evaluate_loc_desc_full to use scoped_value_mark.
    
    Note that this function previously called do_cleanup using the same
    cleanup multiple times.  I had thought this was buggy, but re-reading
    make_my_cleanup2 indicates that it is not.  Nevertheless it is
    surprising, and at least one of the calls (the one that is completely
    removed in this patch) seems to have been done under the assumption
    that it would still have some effect.
    
    2016-12-13  Tom Tromey  <tom@tromey.com>
    
    	* value.h (scoped_value_mark::~scoped_value_mark): Call
    	free_to_mark.
    	(scoped_value_mark::free_to_mark): New method.
    	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use
    	scoped_value_mark.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 01ef9d6..d402851 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2016-12-13  Tom Tromey  <tom@tromey.com>
 
+	* value.h (scoped_value_mark::~scoped_value_mark): Call
+	free_to_mark.
+	(scoped_value_mark::free_to_mark): New method.
+	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Use
+	scoped_value_mark.
+
+2016-12-13  Tom Tromey  <tom@tromey.com>
+
 	* python/py-value.c (valpy_dereference, valpy_referenced_value)
 	(valpy_reference_value, valpy_const_value, valpy_get_address)
 	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index f5ab371..6e36835 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2283,7 +2283,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 			       LONGEST byte_offset)
 {
   struct value *retval;
-  struct cleanup *value_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
   if (byte_offset < 0)
@@ -2297,7 +2296,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
   ctx.per_cu = per_cu;
   ctx.obj_address = 0;
 
-  value_chain = make_cleanup_value_free_to_mark (value_mark ());
+  scoped_value_mark free_values;
 
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
@@ -2312,7 +2311,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
     {
       if (ex.error == NOT_AVAILABLE_ERROR)
 	{
-	  do_cleanups (value_chain);
+	  free_values.free_to_mark ();
 	  retval = allocate_value (type);
 	  mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type));
 	  return retval;
@@ -2321,7 +2320,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	{
 	  if (entry_values_debug)
 	    exception_print (gdb_stdout, ex);
-	  do_cleanups (value_chain);
+	  free_values.free_to_mark ();
 	  return allocate_optimized_out_value (type);
 	}
       else
@@ -2344,7 +2343,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 				  ctx.addr_size, frame);
       /* We must clean up the value chain after creating the piece
 	 closure but before allocating the result.  */
-      do_cleanups (value_chain);
+      free_values.free_to_mark ();
       retval = allocate_computed_value (type, &pieced_value_funcs, c);
       set_value_offset (retval, byte_offset);
     }
@@ -2361,7 +2360,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
 	    if (byte_offset != 0)
 	      error (_("cannot use offset on synthetic pointer to register"));
-	    do_cleanups (value_chain);
+	    free_values.free_to_mark ();
 	    retval = value_from_register (type, gdb_regnum, frame);
 	    if (value_optimized_out (retval))
 	      {
@@ -2373,7 +2372,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 		   inspecting a register ($pc, $sp, etc.), return a
 		   generic optimized out value instead, so that we show
 		   <optimized out> instead of <not saved>.  */
-		do_cleanups (value_chain);
 		tmp = allocate_value (type);
 		value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type));
 		retval = tmp;
@@ -2407,7 +2405,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	      }
 	    address = value_as_address (value_from_pointer (ptr_type, address));
 
-	    do_cleanups (value_chain);
+	    free_values.free_to_mark ();
 	    retval = value_at_lazy (type, address + byte_offset);
 	    if (in_stack_memory)
 	      set_value_stack (retval, 1);
@@ -2420,6 +2418,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	    gdb_byte *contents;
 	    const gdb_byte *val_bytes;
 	    size_t n = TYPE_LENGTH (value_type (value));
+	    struct cleanup *cleanup;
 
 	    if (byte_offset + TYPE_LENGTH (type) > n)
 	      invalid_synthetic_pointer ();
@@ -2432,8 +2431,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	       to the mark, but we still need the value contents
 	       below.  */
 	    value_incref (value);
-	    do_cleanups (value_chain);
-	    make_cleanup_value_free (value);
+	    free_values.free_to_mark ();
+	    cleanup = make_cleanup_value_free (value);
 
 	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
@@ -2446,6 +2445,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 		n = TYPE_LENGTH (type);
 	      }
 	    memcpy (contents, val_bytes, n);
+
+	    do_cleanups (cleanup);
 	  }
 	  break;
 
@@ -2458,7 +2459,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	    if (byte_offset + TYPE_LENGTH (type) > n)
 	      invalid_synthetic_pointer ();
 
-	    do_cleanups (value_chain);
+	    free_values.free_to_mark ();
 	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
 
@@ -2478,7 +2479,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	  break;
 
 	case DWARF_VALUE_OPTIMIZED_OUT:
-	  do_cleanups (value_chain);
+	  free_values.free_to_mark ();
 	  retval = allocate_optimized_out_value (type);
 	  break;
 
@@ -2494,8 +2495,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
   set_value_initialized (retval, ctx.initialized);
 
-  do_cleanups (value_chain);
-
   return retval;
 }
 
diff --git a/gdb/value.h b/gdb/value.h
index 3a0641a..d261148 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -728,7 +728,17 @@ class scoped_value_mark
 
   ~scoped_value_mark ()
   {
-    value_free_to_mark (m_value);
+    free_to_mark ();
+  }
+
+  /* Free the values currently on the value stack.  */
+  void free_to_mark ()
+  {
+    if (m_value != NULL)
+      {
+	value_free_to_mark (m_value);
+	m_value = NULL;
+      }
   }
 
  private:

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-23 19:05         ` Tom Tromey
@ 2016-12-23 19:59           ` Tom Tromey
  2017-01-10 17:57             ` Pedro Alves
  2016-12-23 19:59           ` Tom Tromey
  1 sibling, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-23 19:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> It looks good to me.  I've made this change and I'll send the new
Tom> patches soon.

Here's the new patch to add scoped_value_mark.

Tom

commit 6f8663e26b0498790d3314f0649c5c9c923a48a0
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Nov 21 18:02:11 2016 -0700

    Add scoped_value_mark
    
    This adds a scoped_value_mark class, that records the value mark in
    the constructor and then calls value_free_to_mark in the destructor.
    It then updates various spots in gdb to use this class, rather than a
    cleanup.
    
    It would be better overall to replace "struct value *" with a
    shared_ptr, maybe eliminating the need for this class (watchpoints
    would perhaps need some new mechanism as well).  However, that's
    difficult to do.
    
    2016-12-13  Tom Tromey  <tom@tromey.com>
    
    	* python/py-value.c (valpy_dereference, valpy_referenced_value)
    	(valpy_reference_value, valpy_const_value, valpy_get_address)
    	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
    	(valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
    	(valpy_absolute, valpy_richcompare_throw): Use scoped_value_mark.
    	* dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
    	scoped_value_mark.
    	* dwarf2-frame.c (execute_stack_op): Use scoped_value_mark.
    	* value.h (scoped_value_mark): New class.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8d3c5b1..01ef9d6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
 2016-12-13  Tom Tromey  <tom@tromey.com>
 
+	* python/py-value.c (valpy_dereference, valpy_referenced_value)
+	(valpy_reference_value, valpy_const_value, valpy_get_address)
+	(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
+	(valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
+	(valpy_absolute, valpy_richcompare_throw): Use scoped_value_mark.
+	* dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
+	scoped_value_mark.
+	* dwarf2-frame.c (execute_stack_op): Use scoped_value_mark.
+	* value.h (scoped_value_mark): New class.
+
+2016-12-13  Tom Tromey  <tom@tromey.com>
+
 	* dwarf2read.c (dwarf2_build_psymtabs): Use psymtab_discarder.
 	* psympriv.h (make_cleanup_discard_psymtabs): Don't declare.
 	* psymtab.c (discard_psymtabs_upto): Remove.
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index beab304..93647ab 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -403,10 +403,9 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
 		  CORE_ADDR initial, int initial_in_stack_memory)
 {
   CORE_ADDR result;
-  struct cleanup *old_chain;
 
   dwarf_expr_executor ctx;
-  old_chain = make_cleanup_value_free_to_mark (value_mark ());
+  scoped_value_mark free_values;
 
   ctx.this_frame = this_frame;
   ctx.gdbarch = get_frame_arch (this_frame);
@@ -430,8 +429,6 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
 Not implemented: computing unwound register using explicit value operator"));
     }
 
-  do_cleanups (old_chain);
-
   return result;
 }
 \f
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index d19f6a2..f5ab371 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2801,16 +2801,14 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
 				       struct dwarf2_per_cu_data *per_cu)
 {
   int in_reg;
-  struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
+  scoped_value_mark free_values;
+
   symbol_needs_eval_context ctx;
 
   ctx.needs = SYMBOL_NEEDS_NONE;
   ctx.per_cu = per_cu;
-
-  old_chain = make_cleanup_value_free_to_mark (value_mark ());
-
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
@@ -2831,8 +2829,6 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
           in_reg = 1;
     }
 
-  do_cleanups (old_chain);
-
   if (in_reg)
     ctx.needs = SYMBOL_NEEDS_FRAME;
   return ctx.needs;
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index c1f3e16..f7ec202 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -178,11 +178,10 @@ valpy_dereference (PyObject *self, PyObject *args)
   TRY
     {
       struct value *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       res_val = value_ind (((value_object *) self)->value);
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -209,7 +208,7 @@ valpy_referenced_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val, *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       self_val = ((value_object *) self)->value;
       switch (TYPE_CODE (check_typedef (value_type (self_val))))
@@ -226,7 +225,6 @@ valpy_referenced_value (PyObject *self, PyObject *args)
         }
 
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -247,12 +245,10 @@ valpy_reference_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       self_val = ((value_object *) self)->value;
       result = value_to_value_object (value_ref (self_val));
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -273,13 +269,11 @@ valpy_const_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val, *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       self_val = ((value_object *) self)->value;
       res_val = make_cv_value (1, 0, self_val);
       result = value_to_value_object (res_val);
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -301,12 +295,10 @@ valpy_get_address (PyObject *self, void *closure)
       TRY
 	{
 	  struct value *res_val;
-	  struct cleanup *cleanup
-	    = make_cleanup_value_free_to_mark (value_mark ());
+	  scoped_value_mark free_values;
 
 	  res_val = value_addr (val_obj->value);
 	  val_obj->address = value_to_value_object (res_val);
-	  do_cleanups (cleanup);
 	}
       CATCH (except, RETURN_MASK_ALL)
 	{
@@ -354,7 +346,7 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
   TRY
     {
       struct value *val = obj->value;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       type = value_type (val);
       type = check_typedef (type);
@@ -387,8 +379,6 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
 	  /* Re-use object's static type.  */
 	  type = NULL;
 	}
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -428,7 +418,7 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
 	value = value_ind (value);
@@ -436,8 +426,6 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
       str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
 						 user_encoding,
 						 value_type (value));
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -514,7 +502,7 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
     {
       struct value *val = ((value_object *) self)->value;
       struct value *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       if (op == UNOP_DYNAMIC_CAST)
 	res_val = value_dynamic_cast (type, val);
@@ -527,7 +515,6 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
 	}
 
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -737,8 +724,8 @@ valpy_getitem (PyObject *self, PyObject *key)
   TRY
     {
       struct value *tmp = self_value->value;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
       struct value *res_val = NULL;
+      scoped_value_mark free_values;
 
       if (field)
 	res_val = value_struct_elt (&tmp, NULL, field.get (), NULL,
@@ -783,7 +770,6 @@ valpy_getitem (PyObject *self, PyObject *key)
 
       if (res_val)
 	result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (ex, RETURN_MASK_ALL)
     {
@@ -861,12 +847,11 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark);
+      scoped_value_mark free_values;
       struct value *return_value;
 
       return_value = call_function_by_hand (function, args_count, vargs);
       result = value_to_value_object (return_value);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1014,11 +999,12 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
   PyObject *result = NULL;
 
   struct value *arg1, *arg2;
-  struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
   struct value *res_val = NULL;
   enum exp_opcode op = OP_NULL;
   int handled = 0;
 
+  scoped_value_mark free_values;
+
   /* If the gdb.Value object is the second operand, then it will be
      passed to us as the OTHER argument, and SELF will be an entirely
      different kind of object, altogether.  Because of this, we can't
@@ -1026,17 +1012,11 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
      python as well.  */
   arg1 = convert_value_from_python (self);
   if (arg1 == NULL)
-    {
-      do_cleanups (cleanup);
-      return NULL;
-    }
+    return NULL;
 
   arg2 = convert_value_from_python (other);
   if (arg2 == NULL)
-    {
-      do_cleanups (cleanup);
-      return NULL;
-    }
+    return NULL;
 
   switch (opcode)
     {
@@ -1130,7 +1110,6 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
   if (res_val)
     result = value_to_value_object (res_val);
 
-  do_cleanups (cleanup);
   return result;
 }
 
@@ -1209,12 +1188,11 @@ valpy_negative (PyObject *self)
   TRY
     {
       /* Perhaps overkill, but consistency has some virtue.  */
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
       struct value *val;
 
       val = value_neg (((value_object *) self)->value);
       result = value_to_value_object (val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1239,12 +1217,10 @@ valpy_absolute (PyObject *self)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       if (value_less (value, value_zero (value_type (value), not_lval)))
 	isabs = 0;
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1362,15 +1338,14 @@ valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
   int result;
   struct value *value_other;
   struct value *value_self;
-  struct value *mark = value_mark ();
   struct cleanup *cleanup;
 
+  scoped_value_mark free_values;
+
   value_other = convert_value_from_python (other);
   if (value_other == NULL)
     return -1;
 
-  cleanup = make_cleanup_value_free_to_mark (mark);
-
   value_self = ((value_object *) self)->value;
 
   switch (op)
@@ -1403,7 +1378,6 @@ valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
       break;
     }
 
-  do_cleanups (cleanup);
   return result;
 }
 
diff --git a/gdb/value.h b/gdb/value.h
index f776323..3a0641a 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -714,6 +714,28 @@ extern struct value *value_mark (void);
 
 extern void value_free_to_mark (const struct value *mark);
 
+/* A helper class that uses value_mark at construction time and calls
+   value_free_to_mark in the destructor.  This is used to clear out
+   temporary values created during the lifetime of this object.  */
+class scoped_value_mark
+{
+ public:
+
+  scoped_value_mark ()
+    : m_value (value_mark ())
+  {
+  }
+
+  ~scoped_value_mark ()
+  {
+    value_free_to_mark (m_value);
+  }
+
+ private:
+
+  const struct value *m_value;
+};
+
 extern struct value *value_cstring (const char *ptr, ssize_t len,
 				    struct type *char_type);
 extern struct value *value_string (const char *ptr, ssize_t len,

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-20 18:13         ` Tom Tromey
@ 2016-12-23 20:01           ` Tom Tromey
  2017-01-10 17:59             ` Pedro Alves
  0 siblings, 1 reply; 50+ messages in thread
From: Tom Tromey @ 2016-12-23 20:01 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

Pedro> In some other local patch that I hadn't posted, I handled a similar
Pedro> situation of save/restoring some global that we don't want to expose
Pedro> by making the "make_cleanup_..." function return a scoped_restore, which
Pedro> avoids having to create a new class.  It seems a bit simpler that
Pedro> creating a class to me, and maybe a tiny bit more efficient code-space
Pedro> wise (rtti?)  Did you consider this approach?

Tom> I didn't, but I like it, so I'll make this change.

Here's the new version of this patch.

Tom

commit 20649c18216bf744aade97fed85c8a61b2e2905c
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Nov 28 21:11:53 2016 -0700

    Remove cleanups from execute_gdb_command
    
    This replaces a cleanup in execute_gdb_command with an instance of
    std::string.
    
    Testing showed that this originally missed a cleanup that was returned
    by prevent_dont_repeat.  This version of the patch changes
    prevent_dont_repeat to return a scoped_restore rather than a cleanup.
    
    2016-12-14  Tom Tromey  <tom@tromey.com>
    
    	* top.c (prevent_dont_repeat): Change return type.
    	* python/python.c (execute_gdb_command): Use std::string.
    	Update.
    	* guile/guile.c (gdbscm_execute_gdb_command): Update.
    	* command.h (prevent_dont_repeat): Change return type.
    	* breakpoint.c (bpstat_do_actions_1): Update.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d402851..c482013 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2016-12-14  Tom Tromey  <tom@tromey.com>
+
+	* top.c (prevent_dont_repeat): Change return type.
+	* python/python.c (execute_gdb_command): Use std::string.
+	Update.
+	* guile/guile.c (gdbscm_execute_gdb_command): Update.
+	* command.h (prevent_dont_repeat): Change return type.
+	* breakpoint.c (bpstat_do_actions_1): Update.
+
 2016-12-13  Tom Tromey  <tom@tromey.com>
 
 	* value.h (scoped_value_mark::~scoped_value_mark): Call
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6fd18fd..e47e73b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4685,7 +4685,7 @@ bpstat_do_actions_1 (bpstat *bsp)
   executing_breakpoint_commands = 1;
   old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
 
-  prevent_dont_repeat ();
+  scoped_restore preventer = prevent_dont_repeat ();
 
   /* This pointer will iterate over the list of bpstat's.  */
   bs = *bsp;
diff --git a/gdb/command.h b/gdb/command.h
index 965d91f..924d8d3 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -408,7 +408,7 @@ extern void error_no_arg (const char *) ATTRIBUTE_NORETURN;
 
 extern void dont_repeat (void);
 
-extern struct cleanup *prevent_dont_repeat (void);
+extern scoped_restore_tmpl<int> prevent_dont_repeat (void);
 
 /* Used to mark commands that don't do anything.  If we just leave the
    function field NULL, the command is interpreted as a help topic, or
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index 9a126a1..a95b894 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -332,7 +332,7 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
       inner_cleanups = make_cleanup_restore_integer (&current_ui->async);
       current_ui->async = 0;
 
-      prevent_dont_repeat ();
+      scoped_restore preventer = prevent_dont_repeat ();
       if (to_string)
 	to_string_res = execute_command_to_string (command, from_tty);
       else
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 83b9805..e92f72c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -601,8 +601,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
   TRY
     {
       /* Copy the argument text in case the command modifies it.  */
-      char *copy = xstrdup (arg);
-      struct cleanup *cleanup = make_cleanup (xfree, copy);
+      std::string copy (arg);
       struct interp *interp;
 
       scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
@@ -614,12 +613,11 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
       interp = interp_lookup (current_ui, "console");
       current_uiout = interp_ui_out (interp);
 
-      prevent_dont_repeat ();
+      scoped_restore preventer = prevent_dont_repeat ();
       if (to_string)
-	to_string_res = execute_command_to_string (copy, from_tty);
+	to_string_res = execute_command_to_string (&copy[0], from_tty);
       else
-	execute_command (copy, from_tty);
-      do_cleanups (cleanup);
+	execute_command (&copy[0], from_tty);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/top.c b/gdb/top.c
index 077fb2a..9960e6b 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -757,13 +757,10 @@ dont_repeat (void)
 /* Prevent dont_repeat from working, and return a cleanup that
    restores the previous state.  */
 
-struct cleanup *
+scoped_restore_tmpl<int>
 prevent_dont_repeat (void)
 {
-  struct cleanup *result = make_cleanup_restore_integer (&suppress_dont_repeat);
-
-  suppress_dont_repeat = 1;
-  return result;
+  return make_scoped_restore (&suppress_dont_repeat, 1);
 }
 
 \f

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-23 19:59           ` Tom Tromey
@ 2017-01-10 17:57             ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2017-01-10 17:57 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/23/2016 07:58 PM, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
> 
> Tom> It looks good to me.  I've made this change and I'll send the new
> Tom> patches soon.
> 
> Here's the new patch to add scoped_value_mark.

OK, thanks.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full
  2016-12-23 19:59           ` Tom Tromey
@ 2017-01-10 17:58             ` Pedro Alves
  0 siblings, 0 replies; 50+ messages in thread
From: Pedro Alves @ 2017-01-10 17:58 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/23/2016 07:59 PM, Tom Tromey wrote:
> Tom> It looks good to me.  I've made this change and I'll send the new
> Tom> patches soon.
> 
> Here's the new version of the patch to use scoped_value_mark in
> dwarf2_evaluate_loc_desc_full.

OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2016-12-23 20:01           ` Tom Tromey
@ 2017-01-10 17:59             ` Pedro Alves
  2017-01-10 19:22               ` Tom Tromey
  0 siblings, 1 reply; 50+ messages in thread
From: Pedro Alves @ 2017-01-10 17:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 12/23/2016 08:00 PM, Tom Tromey wrote:
> Pedro> In some other local patch that I hadn't posted, I handled a similar
> Pedro> situation of save/restoring some global that we don't want to expose
> Pedro> by making the "make_cleanup_..." function return a scoped_restore, which
> Pedro> avoids having to create a new class.  It seems a bit simpler that
> Pedro> creating a class to me, and maybe a tiny bit more efficient code-space
> Pedro> wise (rtti?)  Did you consider this approach?
> 
> Tom> I didn't, but I like it, so I'll make this change.
> 
> Here's the new version of this patch.

OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command
  2017-01-10 17:59             ` Pedro Alves
@ 2017-01-10 19:22               ` Tom Tromey
  0 siblings, 0 replies; 50+ messages in thread
From: Tom Tromey @ 2017-01-10 19:22 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

Tom> Here's the new version of this patch.

Pedro> OK.

Thanks for these reviews.  I think now all of my various c++-ification
series are fully approved, so I plan to rebase, re-test (on the
buildbot), and then push.  Once this happens (it may be a day or two)
please let me know if there are any difficulties; I'll fix them as soon
as I'm able.

Tom

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2017-01-10 19:22 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
2016-11-29  5:06 ` [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full Tom Tromey
2016-12-02 14:45   ` Pedro Alves
2016-12-13 13:29     ` Tom Tromey
2016-12-20 14:49       ` Pedro Alves
2016-12-23 19:05         ` Tom Tromey
2016-12-23 19:59           ` Tom Tromey
2017-01-10 17:57             ` Pedro Alves
2016-12-23 19:59           ` Tom Tromey
2017-01-10 17:58             ` Pedro Alves
2016-11-29  5:06 ` [RFA 5/8] Add value_freer Tom Tromey
2016-12-02 14:24   ` Pedro Alves
2016-11-29  5:06 ` [RFA 2/8] Use class to manage BFD reference counts Tom Tromey
2016-12-02 13:05   ` Pedro Alves
2016-12-13 13:26     ` Tom Tromey
2016-12-15  4:12       ` Tom Tromey
2016-12-20 18:18         ` Pedro Alves
2016-12-20 17:19       ` [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts) Pedro Alves
2016-12-20 18:05         ` Tom Tromey
2016-11-29  5:06 ` [RFA 1/8] Add gdb_ref_ptr.h Tom Tromey
2016-12-02 13:08   ` Pedro Alves
2016-12-02 17:46     ` Tom Tromey
2016-12-02 18:11       ` Pedro Alves
2016-12-02 19:52         ` Tom Tromey
2016-12-02 23:45           ` Pedro Alves
2016-12-03  0:05   ` Pedro Alves
2016-12-13 13:13     ` Tom Tromey
2016-11-29  5:06 ` [RFA 4/8] Remove make_cleanup_discard_psymtabs Tom Tromey
2016-12-02 14:21   ` Pedro Alves
2016-11-29  5:06 ` [RFA 3/8] Introduce and use gdb::unlinker Tom Tromey
2016-12-02 13:17   ` Pedro Alves
2016-11-29  5:06 ` [RFA 8/8] Add constructor and destructor to demangle_parse_info Tom Tromey
2016-12-02 15:04   ` Pedro Alves
2016-12-13 13:50     ` Tom Tromey
2016-11-29  5:06 ` [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command Tom Tromey
2016-11-29  5:22   ` Tom Tromey
2016-12-15  3:49     ` Tom Tromey
2016-12-20 17:48       ` Pedro Alves
2016-12-20 18:13         ` Tom Tromey
2016-12-23 20:01           ` Tom Tromey
2017-01-10 17:59             ` Pedro Alves
2017-01-10 19:22               ` Tom Tromey
2016-12-20 23:31         ` Tom Tromey
2016-12-20 23:56           ` Pedro Alves
2016-12-22 14:50             ` Tom Tromey
2016-12-22 15:09               ` Pedro Alves
2016-12-22 15:29                 ` Tom Tromey
2016-12-22 15:40                   ` Pedro Alves
2016-12-02 14:49   ` Pedro Alves
2016-12-13 13:30     ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).