Changeset View
Changeset View
Standalone View
Standalone View
head/devel/gdb/files/commit-7efba073e2
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
commit 7efba073e2b83803a47fd89e701fe60b98f2debc | |||||
Author: John Baldwin <jhb@FreeBSD.org> | |||||
Date: Sat Mar 3 21:25:33 2018 -0800 | |||||
Use signal information to determine SIGTRAP type for FreeBSD. | |||||
Use the signal code from siginfo_t to distinguish SIGTRAP events due | |||||
to trace traps (TRAP_TRACE) and software breakpoints (TRAP_BRKPT). | |||||
For software breakpoints, adjust the PC when the event is reported as | |||||
part of the API when supplying "stopped_by_sw_breakpoint". Currently | |||||
FreeBSD only supports hardware watchpoints and breakpoints on x86 | |||||
which are reported as trace traps. Signal information is not used on | |||||
MIPS and sparc64 kernels which do not reliably report TRAP_BRKPT for | |||||
software breakpoints. | |||||
gdb/ChangeLog: | |||||
* fbsd-nat.c: Include "inf-ptrace.h". | |||||
(USE_SIGTRAP_SIGINFO): Conditionally define. | |||||
[USE_SIGTRAP_SIGINFO] (fbsd_handle_debug_trap): New function. | |||||
(fbsd_wait) [USE_SIGTRAP_SIGINFO]: Call "fbsd_handle_debug_trap". | |||||
[USE_SIGTRAP_SIGINFO] (fbsd_stopped_by_sw_breakpoint): New | |||||
function. | |||||
[USE_SIGTRAP_SIGINFO] (fbsd_supports_stopped_by_sw_breakpoint): | |||||
Likewise. | |||||
[USE_SIGTRAP_SIGINFO] (fbsd_supports_stopped_by_hw_breakpoint): | |||||
Likewise. | |||||
(fbsd_nat_add_target) [USE_SIGTRAP_SIGINFO]: Set | |||||
"stopped_by_sw_breakpoint", "supports_stopped_by_sw_breakpoint", | |||||
"supports_stopped_by_hw_breakpoint" target methods. | |||||
diff --git gdb/fbsd-nat.c gdb/fbsd-nat.c | |||||
index 2516ac5552..bea7f42c7e 100644 | |||||
--- gdb/fbsd-nat.c | |||||
+++ gdb/fbsd-nat.c | |||||
@@ -26,6 +26,7 @@ | |||||
#include "gdbcmd.h" | |||||
#include "gdbthread.h" | |||||
#include "gdb_wait.h" | |||||
+#include "inf-ptrace.h" | |||||
#include <sys/types.h> | |||||
#include <sys/procfs.h> | |||||
#include <sys/ptrace.h> | |||||
@@ -45,6 +46,14 @@ | |||||
#include <list> | |||||
+#ifdef TRAP_BRKPT | |||||
+/* MIPS does not set si_code for SIGTRAP. sparc64 reports | |||||
+ non-standard values in si_code for SIGTRAP. */ | |||||
+# if !defined(__mips__) && !defined(__sparc64__) | |||||
+# define USE_SIGTRAP_SIGINFO | |||||
+# endif | |||||
+#endif | |||||
+ | |||||
/* Return the name of a file that can be opened to get the symbols for | |||||
the child process identified by PID. */ | |||||
@@ -1187,6 +1196,56 @@ fbsd_resume (struct target_ops *ops, | |||||
super_resume (ops, ptid, step, signo); | |||||
} | |||||
+#ifdef USE_SIGTRAP_SIGINFO | |||||
+/* Handle breakpoint and trace traps reported via SIGTRAP. If the | |||||
+ trap was a breakpoint or trace trap that should be reported to the | |||||
+ core, return true. */ | |||||
+ | |||||
+static bool | |||||
+fbsd_handle_debug_trap (struct target_ops *ops, ptid_t ptid, | |||||
+ const struct ptrace_lwpinfo &pl) | |||||
+{ | |||||
+ | |||||
+ /* Ignore traps without valid siginfo or for signals other than | |||||
+ SIGTRAP. */ | |||||
+ if (! (pl.pl_flags & PL_FLAG_SI) || pl.pl_siginfo.si_signo != SIGTRAP) | |||||
+ return false; | |||||
+ | |||||
+ /* Trace traps are either a single step or a hardware watchpoint or | |||||
+ breakpoint. */ | |||||
+ if (pl.pl_siginfo.si_code == TRAP_TRACE) | |||||
+ { | |||||
+ if (debug_fbsd_nat) | |||||
+ fprintf_unfiltered (gdb_stdlog, | |||||
+ "FNAT: trace trap for LWP %ld\n", ptid.lwp ()); | |||||
+ return true; | |||||
+ } | |||||
+ | |||||
+ if (pl.pl_siginfo.si_code == TRAP_BRKPT) | |||||
+ { | |||||
+ /* Fixup PC for the software breakpoint. */ | |||||
+ struct regcache *regcache = get_thread_regcache (ptid); | |||||
+ struct gdbarch *gdbarch = regcache->arch (); | |||||
+ int decr_pc = gdbarch_decr_pc_after_break (gdbarch); | |||||
+ | |||||
+ if (debug_fbsd_nat) | |||||
+ fprintf_unfiltered (gdb_stdlog, | |||||
+ "FNAT: sw breakpoint trap for LWP %ld\n", | |||||
+ ptid.lwp ()); | |||||
+ if (decr_pc != 0) | |||||
+ { | |||||
+ CORE_ADDR pc; | |||||
+ | |||||
+ pc = regcache_read_pc (regcache); | |||||
+ regcache_write_pc (regcache, pc - decr_pc); | |||||
+ } | |||||
+ return true; | |||||
+ } | |||||
+ | |||||
+ return false; | |||||
+} | |||||
+#endif | |||||
+ | |||||
/* Wait for the child specified by PTID to do something. Return the | |||||
process ID of the child, or MINUS_ONE_PTID in case of error; store | |||||
the status in *OURSTATUS. */ | |||||
@@ -1372,6 +1431,11 @@ fbsd_wait (struct target_ops *ops, | |||||
} | |||||
#endif | |||||
+#ifdef USE_SIGTRAP_SIGINFO | |||||
+ if (fbsd_handle_debug_trap (ops, wptid, pl)) | |||||
+ return wptid; | |||||
+#endif | |||||
+ | |||||
/* Note that PL_FLAG_SCE is set for any event reported while | |||||
a thread is executing a system call in the kernel. In | |||||
particular, signals that interrupt a sleep in a system | |||||
@@ -1410,6 +1474,42 @@ fbsd_wait (struct target_ops *ops, | |||||
} | |||||
} | |||||
+#ifdef USE_SIGTRAP_SIGINFO | |||||
+/* Implement the "to_stopped_by_sw_breakpoint" target_ops method. */ | |||||
+ | |||||
+static int | |||||
+fbsd_stopped_by_sw_breakpoint (struct target_ops *ops) | |||||
+{ | |||||
+ struct ptrace_lwpinfo pl; | |||||
+ | |||||
+ if (ptrace (PT_LWPINFO, get_ptrace_pid (inferior_ptid), (caddr_t) &pl, | |||||
+ sizeof pl) == -1) | |||||
+ return 0; | |||||
+ | |||||
+ return ((pl.pl_flags & PL_FLAG_SI) | |||||
+ && pl.pl_siginfo.si_signo == SIGTRAP | |||||
+ && pl.pl_siginfo.si_code == TRAP_BRKPT); | |||||
+} | |||||
+ | |||||
+/* Implement the "to_supports_stopped_by_sw_breakpoint" target_ops | |||||
+ method. */ | |||||
+ | |||||
+static int | |||||
+fbsd_supports_stopped_by_sw_breakpoint (struct target_ops *ops) | |||||
+{ | |||||
+ return 1; | |||||
+} | |||||
+ | |||||
+/* Implement the "to_supports_stopped_by_hw_breakpoint" target_ops | |||||
+ method. */ | |||||
+ | |||||
+static int | |||||
+fbsd_supports_stopped_by_hw_breakpoint (struct target_ops *ops) | |||||
+{ | |||||
+ return ops->to_stopped_by_hw_breakpoint != NULL; | |||||
+} | |||||
+#endif | |||||
+ | |||||
#ifdef TDP_RFPPWAIT | |||||
/* Target hook for follow_fork. On entry and at return inferior_ptid is | |||||
the ptid of the followed inferior. */ | |||||
@@ -1560,6 +1660,13 @@ fbsd_nat_add_target (struct target_ops *t) | |||||
t->to_wait = fbsd_wait; | |||||
t->to_post_startup_inferior = fbsd_post_startup_inferior; | |||||
t->to_post_attach = fbsd_post_attach; | |||||
+#ifdef USE_SIGTRAP_SIGINFO | |||||
+ t->to_stopped_by_sw_breakpoint = fbsd_stopped_by_sw_breakpoint; | |||||
+ t->to_supports_stopped_by_sw_breakpoint | |||||
+ = fbsd_supports_stopped_by_sw_breakpoint; | |||||
+ t->to_supports_stopped_by_hw_breakpoint | |||||
+ = fbsd_supports_stopped_by_hw_breakpoint; | |||||
+#endif | |||||
#ifdef TDP_RFPPWAIT | |||||
t->to_follow_fork = fbsd_follow_fork; | |||||
t->to_insert_fork_catchpoint = fbsd_insert_fork_catchpoint; |