gdb: revert "gdb: unify parts of the Linux and FreeBSD core dumping code"
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 9 Feb 2021 21:41:30 +0000 (21:41 +0000)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 9 Feb 2021 21:46:12 +0000 (21:46 +0000)
This reverts commit 82a1fd3a4935fe665cf08bc6820942c4a091184c.

It was pointed out:

  https://sourceware.org/pipermail/gdb-patches/2021-February/175750.html

that commit 82a1fd3a4935 caused GDB to have an unconditional
dependency on ELF specific parts of BFD.  What this means is that if
GDB and BFD are built for a non-elf target then there will be
undefined symbol references within GDB.

The right solution isn't immediately obvious.  So rather than rush a
fix in I'm reverting this commit for now, and will bring it back once
I have a good solution.

gdb/ChangeLog:

* gcore.c (struct gcore_collect_regset_section_cb_data): Delete.
(gcore_collect_regset_section_cb): Delete.
(gcore_collect_thread_registers): Delete.
(gcore_build_thread_register_notes): Delete.
(gcore_find_signalled_thread): Delete.
* gcore.h: Remove 'gdbsupport/gdb_signals.h' include and delete
'gdbarch' and 'thread_info' declarations.
(gcore_build_thread_register_notes): Delete declaration.
(gcore_find_signalled_thread): Likewise.
* fbsd-tdep.c: Remove 'gcore.h' include.
(struct fbsd_collect_regset_section_cb_data): New struct.
(fbsd_collect_regset_section_cb): New function.
(fbsd_collect_thread_registers): New function.
(struct fbsd_corefile_thread_data): New struct.
(fbsd_corefile_thread): New function.
(fbsd_make_corefile_notes): Call FreeBSD specific code.
* linux-tdep.c: Remove 'gcore.h' include.
(struct linux_collect_regset_section_cb_data): New struct.
(linux_collect_regset_section_cb): New function.
(linux_collect_thread_registers): New function.
(linux_corefile_thread): Call Linux specific code.
(find_signalled_thread): New function.
(linux_make_corefile_notes): Call find_signalled_thread.

gdb/ChangeLog
gdb/fbsd-tdep.c
gdb/gcore.c
gdb/gcore.h
gdb/linux-tdep.c

index 5c66f99e8178ab7b87ae17f04d72b7cfc0a8e7e6..220ef2a52a4e7fc272a3d5b0ad29d14ddd727747 100644 (file)
@@ -1,3 +1,29 @@
+2021-02-09  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gcore.c (struct gcore_collect_regset_section_cb_data): Delete.
+       (gcore_collect_regset_section_cb): Delete.
+       (gcore_collect_thread_registers): Delete.
+       (gcore_build_thread_register_notes): Delete.
+       (gcore_find_signalled_thread): Delete.
+       * gcore.h: Remove 'gdbsupport/gdb_signals.h' include and delete
+       'gdbarch' and 'thread_info' declarations.
+       (gcore_build_thread_register_notes): Delete declaration.
+       (gcore_find_signalled_thread): Likewise.
+       * fbsd-tdep.c: Remove 'gcore.h' include.
+       (struct fbsd_collect_regset_section_cb_data): New struct.
+       (fbsd_collect_regset_section_cb): New function.
+       (fbsd_collect_thread_registers): New function.
+       (struct fbsd_corefile_thread_data): New struct.
+       (fbsd_corefile_thread): New function.
+       (fbsd_make_corefile_notes): Call FreeBSD specific code.
+       * linux-tdep.c: Remove 'gcore.h' include.
+       (struct linux_collect_regset_section_cb_data): New struct.
+       (linux_collect_regset_section_cb): New function.
+       (linux_collect_thread_registers): New function.
+       (linux_corefile_thread): Call Linux specific code.
+       (find_signalled_thread): New function.
+       (linux_make_corefile_notes): Call find_signalled_thread.
+
 2021-02-09  Tom Tromey  <tromey@adacore.com>
 
        * ada-lang.c (coerce_unspec_val_to_type): Avoid making lazy
index edd3edc422093feb063936c7122b995c3922e120..cc51e921ae2f5d4bc9d129c8877fe25e39f52fb1 100644 (file)
@@ -32,7 +32,6 @@
 
 #include "elf-bfd.h"
 #include "fbsd-tdep.h"
-#include "gcore.h"
 
 /* This enum is derived from FreeBSD's <sys/signal.h>.  */
 
@@ -584,6 +583,129 @@ find_signalled_thread (struct thread_info *info, void *data)
   return 0;
 }
 
+/* Structure for passing information from
+   fbsd_collect_thread_registers via an iterator to
+   fbsd_collect_regset_section_cb. */
+
+struct fbsd_collect_regset_section_cb_data
+{
+  fbsd_collect_regset_section_cb_data (const struct regcache *regcache,
+                                      bfd *obfd,
+                                      gdb::unique_xmalloc_ptr<char> &note_data,
+                                      int *note_size,
+                                      unsigned long lwp,
+                                      gdb_signal stop_signal)
+    : regcache (regcache),
+      obfd (obfd),
+      note_data (note_data),
+      note_size (note_size),
+      lwp (lwp),
+      stop_signal (stop_signal)
+  {}
+
+  const struct regcache *regcache;
+  bfd *obfd;
+  gdb::unique_xmalloc_ptr<char> &note_data;
+  int *note_size;
+  unsigned long lwp;
+  enum gdb_signal stop_signal;
+  bool abort_iteration = false;
+};
+
+static void
+fbsd_collect_regset_section_cb (const char *sect_name, int supply_size,
+                               int collect_size, const struct regset *regset,
+                               const char *human_name, void *cb_data)
+{
+  char *buf;
+  struct fbsd_collect_regset_section_cb_data *data
+    = (struct fbsd_collect_regset_section_cb_data *) cb_data;
+
+  if (data->abort_iteration)
+    return;
+
+  gdb_assert (regset->collect_regset);
+
+  buf = (char *) xmalloc (collect_size);
+  regset->collect_regset (regset, data->regcache, -1, buf, collect_size);
+
+  /* PRSTATUS still needs to be treated specially.  */
+  if (strcmp (sect_name, ".reg") == 0)
+    data->note_data.reset (elfcore_write_prstatus
+                            (data->obfd, data->note_data.release (),
+                             data->note_size, data->lwp,
+                             gdb_signal_to_host (data->stop_signal),
+                             buf));
+  else
+    data->note_data.reset (elfcore_write_register_note
+                            (data->obfd, data->note_data.release (),
+                             data->note_size, sect_name, buf,
+                             collect_size));
+  xfree (buf);
+
+  if (data->note_data == NULL)
+    data->abort_iteration = true;
+}
+
+/* Records the thread's register state for the corefile note
+   section.  */
+
+static void
+fbsd_collect_thread_registers (const struct regcache *regcache,
+                              ptid_t ptid, bfd *obfd,
+                              gdb::unique_xmalloc_ptr<char> &note_data,
+                              int *note_size,
+                              enum gdb_signal stop_signal)
+{
+  fbsd_collect_regset_section_cb_data data (regcache, obfd, note_data,
+                                           note_size, ptid.lwp (),
+                                           stop_signal);
+
+  gdbarch_iterate_over_regset_sections (regcache->arch (),
+                                       fbsd_collect_regset_section_cb,
+                                       &data, regcache);
+}
+
+struct fbsd_corefile_thread_data
+{
+  fbsd_corefile_thread_data (struct gdbarch *gdbarch,
+                            bfd *obfd,
+                            gdb::unique_xmalloc_ptr<char> &note_data,
+                            int *note_size,
+                            gdb_signal stop_signal)
+    : gdbarch (gdbarch),
+      obfd (obfd),
+      note_data (note_data),
+      note_size (note_size),
+      stop_signal (stop_signal)
+  {}
+
+  struct gdbarch *gdbarch;
+  bfd *obfd;
+  gdb::unique_xmalloc_ptr<char> &note_data;
+  int *note_size;
+  enum gdb_signal stop_signal;
+};
+
+/* Records the thread's register state for the corefile note
+   section.  */
+
+static void
+fbsd_corefile_thread (struct thread_info *info,
+                     struct fbsd_corefile_thread_data *args)
+{
+  struct regcache *regcache;
+
+  regcache = get_thread_arch_regcache (info->inf->process_target (),
+                                      info->ptid, args->gdbarch);
+
+  target_fetch_registers (regcache, -1);
+
+  fbsd_collect_thread_registers (regcache, info->ptid, args->obfd,
+                                args->note_data, args->note_size,
+                                args->stop_signal);
+}
+
 /* Return a byte_vector containing the contents of a core dump note
    for the target object of type OBJECT.  If STRUCTSIZE is non-zero,
    the data is prefixed with a 32-bit integer size to match the format
@@ -660,17 +782,16 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
        signalled_thr = curr_thr;
     }
 
-  gcore_build_thread_register_notes (gdbarch, signalled_thr,
-                                    signalled_thr->suspend.stop_signal,
-                                    obfd, &note_data, note_size);
+  fbsd_corefile_thread_data thread_args (gdbarch, obfd, note_data, note_size,
+                                        signalled_thr->suspend.stop_signal);
+
+  fbsd_corefile_thread (signalled_thr, &thread_args);
   for (thread_info *thr : current_inferior ()->non_exited_threads ())
     {
       if (thr == signalled_thr)
        continue;
 
-      gcore_build_thread_register_notes (gdbarch, thr,
-                                        signalled_thr->suspend.stop_signal,
-                                        obfd, &note_data, note_size);
+      fbsd_corefile_thread (thr, &thread_args);
     }
 
   /* Auxiliary vector.  */
index d62aa3a710972ed438fc7012a6d80a63b8b61bdc..73ac6b09c7028fd219035f97056f7d51f9ff4b6f 100644 (file)
@@ -579,142 +579,6 @@ gcore_memory_sections (bfd *obfd)
   return 1;
 }
 
-/* Structure for passing information from GCORE_COLLECT_THREAD_REGISTERS
-   via an iterator to GCORE_COLLECT_REGSET_SECTION_CB. */
-
-struct gcore_collect_regset_section_cb_data
-{
-  gcore_collect_regset_section_cb_data (struct gdbarch *gdbarch,
-                                       const struct regcache *regcache,
-                                       bfd *obfd, ptid_t ptid,
-                                       gdb_signal stop_signal,
-                                       gdb::unique_xmalloc_ptr<char> *note_data,
-                                       int *note_size)
-
-    : gdbarch (gdbarch), regcache (regcache), obfd (obfd),
-      note_data (note_data), note_size (note_size),
-      stop_signal (stop_signal)
-  {
-    /* The LWP is often not available for bare metal target, in which case
-       use the tid instead.  */
-    if (ptid.lwp_p ())
-      lwp = ptid.lwp ();
-    else
-      lwp = ptid.tid ();
-  }
-
-  struct gdbarch *gdbarch;
-  const struct regcache *regcache;
-  bfd *obfd;
-  gdb::unique_xmalloc_ptr<char> *note_data;
-  int *note_size;
-  unsigned long lwp;
-  enum gdb_signal stop_signal;
-  bool abort_iteration = false;
-};
-
-/* Callback for ITERATE_OVER_REGSET_SECTIONS that records a single
-   regset in the core file note section.  */
-
-static void
-gcore_collect_regset_section_cb (const char *sect_name, int supply_size,
-                                int collect_size,
-                                const struct regset *regset,
-                                const char *human_name, void *cb_data)
-{
-  struct gcore_collect_regset_section_cb_data *data
-    = (struct gcore_collect_regset_section_cb_data *) cb_data;
-  bool variable_size_section = (regset != NULL
-                               && regset->flags & REGSET_VARIABLE_SIZE);
-
-  gdb_assert (variable_size_section || supply_size == collect_size);
-
-  if (data->abort_iteration)
-    return;
-
-  gdb_assert (regset != nullptr && regset->collect_regset != nullptr);
-
-  /* This is intentionally zero-initialized by using std::vector, so
-     that any padding bytes in the core file will show as 0.  */
-  std::vector<gdb_byte> buf (collect_size);
-
-  regset->collect_regset (regset, data->regcache, -1, buf.data (),
-                         collect_size);
-
-  /* PRSTATUS still needs to be treated specially.  */
-  if (strcmp (sect_name, ".reg") == 0)
-    data->note_data->reset (elfcore_write_prstatus
-                           (data->obfd, data->note_data->release (),
-                            data->note_size, data->lwp,
-                            gdb_signal_to_host (data->stop_signal),
-                            buf.data ()));
-  else
-    data->note_data->reset (elfcore_write_register_note
-                           (data->obfd, data->note_data->release (),
-                            data->note_size, sect_name, buf.data (),
-                            collect_size));
-
-  if (data->note_data == nullptr)
-    data->abort_iteration = true;
-}
-
-/* Records the register state of thread PTID out of REGCACHE into the note
-   buffer represented by *NOTE_DATA and NOTE_SIZE.  OBFD is the bfd into
-   which the core file is being created, and STOP_SIGNAL is the signal that
-   cause thread PTID to stop.  */
-
-static void
-gcore_collect_thread_registers (const struct regcache *regcache,
-                               ptid_t ptid, bfd *obfd,
-                               gdb::unique_xmalloc_ptr<char> *note_data,
-                               int *note_size,
-                               enum gdb_signal stop_signal)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  gcore_collect_regset_section_cb_data data (gdbarch, regcache, obfd, ptid,
-                                            stop_signal, note_data,
-                                            note_size);
-  gdbarch_iterate_over_regset_sections (gdbarch,
-                                       gcore_collect_regset_section_cb,
-                                       &data, regcache);
-}
-
-/* See gcore.h.  */
-
-void
-gcore_build_thread_register_notes
-  (struct gdbarch *gdbarch, struct thread_info *info, gdb_signal stop_signal,
-   bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size)
-{
-  struct regcache *regcache
-    = get_thread_arch_regcache (info->inf->process_target (),
-                               info->ptid, gdbarch);
-  target_fetch_registers (regcache, -1);
-  gcore_collect_thread_registers (regcache, info->ptid, obfd, note_data,
-                                 note_size, stop_signal);
-}
-
-/* See gcore.h.  */
-
-thread_info *
-gcore_find_signalled_thread ()
-{
-  thread_info *curr_thr = inferior_thread ();
-  if (curr_thr->state != THREAD_EXITED
-      && curr_thr->suspend.stop_signal != GDB_SIGNAL_0)
-    return curr_thr;
-
-  for (thread_info *thr : current_inferior ()->non_exited_threads ())
-    if (thr->suspend.stop_signal != GDB_SIGNAL_0)
-      return thr;
-
-  /* Default to the current thread, unless it has exited.  */
-  if (curr_thr->state != THREAD_EXITED)
-    return curr_thr;
-
-  return nullptr;
-}
-
 void _initialize_gcore ();
 void
 _initialize_gcore ()
index ce60841c1a55ae338ccfee645ffd0168afb0e786..af37ff39b414d1cf9bfa1930563ecfbd82248c05 100644 (file)
 #define GCORE_H 1
 
 #include "gdb_bfd.h"
-#include "gdbsupport/gdb_signals.h"
-
-struct gdbarch;
-struct thread_info;
 
 extern gdb_bfd_ref_ptr create_gcore_bfd (const char *filename);
 extern void write_gcore_file (bfd *obfd);
@@ -32,20 +28,4 @@ extern int objfile_find_memory_regions (struct target_ops *self,
                                        find_memory_region_ftype func,
                                        void *obfd);
 
-/* Add content to *NOTE_DATA (and update *NOTE_SIZE) to describe the
-   registers of thread INFO.  Report the thread as having stopped with
-   STOP_SIGNAL.  The core file is being written to OFD, and GDBARCH is the
-   architecture for which the core file is being generated.  */
-
-extern void gcore_build_thread_register_notes
-  (struct gdbarch *gdbarch, struct thread_info *info, gdb_signal stop_signal,
-   bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size);
-
-/* Find the signalled thread.  In case there's more than one signalled
-   thread, prefer the current thread, if it is signalled.  If no thread was
-   signalled, default to the current thread, unless it has exited, in which
-   case return NULL.  */
-
-extern thread_info *gcore_find_signalled_thread ();
-
 #endif /* GCORE_H */
index 3db4d31de377a40c07dddd7aef22a971cac6a11d..e9f8e1b61336ad4d4d4492680b0bd1878e9dfe78 100644 (file)
@@ -39,7 +39,6 @@
 #include "gdb_regex.h"
 #include "gdbsupport/enum-flags.h"
 #include "gdbsupport/gdb_optional.h"
-#include "gcore.h"
 
 #include <ctype.h>
 
@@ -1598,6 +1597,104 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
     }
 }
 
+/* Structure for passing information from
+   linux_collect_thread_registers via an iterator to
+   linux_collect_regset_section_cb. */
+
+struct linux_collect_regset_section_cb_data
+{
+  linux_collect_regset_section_cb_data (struct gdbarch *gdbarch,
+                                       const struct regcache *regcache,
+                                       bfd *obfd,
+                                       gdb::unique_xmalloc_ptr<char> &note_data,
+                                       int *note_size,
+                                       unsigned long lwp,
+                                       gdb_signal stop_signal)
+    : gdbarch (gdbarch), regcache (regcache), obfd (obfd),
+      note_data (note_data), note_size (note_size), lwp (lwp),
+      stop_signal (stop_signal)
+  {}
+
+  struct gdbarch *gdbarch;
+  const struct regcache *regcache;
+  bfd *obfd;
+  gdb::unique_xmalloc_ptr<char> &note_data;
+  int *note_size;
+  unsigned long lwp;
+  enum gdb_signal stop_signal;
+  bool abort_iteration = false;
+};
+
+/* Callback for iterate_over_regset_sections that records a single
+   regset in the corefile note section.  */
+
+static void
+linux_collect_regset_section_cb (const char *sect_name, int supply_size,
+                                int collect_size, const struct regset *regset,
+                                const char *human_name, void *cb_data)
+{
+  struct linux_collect_regset_section_cb_data *data
+    = (struct linux_collect_regset_section_cb_data *) cb_data;
+  bool variable_size_section = (regset != NULL
+                               && regset->flags & REGSET_VARIABLE_SIZE);
+
+  if (!variable_size_section)
+    gdb_assert (supply_size == collect_size);
+
+  if (data->abort_iteration)
+    return;
+
+  gdb_assert (regset && regset->collect_regset);
+
+  /* This is intentionally zero-initialized by using std::vector, so
+     that any padding bytes in the core file will show as 0.  */
+  std::vector<gdb_byte> buf (collect_size);
+
+  regset->collect_regset (regset, data->regcache, -1, buf.data (),
+                         collect_size);
+
+  /* PRSTATUS still needs to be treated specially.  */
+  if (strcmp (sect_name, ".reg") == 0)
+    data->note_data.reset (elfcore_write_prstatus
+                            (data->obfd, data->note_data.release (),
+                             data->note_size, data->lwp,
+                             gdb_signal_to_host (data->stop_signal),
+                             buf.data ()));
+  else
+    data->note_data.reset (elfcore_write_register_note
+                          (data->obfd, data->note_data.release (),
+                           data->note_size, sect_name, buf.data (),
+                           collect_size));
+
+  if (data->note_data == NULL)
+    data->abort_iteration = true;
+}
+
+/* Records the thread's register state for the corefile note
+   section.  */
+
+static void
+linux_collect_thread_registers (const struct regcache *regcache,
+                               ptid_t ptid, bfd *obfd,
+                               gdb::unique_xmalloc_ptr<char> &note_data,
+                               int *note_size,
+                               enum gdb_signal stop_signal)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  /* For remote targets the LWP may not be available, so use the TID.  */
+  long lwp = ptid.lwp ();
+  if (lwp == 0)
+    lwp = ptid.tid ();
+
+  linux_collect_regset_section_cb_data data (gdbarch, regcache, obfd, note_data,
+                                            note_size, lwp, stop_signal);
+
+  gdbarch_iterate_over_regset_sections (gdbarch,
+                                       linux_collect_regset_section_cb,
+                                       &data, regcache);
+}
+
 /* Fetch the siginfo data for the specified thread, if it exists.  If
    there is no data, or we could not read it, return an empty
    buffer.  */
@@ -1649,16 +1746,22 @@ static void
 linux_corefile_thread (struct thread_info *info,
                       struct linux_corefile_thread_data *args)
 {
-  gcore_build_thread_register_notes (args->gdbarch, info, args->stop_signal,
-                                    args->obfd, &args->note_data,
-                                    args->note_size);
+  struct regcache *regcache;
+
+  regcache = get_thread_arch_regcache (info->inf->process_target (),
+                                      info->ptid, args->gdbarch);
+
+  target_fetch_registers (regcache, -1);
+  gdb::byte_vector siginfo_data = linux_get_siginfo_data (info, args->gdbarch);
+
+  linux_collect_thread_registers (regcache, info->ptid, args->obfd,
+                                 args->note_data, args->note_size,
+                                 args->stop_signal);
 
   /* Don't return anything if we got no register information above,
      such a core file is useless.  */
   if (args->note_data != NULL)
     {
-      gdb::byte_vector siginfo_data
-       = linux_get_siginfo_data (info, args->gdbarch);
       if (!siginfo_data.empty ())
        args->note_data.reset (elfcore_write_note (args->obfd,
                                                   args->note_data.release (),
@@ -1857,6 +1960,30 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
   return 1;
 }
 
+/* Find the signalled thread.  In case there's more than one signalled
+   thread, prefer the current thread, if it is signalled.  If no
+   thread was signalled, default to the current thread, unless it has
+   exited, in which case return NULL.  */
+
+static thread_info *
+find_signalled_thread ()
+{
+  thread_info *curr_thr = inferior_thread ();
+  if (curr_thr->state != THREAD_EXITED
+      && curr_thr->suspend.stop_signal != GDB_SIGNAL_0)
+    return curr_thr;
+
+  for (thread_info *thr : current_inferior ()->non_exited_threads ())
+    if (thr->suspend.stop_signal != GDB_SIGNAL_0)
+      return thr;
+
+  /* Default to the current thread, unless it has exited.  */
+  if (curr_thr->state != THREAD_EXITED)
+    return curr_thr;
+
+  return nullptr;
+}
+
 /* Build the note section for a corefile, and return it in a malloc
    buffer.  */
 
@@ -1894,7 +2021,7 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
   /* Like the kernel, prefer dumping the signalled thread first.
      "First thread" is what tools use to infer the signalled
      thread.  */
-  thread_info *signalled_thr = gcore_find_signalled_thread ();
+  thread_info *signalled_thr = find_signalled_thread ();
   gdb_signal stop_signal;
   if (signalled_thr != nullptr)
     stop_signal = signalled_thr->suspend.stop_signal;