[gdb/testsuite] Rewrite gdb_test_lines
[deliverable/binutils-gdb.git] / gdb / fbsd-tdep.c
index cc51e921ae2f5d4bc9d129c8877fe25e39f52fb1..5cb6fa31500c4a533e16d76579fa15ca63597513 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "elf-bfd.h"
 #include "fbsd-tdep.h"
+#include "gcore-elf.h"
 
 /* This enum is derived from FreeBSD's <sys/signal.h>.  */
 
@@ -74,6 +75,63 @@ enum
     FREEBSD_SIGRTMAX = 126,
   };
 
+/* Constants for values of si_code as defined in FreeBSD's
+   <sys/signal.h>.  */
+
+#define        FBSD_SI_USER            0x10001
+#define        FBSD_SI_QUEUE           0x10002
+#define        FBSD_SI_TIMER           0x10003
+#define        FBSD_SI_ASYNCIO         0x10004
+#define        FBSD_SI_MESGQ           0x10005
+#define        FBSD_SI_KERNEL          0x10006
+#define        FBSD_SI_LWP             0x10007
+
+#define        FBSD_ILL_ILLOPC         1
+#define        FBSD_ILL_ILLOPN         2
+#define        FBSD_ILL_ILLADR         3
+#define        FBSD_ILL_ILLTRP         4
+#define        FBSD_ILL_PRVOPC         5
+#define        FBSD_ILL_PRVREG         6
+#define        FBSD_ILL_COPROC         7
+#define        FBSD_ILL_BADSTK         8
+
+#define        FBSD_BUS_ADRALN         1
+#define        FBSD_BUS_ADRERR         2
+#define        FBSD_BUS_OBJERR         3
+#define        FBSD_BUS_OOMERR         100
+
+#define        FBSD_SEGV_MAPERR        1
+#define        FBSD_SEGV_ACCERR        2
+#define        FBSD_SEGV_PKUERR        100
+
+#define        FBSD_FPE_INTOVF         1
+#define        FBSD_FPE_INTDIV         2
+#define        FBSD_FPE_FLTDIV         3
+#define        FBSD_FPE_FLTOVF         4
+#define        FBSD_FPE_FLTUND         5
+#define        FBSD_FPE_FLTRES         6
+#define        FBSD_FPE_FLTINV         7
+#define        FBSD_FPE_FLTSUB         8
+
+#define        FBSD_TRAP_BRKPT         1
+#define        FBSD_TRAP_TRACE         2
+#define        FBSD_TRAP_DTRACE        3
+#define        FBSD_TRAP_CAP           4
+
+#define        FBSD_CLD_EXITED         1
+#define        FBSD_CLD_KILLED         2
+#define        FBSD_CLD_DUMPED         3
+#define        FBSD_CLD_TRAPPED        4
+#define        FBSD_CLD_STOPPED        5
+#define        FBSD_CLD_CONTINUED      6
+
+#define        FBSD_POLL_IN            1
+#define        FBSD_POLL_OUT           2
+#define        FBSD_POLL_MSG           3
+#define        FBSD_POLL_ERR           4
+#define        FBSD_POLL_PRI           5
+#define        FBSD_POLL_HUP           6
+
 /* FreeBSD kernels 12.0 and later include a copy of the
    'ptrace_lwpinfo' structure returned by the PT_LWPINFO ptrace
    operation in an ELF core note (NT_FREEBSD_PTLWPINFO) for each LWP.
@@ -583,129 +641,6 @@ 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
@@ -715,7 +650,7 @@ static gdb::optional<gdb::byte_vector>
 fbsd_make_note_desc (enum target_object object, uint32_t structsize)
 {
   gdb::optional<gdb::byte_vector> buf =
-    target_read_alloc (current_top_target (), object, NULL);
+    target_read_alloc (current_inferior ()->top_target (), object, NULL);
   if (!buf || buf->empty ())
     return {};
 
@@ -782,16 +717,16 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
        signalled_thr = curr_thr;
     }
 
-  fbsd_corefile_thread_data thread_args (gdbarch, obfd, note_data, note_size,
-                                        signalled_thr->suspend.stop_signal);
-
-  fbsd_corefile_thread (signalled_thr, &thread_args);
+  enum gdb_signal stop_signal = signalled_thr->suspend.stop_signal;
+  gcore_elf_build_thread_register_notes (gdbarch, signalled_thr, stop_signal,
+                                        obfd, &note_data, note_size);
   for (thread_info *thr : current_inferior ()->non_exited_threads ())
     {
       if (thr == signalled_thr)
        continue;
 
-      fbsd_corefile_thread (thr, &thread_args);
+      gcore_elf_build_thread_register_notes (gdbarch, thr, stop_signal,
+                                            obfd, &note_data, note_size);
     }
 
   /* Auxiliary vector.  */
@@ -834,6 +769,9 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
        return NULL;
     }
 
+  /* Include the target description when possible.  */
+  gcore_elf_make_tdesc_note (obfd, &note_data, note_size);
+
   return note_data;
 }
 
@@ -2107,6 +2045,220 @@ fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 0;
 }
 
+/* Return description of signal code or nullptr.  */
+
+static const char *
+fbsd_signal_cause (enum gdb_signal siggnal, int code)
+{
+  /* Signal-independent causes.  */
+  switch (code)
+    {
+    case FBSD_SI_USER:
+      return _("Sent by kill()");
+    case FBSD_SI_QUEUE:
+      return _("Sent by sigqueue()");
+    case FBSD_SI_TIMER:
+      return _("Timer expired");
+    case FBSD_SI_ASYNCIO:
+      return _("Asynchronous I/O request completed");
+    case FBSD_SI_MESGQ:
+      return _("Message arrived on empty message queue");
+    case FBSD_SI_KERNEL:
+      return _("Sent by kernel");
+    case FBSD_SI_LWP:
+      return _("Sent by thr_kill()");
+    }
+
+  switch (siggnal)
+    {
+    case GDB_SIGNAL_ILL:
+      switch (code)
+       {
+       case FBSD_ILL_ILLOPC:
+         return _("Illegal opcode");
+       case FBSD_ILL_ILLOPN:
+         return _("Illegal operand");
+       case FBSD_ILL_ILLADR:
+         return _("Illegal addressing mode");
+       case FBSD_ILL_ILLTRP:
+         return _("Illegal trap");
+       case FBSD_ILL_PRVOPC:
+         return _("Privileged opcode");
+       case FBSD_ILL_PRVREG:
+         return _("Privileged register");
+       case FBSD_ILL_COPROC:
+         return _("Coprocessor error");
+       case FBSD_ILL_BADSTK:
+         return _("Internal stack error");
+       }
+      break;
+    case GDB_SIGNAL_BUS:
+      switch (code)
+       {
+       case FBSD_BUS_ADRALN:
+         return _("Invalid address alignment");
+       case FBSD_BUS_ADRERR:
+         return _("Address not present");
+       case FBSD_BUS_OBJERR:
+         return _("Object-specific hardware error");
+       case FBSD_BUS_OOMERR:
+         return _("Out of memory");
+       }
+      break;
+    case GDB_SIGNAL_SEGV:
+      switch (code)
+       {
+       case FBSD_SEGV_MAPERR:
+         return _("Address not mapped to object");
+       case FBSD_SEGV_ACCERR:
+         return _("Invalid permissions for mapped object");
+       case FBSD_SEGV_PKUERR:
+         return _("PKU violation");
+       }
+      break;
+    case GDB_SIGNAL_FPE:
+      switch (code)
+       {
+       case FBSD_FPE_INTOVF:
+         return _("Integer overflow");
+       case FBSD_FPE_INTDIV:
+         return _("Integer divide by zero");
+       case FBSD_FPE_FLTDIV:
+         return _("Floating point divide by zero");
+       case FBSD_FPE_FLTOVF:
+         return _("Floating point overflow");
+       case FBSD_FPE_FLTUND:
+         return _("Floating point underflow");
+       case FBSD_FPE_FLTRES:
+         return _("Floating point inexact result");
+       case FBSD_FPE_FLTINV:
+         return _("Invalid floating point operation");
+       case FBSD_FPE_FLTSUB:
+         return _("Subscript out of range");
+       }
+      break;
+    case GDB_SIGNAL_TRAP:
+      switch (code)
+       {
+       case FBSD_TRAP_BRKPT:
+         return _("Breakpoint");
+       case FBSD_TRAP_TRACE:
+         return _("Trace trap");
+       case FBSD_TRAP_DTRACE:
+         return _("DTrace-induced trap");
+       case FBSD_TRAP_CAP:
+         return _("Capability violation");
+       }
+      break;
+    case GDB_SIGNAL_CHLD:
+      switch (code)
+       {
+       case FBSD_CLD_EXITED:
+         return _("Child has exited");
+       case FBSD_CLD_KILLED:
+         return _("Child has terminated abnormally");
+       case FBSD_CLD_DUMPED:
+         return _("Child has dumped core");
+       case FBSD_CLD_TRAPPED:
+         return _("Traced child has trapped");
+       case FBSD_CLD_STOPPED:
+         return _("Child has stopped");
+       case FBSD_CLD_CONTINUED:
+         return _("Stopped child has continued");
+       }
+      break;
+    case GDB_SIGNAL_POLL:
+      switch (code)
+       {
+       case FBSD_POLL_IN:
+         return _("Data input available");
+       case FBSD_POLL_OUT:
+         return _("Output buffers available");
+       case FBSD_POLL_MSG:
+         return _("Input message available");
+       case FBSD_POLL_ERR:
+         return _("I/O error");
+       case FBSD_POLL_PRI:
+         return _("High priority input available");
+       case FBSD_POLL_HUP:
+         return _("Device disconnected");
+       }
+      break;
+    }
+
+  return nullptr;
+}
+
+/* Report additional details for a signal stop.  */
+
+static void
+fbsd_report_signal_info (struct gdbarch *gdbarch, struct ui_out *uiout,
+                        enum gdb_signal siggnal)
+{
+  LONGEST code, mqd, pid, status, timerid, uid;
+
+  try
+    {
+      code = parse_and_eval_long ("$_siginfo.si_code");
+      pid = parse_and_eval_long ("$_siginfo.si_pid");
+      uid = parse_and_eval_long ("$_siginfo.si_uid");
+      status = parse_and_eval_long ("$_siginfo.si_status");
+      timerid = parse_and_eval_long ("$_siginfo._reason._timer.si_timerid");
+      mqd = parse_and_eval_long ("$_siginfo._reason._mesgq.si_mqd");
+    }
+  catch (const gdb_exception_error &e)
+    {
+      return;
+    }
+
+  const char *meaning = fbsd_signal_cause (siggnal, code);
+  if (meaning == nullptr)
+    return;
+
+  uiout->text (".\n");
+  uiout->field_string ("sigcode-meaning", meaning);
+
+  switch (code)
+    {
+    case FBSD_SI_USER:
+    case FBSD_SI_QUEUE:
+    case FBSD_SI_LWP:
+      uiout->text (" from pid ");
+      uiout->field_string ("sending-pid", plongest (pid));
+      uiout->text (" and user ");
+      uiout->field_string ("sending-uid", plongest (uid));
+      return;
+    case FBSD_SI_TIMER:
+      uiout->text (": timerid ");
+      uiout->field_string ("timerid", plongest (timerid));
+      return;
+    case FBSD_SI_MESGQ:
+      uiout->text (": message queue ");
+      uiout->field_string ("message-queue", plongest (mqd));
+      return;
+    case FBSD_SI_ASYNCIO:
+      return;
+    }
+
+  if (siggnal == GDB_SIGNAL_CHLD)
+    {
+      uiout->text (": pid ");
+      uiout->field_string ("child-pid", plongest (pid));
+      uiout->text (", uid ");
+      uiout->field_string ("child-uid", plongest (uid));
+      if (code == FBSD_CLD_EXITED)
+       {
+         uiout->text (", exit status ");
+         uiout->field_string ("exit-status", plongest (status));
+       }
+      else
+       {
+         uiout->text (", signal ");
+         uiout->field_string ("signal", plongest (status));
+       }
+    }
+}
+
 /* To be called from GDB_OSABI_FREEBSD handlers. */
 
 void
@@ -2121,6 +2273,7 @@ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_get_siginfo_type (gdbarch, fbsd_get_siginfo_type);
   set_gdbarch_gdb_signal_from_target (gdbarch, fbsd_gdb_signal_from_target);
   set_gdbarch_gdb_signal_to_target (gdbarch, fbsd_gdb_signal_to_target);
+  set_gdbarch_report_signal_info (gdbarch, fbsd_report_signal_info);
   set_gdbarch_skip_solib_resolver (gdbarch, fbsd_skip_solib_resolver);
 
   /* `catch syscall' */
This page took 0.028089 seconds and 4 git commands to generate.