Bug 133794 - On amd64 PTRACE_SINGLESTEP to deliver signal runs handler without single-step
Summary: On amd64 PTRACE_SINGLESTEP to deliver signal runs handler without single-step
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: kernel
Version: 3.0
Hardware: x86_64
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jim Paradis
QA Contact: Brian Brock
URL:
Whiteboard:
Depends On:
Blocks: 116894 117972 127692
TreeView+ depends on / blocked
 
Reported: 2004-09-27 14:54 UTC by Andrew Cagney
Modified: 2007-11-30 22:07 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2004-12-20 20:56:43 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2004:550 0 normal SHIPPED_LIVE Updated kernel packages available for Red Hat Enterprise Linux 3 Update 4 2004-12-20 05:00:00 UTC

Description Andrew Cagney 2004-09-27 14:54:12 UTC
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.

Comment 1 Elena Zannoni 2004-10-11 15:00:43 UTC
What's the status on this bug? It block a gdb blocker-mustfix for U4.
Is it going to be addresses for U4?


Comment 4 Jim Paradis 2004-10-15 03:27:13 UTC
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.



Comment 5 Ernie Petrides 2004-10-22 23:27:46 UTC
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).


Comment 7 John Flanagan 2004-12-20 20:56:43 UTC
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



Note You need to log in before you can comment on or make changes to this bug.