Regression

Mark Kettenis mark.kettenis@xs4all.nl
Tue Feb 10 18:40:00 GMT 2009


> 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.



More information about the Gdb mailing list