Discussion:
[Bug gdb/22645] New: gdb hangs on 32-bit ARM armv7l at SIGTRAP from "bkpt" instruction 0xe1200070
jreiser at BitWagon dot com
2017-12-26 04:03:27 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22645

Bug ID: 22645
Summary: gdb hangs on 32-bit ARM armv7l at SIGTRAP from "bkpt"
instruction 0xe1200070
Product: gdb
Version: HEAD
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: gdb
Assignee: unassigned at sourceware dot org
Reporter: jreiser at BitWagon dot com
Target Milestone: ---

gdb hangs in an infinite loop instead of stopping upon SIGTRAP when an inferior
on 32-bit ARM architecture 'armv7l' (such as RaspberryPi-3B in 32-bit mode)
executes the instruction "bkpt", which is 0xe1200070. The Linux kernel sends
SIGTRAP, but gdb processing tries PTRACE_CONT, which re-triggers the SIGTRAP.
Interrupting the gdb hang with SIGINT (ctrl-C) revives gdb, and the output for
SIGINT looks like the way gdb should have responded in the first place to the
SIGTRAP.

Here is an annotated transcript of a console terminal session which contains a
4-line reproducible test case plus recipe, as well as some 'strace' debugging
of the ptrace() calls used by gdb.
=====
$ uname -a ## the hardware and operating system environment
Linux host 4.14.7-300.fc27.armv7hl #1 SMP Mon Dec 18 17:10:15 UTC 2017 armv7l
armv7l armv7l GNU/Linux

$ cat bkpt.S ## the test case
.globl _start
_start:
bkpt
nop

$ gcc -o bkpt -nostartfiles -nostdlib bkpt.S ## the build recipe

$ ./bkpt ## bare execution gets SIGTRAP
Trace/breakpoint trap (core dumped)
$ echo $? ## shell exit code of previous process in this shell
133 ## 133 = 128 + 5; 5 ==> SIGTRAP
$ strace ./bkpt
execve("./bkpt", ["./bkpt"], 0xbeebe4c0 /* 28 vars */) = 0
--- SIGTRAP {si_signo=SIGTRAP, si_code=TRAP_HWBKPT, si_pid=65688, si_uid=0} ---
+++ killed by SIGTRAP (core dumped) +++
Trace/breakpoint trap (core dumped)

$ gdb --version
GNU gdb (GDB) 8.0.50.20171216-git
$ gdb bkpt ## gdb hangs
(gdb) x/12i _start ## verify correct assembly
0x10098 <_start>: bkpt 0x0000
0x1009c <_start+4>: nop {0}
0x100a0: Cannot access memory at address 0x100a0
(gdb) x/12x _start
0x10098 <_start>: 0xe1200070 0xe320f000 Cannot access memory at
address 0x100a0
(gdb) run
Starting program: /path/to/bkpt
^C ## session appears to be hung (gdb "unhealthy"), so send SIGINT from
console
Program received signal SIGINT, Interrupt.
0x00010098 in _start () ## gdb acts healthy for SIGINT; why not for SIGTRAP?
(gdb) x/i $pc
=> 0x10098 <_start>: bkpt 0x0000 ## the correct place
(gdb)
0x1009c <_start+4>: nop {0}
(gdb) q

$ dmesg | tail ## what happened while SIGTRAP under gdb
[ 483.287100] Unhandled prefetch abort: breakpoint debug exception (0x002) at
0x00010098
[ 483.295547] Unhandled prefetch abort: breakpoint debug exception (0x002) at
0x00010098
[ 483.303960] Unhandled prefetch abort: breakpoint debug exception (0x002) at
0x00010098

$ strace -e trace=ptrace -o strace-gdb.out gdb ./bkpt ## note strange
PTRACE_CONT after SIGTRAP (33 lines below; "what is this?")
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1307, si_uid=1000,
si_status=0, si_utime=0, si_stime=0} ---
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGS, 1308, NULL, 0xbe84ec60) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=SI_USER,
si_pid=1308, si_uid=1000}) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGS, 1308, NULL, 0xbe84ec60) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=SI_USER,
si_pid=1308, si_uid=1000}) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1309, si_uid=1000,
si_status=SIGSTOP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_SETOPTIONS, 1309, NULL, PTRACE_O_TRACESYSGOOD) = 0
ptrace(PTRACE_SETOPTIONS, 1309, NULL, PTRACE_O_TRACEFORK) = 0
ptrace(PTRACE_SETOPTIONS, 1309, NULL,
PTRACE_O_TRACEFORK|PTRACE_O_TRACEVFORKDONE) = 0
ptrace(PTRACE_CONT, 1309, NULL, SIG_0) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1309, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETEVENTMSG, 1309, NULL, [1310]) = 0
ptrace(PTRACE_KILL, 1310) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=1310, si_uid=1000,
si_status=SIGKILL, si_utime=0, si_stime=0} ---
ptrace(PTRACE_SETOPTIONS, 1309, NULL, PTRACE_O_EXITKILL) = 0
ptrace(PTRACE_KILL, 1309) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1309, si_uid=1000,
si_status=SIGCHLD, si_utime=0, si_stime=0} ---
ptrace(PTRACE_KILL, 1309) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=1309, si_uid=1000,
si_status=SIGKILL, si_utime=0, si_stime=0} ---
ptrace(PTRACE_SETOPTIONS, 1308, NULL,
PTRACE_O_TRACESYSGOOD|PTRACE_O_TRACEFORK|PTRACE_O_TRACEVFORK|PTRACE_O_TRACECLONE|PTRACE_O_TRACEEXEC|PTRACE_O_TRACEVFORKDONE|PTRACE_O_EXITKILL)
= 0
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84efa8,
iov_len=72}]) = 0
ptrace(PTRACE_GETVFPREGS, 1308, NULL, 0xbe84ee88) = 0
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ef70,
iov_len=72}]) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ede8,
iov_len=72}]) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0, si_value={int=1308, ptr=0x51c}}) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0}) = 0
ptrace(PTRACE_GETHBPREGS, 1308, NULL, 0xbe84edec) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0 ## what is this?
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ede8,
iov_len=72}]) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0, si_value={int=1308, ptr=0x51c}}) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0}) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ede8,
iov_len=72}]) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0, si_value={int=1308, ptr=0x51c}}) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0}) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=1} ---
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ede8,
iov_len=72}]) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0, si_value={int=1308, ptr=0x51c}}) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0}) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0

<<snip>>

--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGTRAP, si_utime=0, si_stime=20} ---
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ede8,
iov_len=72}]) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0, si_value={int=1308, ptr=0x51c}}) = 0
ptrace(PTRACE_GETSIGINFO, 1308, NULL, {si_signo=SIGTRAP, si_code=TRAP_HWBKPT,
si_pid=65688, si_uid=0}) = 0
ptrace(PTRACE_CONT, 1308, 0x1, SIG_0) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=1308, si_uid=1000,
si_status=SIGINT, si_utime=0, si_stime=20} ---
ptrace(PTRACE_GETREGSET, 1308, NT_PRSTATUS, [{iov_base=0xbe84ef68,
iov_len=72}]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10094, [0xbd7e609d]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_PEEKTEXT, 1308, 0x10098, [0xe1200070]) = 0
ptrace(PTRACE_KILL, 1308) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=1308, si_uid=1000,
si_status=SIGKILL, si_utime=0, si_stime=20} ---
ptrace(PTRACE_KILL, 1308) = -1 ESRCH (No such process)
+++ exited with 0 +++

=====
--
You are receiving this mail because:
You are on the CC list for the bug.
jreiser at BitWagon dot com
2017-12-26 04:15:14 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22645

--- Comment #1 from John Reiser <jreiser at BitWagon dot com> ---
The same bad behavior also occurs when the bkpt is not the first instruction:
=====
.globl _start
_start:
nop
bkpt
nop
=====

In the past gdb has had trouble when the very first instruction after execve
generated a trap:
https://bugzilla.redhat.com/show_bug.cgi?id=162775
"gdb ignores SIGTRAP at entry address"
2008-03-10 [almost ten years ago]

but the revised test case above, where the SIGTRAP is at the second
instruction, still hangs under gdb.
--
You are receiving this mail because:
You are on the CC list for the bug.
jreiser at BitWagon dot com
2017-12-27 05:34:51 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22645

--- Comment #2 from John Reiser <jreiser at BitWagon dot com> ---
Contrasting with the similar "brk #0" (.word 0xd4200000) on 64-bit ARM aarch64:
gdb stops and reports SIGTRAP the first time (does not silently loop using
PTRACE_CONT) and strace shows
=====
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=9705, si_uid=1000,
si_status=SIGTRAP, si_utime=1, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 9705, NT_PRSTATUS, [{iov_base=0xffffe5b28e88,
iov_len=272}]) = 0
ptrace(PTRACE_GETSIGINFO, 9705, NULL, {si_signo=SIGTRAP, si_code=TRAP_BRKPT,
si_pid=4194520, si_uid=0, si_value={int=-441282160, ptr=0xffffe5b29190}}) = 0
ptrace(PTRACE_PEEKTEXT, 9705, 0x4000d8, [0xd503201fd4200000]) = 0
ptrace(PTRACE_PEEKTEXT, 9705, 0x4000d8, [0xd503201fd4200000]) = 0
ptrace(PTRACE_PEEKTEXT, 9705, 0x4000d0, [0xd503201f155c8bda]) = 0
ptrace(PTRACE_PEEKTEXT, 9705, 0x4000d8, [0xd503201fd4200000]) = 0
=====
One notable difference is:
si_code=TRAP_BRKPT on 64-bit ARM
si_code=TRAP_HWBKPT on 32-bit ARM
--
You are receiving this mail because:
You are on the CC list for the bug.
jreiser at BitWagon dot com
2018-10-03 03:43:08 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22645

--- Comment #3 from John Reiser <jreiser at BitWagon dot com> ---
The same bad behavior persists in GNU gdb (GDB) Fedora 8.2-2.fc29
--
You are receiving this mail because:
You are on the CC list for the bug.
Loading...