This is taken from i386 (bz 130995), amd64 exibits the same symptoms: Description of problem: The ptrace(PT_STEP,SIGALARM) system call instead implements ptrace(PT_CONTINUE,SIGALARM). Version-Release number of selected component (if applicable): Roland says this is present in all i386 kernels. How reproducible: Always. Steps to Reproduce: In the below, target_resume(...) corresponds directly to a ptrace call. cagney@tomago$ gdb ./a.out [...] (gdb) b handler Breakpoint 1 at 0x80483bb: file sigstep.c, line 31. (gdb) list main 39 itimer_real = ITIMER_REAL, 40 itimer_virtual = ITIMER_VIRTUAL 41 } itimer = ITIMER_REAL; /* ITIMER_VIRTUAL; */ 42 43 main () 44 { 45 46 /* Set up the signal handler. */ 47 memset (&action, 0, sizeof (action)); 48 action.sa_handler = handler; (gdb) 49 sigaction (SIGVTALRM, &action, NULL); 50 sigaction (SIGALRM, &action, NULL); 51 52 /* The values needed for the itimer. This needs to be at least long 53 enough for the setitimer() call to return. */ 54 memset (&itime, 0, sizeof (itime)); 55 itime.it_value.tv_usec = 250 * 1000; 56 57 /* Loop for ever, constantly taking an interrupt. */ 58 while (1) (gdb) 59 { 60 /* Set up a one-off timer. A timer, rather than SIGSEGV, is 61 used as after a timer handler finishes the interrupted code 62 can safely resume. */ 63 setitimer (itimer, &itime, NULL); 64 /* Wait. */ 65 while (!done); 66 done = 0; 67 } 68 } (gdb) break 65 Breakpoint 2 at 0x8048456: file sigstep.c, line 65. (gdb) set debug target 1 (gdb) run Starting program: /home/cagney/tmp/sigstep/a.out [...] Breakpoint 2, main () at sigstep.c:65 65 while (!done); (gdb) step target_terminal_inferior () target_xfer_memory (0x8048456, xxx, 2, read, xxx) = 2, bytes = a1 64 Try to step off breakpoint, get back SIGALRM (ok), EIP doesn't change (ok). target_resume (27256, step, 0) target_wait (-1, status) = 27256, status->kind = stopped, signal = SIGALRM target_fetch_registers (eip) = 56840408 0x8048456 134513750 target_terminal_inferior () target_xfer_memory (0x8048456, xxx, 2, read, xxx) = 2, bytes = a1 64 Try to deliver SIGALRM, get back SIGTRAP (ok), EIP didn't change (not ok, should have been handler or signal trampoline). target_resume (27256, step, SIGALRM) target_wait (-1, status) = 27256, status->kind = stopped, signal = SIGTRAP target_fetch_registers (eip) = 56840408 0x8048456 134513750 target_xfer_memory (0x80483bb, xxx, 1, read, xxx) = 1, bytes = c7 target_xfer_memory (0x80483bb, xxx, 1, write, xxx) = 1, bytes = cc target_insert_breakpoint (0x80483bb, xxx) = 0 target_xfer_memory (0x8048456, xxx, 1, read, xxx) = 1, bytes = a1 target_xfer_memory (0x8048456, xxx, 1, write, xxx) = 1, bytes = cc target_insert_breakpoint (0x8048456, xxx) = 0 target_xfer_memory (0x4e02b0, xxx, 1, read, xxx) = 1, bytes = 55 target_xfer_memory (0x4e02b0, xxx, 1, write, xxx) = 1, bytes = cc target_insert_breakpoint (0x4e02b0, xxx) = 0 target_xfer_memory (0x4e3310, xxx, 1, read, xxx) = 1, bytes = 55 target_xfer_memory (0x4e3310, xxx, 1, write, xxx) = 1, bytes = cc target_insert_breakpoint (0x4e3310, xxx) = 0 target_xfer_memory (0x320820, xxx, 1, read, xxx) = 1, bytes = 55 target_xfer_memory (0x320820, xxx, 1, write, xxx) = 1, bytes = cc target_insert_breakpoint (0x320820, xxx) = 0 target_terminal_inferior () target_xfer_memory (0x8048457, xxx, 1, read, xxx) = 1, bytes = 64 GDB thinks it's still single stepping in main() so tries to do another single-step but with breakpoints inserted (it assumed the above managed to step off the breakpoint at 65). Since the PC didn't change, it re-hits the breakpoint at 65 causing a SIGTRAP and an off-by-one PC - decremented so that it matches the breakpoint. target_resume (-1, step, 0) target_wait (-1, status) = 27256, status->kind = stopped, signal = SIGTRAP target_fetch_registers (eip) = 57840408 0x8048457 134513751 target_prepare_to_store () target_store_registers (eip) = 56840408 0x8048456 134513750 target_xfer_memory (0x80483bb, xxx, 1, write, xxx) = 1, bytes = c7 target_remove_breakpoint (0x80483bb, xxx) = 0 target_xfer_memory (0x8048456, xxx, 1, write, xxx) = 1, bytes = a1 target_remove_breakpoint (0x8048456, xxx) = 0 target_xfer_memory (0x4e02b0, xxx, 1, write, xxx) = 1, bytes = 55 target_remove_breakpoint (0x4e02b0, xxx) = 0 target_xfer_memory (0x4e3310, xxx, 1, write, xxx) = 1, bytes = 55 target_remove_breakpoint (0x4e3310, xxx) = 0 target_xfer_memory (0x320820, xxx, 1, write, xxx) = 1, bytes = 55 target_remove_breakpoint (0x320820, xxx) = 0 target_terminal_ours () Breakpoint 2, main () at sigstep.c:65 65 while (!done); (gdb) The ptrace(PT_STEP,SIGNAL) should setup the signal and then execute no instructions.
What's the status on this bug? It block a gdb blocker-mustfix for U4. Is it going to be addresses for U4?
I have verified that the patch attached to bug 130995 does indeed fix this issue for x86_64, for both 64-bit native and 32-bit compatibility modes. This patch is part of U4.
The patch that Jim refers to was committed to the RHEL3 U4 patch pool on 19-Sep-2004 (in kernel version 2.4.21-20.8.EL).
An errata has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2004-550.html