Workaround a FreeBSD kernel bug resulting in spurious SIGTRAP events.

The ptrace command PT_LWPINFO to request detailed information about a
stopped thread can return stale signal information from an earlier
stop.  Events which are reporting an intercepted signal will always
report the correct information, but signal stops for some other events
such as system call enter/exit events might include stale siginfo from
an earlier signal.  In particular, if a thread reports a system call
entry or exit event after previously reporting a single-step or
breakpoint event via SIGTRAP, fbsd_handle_debug_trap believed the
system call event was the previous event and claimed it resulting in a
spurious SIGTRAP event.

True breakpoint and single-step events will never report another event
in the pl_flags member of struct ptrace_lwpinfo.  Use this to detect
stale siginfo by requiring pl_flags to have only the PL_FLAG_SI flag
and no other flags before treating a SIGTRAP as a single-step or
breakpoint trap.

gdb/ChangeLog:

	* fbsd-nat.c (fbsd_handle_debug_trap): Require pl.pl_flags to
	equal PL_FLAG_SI.
	(fbsd_nat_target::stopped_by_sw_breakpoint): Likewise.
This commit is contained in:
John Baldwin 2018-12-21 10:18:11 -08:00
parent d00a27c5ad
commit 6d78332e77
2 changed files with 15 additions and 3 deletions

View File

@ -1,3 +1,9 @@
2018-12-21 John Baldwin <jhb@FreeBSD.org>
* fbsd-nat.c (fbsd_handle_debug_trap): Require pl.pl_flags to
equal PL_FLAG_SI.
(fbsd_nat_target::stopped_by_sw_breakpoint): Likewise.
2018-12-21 Paul Marechal <paul.marechal@ericsson.com>
PR gdb/23974

View File

@ -1238,8 +1238,14 @@ fbsd_handle_debug_trap (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)
SIGTRAP.
FreeBSD kernels prior to r341800 can return stale siginfo for at
least some events, but those events can be identified by
additional flags set in pl_flags. True breakpoint and
single-step traps should not have other flags set in
pl_flags. */
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
@ -1517,7 +1523,7 @@ fbsd_nat_target::stopped_by_sw_breakpoint ()
sizeof pl) == -1)
return false;
return ((pl.pl_flags & PL_FLAG_SI)
return (pl.pl_flags == PL_FLAG_SI
&& pl.pl_siginfo.si_signo == SIGTRAP
&& pl.pl_siginfo.si_code == TRAP_BRKPT);
}