aboutsummaryrefslogtreecommitdiff
path: root/gdb/fbsd-tdep.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2021-06-03 10:32:04 -0700
committerJohn Baldwin <jhb@FreeBSD.org>2021-06-03 10:32:20 -0700
commit83810881192e950dce39be4d55e21d52ba68fb60 (patch)
tree3d70a57317deee72f0fcd3d36aaa27bb02106c86 /gdb/fbsd-tdep.c
parent4c958d7911cad25699b345f82d74411918588399 (diff)
downloadgdb-83810881192e950dce39be4d55e21d52ba68fb60.zip
gdb-83810881192e950dce39be4d55e21d52ba68fb60.tar.gz
gdb-83810881192e950dce39be4d55e21d52ba68fb60.tar.bz2
Report additional details for signals received on FreeBSD.
Provide a description for si_code values as a sigcode-meaning field. For signals raised by a system call, provide the pid and user ID of the sending process. For signals raised by a POSIX timer exparation, provide the id of the timer. For signals raised by a POSIX message queue, provide the id of the message queue. For SIGCHLD provide the pid and user ID of the child process along with the exit status or relevant signal number. Sample output for SIGUSR1 raised by kill(): before: Program received signal SIGUSR1, User defined signal 1. kill () at kill.S:4 4 RSYSCALL(kill) after: Program received signal SIGUSR1, User defined signal 1. Sent by kill() from pid 30529 and user 1001. kill () at kill.S:4 4 RSYSCALL(kill) SIGCHLD for exited process: before: Program received signal SIGCHLD, Child status changed. after: Program received signal SIGCHLD, Child status changed. Child has exited: pid 31929, uid 1001, exit status 0. SIGALRM raised by a POSIX timer (timer_create): before: Program received signal SIGALRM, Alarm clock. after: Program received signal SIGALRM, Alarm clock. Timer expired: timerid 3. gdb/ChangeLog: * fbsd-tdep.c (FBSD_SI_USER, FBSD_SI_QUEUE, FBSD_SI_TIMER) (FBSD_SI_ASYNCIO, FBSD_SI_MESGQ, FBSD_SI_KERNEL, FBSD_SI_LWP) (FBSD_ILL_ILLOPC, FBSD_ILL_ILLOPN, FBSD_ILL_ILLADR) (FBSD_ILL_ILLTRP, FBSD_ILL_PRVOPC, FBSD_ILL_PRVREG) (FBSD_ILL_COPROC, FBSD_ILL_BADSTK, FBSD_BUS_ADRALN) (FBSD_BUS_ADRERR, FBSD_BUS_OBJERR, FBSD_BUS_OOMERR) (FBSD_SEGV_MAPERR, FBSD_SEGV_ACCERR, FBSD_SEGV_PKUERR) (FBSD_FPE_INTOVF, FBSD_FPE_INTDIV, FBSD_FPE_FLTDIV) (FBSD_FPE_FLTOVF, FBSD_FPE_FLTUND, FBSD_FPE_FLTRES) (FBSD_FPE_FLTINV, FBSD_FPE_FLTSUB, FBSD_TRAP_BRKPT) (FBSD_TRAP_TRACE, FBSD_TRAP_DTRACE, FBSD_TRAP_CAP) (FBSD_CLD_EXITED, FBSD_CLD_KILLED, FBSD_CLD_DUMPED) (FBSD_CLD_TRAPPED, FBSD_CLD_STOPPED, FBSD_CLD_CONTINUED) (FBSD_POLL_IN, FBSD_POLL_OUT, FBSD_POLL_MSG, FBSD_POLL_ERR) (FBSD_POLL_PRI, FBSD_POLL_HUP, fbsd_signal_cause) (fbsd_report_signal_info): New. (fbsd_init_abi): Use fbsd_report_signal_info as gdbarch report_signal_info method.
Diffstat (limited to 'gdb/fbsd-tdep.c')
-rw-r--r--gdb/fbsd-tdep.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 6cab31d..5cb6fa3 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -75,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.
@@ -1988,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
@@ -2002,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' */