lwp_info: Make the arch code free arch_lwp_info
authorSimon Marchi <simon.marchi@ericsson.com>
Thu, 12 Oct 2017 20:48:22 +0000 (16:48 -0400)
committerSimon Marchi <simon.marchi@ericsson.com>
Thu, 12 Oct 2017 20:48:22 +0000 (16:48 -0400)
I have the goal of "poisoning" the XNEW/xfree-family of functions, so
that we catch their usages with non-POD types.  A few things need to be
fixed in the mean time, this is one.

The common lwp code in linux-nat.c and gdbserver/linux-low.c xfrees the
private lwp data of type arch_lwp_info.  However, that type is opaque
from its point of view, as its defined differently in each arch-specific
implementation.  This trips on the std::is_pod<T> check, since the
compiler can't tell whether the type is POD or not if it doesn't know
about it.

My initial patch [1] made a class hierarchy with a virtual destructor.
However, as Pedro pointed out, we only have one native architecture at
the time built in gdb and gdbserver, so that's overkill.  Instead, we
can move the responsibility of free'ing arch_lwp_info to the arch code
(which is also the one that allocated it in the first place).  This is
what this patch does.

Also, I had the concern that if we wanted to use C++ features in these
structures, we would have a problem with the one-definition rule.
However, since a build will only have one version of arch_lwp_info,
that's not a problem.

There are changes in arch-specific files, I was only able to built-test
this patch with the following cross-compilers:

  aarch64-linux-gnu
  alpha-linux-gnu
  arm-linux-gnueabihf
  hppa-linux-gnu
  m68k-linux-gnu
  mips64el-linux-gnuabi64
  powerpc64-linux-gnu
  s390x-linux-gnu
  sh4-linux-gnu
  sparc64-linux-gnu
  x86_64-linux-gnu
  x86_64-w64-mingw32

A buildbot run didn't find any regression.

[1] https://sourceware.org/ml/gdb-patches/2017-08/msg00255.html

gdb/ChangeLog:

* linux-nat.h (linux_nat_set_delete_thread): New declaration.
* linux-nat.c (linux_nat_delete_thread): New variable.
(lwp_free): Invoke linux_nat_delete_thread if set.
(linux_nat_set_delete_thread): New function.
* aarch64-linux-nat.c (_initialize_aarch64_linux_nat): Assign
thread delete callback.
* arm-linux-nat.c (arm_linux_delete_thread): New function.
(_initialize_arm_linux_nat): Assign thread delete callback.
* s390-linux-nat.c (s390_delete_thread): New function.
(_initialize_s390_nat): Assign thread delete callback.
* x86-linux-nat.c (x86_linux_add_target): Likewise.
* nat/aarch64-linux.c (aarch64_linux_delete_thread): New
function.
* nat/aarch64-linux.h (aarch64_linux_delete_thread): New
declaration.
* nat/x86-linux.c (x86_linux_delete_thread): New function.
* nat/x86-linux.h (x86_linux_delete_thread): New declaration.

gdb/gdbserver/ChangeLog:

* linux-aarch64-low.c (the_low_target): Add thread delete
callback.
* linux-arm-low.c (arm_delete_thread): New function.
(the_low_target): Add thread delete callback.
* linux-bfin-low.c (the_low_target): Likewise.
* linux-crisv32-low.c (the_low_target): Likewise.
* linux-low.c (delete_lwp): Invoke delete_thread callback if
set.
* linux-low.h (struct linux_target_ops) <delete_thread>: New
field.
* linux-m32r-low.c (the_low_target): Add thread delete callback.
* linux-mips-low.c (mips_linux_delete_thread): New function.
(the_low_target): Add thread delete callback.
* linux-ppc-low.c (the_low_target): Likewise.
* linux-s390-low.c (the_low_target): Likewise.
* linux-sh-low.c (the_low_target): Likewise.
* linux-tic6x-low.c (the_low_target): Likewise.
* linux-tile-low.c (the_low_target): Likewise.
* linux-x86-low.c (the_low_target): Likewise.
* linux-xtensa-low.c (the_low_target): Likewise.

27 files changed:
gdb/ChangeLog
gdb/aarch64-linux-nat.c
gdb/arm-linux-nat.c
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-aarch64-low.c
gdb/gdbserver/linux-arm-low.c
gdb/gdbserver/linux-bfin-low.c
gdb/gdbserver/linux-crisv32-low.c
gdb/gdbserver/linux-low.c
gdb/gdbserver/linux-low.h
gdb/gdbserver/linux-m32r-low.c
gdb/gdbserver/linux-mips-low.c
gdb/gdbserver/linux-ppc-low.c
gdb/gdbserver/linux-s390-low.c
gdb/gdbserver/linux-sh-low.c
gdb/gdbserver/linux-tic6x-low.c
gdb/gdbserver/linux-tile-low.c
gdb/gdbserver/linux-x86-low.c
gdb/gdbserver/linux-xtensa-low.c
gdb/linux-nat.c
gdb/linux-nat.h
gdb/nat/aarch64-linux.c
gdb/nat/aarch64-linux.h
gdb/nat/x86-linux.c
gdb/nat/x86-linux.h
gdb/s390-linux-nat.c
gdb/x86-linux-nat.c

index 532c2b996317127e0ee5b12c1d3786d257bea0f7..2126c335c425048d2d8ea09aa3b3ef7ee1db8fb6 100644 (file)
@@ -1,3 +1,23 @@
+2017-10-12  Simon Marchi  <simon.marchi@ericsson.com>
+
+       * linux-nat.h (linux_nat_set_delete_thread): New declaration.
+       * linux-nat.c (linux_nat_delete_thread): New variable.
+       (lwp_free): Invoke linux_nat_delete_thread if set.
+       (linux_nat_set_delete_thread): New function.
+       * aarch64-linux-nat.c (_initialize_aarch64_linux_nat): Assign
+       thread delete callback.
+       * arm-linux-nat.c (arm_linux_delete_thread): New function.
+       (_initialize_arm_linux_nat): Assign thread delete callback.
+       * s390-linux-nat.c (s390_delete_thread): New function.
+       (_initialize_s390_nat): Assign thread delete callback.
+       * x86-linux-nat.c (x86_linux_add_target): Likewise.
+       * nat/aarch64-linux.c (aarch64_linux_delete_thread): New
+       function.
+       * nat/aarch64-linux.h (aarch64_linux_delete_thread): New
+       declaration.
+       * nat/x86-linux.c (x86_linux_delete_thread): New function.
+       * nat/x86-linux.h (x86_linux_delete_thread): New declaration.
+
 2017-10-09  Tom Tromey  <tom@tromey.com>
 
        * tui/tui-win.c (tui_set_win_height, parse_scrolling_args): Use
index 6ad6f663bfeaac2b38425a8a5791e0c312cf8aac..4feaec39d910485d66cdb87a3615eee8a0c112e4 100644 (file)
@@ -837,6 +837,7 @@ _initialize_aarch64_linux_nat (void)
   /* Register the target.  */
   linux_nat_add_target (t);
   linux_nat_set_new_thread (t, aarch64_linux_new_thread);
+  linux_nat_set_delete_thread (t, aarch64_linux_delete_thread);
   linux_nat_set_new_fork (t, aarch64_linux_new_fork);
   linux_nat_set_forget_process (t, aarch64_forget_process);
   linux_nat_set_prepare_to_resume (t, aarch64_linux_prepare_to_resume);
index fc66063ce50dc9ab98cd3704d3efe2665d0d6238..8b25ff7f9482c9eef6b84c492b0c16dc0ff46618 100644 (file)
@@ -1202,6 +1202,14 @@ arm_linux_new_thread (struct lwp_info *lp)
   lp->arch_private = info;
 }
 
+/* Function to call when a thread is being deleted.  */
+
+static void
+arm_linux_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
 /* Called when resuming a thread.
    The hardware debug registers are updated when there is any change.  */
 
@@ -1313,6 +1321,7 @@ _initialize_arm_linux_nat (void)
 
   /* Handle thread creation and exit.  */
   linux_nat_set_new_thread (t, arm_linux_new_thread);
+  linux_nat_set_delete_thread (t, arm_linux_delete_thread);
   linux_nat_set_prepare_to_resume (t, arm_linux_prepare_to_resume);
 
   /* Handle process creation and exit.  */
index 5bcd717afe76a7e0c3bab905f77ab3f0b7ad57bf..1edb8495fd5928f1314bc7c9109eb65ef2751b0b 100644 (file)
@@ -1,3 +1,26 @@
+2017-10-12  Simon Marchi  <simon.marchi@ericsson.com>
+
+       * linux-aarch64-low.c (the_low_target): Add thread delete
+       callback.
+       * linux-arm-low.c (arm_delete_thread): New function.
+       (the_low_target): Add thread delete callback.
+       * linux-bfin-low.c (the_low_target): Likewise.
+       * linux-crisv32-low.c (the_low_target): Likewise.
+       * linux-low.c (delete_lwp): Invoke delete_thread callback if
+       set.
+       * linux-low.h (struct linux_target_ops) <delete_thread>: New
+       field.
+       * linux-m32r-low.c (the_low_target): Add thread delete callback.
+       * linux-mips-low.c (mips_linux_delete_thread): New function.
+       (the_low_target): Add thread delete callback.
+       * linux-ppc-low.c (the_low_target): Likewise.
+       * linux-s390-low.c (the_low_target): Likewise.
+       * linux-sh-low.c (the_low_target): Likewise.
+       * linux-tic6x-low.c (the_low_target): Likewise.
+       * linux-tile-low.c (the_low_target): Likewise.
+       * linux-x86-low.c (the_low_target): Likewise.
+       * linux-xtensa-low.c (the_low_target): Likewise.
+
 2017-10-06  Yuanhui Zhang  <asmwarrior@gmail.com>
 
        * win32-low.c: Include "common-inferior.h".
index 334310be579e7365c54492ec371db3e45d9a883f..ed6a9931d2e24948abe6a0cb8004623eaab82e4b 100644 (file)
@@ -2991,6 +2991,7 @@ struct linux_target_ops the_low_target =
   aarch64_linux_siginfo_fixup,
   aarch64_linux_new_process,
   aarch64_linux_new_thread,
+  aarch64_linux_delete_thread,
   aarch64_linux_new_fork,
   aarch64_linux_prepare_to_resume,
   NULL, /* process_qsupported */
index 5a3f465dee1c4fb75d30a107f368a5cc4b80a777..b27c47e84c4ffe15a4ebba517f78688baca2e4ec 100644 (file)
@@ -655,6 +655,14 @@ arm_new_thread (struct lwp_info *lwp)
   lwp->arch_private = info;
 }
 
+/* Function to call when a thread is being deleted.  */
+
+static void
+arm_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
 static void
 arm_new_fork (struct process_info *parent, struct process_info *child)
 {
@@ -1053,6 +1061,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   arm_new_process,
   arm_new_thread,
+  arm_delete_thread,
   arm_new_fork,
   arm_prepare_to_resume,
   NULL, /* process_qsupported */
index d43b05dd37e06e02b9a4004405fbcf2b48fbb918..175152c4598cf69258a1b13fcae4ec55b44761f0 100644 (file)
@@ -136,6 +136,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index 5b3888ea3646e72878b289685953a70a09334105..79111048faeab75aa5c05b802540df166753f7c2 100644 (file)
@@ -416,6 +416,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index 54005c1f1d46dd243119c6a96f0643233716c10a..a762b8f0818c09ffa79e51b8fcae57f5857abff9 100644 (file)
@@ -414,7 +414,12 @@ delete_lwp (struct lwp_info *lwp)
     debug_printf ("deleting %ld\n", lwpid_of (thr));
 
   remove_thread (thr);
-  free (lwp->arch_private);
+
+  if (the_low_target.delete_thread != NULL)
+    the_low_target.delete_thread (lwp->arch_private);
+  else
+    gdb_assert (lwp->arch_private == NULL);
+
   free (lwp);
 }
 
index 0ece7bc25bfedc4374c7121cd28b52215ec7b6df..9c69dece96d5515b002c4907da01b94f0ea52324 100644 (file)
@@ -194,6 +194,10 @@ struct linux_target_ops
      allocate it here.  */
   void (*new_thread) (struct lwp_info *);
 
+  /* Hook to call when a thread is being deleted.  If extra per-thread
+     architecture-specific data is needed, delete it here.  */
+  void (*delete_thread) (struct arch_lwp_info *);
+
   /* Hook to call, if any, when a new fork is attached.  */
   void (*new_fork) (struct process_info *parent, struct process_info *child);
 
index b3ee11ac109bf5a9581ec959032f75e946636fe2..b947fa065857d811c1519a2ba438c86a84f96a56 100644 (file)
@@ -135,6 +135,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index b4a83b0e21ea94936f55c2b76c8f13266d7d75a0..ec26c2a8c56c91bf8f96636cf790225406193cd3 100644 (file)
@@ -341,6 +341,14 @@ mips_linux_new_thread (struct lwp_info *lwp)
   lwp->arch_private = info;
 }
 
+/* Function to call when a thread is being deleted.  */
+
+static void
+mips_linux_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
 /* Create a new mips_watchpoint and add it to the list.  */
 
 static void
@@ -893,6 +901,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   mips_linux_new_process,
   mips_linux_new_thread,
+  mips_linux_delete_thread,
   mips_linux_new_fork,
   mips_linux_prepare_to_resume
 };
index 33a9feb12c617b90cfa28a90f9f3055d4af978e4..f31a47b5f198d48f394019c7d8fc6959ab757e31 100644 (file)
@@ -3125,6 +3125,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index d7aa31c319a537795af878f2bb08642ce0e1f047..1a4c3407fbc0f989202ecc733d345b3f556863a2 100644 (file)
@@ -2830,6 +2830,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index ac084c994fa0279742eb0a95352494151a2ae9d2..273062faa08a3363cb67e86cacb76f03b41ba550 100644 (file)
@@ -165,6 +165,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index 8931d699a040f06422e2b80ff4bdeb64f9891971..8b2a6f35ca8ea85200bd5dec407aa357b8798c98 100644 (file)
@@ -398,6 +398,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index ee1f1968364b53363886a97f3feb8df1ef707586..c5b344bd631df8091ecd3e97d7d75bc46caeaf89 100644 (file)
@@ -197,6 +197,7 @@ struct linux_target_ops the_low_target =
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index 49f6b2d4892eef731c9afebb5982f21f181db09f..9597502dfcade503f5cfcae11082bbe84cebaa8a 100644 (file)
@@ -2867,6 +2867,7 @@ struct linux_target_ops the_low_target =
   x86_siginfo_fixup,
   x86_linux_new_process,
   x86_linux_new_thread,
+  x86_linux_delete_thread,
   x86_linux_new_fork,
   x86_linux_prepare_to_resume,
   x86_linux_process_qsupported,
index 214abdc938b39f5ddabcd47e7c62aab71525b2c8..5f2566cc0b0c81bb39cc17354fd54feb12167f61 100644 (file)
@@ -289,6 +289,7 @@ struct linux_target_ops the_low_target = {
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
index 60804159f1aad18c16b7ffbcfd941b50a5cde62d..c89303c161f36075feaaee877d2715f27af87f0b 100644 (file)
@@ -197,6 +197,9 @@ static struct target_ops linux_ops_saved;
 /* The method to call, if any, when a new thread is attached.  */
 static void (*linux_nat_new_thread) (struct lwp_info *);
 
+/* The method to call, if any, when a thread is destroyed.  */
+static void (*linux_nat_delete_thread) (struct arch_lwp_info *);
+
 /* The method to call, if any, when a new fork is attached.  */
 static linux_nat_new_fork_ftype *linux_nat_new_fork;
 
@@ -839,7 +842,12 @@ static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp);
 static void
 lwp_free (struct lwp_info *lp)
 {
-  xfree (lp->arch_private);
+  /* Let the arch specific bits release arch_lwp_info.  */
+  if (linux_nat_delete_thread != NULL)
+    linux_nat_delete_thread (lp->arch_private);
+  else
+    gdb_assert (lp->arch_private == NULL);
+
   xfree (lp);
 }
 
@@ -4873,6 +4881,17 @@ linux_nat_set_new_thread (struct target_ops *t,
   linux_nat_new_thread = new_thread;
 }
 
+/* Register a method to call whenever a new thread is attached.  */
+void
+linux_nat_set_delete_thread (struct target_ops *t,
+                            void (*delete_thread) (struct arch_lwp_info *))
+{
+  /* Save the pointer.  We only support a single registered instance
+     of the GNU/Linux native target, so we do not need to map this to
+     T.  */
+  linux_nat_delete_thread = delete_thread;
+}
+
 /* See declaration in linux-nat.h.  */
 
 void
index 3378bd6401772428c72071bef35cb2c5ab5372ba..c00267959d15c0a80696b56be02dd78d1481960d 100644 (file)
@@ -165,6 +165,9 @@ void linux_nat_add_target (struct target_ops *);
 /* Register a method to call whenever a new thread is attached.  */
 void linux_nat_set_new_thread (struct target_ops *, void (*) (struct lwp_info *));
 
+/* Register a method to call whenever a new thread is deleted.  */
+void linux_nat_set_delete_thread (struct target_ops *,
+                                 void (*) (struct arch_lwp_info *));
 
 /* Register a method to call whenever a new fork is attached.  */
 typedef void (linux_nat_new_fork_ftype) (struct lwp_info *parent,
index 388eee8a6e43f00472c9f6d4b9d41c212d8415c9..d7abee8824bf4f015f04051c9c6bf1832f52cf2f 100644 (file)
@@ -84,6 +84,14 @@ aarch64_linux_new_thread (struct lwp_info *lwp)
   lwp_set_arch_private_info (lwp, info);
 }
 
+/* See nat/aarch64-linux.h.  */
+
+void
+aarch64_linux_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
 /* Convert native siginfo FROM to the siginfo in the layout of the
    inferior's architecture TO.  */
 
index 191e1c62ba56b8917523aa0628911cc48485687f..db98df4725f6d994c3e74e2e43a8831868be7b0a 100644 (file)
@@ -122,6 +122,9 @@ void aarch64_linux_prepare_to_resume (struct lwp_info *lwp);
 
 void aarch64_linux_new_thread (struct lwp_info *lwp);
 
+/* Function to call when a thread is being deleted.  */
+void aarch64_linux_delete_thread (struct arch_lwp_info *arch_lwp);
+
 ps_err_e aarch64_ps_get_thread_area (struct ps_prochandle *ph,
                                       lwpid_t lwpid, int idx, void **base,
                                       int is_64bit_p);
index b499e74e3ff30952ab851f39885b0dde6f022e46..fc68106fe489a0eaf791bb556618c11d9633fe8d 100644 (file)
@@ -67,6 +67,14 @@ x86_linux_new_thread (struct lwp_info *lwp)
 
 /* See nat/x86-linux.h.  */
 
+void
+x86_linux_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
+/* See nat/x86-linux.h.  */
+
 void
 x86_linux_prepare_to_resume (struct lwp_info *lwp)
 {
index 1b7fee4263ab5c97e8dd43b1981488afe1bfe882..493c722d7f83785b75f2e7b14e5961de39dcfbc5 100644 (file)
@@ -39,6 +39,10 @@ extern int lwp_debug_registers_changed (struct lwp_info *lwp);
 
 extern void x86_linux_new_thread (struct lwp_info *lwp);
 
+/* Function to call when a thread is being deleted.  */
+
+extern void x86_linux_delete_thread (struct arch_lwp_info *arch_lwp);
+
 /* Function to call prior to resuming a thread.  */
 
 extern void x86_linux_prepare_to_resume (struct lwp_info *lwp);
index 4d1b8b54ae5d25c0e2ec0fbd71df12a8c580547c..88ae5750908734acee43ebd0d5404b41bfb9d5a4 100644 (file)
@@ -789,6 +789,14 @@ s390_new_thread (struct lwp_info *lp)
   s390_mark_per_info_changed (lp);
 }
 
+/* Function to call when a thread is being deleted.  */
+
+static void
+s390_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
 /* Iterator callback for s390_refresh_per_info.  */
 
 static int
@@ -1050,6 +1058,7 @@ _initialize_s390_nat (void)
   /* Register the target.  */
   linux_nat_add_target (t);
   linux_nat_set_new_thread (t, s390_new_thread);
+  linux_nat_set_delete_thread (t, s390_delete_thread);
   linux_nat_set_prepare_to_resume (t, s390_prepare_to_resume);
   linux_nat_set_forget_process (t, s390_forget_process);
   linux_nat_set_new_fork (t, s390_linux_new_fork);
index 46115270581e580aeb2a9fb662fb366798d8beb9..ce56c2e65219164d97c676282fe29a8e8aefea79 100644 (file)
@@ -354,6 +354,7 @@ x86_linux_add_target (struct target_ops *t)
 {
   linux_nat_add_target (t);
   linux_nat_set_new_thread (t, x86_linux_new_thread);
+  linux_nat_set_delete_thread (t, x86_linux_delete_thread);
   linux_nat_set_new_fork (t, x86_linux_new_fork);
   linux_nat_set_forget_process (t, x86_forget_process);
   linux_nat_set_prepare_to_resume (t, x86_linux_prepare_to_resume);