Regression

Pedro Alves pedro@codesourcery.com
Tue Feb 10 18:00:00 GMT 2009


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.

-- 
Pedro Alves



More information about the Gdb mailing list