This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Re: Regression
> From: Pedro Alves <pedro@codesourcery.com>
> Date: Tue, 10 Feb 2009 18:00:35 +0000
Thanks Pedro, for looking into this!
> Opps, my logs didn't show something as clearly as I indended:
>
> > $1 = (void (*)()) 0xa43a633 <printf+19>
>
> vs
>
> > infrun: stop_pc = 0xeff4636
>
> > Here, it seems like telling BSD to single-step, and, to deliver
> > a signal at the same time, just single-steps, resulting in a SIGTRAP.
>
> Errr, here it tells that I re-ran the inferior to get first PC, after
> having pased the stop_pc bit already, from a previous run. Different runs,
> different PCs, notice the randomization affecting the first bytes of the
> addresses. Sorry for any confusion it may have caused.
>
> Here's a run, to show how OpenBSD forgets to single-step into
> the handler:
>
> (gdb) p $pc
> $1 = (void (*)()) 0x51b0633 <printf+19>
> (gdb) signal SIGUSR1
> Continuing with signal SIGUSR1.
> infrun: clear_proceed_status_thread (process 18606)
> infrun: proceed (addr=0xffffffff, signal=30, step=0)
> infrun: resume (step=1, signal=30), trap_expected=1
> infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
> infrun: target_wait (-1, status) = 18606, status->kind = stopped, signal = SIGTRAP
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> infrun: stop_pc = 0x51b0636
>
> Then, I've added a printf in the signal handler itself, to see
> if it runs at all:
>
> (gdb) signal SIGUSR1
> Continuing with signal SIGUSR1.
> infrun: clear_proceed_status_thread (process 1505)
> infrun: proceed (addr=0xffffffff, signal=30, step=0)
> infrun: resume (step=1, signal=30), trap_expected=1
> infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
> handle_USR1
> ^^^^^^^^^^^ (1)
> infrun: target_wait (-1, status) = 1505, status->kind = stopped, signal = SIGTRAP
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> infrun: stop_pc = 0x6919636
> infrun: no stepping, continue
> infrun: resume (step=0, signal=0), trap_expected=0
> ^^^^^^^^^^^^^^ (2)
> infrun: prepare_to_wait
> my_array[2] is 3
> infrun: target_wait (-1, status) = 1505, status->kind = exited, status = 0
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_EXITED
>
> So, it does run, according to (1) above, but, since we were stepping
> over a breakpoint notice (trap_expected=1), GDB had removed breakpoints
> from the inferior. They're only inserted on the following resume, at (2).
> That's why you miss the breakpoint in the signal handler.
>
> Without Daniel's patch, "signal FOO" *would not remove breakpoints*, since
> it was calling `proceed' like if it was a "jump".
>
> Here's the same on i386-linux:
>
> Breakpoint 1, 0x00007ffff784ae40 in printf () from /lib/libc.so.6
> (gdb) set debug infrun 1
> (gdb) signal SIGUSR1
> Continuing with signal SIGUSR1.
> infrun: clear_proceed_status_thread (process 17569)
> infrun: proceed (addr=0xffffffffffffffff, signal=30, step=0)
> infrun: resume (step=1, signal=30), trap_expected=1
> infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
> infrun: target_wait (-1, status) = 17569, status->kind = stopped, signal = SIGTRAP
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> infrun: stop_pc = 0x400528
> ^^^^^^^^^^^^^^^^^^
> infrun: no stepping, continue
> infrun: resume (step=0, signal=0), trap_expected=0
> infrun: prepare_to_wait
> infrun: target_wait (-1, status) = 17569, status->kind = stopped, signal = SIGTRAP
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> infrun: stop_pc = 0x40052f
> infrun: BPSTAT_WHAT_STOP_NOISY
> infrun: stop_stepping
>
> Breakpoint 2, handle_USR1 (sig=10) at ../../../src/gdb/testsuite/gdb.base/annota1.c:19
> 19 }
>
> That stop was a finished single-step to the start of the signal handler:
>
> (gdb) disassemble 0x400528 (0x400528 + 100)
> Dump of assembler code from 0x400528 to 0x40058c:
> 0x0000000000400528 <handle_USR1+0>: push %rbp
> 0x0000000000400529 <handle_USR1+1>: mov %rsp,%rbp
> 0x000000000040052c <handle_USR1+4>: mov %edi,-0x4(%rbp)
> 0x000000000040052f <handle_USR1+7>: leaveq
> 0x0000000000400530 <handle_USR1+8>: retq
> (...)
>
> So, linux can single-step into a signal handler, OpenBSD doesn't.
Indeed. OpenBSD/i386 (as well as NetBSD, FreeBSD and probably Darwin)
clears the trace bit before running the signal handler.
I've looked at the PR mentioned in the commi message, and I don't
quite understand how the change to the signal command has anything to
do with that.