[PATCH] gdb/riscv: delete target descriptions when gdb exits

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] gdb/riscv: delete target descriptions when gdb exits

Andrew Burgess
It was pointed out on IRC that the RISC-V target allocates target
descriptions and stores them in a global map, and doesn't delete these
target descriptions when GDB shuts down.

This isn't a particular problem, the total number of target
descriptions we can create is very limited so creating these on demand
and holding them for the entire run on GDB seems reasonable.

However, not deleting these objects on GDB exit means extra warnings
are printed from tools like valgrind, and the address sanitiser,
making it harder to spot real issues.  As it's reasonably easy to have
GDB correctly delete these objects on exit, lets just do that.

I started by noticing that we already have a target_desc_up type, a
wrapper around unique_ptr that calls a function that will correctly
delete target descriptions, so I want to use that, but....

...that type is declared in gdb/target-descriptions.h.  If I try to
include that file in gdb/arch/riscv.c I run into a problem, that file
is compiled into both GDB and GDBServer.

OK, I could guard the include with #ifdef, but surely we can do
better.

So then I decided to move the target_desc_up type into
gdbsupport/tdesc.h, this is the interface file for generic code shared
between GDB and GDBserver (relating to target descriptions).  The
actual implementation for the delete function still lives in
gdb/target-description.c, but now gdb/arch/riscv.c can see the
declaration.  Problem solved....

... but, though RISC-V doesn't use it I've now exposed the
target_desc_up type to gdbserver, so in future someone _might_ start
using it, which is fine, except right now there's no definition of the
delete function - remember the delete I used is only defined in GDB
code.

No problem, I add an implementation of the delete operator into
gdbserver/tdesc.cc, and all is good..... except....

I start getting this error from GCC:

  tdesc.cc:109:10: error: deleting object of polymorphic class type ‘target_desc’ which has non-virtual destructor might cause undefined behavior [-Werror=delete-non-virtual-dtor]

This seems a little strange to me as target_desc is not a polymorphic
class as far as I can tell, so I don't quite understand why GCC is
complaining about this.

Still by making gdbserver's target_desc class final this seems to
resolve this issue.  This should be fine so long as we never try to
inherit from target_desc, but if we do we probably should make the
destructor virtual, so that wouldn't be an issue.

gdb/ChangeLog:

        * arch/riscv.c (riscv_tdesc_cache): Change map type.
        (riscv_lookup_target_description): Return pointer out of
        unique_ptr.
        * target-descriptions.c (allocate_target_description): Add
        comment.
        (target_desc_deleter::operator()): Likewise.
        * target-descriptions.h (struct target_desc_deleter): Moved to
        gdbsupport/tdesc.h.
        (target_desc_up): Likewise.

gdbserver/ChangeLog:

        * tdesc.cc (allocate_target_description): Add header comment.
        (target_desc_deleter::operator()): New function.
        * tdesc.h (struct target_desc): Declare as final.

gdbsupport/ChangeLog:

        * tdesc.h (struct target_desc_deleter): Moved here
        from gdb/target-descriptions.h.
        (target_desc_up): Likewise.
---
 gdb/ChangeLog             | 12 ++++++++++++
 gdb/arch/riscv.c          |  8 +++++---
 gdb/target-descriptions.c |  4 ++++
 gdb/target-descriptions.h | 12 ------------
 gdbserver/ChangeLog       |  6 ++++++
 gdbserver/tdesc.cc        | 10 ++++++++++
 gdbserver/tdesc.h         |  2 +-
 gdbsupport/ChangeLog      |  6 ++++++
 gdbsupport/tdesc.h        | 11 +++++++++++
 9 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/gdb/arch/riscv.c b/gdb/arch/riscv.c
index a02c18b4c91..e43aafc1c2f 100644
--- a/gdb/arch/riscv.c
+++ b/gdb/arch/riscv.c
@@ -91,7 +91,7 @@ struct riscv_gdbarch_features_hasher
 /* Cache of previously seen target descriptions, indexed by the feature set
    that created them.  */
 static std::unordered_map<riscv_gdbarch_features,
-  const target_desc *,
+  const target_desc_up,
   riscv_gdbarch_features_hasher> riscv_tdesc_cache;
 
 /* See arch/riscv.h.  */
@@ -99,10 +99,12 @@ static std::unordered_map<riscv_gdbarch_features,
 const target_desc *
 riscv_lookup_target_description (const struct riscv_gdbarch_features features)
 {
-  /* Lookup in the cache.  */
+  /* Lookup in the cache.  If we find it then return the pointer out of
+     the target_desc_up (which is a unique_ptr).  This is safe as the
+     riscv_tdesc_cache will exist until GDB exits.  */
   const auto it = riscv_tdesc_cache.find (features);
   if (it != riscv_tdesc_cache.end ())
-    return it->second;
+    return it->second.get ();
 
   target_desc *tdesc = riscv_create_target_description (features);
 
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 2f4b17727b8..20d624c0c65 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -1206,12 +1206,16 @@ tdesc_create_feature (struct target_desc *tdesc, const char *name)
   return new_feature;
 }
 
+/* See gdbsupport/tdesc.h.  */
+
 struct target_desc *
 allocate_target_description (void)
 {
   return new target_desc ();
 }
 
+/* See gdbsupport/tdesc.h.  */
+
 void
 target_desc_deleter::operator() (struct target_desc *target_desc) const
 {
diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h
index 6d842bf07ed..66a2c213dc2 100644
--- a/gdb/target-descriptions.h
+++ b/gdb/target-descriptions.h
@@ -225,18 +225,6 @@ struct type *tdesc_find_type (struct gdbarch *gdbarch, const char *id);
 int tdesc_register_in_reggroup_p (struct gdbarch *gdbarch, int regno,
   struct reggroup *reggroup);
 
-
-/* A deleter adapter for a target desc.  */
-
-struct target_desc_deleter
-{
-  void operator() (struct target_desc *desc) const;
-};
-
-/* A unique pointer specialization that holds a target_desc.  */
-
-typedef std::unique_ptr<target_desc, target_desc_deleter> target_desc_up;
-
 /* Methods for constructing a target description.  */
 
 void set_tdesc_architecture (struct target_desc *,
diff --git a/gdbserver/tdesc.cc b/gdbserver/tdesc.cc
index d21688b932b..e639017cc31 100644
--- a/gdbserver/tdesc.cc
+++ b/gdbserver/tdesc.cc
@@ -93,12 +93,22 @@ init_target_desc (struct target_desc *tdesc,
 #endif
 }
 
+/* See gdbsupport/tdesc.h.  */
+
 struct target_desc *
 allocate_target_description (void)
 {
   return new target_desc ();
 }
 
+/* See gdbsupport/tdesc.h.  */
+
+void
+target_desc_deleter::operator() (struct target_desc *target_desc) const
+{
+  delete target_desc;
+}
+
 #ifndef IN_PROCESS_AGENT
 
 static const struct target_desc default_description {};
diff --git a/gdbserver/tdesc.h b/gdbserver/tdesc.h
index f9ca478ff6d..681de64d0aa 100644
--- a/gdbserver/tdesc.h
+++ b/gdbserver/tdesc.h
@@ -27,7 +27,7 @@
 /* A target description.  Inherit from tdesc_feature so that target_desc
    can be used as tdesc_feature.  */
 
-struct target_desc : tdesc_element
+struct target_desc final : tdesc_element
 {
   /* A vector of elements of register definitions that
      describe the inferior's register set.  */
diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
index 456e8e070b1..e36137cacd0 100644
--- a/gdbsupport/tdesc.h
+++ b/gdbsupport/tdesc.h
@@ -312,6 +312,17 @@ struct tdesc_feature : tdesc_element
 
 typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
 
+/* A deleter adapter for a target desc.  */
+
+struct target_desc_deleter
+{
+  void operator() (struct target_desc *desc) const;
+};
+
+/* A unique pointer specialization that holds a target_desc.  */
+
+typedef std::unique_ptr<target_desc, target_desc_deleter> target_desc_up;
+
 /* Allocate a new target_desc.  */
 target_desc *allocate_target_description (void);
 
--
2.25.4

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Simon Marchi-4
On 2020-07-16 1:29 p.m., Andrew Burgess wrote:

> It was pointed out on IRC that the RISC-V target allocates target
> descriptions and stores them in a global map, and doesn't delete these
> target descriptions when GDB shuts down.
>
> This isn't a particular problem, the total number of target
> descriptions we can create is very limited so creating these on demand
> and holding them for the entire run on GDB seems reasonable.
>
> However, not deleting these objects on GDB exit means extra warnings
> are printed from tools like valgrind, and the address sanitiser,
> making it harder to spot real issues.  As it's reasonably easy to have
> GDB correctly delete these objects on exit, lets just do that.
>
> I started by noticing that we already have a target_desc_up type, a
> wrapper around unique_ptr that calls a function that will correctly
> delete target descriptions, so I want to use that, but....
>
> ...that type is declared in gdb/target-descriptions.h.  If I try to
> include that file in gdb/arch/riscv.c I run into a problem, that file
> is compiled into both GDB and GDBServer.
>
> OK, I could guard the include with #ifdef, but surely we can do
> better.
>
> So then I decided to move the target_desc_up type into
> gdbsupport/tdesc.h, this is the interface file for generic code shared
> between GDB and GDBserver (relating to target descriptions).  The
> actual implementation for the delete function still lives in
> gdb/target-description.c, but now gdb/arch/riscv.c can see the
> declaration.  Problem solved....
>
> ... but, though RISC-V doesn't use it I've now exposed the
> target_desc_up type to gdbserver, so in future someone _might_ start
> using it, which is fine, except right now there's no definition of the
> delete function - remember the delete I used is only defined in GDB
> code.
>
> No problem, I add an implementation of the delete operator into
> gdbserver/tdesc.cc, and all is good..... except....
>
> I start getting this error from GCC:
>
>   tdesc.cc:109:10: error: deleting object of polymorphic class type ‘target_desc’ which has non-virtual destructor might cause undefined behavior [-Werror=delete-non-virtual-dtor]
>
> This seems a little strange to me as target_desc is not a polymorphic
> class as far as I can tell, so I don't quite understand why GCC is
> complaining about this.
>
> Still by making gdbserver's target_desc class final this seems to
> resolve this issue.  This should be fine so long as we never try to
> inherit from target_desc, but if we do we probably should make the
> destructor virtual, so that wouldn't be an issue.

I think this is all reasonable.  The unique_ptr has to be a bit awkward
(have a custom deleter, and distinct implementations in gdb and gdbserver)
because gdb and gdbserver don't share a target_desc type.  They have the
same name, but that's about it.

I guess an alternative would be to templatize everything.  Both users
(gdb and gdbserver) would pass in their own target_desc type as a template
parameter.

Could you also make allocate_target_description return a target_desc_up?
It could be a separate patch on top.

> diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
> index 456e8e070b1..e36137cacd0 100644
> --- a/gdbsupport/tdesc.h
> +++ b/gdbsupport/tdesc.h
> @@ -312,6 +312,17 @@ struct tdesc_feature : tdesc_element
>  
>  typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
>  
> +/* A deleter adapter for a target desc.  */
> +
> +struct target_desc_deleter
> +{
> +  void operator() (struct target_desc *desc) const;
> +};

It would be good to say in the comment that there are two distinct implementations
for this, in gdb and gdbserver.

Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Andrew Burgess
* Simon Marchi <[hidden email]> [2020-07-16 15:58:25 -0400]:

> On 2020-07-16 1:29 p.m., Andrew Burgess wrote:
> > It was pointed out on IRC that the RISC-V target allocates target
> > descriptions and stores them in a global map, and doesn't delete these
> > target descriptions when GDB shuts down.
> >
> > This isn't a particular problem, the total number of target
> > descriptions we can create is very limited so creating these on demand
> > and holding them for the entire run on GDB seems reasonable.
> >
> > However, not deleting these objects on GDB exit means extra warnings
> > are printed from tools like valgrind, and the address sanitiser,
> > making it harder to spot real issues.  As it's reasonably easy to have
> > GDB correctly delete these objects on exit, lets just do that.
> >
> > I started by noticing that we already have a target_desc_up type, a
> > wrapper around unique_ptr that calls a function that will correctly
> > delete target descriptions, so I want to use that, but....
> >
> > ...that type is declared in gdb/target-descriptions.h.  If I try to
> > include that file in gdb/arch/riscv.c I run into a problem, that file
> > is compiled into both GDB and GDBServer.
> >
> > OK, I could guard the include with #ifdef, but surely we can do
> > better.
> >
> > So then I decided to move the target_desc_up type into
> > gdbsupport/tdesc.h, this is the interface file for generic code shared
> > between GDB and GDBserver (relating to target descriptions).  The
> > actual implementation for the delete function still lives in
> > gdb/target-description.c, but now gdb/arch/riscv.c can see the
> > declaration.  Problem solved....
> >
> > ... but, though RISC-V doesn't use it I've now exposed the
> > target_desc_up type to gdbserver, so in future someone _might_ start
> > using it, which is fine, except right now there's no definition of the
> > delete function - remember the delete I used is only defined in GDB
> > code.
> >
> > No problem, I add an implementation of the delete operator into
> > gdbserver/tdesc.cc, and all is good..... except....
> >
> > I start getting this error from GCC:
> >
> >   tdesc.cc:109:10: error: deleting object of polymorphic class type ‘target_desc’ which has non-virtual destructor might cause undefined behavior [-Werror=delete-non-virtual-dtor]
> >
> > This seems a little strange to me as target_desc is not a polymorphic
> > class as far as I can tell, so I don't quite understand why GCC is
> > complaining about this.
> >
> > Still by making gdbserver's target_desc class final this seems to
> > resolve this issue.  This should be fine so long as we never try to
> > inherit from target_desc, but if we do we probably should make the
> > destructor virtual, so that wouldn't be an issue.
>
> I think this is all reasonable.  The unique_ptr has to be a bit awkward
> (have a custom deleter, and distinct implementations in gdb and gdbserver)
> because gdb and gdbserver don't share a target_desc type.  They have the
> same name, but that's about it.
>
> I guess an alternative would be to templatize everything.  Both users
> (gdb and gdbserver) would pass in their own target_desc type as a template
> parameter.
>
> Could you also make allocate_target_description return a target_desc_up?
> It could be a separate patch on top.
>
> > diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
> > index 456e8e070b1..e36137cacd0 100644
> > --- a/gdbsupport/tdesc.h
> > +++ b/gdbsupport/tdesc.h
> > @@ -312,6 +312,17 @@ struct tdesc_feature : tdesc_element
> >  
> >  typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
> >  
> > +/* A deleter adapter for a target desc.  */
> > +
> > +struct target_desc_deleter
> > +{
> > +  void operator() (struct target_desc *desc) const;
> > +};
>
> It would be good to say in the comment that there are two distinct implementations
> for this, in gdb and gdbserver.

Thanks for the feedback.  Here's an updated patch with an extended
comment.  I did consider the template approach, but unless I'm missing
something I'm not sure it actually changes things much - the calls to
delete still need to live in a location where the full class type is
known, so we'd still end up with two blocks of code, on in gdb and one
in gdbserver.  But maybe I'm not understanding.

Anyway, I'm hoping you'll be happy to have this merged for now, and
any template based improvements could possibly be added later?

Thanks,
Andrew

---

commit 2238967c0d3eb179c1e3ba289c012a61b6910d26
Author: Andrew Burgess <[hidden email]>
Date:   Thu Jul 16 17:48:12 2020 +0100

    gdb/riscv: delete target descriptions when gdb exits
   
    It was pointed out on IRC that the RISC-V target allocates target
    descriptions and stores them in a global map, and doesn't delete these
    target descriptions when GDB shuts down.
   
    This isn't a particular problem, the total number of target
    descriptions we can create is very limited so creating these on demand
    and holding them for the entire run on GDB seems reasonable.
   
    However, not deleting these objects on GDB exit means extra warnings
    are printed from tools like valgrind, and the address sanitiser,
    making it harder to spot real issues.  As it's reasonably easy to have
    GDB correctly delete these objects on exit, lets just do that.
   
    I started by noticing that we already have a target_desc_up type, a
    wrapper around unique_ptr that calls a function that will correctly
    delete target descriptions, so I want to use that, but....
   
    ...that type is declared in gdb/target-descriptions.h.  If I try to
    include that file in gdb/arch/riscv.c I run into a problem, that file
    is compiled into both GDB and GDBServer.
   
    OK, I could guard the include with #ifdef, but surely we can do
    better.
   
    So then I decided to move the target_desc_up type into
    gdbsupport/tdesc.h, this is the interface file for generic code shared
    between GDB and GDBserver (relating to target descriptions).  The
    actual implementation for the delete function still lives in
    gdb/target-description.c, but now gdb/arch/riscv.c can see the
    declaration.  Problem solved....
   
    ... but, though RISC-V doesn't use it I've now exposed the
    target_desc_up type to gdbserver, so in future someone _might_ start
    using it, which is fine, except right now there's no definition of the
    delete function - remember the delete I used is only defined in GDB
    code.
   
    No problem, I add an implementation of the delete operator into
    gdbserver/tdesc.cc, and all is good..... except....
   
    I start getting this error from GCC:
   
      tdesc.cc:109:10: error: deleting object of polymorphic class type ‘target_desc’ which has non-virtual destructor might cause undefined behavior [-Werror=delete-non-virtual-dtor]
   
    This seems a little strange to me as target_desc is not a polymorphic
    class as far as I can tell, so I don't quite understand why GCC is
    complaining about this.
   
    Still by making gdbserver's target_desc class final this seems to
    resolve this issue.  This should be fine so long as we never try to
    inherit from target_desc, but if we do we probably should make the
    destructor virtual, so that wouldn't be an issue.
   
    gdb/ChangeLog:
   
            * arch/riscv.c (riscv_tdesc_cache): Change map type.
            (riscv_lookup_target_description): Return pointer out of
            unique_ptr.
            * target-descriptions.c (allocate_target_description): Add
            comment.
            (target_desc_deleter::operator()): Likewise.
            * target-descriptions.h (struct target_desc_deleter): Moved to
            gdbsupport/tdesc.h.
            (target_desc_up): Likewise.
   
    gdbserver/ChangeLog:
   
            * tdesc.cc (allocate_target_description): Add header comment.
            (target_desc_deleter::operator()): New function.
            * tdesc.h (struct target_desc): Declare as final.
   
    gdbsupport/ChangeLog:
   
            * tdesc.h (struct target_desc_deleter): Moved here
            from gdb/target-descriptions.h, extend comment.
            (target_desc_up): Likewise.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f30edafdf92..9195a396a20 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,15 @@
+2020-07-16  Andrew Burgess  <[hidden email]>
+
+ * arch/riscv.c (riscv_tdesc_cache): Change map type.
+ (riscv_lookup_target_description): Return pointer out of
+ unique_ptr.
+ * target-descriptions.c (allocate_target_description): Add
+ comment.
+ (target_desc_deleter::operator()): Likewise.
+ * target-descriptions.h (struct target_desc_deleter): Moved to
+ gdbsupport/tdesc.h.
+ (target_desc_up): Likewise.
+
 2020-07-15  Andrew Burgess  <[hidden email]>
 
  * f-typeprint.c (f_type_print_base): Allow for dynamic types not
diff --git a/gdb/arch/riscv.c b/gdb/arch/riscv.c
index a02c18b4c91..e43aafc1c2f 100644
--- a/gdb/arch/riscv.c
+++ b/gdb/arch/riscv.c
@@ -91,7 +91,7 @@ struct riscv_gdbarch_features_hasher
 /* Cache of previously seen target descriptions, indexed by the feature set
    that created them.  */
 static std::unordered_map<riscv_gdbarch_features,
-  const target_desc *,
+  const target_desc_up,
   riscv_gdbarch_features_hasher> riscv_tdesc_cache;
 
 /* See arch/riscv.h.  */
@@ -99,10 +99,12 @@ static std::unordered_map<riscv_gdbarch_features,
 const target_desc *
 riscv_lookup_target_description (const struct riscv_gdbarch_features features)
 {
-  /* Lookup in the cache.  */
+  /* Lookup in the cache.  If we find it then return the pointer out of
+     the target_desc_up (which is a unique_ptr).  This is safe as the
+     riscv_tdesc_cache will exist until GDB exits.  */
   const auto it = riscv_tdesc_cache.find (features);
   if (it != riscv_tdesc_cache.end ())
-    return it->second;
+    return it->second.get ();
 
   target_desc *tdesc = riscv_create_target_description (features);
 
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 2f4b17727b8..20d624c0c65 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -1206,12 +1206,16 @@ tdesc_create_feature (struct target_desc *tdesc, const char *name)
   return new_feature;
 }
 
+/* See gdbsupport/tdesc.h.  */
+
 struct target_desc *
 allocate_target_description (void)
 {
   return new target_desc ();
 }
 
+/* See gdbsupport/tdesc.h.  */
+
 void
 target_desc_deleter::operator() (struct target_desc *target_desc) const
 {
diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h
index 6d842bf07ed..66a2c213dc2 100644
--- a/gdb/target-descriptions.h
+++ b/gdb/target-descriptions.h
@@ -225,18 +225,6 @@ struct type *tdesc_find_type (struct gdbarch *gdbarch, const char *id);
 int tdesc_register_in_reggroup_p (struct gdbarch *gdbarch, int regno,
   struct reggroup *reggroup);
 
-
-/* A deleter adapter for a target desc.  */
-
-struct target_desc_deleter
-{
-  void operator() (struct target_desc *desc) const;
-};
-
-/* A unique pointer specialization that holds a target_desc.  */
-
-typedef std::unique_ptr<target_desc, target_desc_deleter> target_desc_up;
-
 /* Methods for constructing a target description.  */
 
 void set_tdesc_architecture (struct target_desc *,
diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog
index 1ee716f52d7..402944419cc 100644
--- a/gdbserver/ChangeLog
+++ b/gdbserver/ChangeLog
@@ -1,3 +1,9 @@
+2020-07-16  Andrew Burgess  <[hidden email]>
+
+ * tdesc.cc (allocate_target_description): Add header comment.
+ (target_desc_deleter::operator()): New function.
+ * tdesc.h (struct target_desc): Declare as final.
+
 2020-07-13  Simon Marchi  <[hidden email]>
 
  * server.cc (handle_query): Use std::vector of
diff --git a/gdbserver/tdesc.cc b/gdbserver/tdesc.cc
index d21688b932b..e639017cc31 100644
--- a/gdbserver/tdesc.cc
+++ b/gdbserver/tdesc.cc
@@ -93,12 +93,22 @@ init_target_desc (struct target_desc *tdesc,
 #endif
 }
 
+/* See gdbsupport/tdesc.h.  */
+
 struct target_desc *
 allocate_target_description (void)
 {
   return new target_desc ();
 }
 
+/* See gdbsupport/tdesc.h.  */
+
+void
+target_desc_deleter::operator() (struct target_desc *target_desc) const
+{
+  delete target_desc;
+}
+
 #ifndef IN_PROCESS_AGENT
 
 static const struct target_desc default_description {};
diff --git a/gdbserver/tdesc.h b/gdbserver/tdesc.h
index f9ca478ff6d..681de64d0aa 100644
--- a/gdbserver/tdesc.h
+++ b/gdbserver/tdesc.h
@@ -27,7 +27,7 @@
 /* A target description.  Inherit from tdesc_feature so that target_desc
    can be used as tdesc_feature.  */
 
-struct target_desc : tdesc_element
+struct target_desc final : tdesc_element
 {
   /* A vector of elements of register definitions that
      describe the inferior's register set.  */
diff --git a/gdbsupport/ChangeLog b/gdbsupport/ChangeLog
index e1b040d5827..c148975aa41 100644
--- a/gdbsupport/ChangeLog
+++ b/gdbsupport/ChangeLog
@@ -1,3 +1,9 @@
+2020-07-16  Andrew Burgess  <[hidden email]>
+
+ * tdesc.h (struct target_desc_deleter): Moved here
+ from gdb/target-descriptions.h, extend comment.
+ (target_desc_up): Likewise.
+
 2020-06-30  Tom Tromey  <[hidden email]>
 
  PR build/26183:
diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
index 456e8e070b1..025aa744bfb 100644
--- a/gdbsupport/tdesc.h
+++ b/gdbsupport/tdesc.h
@@ -312,6 +312,20 @@ struct tdesc_feature : tdesc_element
 
 typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
 
+/* A deleter adapter for a target desc.  There are different
+   implementations of this class in gdb and gdbserver because even thought
+   the  target_desc name is shared between the two projects, the actual
+   implementations of target_desc are completely different.  */
+
+struct target_desc_deleter
+{
+  void operator() (struct target_desc *desc) const;
+};
+
+/* A unique pointer specialization that holds a target_desc.  */
+
+typedef std::unique_ptr<target_desc, target_desc_deleter> target_desc_up;
+
 /* Allocate a new target_desc.  */
 target_desc *allocate_target_description (void);
 
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Andrew Burgess
In reply to this post by Simon Marchi-4
* Simon Marchi <[hidden email]> [2020-07-16 15:58:25 -0400]:

> On 2020-07-16 1:29 p.m., Andrew Burgess wrote:
> > It was pointed out on IRC that the RISC-V target allocates target
> > descriptions and stores them in a global map, and doesn't delete these
> > target descriptions when GDB shuts down.
> >
> > This isn't a particular problem, the total number of target
> > descriptions we can create is very limited so creating these on demand
> > and holding them for the entire run on GDB seems reasonable.
> >
> > However, not deleting these objects on GDB exit means extra warnings
> > are printed from tools like valgrind, and the address sanitiser,
> > making it harder to spot real issues.  As it's reasonably easy to have
> > GDB correctly delete these objects on exit, lets just do that.
> >
> > I started by noticing that we already have a target_desc_up type, a
> > wrapper around unique_ptr that calls a function that will correctly
> > delete target descriptions, so I want to use that, but....
> >
> > ...that type is declared in gdb/target-descriptions.h.  If I try to
> > include that file in gdb/arch/riscv.c I run into a problem, that file
> > is compiled into both GDB and GDBServer.
> >
> > OK, I could guard the include with #ifdef, but surely we can do
> > better.
> >
> > So then I decided to move the target_desc_up type into
> > gdbsupport/tdesc.h, this is the interface file for generic code shared
> > between GDB and GDBserver (relating to target descriptions).  The
> > actual implementation for the delete function still lives in
> > gdb/target-description.c, but now gdb/arch/riscv.c can see the
> > declaration.  Problem solved....
> >
> > ... but, though RISC-V doesn't use it I've now exposed the
> > target_desc_up type to gdbserver, so in future someone _might_ start
> > using it, which is fine, except right now there's no definition of the
> > delete function - remember the delete I used is only defined in GDB
> > code.
> >
> > No problem, I add an implementation of the delete operator into
> > gdbserver/tdesc.cc, and all is good..... except....
> >
> > I start getting this error from GCC:
> >
> >   tdesc.cc:109:10: error: deleting object of polymorphic class type ‘target_desc’ which has non-virtual destructor might cause undefined behavior [-Werror=delete-non-virtual-dtor]
> >
> > This seems a little strange to me as target_desc is not a polymorphic
> > class as far as I can tell, so I don't quite understand why GCC is
> > complaining about this.
> >
> > Still by making gdbserver's target_desc class final this seems to
> > resolve this issue.  This should be fine so long as we never try to
> > inherit from target_desc, but if we do we probably should make the
> > destructor virtual, so that wouldn't be an issue.
>
> I think this is all reasonable.  The unique_ptr has to be a bit awkward
> (have a custom deleter, and distinct implementations in gdb and gdbserver)
> because gdb and gdbserver don't share a target_desc type.  They have the
> same name, but that's about it.
>
> I guess an alternative would be to templatize everything.  Both users
> (gdb and gdbserver) would pass in their own target_desc type as a template
> parameter.
>
> Could you also make allocate_target_description return a target_desc_up?
> It could be a separate patch on top.

I've started working through this, but it's pretty big change.  Having
allocate_target_description return a target_desc_up and then having
every caller immediately call .release () is not _too_ painful, but
seems rather pointless.

I looked at having those targets that generate an initialize_tdesc_*
function in gdb/features/*.c store the global target_desc as a
target_desc_up, but you can't do this target by target, so most
targets need to be updated.

I'm still working through this, but I'm hoping that we might consider
merging my update of the original patch, while leaving
allocate_target_description unchanged for now.  I think this is
useful, it gives targets like RISC-V, and ARC, the opportunity to have
the target_desc be deleted if they want, wile other targets can
continue doing their thing.

Thanks,
Andrew

>
> > diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
> > index 456e8e070b1..e36137cacd0 100644
> > --- a/gdbsupport/tdesc.h
> > +++ b/gdbsupport/tdesc.h
> > @@ -312,6 +312,17 @@ struct tdesc_feature : tdesc_element
> >  
> >  typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
> >  
> > +/* A deleter adapter for a target desc.  */
> > +
> > +struct target_desc_deleter
> > +{
> > +  void operator() (struct target_desc *desc) const;
> > +};
>
> It would be good to say in the comment that there are two distinct implementations
> for this, in gdb and gdbserver.
>
> Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Simon Marchi-4
In reply to this post by Andrew Burgess
On 2020-07-17 5:32 a.m., Andrew Burgess wrote:
> Thanks for the feedback.  Here's an updated patch with an extended
> comment.  I did consider the template approach, but unless I'm missing
> something I'm not sure it actually changes things much - the calls to
> delete still need to live in a location where the full class type is
> known, so we'd still end up with two blocks of code, on in gdb and one
> in gdbserver.  But maybe I'm not understanding.

I'm also not sure how that would work.

>
> Anyway, I'm hoping you'll be happy to have this merged for now, and
> any template based improvements could possibly be added later?

I think the current approach is good enough and there's no point changing
it to a template based, it was just a thought like that.

> diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
> index 456e8e070b1..025aa744bfb 100644
> --- a/gdbsupport/tdesc.h
> +++ b/gdbsupport/tdesc.h
> @@ -312,6 +312,20 @@ struct tdesc_feature : tdesc_element
>  
>  typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
>  
> +/* A deleter adapter for a target desc.  There are different
> +   implementations of this class in gdb and gdbserver because even thought

thought -> though

> +   the  target_desc name is shared between the two projects, the actual

unexpected two spaces

Otherwise, LGTM.

Btw, about the "final" on gdbserver's target_desc: it's because target_desc inherits from
tdesc_element, which itself has a virtual `accept` method.  So target_desc's `accept`
method is also virtual.  By making the class final, you tell the compiler that a pointer
to a target_desc will always point to a target_desc, not some sub-class, so it can probably
call the target_desc destructor directly.

Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Simon Marchi-4
In reply to this post by Andrew Burgess
On 2020-07-17 10:58 a.m., Andrew Burgess wrote:
> I've started working through this, but it's pretty big change.  Having
> allocate_target_description return a target_desc_up and then having
> every caller immediately call .release () is not _too_ painful, but
> seems rather pointless.

I don't think it's pointless, it's a small step in the right direction.  Ideally,
the whole chain would use unique pointers when returning a newly allocated tdesc
and transferring ownership, and it is one step towards that.

> I looked at having those targets that generate an initialize_tdesc_*
> function in gdb/features/*.c store the global target_desc as a
> target_desc_up, but you can't do this target by target, so most
> targets need to be updated.
>
> I'm still working through this, but I'm hoping that we might consider
> merging my update of the original patch, while leaving
> allocate_target_description unchanged for now.  I think this is
> useful, it gives targets like RISC-V, and ARC, the opportunity to have
> the target_desc be deleted if they want, wile other targets can
> continue doing their thing.

Sure, that's fine, and you also don't have to do it if you don't want to :).

Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Sourceware - gdb-patches mailing list
In reply to this post by Andrew Burgess
Hi Andrew,

Thank you for your care. If the remarks from [1] are resolved, this
looks (very) good to me.

I can also rework those remarks and apply the patch (under your name).


Shahab

[1] Simon's remarks on second iteration of the patch
https://sourceware.org/pipermail/gdb-patches/2020-July/170540.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Andrew Burgess
* Shahab Vahedi <[hidden email]> [2020-07-21 12:14:34 +0200]:

> Hi Andrew,
>
> Thank you for your care. If the remarks from [1] are resolved, this
> looks (very) good to me.
>
> I can also rework those remarks and apply the patch (under your name).
>
>
> Shahab
>
> [1] Simon's remarks on second iteration of the patch
> https://sourceware.org/pipermail/gdb-patches/2020-July/170540.html

I resolved these issues and pushed this patch.  I hope you find this
helpful.

Thanks,
Andrew
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Andrew Burgess
In reply to this post by Simon Marchi-4
* Simon Marchi <[hidden email]> [2020-07-17 12:20:44 -0400]:

> On 2020-07-17 10:58 a.m., Andrew Burgess wrote:
> > I've started working through this, but it's pretty big change.  Having
> > allocate_target_description return a target_desc_up and then having
> > every caller immediately call .release () is not _too_ painful, but
> > seems rather pointless.
>
> I don't think it's pointless, it's a small step in the right direction.  Ideally,
> the whole chain would use unique pointers when returning a newly allocated tdesc
> and transferring ownership, and it is one step towards that.

OK then.

Below is a patch to make allocate_target_description return a
target_desc_up, in almost all cases this unique_ptr is then released.
The RISC-V code doesn't do this, and I also updated a case in
gdbserver to hold global target_desc_up objects rather than the raw
pointers.

There's lots of churn due to regenerating everything under
gdb/features/*, but it is all auto-generated, review one file, and
you've reviewed 'em all.

Thoughts / feedback welcome.

Thanks,
Andrew

---

commit 769d6fa057d53001fc3eb7118cba4a56949b297f
Author: Andrew Burgess <[hidden email]>
Date:   Mon Jul 20 14:18:04 2020 +0100

    gdb: Have allocate_target_description return a unique_ptr
   
    Update allocate_target_description to return a target_desc_up, a
    specialisation of unique_ptr.
   
    This commit does not attempt to make use of the unique_ptr in the
    best possible way, in almost all cases we immediately release the
    pointer from within the unique_ptr and then continue as before.
   
    There are a few places where it was easy to handle the unique_ptr, and
    in these cases I've done that.
   
    Everything under gdb/features/* is auto-regenerated.
   
    There should be no user visible changes after this commit.
   
    gdb/ChangeLog:
   
            * arch/aarch32.c (aarch32_create_target_description): Release
            unique_ptr returned from allocate_target_description.
            * arch/aarch64.c (aarch64_create_target_description): Likewise.
            * arch/amd64.c (amd64_create_target_description): Likewise.
            * arch/arc.c (arc_create_target_description): Likewise.
            * arch/arm.c (arm_create_target_description): Likewise.
            * arch/i386.c (i386_create_target_description): Likewise.
            * arch/riscv.c (riscv_create_target_description): Update return
            type.  Handle allocate_target_description returning a unique_ptr.
            (riscv_lookup_target_description): Update to handle unique_ptr.
            * arch/tic6x.c (tic6x_create_target_description): Release
            unique_ptr returned from allocate_target_description.
            * features/microblaze-with-stack-protect.c: Regenerate.
            * features/microblaze.c: Regenerate.
            * features/mips-dsp-linux.c: Regenerate.
            * features/mips-linux.c: Regenerate.
            * features/mips64-dsp-linux.c: Regenerate.
            * features/mips64-linux.c: Regenerate.
            * features/nds32.c: Regenerate.
            * features/nios2.c: Regenerate.
            * features/or1k.c: Regenerate.
            * features/rs6000/powerpc-32.c: Regenerate.
            * features/rs6000/powerpc-32l.c: Regenerate.
            * features/rs6000/powerpc-403.c: Regenerate.
            * features/rs6000/powerpc-403gc.c: Regenerate.
            * features/rs6000/powerpc-405.c: Regenerate.
            * features/rs6000/powerpc-505.c: Regenerate.
            * features/rs6000/powerpc-601.c: Regenerate.
            * features/rs6000/powerpc-602.c: Regenerate.
            * features/rs6000/powerpc-603.c: Regenerate.
            * features/rs6000/powerpc-604.c: Regenerate.
            * features/rs6000/powerpc-64.c: Regenerate.
            * features/rs6000/powerpc-64l.c: Regenerate.
            * features/rs6000/powerpc-7400.c: Regenerate.
            * features/rs6000/powerpc-750.c: Regenerate.
            * features/rs6000/powerpc-860.c: Regenerate.
            * features/rs6000/powerpc-altivec32.c: Regenerate.
            * features/rs6000/powerpc-altivec32l.c: Regenerate.
            * features/rs6000/powerpc-altivec64.c: Regenerate.
            * features/rs6000/powerpc-altivec64l.c: Regenerate.
            * features/rs6000/powerpc-e500.c: Regenerate.
            * features/rs6000/powerpc-e500l.c: Regenerate.
            * features/rs6000/powerpc-isa205-32l.c: Regenerate.
            * features/rs6000/powerpc-isa205-64l.c: Regenerate.
            * features/rs6000/powerpc-isa205-altivec32l.c: Regenerate.
            * features/rs6000/powerpc-isa205-altivec64l.c: Regenerate.
            * features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c: Regenerate.
            * features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c: Regenerate.
            * features/rs6000/powerpc-isa205-vsx32l.c: Regenerate.
            * features/rs6000/powerpc-isa205-vsx64l.c: Regenerate.
            * features/rs6000/powerpc-isa207-htm-vsx32l.c: Regenerate.
            * features/rs6000/powerpc-isa207-htm-vsx64l.c: Regenerate.
            * features/rs6000/powerpc-isa207-vsx32l.c: Regenerate.
            * features/rs6000/powerpc-isa207-vsx64l.c: Regenerate.
            * features/rs6000/powerpc-vsx32.c: Regenerate.
            * features/rs6000/powerpc-vsx32l.c: Regenerate.
            * features/rs6000/powerpc-vsx64.c: Regenerate.
            * features/rs6000/powerpc-vsx64l.c: Regenerate.
            * features/rs6000/rs6000.c: Regenerate.
            * features/rx.c: Regenerate.
            * features/s390-gs-linux64.c: Regenerate.
            * features/s390-linux32.c: Regenerate.
            * features/s390-linux32v1.c: Regenerate.
            * features/s390-linux32v2.c: Regenerate.
            * features/s390-linux64.c: Regenerate.
            * features/s390-linux64v1.c: Regenerate.
            * features/s390-linux64v2.c: Regenerate.
            * features/s390-te-linux64.c: Regenerate.
            * features/s390-tevx-linux64.c: Regenerate.
            * features/s390-vx-linux64.c: Regenerate.
            * features/s390x-gs-linux64.c: Regenerate.
            * features/s390x-linux64.c: Regenerate.
            * features/s390x-linux64v1.c: Regenerate.
            * features/s390x-linux64v2.c: Regenerate.
            * features/s390x-te-linux64.c: Regenerate.
            * features/s390x-tevx-linux64.c: Regenerate.
            * features/s390x-vx-linux64.c: Regenerate.
            * mips-tdep.c (_initialize_mips_tdep): Release unique_ptr returned
            from allocate_target_description.
            * target-descriptions.c (allocate_target_description): Update
            return type.
            (print_c_tdesc::visit_pre): Release unique_ptr returned from
            allocate_target_description.
   
    gdbserver/ChangeLog:
   
            * linux-low.cc (linux_process_target::handle_extended_wait):
            Release the unique_ptr returned from allocate_target_description.
            * linux-riscv-low.cc (riscv_target::low_arch_setup): Likewise.
            * linux-x86-low.cc (tdesc_amd64_linux_no_xml): Change type.
            (tdesc_i386_linux_no_xml): Change type.
            (x86_linux_read_description): Borrow pointer from unique_ptr
            object.
            (x86_target::get_ipa_tdesc_idx): Likewise.
            (initialize_low_arch): Likewise.
            * tdesc.cc (allocate_target_description): Update return type.
   
    gdbsupport/ChangeLog:
   
            * tdesc.h (allocate_target_description): Update return type.

diff --git a/gdb/arch/aarch32.c b/gdb/arch/aarch32.c
index 5bc24a30164..bf7a33230e0 100644
--- a/gdb/arch/aarch32.c
+++ b/gdb/arch/aarch32.c
@@ -26,7 +26,7 @@
 target_desc *
 aarch32_create_target_description ()
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
 #ifndef IN_PROCESS_AGENT
   set_tdesc_architecture (tdesc, "arm");
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index f6115434989..c0af7b0906f 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -29,7 +29,7 @@
 target_desc *
 aarch64_create_target_description (uint64_t vq, bool pauth_p)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
 #ifndef IN_PROCESS_AGENT
   set_tdesc_architecture (tdesc, "aarch64");
diff --git a/gdb/arch/amd64.c b/gdb/arch/amd64.c
index a388c7e49d1..b11a4fdc0fc 100644
--- a/gdb/arch/amd64.c
+++ b/gdb/arch/amd64.c
@@ -40,7 +40,7 @@ target_desc *
 amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
  bool segments)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
 #ifndef IN_PROCESS_AGENT
   set_tdesc_architecture (tdesc, is_x32 ? "i386:x64-32" : "i386:x86-64");
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..8d702031423 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -32,7 +32,7 @@
 target_desc *
 arc_create_target_description (arc_sys_type sys_type)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
   long regnum = 0;
 
diff --git a/gdb/arch/arm.c b/gdb/arch/arm.c
index faa2b4fbd4b..dc67e40f9cf 100644
--- a/gdb/arch/arm.c
+++ b/gdb/arch/arm.c
@@ -374,7 +374,7 @@ shifted_reg_val (struct regcache *regcache, unsigned long inst,
 target_desc *
 arm_create_target_description (arm_fp_type fp_type)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
 #ifndef IN_PROCESS_AGENT
   if (fp_type == ARM_FP_TYPE_IWMMXT)
@@ -416,7 +416,7 @@ arm_create_target_description (arm_fp_type fp_type)
 target_desc *
 arm_create_mprofile_target_description (arm_m_profile_type m_type)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
 #ifndef IN_PROCESS_AGENT
   set_tdesc_architecture (tdesc, "arm");
diff --git a/gdb/arch/i386.c b/gdb/arch/i386.c
index 099a20b98a2..13201db1d74 100644
--- a/gdb/arch/i386.c
+++ b/gdb/arch/i386.c
@@ -35,7 +35,7 @@
 target_desc *
 i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
 #ifndef IN_PROCESS_AGENT
   set_tdesc_architecture (tdesc, "i386");
diff --git a/gdb/arch/riscv.c b/gdb/arch/riscv.c
index e43aafc1c2f..a6538dee541 100644
--- a/gdb/arch/riscv.c
+++ b/gdb/arch/riscv.c
@@ -33,11 +33,11 @@
 
 /* See arch/riscv.h.  */
 
-STATIC_IN_GDB target_desc *
+STATIC_IN_GDB target_desc_up
 riscv_create_target_description (const struct riscv_gdbarch_features features)
 {
   /* Now we should create a new target description.  */
-  target_desc *tdesc = allocate_target_description ();
+  target_desc_up tdesc = allocate_target_description ();
 
 #ifndef IN_PROCESS_AGENT
   std::string arch_name = "riscv";
@@ -56,22 +56,22 @@ riscv_create_target_description (const struct riscv_gdbarch_features features)
   else if (features.flen == 16)
     arch_name.append ("q");
 
-  set_tdesc_architecture (tdesc, arch_name.c_str ());
+  set_tdesc_architecture (tdesc.get (), arch_name.c_str ());
 #endif
 
   long regnum = 0;
 
   /* For now we only support creating 32-bit or 64-bit x-registers.  */
   if (features.xlen == 4)
-    regnum = create_feature_riscv_32bit_cpu (tdesc, regnum);
+    regnum = create_feature_riscv_32bit_cpu (tdesc.get (), regnum);
   else if (features.xlen == 8)
-    regnum = create_feature_riscv_64bit_cpu (tdesc, regnum);
+    regnum = create_feature_riscv_64bit_cpu (tdesc.get (), regnum);
 
   /* For now we only support creating 32-bit or 64-bit f-registers.  */
   if (features.flen == 4)
-    regnum = create_feature_riscv_32bit_fpu (tdesc, regnum);
+    regnum = create_feature_riscv_32bit_fpu (tdesc.get (), regnum);
   else if (features.flen == 8)
-    regnum = create_feature_riscv_64bit_fpu (tdesc, regnum);
+    regnum = create_feature_riscv_64bit_fpu (tdesc.get (), regnum);
 
   return tdesc;
 }
@@ -106,12 +106,14 @@ riscv_lookup_target_description (const struct riscv_gdbarch_features features)
   if (it != riscv_tdesc_cache.end ())
     return it->second.get ();
 
-  target_desc *tdesc = riscv_create_target_description (features);
+  target_desc_up tdesc (riscv_create_target_description (features));
 
-  /* Add to the cache.  */
-  riscv_tdesc_cache.emplace (features, tdesc);
-
-  return tdesc;
+  /* Add to the cache, and return a pointer borrowed from the
+     target_desc_up.  This is safe as the cache (and the pointers
+     contained within it) are not deleted until GDB exits.  */
+  target_desc *ptr = tdesc.get ();
+  riscv_tdesc_cache.emplace (features, std::move (tdesc));
+  return ptr;
 }
 
 #endif /* !GDBSERVER */
diff --git a/gdb/arch/tic6x.c b/gdb/arch/tic6x.c
index 5f14d34750b..dad4dd85a4d 100644
--- a/gdb/arch/tic6x.c
+++ b/gdb/arch/tic6x.c
@@ -28,7 +28,7 @@
 target_desc *
 tic6x_create_target_description (enum c6x_feature feature)
 {
-  target_desc *tdesc = allocate_target_description ();
+  target_desc *tdesc = allocate_target_description ().release ();
 
   set_tdesc_architecture (tdesc, "tic6x");
   set_tdesc_osabi (tdesc, "GNU/Linux");
diff --git a/gdb/features/microblaze-with-stack-protect.c b/gdb/features/microblaze-with-stack-protect.c
index b39aa198874..994750cd29c 100644
--- a/gdb/features/microblaze-with-stack-protect.c
+++ b/gdb/features/microblaze-with-stack-protect.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_microblaze_with_stack_protect;
 static void
 initialize_tdesc_microblaze_with_stack_protect (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.microblaze.core");
diff --git a/gdb/features/microblaze.c b/gdb/features/microblaze.c
index 6c86fc07700..011e7e685f1 100644
--- a/gdb/features/microblaze.c
+++ b/gdb/features/microblaze.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_microblaze;
 static void
 initialize_tdesc_microblaze (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.microblaze.core");
diff --git a/gdb/features/mips-dsp-linux.c b/gdb/features/mips-dsp-linux.c
index 26e9c6b01de..4df8db526bc 100644
--- a/gdb/features/mips-dsp-linux.c
+++ b/gdb/features/mips-dsp-linux.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_mips_dsp_linux;
 static void
 initialize_tdesc_mips_dsp_linux (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("mips"));
 
   set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
diff --git a/gdb/features/mips-linux.c b/gdb/features/mips-linux.c
index c9ad3ca7eba..8808ff25780 100644
--- a/gdb/features/mips-linux.c
+++ b/gdb/features/mips-linux.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_mips_linux;
 static void
 initialize_tdesc_mips_linux (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("mips"));
 
   set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
diff --git a/gdb/features/mips64-dsp-linux.c b/gdb/features/mips64-dsp-linux.c
index 05317b70f4f..7a5fa080408 100644
--- a/gdb/features/mips64-dsp-linux.c
+++ b/gdb/features/mips64-dsp-linux.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_mips64_dsp_linux;
 static void
 initialize_tdesc_mips64_dsp_linux (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("mips"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/mips64-linux.c b/gdb/features/mips64-linux.c
index 4814152c430..c1fc8926ff1 100644
--- a/gdb/features/mips64-linux.c
+++ b/gdb/features/mips64-linux.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_mips64_linux;
 static void
 initialize_tdesc_mips64_linux (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("mips"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/nds32.c b/gdb/features/nds32.c
index 89b246b8ce0..e867949ca04 100644
--- a/gdb/features/nds32.c
+++ b/gdb/features/nds32.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_nds32;
 static void
 initialize_tdesc_nds32 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("n1h"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/nios2.c b/gdb/features/nios2.c
index 705f499e65b..fd26781faf4 100644
--- a/gdb/features/nios2.c
+++ b/gdb/features/nios2.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_nios2;
 static void
 initialize_tdesc_nios2 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("nios2"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/or1k.c b/gdb/features/or1k.c
index 9169cae940e..e85f32d0f93 100644
--- a/gdb/features/or1k.c
+++ b/gdb/features/or1k.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_or1k;
 static void
 initialize_tdesc_or1k (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("or1k"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-32.c b/gdb/features/rs6000/powerpc-32.c
index 39f5b14bb43..addda76ab8e 100644
--- a/gdb/features/rs6000/powerpc-32.c
+++ b/gdb/features/rs6000/powerpc-32.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_32;
 static void
 initialize_tdesc_powerpc_32 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-32l.c b/gdb/features/rs6000/powerpc-32l.c
index 8089c0434ee..22d9c990d8e 100644
--- a/gdb/features/rs6000/powerpc-32l.c
+++ b/gdb/features/rs6000/powerpc-32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_32l;
 static void
 initialize_tdesc_powerpc_32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-403.c b/gdb/features/rs6000/powerpc-403.c
index a9106f5c536..7c2dbc7c8b5 100644
--- a/gdb/features/rs6000/powerpc-403.c
+++ b/gdb/features/rs6000/powerpc-403.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_403;
 static void
 initialize_tdesc_powerpc_403 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-403gc.c b/gdb/features/rs6000/powerpc-403gc.c
index 402b747a48f..670f25ba3ec 100644
--- a/gdb/features/rs6000/powerpc-403gc.c
+++ b/gdb/features/rs6000/powerpc-403gc.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_403gc;
 static void
 initialize_tdesc_powerpc_403gc (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-405.c b/gdb/features/rs6000/powerpc-405.c
index bcfa1445d23..d0113311b9f 100644
--- a/gdb/features/rs6000/powerpc-405.c
+++ b/gdb/features/rs6000/powerpc-405.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_405;
 static void
 initialize_tdesc_powerpc_405 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-505.c b/gdb/features/rs6000/powerpc-505.c
index 09b0c7a3854..653d1322261 100644
--- a/gdb/features/rs6000/powerpc-505.c
+++ b/gdb/features/rs6000/powerpc-505.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_505;
 static void
 initialize_tdesc_powerpc_505 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-601.c b/gdb/features/rs6000/powerpc-601.c
index f30f5e66f82..bbf5d03ede0 100644
--- a/gdb/features/rs6000/powerpc-601.c
+++ b/gdb/features/rs6000/powerpc-601.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_601;
 static void
 initialize_tdesc_powerpc_601 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-602.c b/gdb/features/rs6000/powerpc-602.c
index 769671746ad..8d6b5b5c884 100644
--- a/gdb/features/rs6000/powerpc-602.c
+++ b/gdb/features/rs6000/powerpc-602.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_602;
 static void
 initialize_tdesc_powerpc_602 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-603.c b/gdb/features/rs6000/powerpc-603.c
index d5dae39b10d..ea74a74b738 100644
--- a/gdb/features/rs6000/powerpc-603.c
+++ b/gdb/features/rs6000/powerpc-603.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_603;
 static void
 initialize_tdesc_powerpc_603 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-604.c b/gdb/features/rs6000/powerpc-604.c
index 44dc8caf47e..6a4cea921fb 100644
--- a/gdb/features/rs6000/powerpc-604.c
+++ b/gdb/features/rs6000/powerpc-604.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_604;
 static void
 initialize_tdesc_powerpc_604 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-64.c b/gdb/features/rs6000/powerpc-64.c
index a9760a37d95..0e74d03011a 100644
--- a/gdb/features/rs6000/powerpc-64.c
+++ b/gdb/features/rs6000/powerpc-64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_64;
 static void
 initialize_tdesc_powerpc_64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-64l.c b/gdb/features/rs6000/powerpc-64l.c
index 408794e13a0..7eea0b10df2 100644
--- a/gdb/features/rs6000/powerpc-64l.c
+++ b/gdb/features/rs6000/powerpc-64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_64l;
 static void
 initialize_tdesc_powerpc_64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-7400.c b/gdb/features/rs6000/powerpc-7400.c
index 58f8a69a1e2..afa80c040a2 100644
--- a/gdb/features/rs6000/powerpc-7400.c
+++ b/gdb/features/rs6000/powerpc-7400.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_7400;
 static void
 initialize_tdesc_powerpc_7400 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-750.c b/gdb/features/rs6000/powerpc-750.c
index 099a478518f..91e7c97058e 100644
--- a/gdb/features/rs6000/powerpc-750.c
+++ b/gdb/features/rs6000/powerpc-750.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_750;
 static void
 initialize_tdesc_powerpc_750 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-860.c b/gdb/features/rs6000/powerpc-860.c
index 0692feb2a5e..3050a1ffbfd 100644
--- a/gdb/features/rs6000/powerpc-860.c
+++ b/gdb/features/rs6000/powerpc-860.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_860;
 static void
 initialize_tdesc_powerpc_860 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
diff --git a/gdb/features/rs6000/powerpc-altivec32.c b/gdb/features/rs6000/powerpc-altivec32.c
index bbb36c8aa59..6928801830a 100644
--- a/gdb/features/rs6000/powerpc-altivec32.c
+++ b/gdb/features/rs6000/powerpc-altivec32.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_altivec32;
 static void
 initialize_tdesc_powerpc_altivec32 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-altivec32l.c b/gdb/features/rs6000/powerpc-altivec32l.c
index 81862cb9ef4..05cf5c39311 100644
--- a/gdb/features/rs6000/powerpc-altivec32l.c
+++ b/gdb/features/rs6000/powerpc-altivec32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_altivec32l;
 static void
 initialize_tdesc_powerpc_altivec32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-altivec64.c b/gdb/features/rs6000/powerpc-altivec64.c
index f7a7c729637..fd5de0a4dac 100644
--- a/gdb/features/rs6000/powerpc-altivec64.c
+++ b/gdb/features/rs6000/powerpc-altivec64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_altivec64;
 static void
 initialize_tdesc_powerpc_altivec64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-altivec64l.c b/gdb/features/rs6000/powerpc-altivec64l.c
index ce0bc86137e..c8f427b8c93 100644
--- a/gdb/features/rs6000/powerpc-altivec64l.c
+++ b/gdb/features/rs6000/powerpc-altivec64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_altivec64l;
 static void
 initialize_tdesc_powerpc_altivec64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-e500.c b/gdb/features/rs6000/powerpc-e500.c
index 4466bc79a9b..447eab49bd3 100644
--- a/gdb/features/rs6000/powerpc-e500.c
+++ b/gdb/features/rs6000/powerpc-e500.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_e500;
 static void
 initialize_tdesc_powerpc_e500 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:e500"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-e500l.c b/gdb/features/rs6000/powerpc-e500l.c
index 61acbf3dd31..1d0b798aee6 100644
--- a/gdb/features/rs6000/powerpc-e500l.c
+++ b/gdb/features/rs6000/powerpc-e500l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_e500l;
 static void
 initialize_tdesc_powerpc_e500l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:e500"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-32l.c b/gdb/features/rs6000/powerpc-isa205-32l.c
index de6548fdf7c..bab1945411a 100644
--- a/gdb/features/rs6000/powerpc-isa205-32l.c
+++ b/gdb/features/rs6000/powerpc-isa205-32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_32l;
 static void
 initialize_tdesc_powerpc_isa205_32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-64l.c b/gdb/features/rs6000/powerpc-isa205-64l.c
index cd3b2c10a6c..12e166aa9ac 100644
--- a/gdb/features/rs6000/powerpc-isa205-64l.c
+++ b/gdb/features/rs6000/powerpc-isa205-64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_64l;
 static void
 initialize_tdesc_powerpc_isa205_64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-altivec32l.c b/gdb/features/rs6000/powerpc-isa205-altivec32l.c
index 09f5c075c8a..fe9d1356c58 100644
--- a/gdb/features/rs6000/powerpc-isa205-altivec32l.c
+++ b/gdb/features/rs6000/powerpc-isa205-altivec32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_altivec32l;
 static void
 initialize_tdesc_powerpc_isa205_altivec32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-altivec64l.c b/gdb/features/rs6000/powerpc-isa205-altivec64l.c
index 246fcef085c..e28b5a945a9 100644
--- a/gdb/features/rs6000/powerpc-isa205-altivec64l.c
+++ b/gdb/features/rs6000/powerpc-isa205-altivec64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_altivec64l;
 static void
 initialize_tdesc_powerpc_isa205_altivec64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c b/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c
index c8f56ea0294..8ec604b1a89 100644
--- a/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c
+++ b/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_ppr_dscr_vsx32l;
 static void
 initialize_tdesc_powerpc_isa205_ppr_dscr_vsx32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c b/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c
index 76e32f3b1b6..febb8542f10 100644
--- a/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c
+++ b/gdb/features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_ppr_dscr_vsx64l;
 static void
 initialize_tdesc_powerpc_isa205_ppr_dscr_vsx64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-vsx32l.c b/gdb/features/rs6000/powerpc-isa205-vsx32l.c
index 2a6e232e994..6814536c4f2 100644
--- a/gdb/features/rs6000/powerpc-isa205-vsx32l.c
+++ b/gdb/features/rs6000/powerpc-isa205-vsx32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_vsx32l;
 static void
 initialize_tdesc_powerpc_isa205_vsx32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa205-vsx64l.c b/gdb/features/rs6000/powerpc-isa205-vsx64l.c
index d0e32f29b1b..836f8e914bd 100644
--- a/gdb/features/rs6000/powerpc-isa205-vsx64l.c
+++ b/gdb/features/rs6000/powerpc-isa205-vsx64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa205_vsx64l;
 static void
 initialize_tdesc_powerpc_isa205_vsx64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c b/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c
index e1b933c8fb3..4edb5b37350 100644
--- a/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c
+++ b/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa207_htm_vsx32l;
 static void
 initialize_tdesc_powerpc_isa207_htm_vsx32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c b/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c
index 0d818d01593..decebc1a331 100644
--- a/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c
+++ b/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa207_htm_vsx64l;
 static void
 initialize_tdesc_powerpc_isa207_htm_vsx64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa207-vsx32l.c b/gdb/features/rs6000/powerpc-isa207-vsx32l.c
index 8fe0f5e4384..9156b704789 100644
--- a/gdb/features/rs6000/powerpc-isa207-vsx32l.c
+++ b/gdb/features/rs6000/powerpc-isa207-vsx32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa207_vsx32l;
 static void
 initialize_tdesc_powerpc_isa207_vsx32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-isa207-vsx64l.c b/gdb/features/rs6000/powerpc-isa207-vsx64l.c
index 0af1879e10a..0bfdaa39504 100644
--- a/gdb/features/rs6000/powerpc-isa207-vsx64l.c
+++ b/gdb/features/rs6000/powerpc-isa207-vsx64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_isa207_vsx64l;
 static void
 initialize_tdesc_powerpc_isa207_vsx64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-vsx32.c b/gdb/features/rs6000/powerpc-vsx32.c
index 9eafb1c4823..11c2b05c5fd 100644
--- a/gdb/features/rs6000/powerpc-vsx32.c
+++ b/gdb/features/rs6000/powerpc-vsx32.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_vsx32;
 static void
 initialize_tdesc_powerpc_vsx32 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-vsx32l.c b/gdb/features/rs6000/powerpc-vsx32l.c
index f08df14f9e8..41411f3b969 100644
--- a/gdb/features/rs6000/powerpc-vsx32l.c
+++ b/gdb/features/rs6000/powerpc-vsx32l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_vsx32l;
 static void
 initialize_tdesc_powerpc_vsx32l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-vsx64.c b/gdb/features/rs6000/powerpc-vsx64.c
index 7991115cf6e..67ba593a969 100644
--- a/gdb/features/rs6000/powerpc-vsx64.c
+++ b/gdb/features/rs6000/powerpc-vsx64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_vsx64;
 static void
 initialize_tdesc_powerpc_vsx64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/powerpc-vsx64l.c b/gdb/features/rs6000/powerpc-vsx64l.c
index 1726e6754fd..6ead95b5cb6 100644
--- a/gdb/features/rs6000/powerpc-vsx64l.c
+++ b/gdb/features/rs6000/powerpc-vsx64l.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_powerpc_vsx64l;
 static void
 initialize_tdesc_powerpc_vsx64l (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rs6000/rs6000.c b/gdb/features/rs6000/rs6000.c
index 709b5da405d..39c2601c4e0 100644
--- a/gdb/features/rs6000/rs6000.c
+++ b/gdb/features/rs6000/rs6000.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_rs6000;
 static void
 initialize_tdesc_rs6000 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("rs6000:6000"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/rx.c b/gdb/features/rx.c
index d2c29c126f7..038b48b9db1 100644
--- a/gdb/features/rx.c
+++ b/gdb/features/rx.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_rx;
 static void
 initialize_tdesc_rx (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   struct tdesc_feature *feature;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.rx.core");
diff --git a/gdb/features/s390-gs-linux64.c b/gdb/features/s390-gs-linux64.c
index 1416183d3db..2bd52258c51 100644
--- a/gdb/features/s390-gs-linux64.c
+++ b/gdb/features/s390-gs-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_gs_linux64;
 static void
 initialize_tdesc_s390_gs_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-linux32.c b/gdb/features/s390-linux32.c
index 01c136c933e..9336ee55d01 100644
--- a/gdb/features/s390-linux32.c
+++ b/gdb/features/s390-linux32.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_linux32;
 static void
 initialize_tdesc_s390_linux32 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-linux32v1.c b/gdb/features/s390-linux32v1.c
index 65a4a504d33..c9d9818e973 100644
--- a/gdb/features/s390-linux32v1.c
+++ b/gdb/features/s390-linux32v1.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_linux32v1;
 static void
 initialize_tdesc_s390_linux32v1 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-linux32v2.c b/gdb/features/s390-linux32v2.c
index b5d25ec75bf..bbf031fca85 100644
--- a/gdb/features/s390-linux32v2.c
+++ b/gdb/features/s390-linux32v2.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_linux32v2;
 static void
 initialize_tdesc_s390_linux32v2 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-linux64.c b/gdb/features/s390-linux64.c
index 531d3a1ca82..d3144b9e7bc 100644
--- a/gdb/features/s390-linux64.c
+++ b/gdb/features/s390-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_linux64;
 static void
 initialize_tdesc_s390_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-linux64v1.c b/gdb/features/s390-linux64v1.c
index d75deca23fa..fccee9d3629 100644
--- a/gdb/features/s390-linux64v1.c
+++ b/gdb/features/s390-linux64v1.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_linux64v1;
 static void
 initialize_tdesc_s390_linux64v1 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-linux64v2.c b/gdb/features/s390-linux64v2.c
index bd10ee8ffe3..5dd076b793c 100644
--- a/gdb/features/s390-linux64v2.c
+++ b/gdb/features/s390-linux64v2.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_linux64v2;
 static void
 initialize_tdesc_s390_linux64v2 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-te-linux64.c b/gdb/features/s390-te-linux64.c
index fe2020ac65a..260560e472f 100644
--- a/gdb/features/s390-te-linux64.c
+++ b/gdb/features/s390-te-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_te_linux64;
 static void
 initialize_tdesc_s390_te_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-tevx-linux64.c b/gdb/features/s390-tevx-linux64.c
index ae62e8de372..a03399e598e 100644
--- a/gdb/features/s390-tevx-linux64.c
+++ b/gdb/features/s390-tevx-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_tevx_linux64;
 static void
 initialize_tdesc_s390_tevx_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390-vx-linux64.c b/gdb/features/s390-vx-linux64.c
index d3ec0814608..cb632669d3e 100644
--- a/gdb/features/s390-vx-linux64.c
+++ b/gdb/features/s390-vx-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390_vx_linux64;
 static void
 initialize_tdesc_s390_vx_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-gs-linux64.c b/gdb/features/s390x-gs-linux64.c
index d253a09997a..3a822dd7646 100644
--- a/gdb/features/s390x-gs-linux64.c
+++ b/gdb/features/s390x-gs-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_gs_linux64;
 static void
 initialize_tdesc_s390x_gs_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-linux64.c b/gdb/features/s390x-linux64.c
index 9d48ea332bd..5b590cdea1a 100644
--- a/gdb/features/s390x-linux64.c
+++ b/gdb/features/s390x-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_linux64;
 static void
 initialize_tdesc_s390x_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-linux64v1.c b/gdb/features/s390x-linux64v1.c
index b95f1c4ccc2..4a36ecbe4ed 100644
--- a/gdb/features/s390x-linux64v1.c
+++ b/gdb/features/s390x-linux64v1.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_linux64v1;
 static void
 initialize_tdesc_s390x_linux64v1 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-linux64v2.c b/gdb/features/s390x-linux64v2.c
index 9aab89f458c..dc40e811d97 100644
--- a/gdb/features/s390x-linux64v2.c
+++ b/gdb/features/s390x-linux64v2.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_linux64v2;
 static void
 initialize_tdesc_s390x_linux64v2 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-te-linux64.c b/gdb/features/s390x-te-linux64.c
index babd3bdb03d..ce10bb6805e 100644
--- a/gdb/features/s390x-te-linux64.c
+++ b/gdb/features/s390x-te-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_te_linux64;
 static void
 initialize_tdesc_s390x_te_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-tevx-linux64.c b/gdb/features/s390x-tevx-linux64.c
index 1ac3249a054..7d6884b00e0 100644
--- a/gdb/features/s390x-tevx-linux64.c
+++ b/gdb/features/s390x-tevx-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_tevx_linux64;
 static void
 initialize_tdesc_s390x_tevx_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/features/s390x-vx-linux64.c b/gdb/features/s390x-vx-linux64.c
index 2e3d3824a26..c40c880646c 100644
--- a/gdb/features/s390x-vx-linux64.c
+++ b/gdb/features/s390x-vx-linux64.c
@@ -9,7 +9,7 @@ struct target_desc *tdesc_s390x_vx_linux64;
 static void
 initialize_tdesc_s390x_vx_linux64 (void)
 {
-  struct target_desc *result = allocate_target_description ();
+  struct target_desc *result = allocate_target_description ().release ();
   set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
 
   struct tdesc_feature *feature;
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index e0f04888808..03e02f5dadc 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -8958,10 +8958,10 @@ _initialize_mips_tdep ()
 
   /* Create feature sets with the appropriate properties.  The values
      are not important.  */
-  mips_tdesc_gp32 = allocate_target_description ();
+  mips_tdesc_gp32 = allocate_target_description ().release ();
   set_tdesc_property (mips_tdesc_gp32, PROPERTY_GP32, "");
 
-  mips_tdesc_gp64 = allocate_target_description ();
+  mips_tdesc_gp64 = allocate_target_description ().release ();
   set_tdesc_property (mips_tdesc_gp64, PROPERTY_GP64, "");
 
   /* Add root prefix command for all "set mips"/"show mips" commands.  */
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 20d624c0c65..c25fcb48cb6 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -1208,10 +1208,10 @@ tdesc_create_feature (struct target_desc *tdesc, const char *name)
 
 /* See gdbsupport/tdesc.h.  */
 
-struct target_desc *
+target_desc_up
 allocate_target_description (void)
 {
-  return new target_desc ();
+  return target_desc_up (new target_desc ());
 }
 
 /* See gdbsupport/tdesc.h.  */
@@ -1378,7 +1378,7 @@ class print_c_tdesc : public tdesc_element_visitor
     printf_unfiltered ("initialize_tdesc_%s (void)\n", m_function);
     printf_unfiltered ("{\n");
     printf_unfiltered
-      ("  struct target_desc *result = allocate_target_description ();\n");
+      ("  struct target_desc *result = allocate_target_description ().release ();\n");
 
     if (tdesc_architecture (e) != NULL)
       {
diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
index 9684922d1a1..2bfe10a9aea 100644
--- a/gdbserver/linux-low.cc
+++ b/gdbserver/linux-low.cc
@@ -497,7 +497,6 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp,
   struct process_info *child_proc;
   struct lwp_info *child_lwp;
   struct thread_info *child_thr;
-  struct target_desc *tdesc;
 
   ptid = ptid_t (new_pid, new_pid, 0);
 
@@ -553,9 +552,9 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp,
 
   clone_all_breakpoints (child_thr, event_thr);
 
-  tdesc = allocate_target_description ();
-  copy_target_description (tdesc, parent_proc->tdesc);
-  child_proc->tdesc = tdesc;
+  target_desc_up tdesc = allocate_target_description ();
+  copy_target_description (tdesc.get (), parent_proc->tdesc);
+  child_proc->tdesc = tdesc.release ();
 
   /* Clone arch-specific process data.  */
   low_new_fork (parent_proc, child_proc);
diff --git a/gdbserver/linux-riscv-low.cc b/gdbserver/linux-riscv-low.cc
index 1c6e8c44dd9..32f191ea851 100644
--- a/gdbserver/linux-riscv-low.cc
+++ b/gdbserver/linux-riscv-low.cc
@@ -88,11 +88,11 @@ riscv_target::low_arch_setup ()
 
   const riscv_gdbarch_features features
     = riscv_linux_read_features (lwpid_of (current_thread));
-  target_desc *tdesc = riscv_create_target_description (features);
+  target_desc_up tdesc = riscv_create_target_description (features);
 
   if (!tdesc->expedite_regs)
-    init_target_desc (tdesc, expedite_regs);
-  current_process ()->tdesc = tdesc;
+    init_target_desc (tdesc.get (), expedite_regs);
+  current_process ()->tdesc = tdesc.release ();
 }
 
 /* Collect GPRs from REGCACHE into BUF.  */
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index 37d3626e1f7..a10b00c3b28 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -48,9 +48,9 @@
 #include "linux-x86-tdesc.h"
 
 #ifdef __x86_64__
-static struct target_desc *tdesc_amd64_linux_no_xml;
+static target_desc_up tdesc_amd64_linux_no_xml;
 #endif
-static struct target_desc *tdesc_i386_linux_no_xml;
+static target_desc_up tdesc_i386_linux_no_xml;
 
 
 static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 };
@@ -899,10 +899,10 @@ x86_linux_read_description (void)
       /* Don't use XML.  */
 #ifdef __x86_64__
       if (machine == EM_X86_64)
- return tdesc_amd64_linux_no_xml;
+ return tdesc_amd64_linux_no_xml.get ();
       else
 #endif
- return tdesc_i386_linux_no_xml;
+ return tdesc_i386_linux_no_xml.get ();
     }
 
   if (have_ptrace_getregset == -1)
@@ -2955,7 +2955,7 @@ x86_target::get_ipa_tdesc_idx ()
   return amd64_get_ipa_tdesc_idx (tdesc);
 #endif
 
-  if (tdesc == tdesc_i386_linux_no_xml)
+  if (tdesc == tdesc_i386_linux_no_xml.get ())
     return X86_TDESC_SSE;
 
   return i386_get_ipa_tdesc_idx (tdesc);
@@ -2971,14 +2971,14 @@ initialize_low_arch (void)
   /* Initialize the Linux target descriptions.  */
 #ifdef __x86_64__
   tdesc_amd64_linux_no_xml = allocate_target_description ();
-  copy_target_description (tdesc_amd64_linux_no_xml,
+  copy_target_description (tdesc_amd64_linux_no_xml.get (),
    amd64_linux_read_description (X86_XSTATE_SSE_MASK,
  false));
   tdesc_amd64_linux_no_xml->xmltarget = xmltarget_amd64_linux_no_xml;
 #endif
 
   tdesc_i386_linux_no_xml = allocate_target_description ();
-  copy_target_description (tdesc_i386_linux_no_xml,
+  copy_target_description (tdesc_i386_linux_no_xml.get (),
    i386_linux_read_description (X86_XSTATE_SSE_MASK));
   tdesc_i386_linux_no_xml->xmltarget = xmltarget_i386_linux_no_xml;
 
diff --git a/gdbserver/tdesc.cc b/gdbserver/tdesc.cc
index e639017cc31..b7e6057ccbe 100644
--- a/gdbserver/tdesc.cc
+++ b/gdbserver/tdesc.cc
@@ -95,10 +95,10 @@ init_target_desc (struct target_desc *tdesc,
 
 /* See gdbsupport/tdesc.h.  */
 
-struct target_desc *
+target_desc_up
 allocate_target_description (void)
 {
-  return new target_desc ();
+  return target_desc_up (new target_desc ());
 }
 
 /* See gdbsupport/tdesc.h.  */
diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
index fdc2a6a3708..a456f19a641 100644
--- a/gdbsupport/tdesc.h
+++ b/gdbsupport/tdesc.h
@@ -327,7 +327,7 @@ struct target_desc_deleter
 typedef std::unique_ptr<target_desc, target_desc_deleter> target_desc_up;
 
 /* Allocate a new target_desc.  */
-target_desc *allocate_target_description (void);
+target_desc_up allocate_target_description (void);
 
 /* Set TARGET_DESC's architecture by NAME.  */
 void set_tdesc_architecture (target_desc *target_desc,
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] gdb/riscv: delete target descriptions when gdb exits

Simon Marchi-4
On 2020-07-21 9:19 a.m., Andrew Burgess wrote:

> * Simon Marchi <[hidden email]> [2020-07-17 12:20:44 -0400]:
>
>> On 2020-07-17 10:58 a.m., Andrew Burgess wrote:
>>> I've started working through this, but it's pretty big change.  Having
>>> allocate_target_description return a target_desc_up and then having
>>> every caller immediately call .release () is not _too_ painful, but
>>> seems rather pointless.
>>
>> I don't think it's pointless, it's a small step in the right direction.  Ideally,
>> the whole chain would use unique pointers when returning a newly allocated tdesc
>> and transferring ownership, and it is one step towards that.
>
> OK then.
>
> Below is a patch to make allocate_target_description return a
> target_desc_up, in almost all cases this unique_ptr is then released.
> The RISC-V code doesn't do this, and I also updated a case in
> gdbserver to hold global target_desc_up objects rather than the raw
> pointers.
>
> There's lots of churn due to regenerating everything under
> gdb/features/*, but it is all auto-generated, review one file, and
> you've reviewed 'em all.
>
> Thoughts / feedback welcome.
>
> Thanks,
> Andrew

Awesome, thanks.  We can then have small cleanup patches here and there that
propagate the use of target_desc_up a bit further.  The only thing I noticed
is that the field `current_process ()->tdesc` seems to sometimes contained
an owned target desc, sometimes a borrowed one, so it will be a bit tricky.

Simon