Bug 133782

Summary: On PowerPC PTRACE_SINGLESTEP to deliver signal runs handler without single-step
Product: Red Hat Enterprise Linux 3 Reporter: Andrew Cagney <cagney>
Component: kernelAssignee: David Woodhouse <dwmw2>
Status: CLOSED ERRATA QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 3.0CC: dwmw2, jlaska, peterm, petrides, riel, roland
Target Milestone: ---   
Target Release: ---   
Hardware: powerpc   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-12-20 20:56:42 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 116894, 117972, 127692    

Description Andrew Cagney 2004-09-27 13:08:45 UTC
Example from BZ 130995

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 8 Ernie Petrides 2004-10-12 19:30:09 UTC
Thanks, David.

Andrew, could you please verify that this bug has been fixed by
testing on p630.lab.boston.redhat.com (or installing a kernel
from porkchop as described in comment #6)?

Comment 9 Andrew Cagney 2004-10-14 22:01:58 UTC
In 32-bit mode, the PT_STEP, it's issuing one instruction after
constructing the signal frame.  It should just construct the signal
frame, adjust the PC to signal-handler address and then fake a
sigtrap.  See the corresponding i386 PR for the background.

(gdb) b 65 
Breakpoint 1 at 0x10000550: file sigstep.c, line 65.
(gdb) run
Starting program: /tmp/cagney/sigstep 
Breakpoint 1, main () at sigstep.c:65
65            while (!done);
(gdb) break *handler
Breakpoint 2 at 0x10000480: file sigstep.c, line 30.
(gdb) stepi
0x10000554      65            while (!done);

in detail:

(gdb) stepi
target_xfer_memory (0x100004ac, xxx, 4, read, xxx) = 4, bytes = 94 21
ff e0
target_xfer_memory (0x100004b0, xxx, 4, read, xxx) = 4, bytes = 7c 08
02 a6
target_xfer_memory (0x100004b4, xxx, 4, read, xxx) = 4, bytes = 93 e1
00 1c
target_xfer_memory (0x100004b8, xxx, 4, read, xxx) = 4, bytes = 90 01
00 24
target_xfer_memory (0x100004bc, xxx, 4, read, xxx) = 4, bytes = 7c 3f
0b 78
target_xfer_memory (0x100004c0, xxx, 4, read, xxx) = 4, bytes = 3d 20
10 01
target_fetch_registers (r1) = ffffdbe0 0xffffdbe0 4294958048
target_xfer_memory (0xffffdbe0, xxx, 4, read, xxx) = 4, bytes = ff ff
dc 00
target_fetch_registers (r31) = ffffdbe0 0xffffdbe0 4294958048
target_terminal_inferior ()
target_resume (10456, step, 0)
target_wait (-1, status) = 10456,   status->kind = stopped, signal =
SIGALRM
target_fetch_registers (pc) = 10000550 0x10000550 268436816
target_xfer_memory (0x10000550, xxx, 4, read, xxx) = 4, bytes = 3d 20
10 01
target_xfer_memory (0x1000054c, xxx, 4, read, xxx) = 4, bytes = 48 01
05 55
target_xfer_memory (0x10000550, xxx, 4, read, xxx) = 4, bytes = 3d 20
10 01
target_xfer_memory (0x1000054c, xxx, 4, read, xxx) = 4, bytes = 48 01
05 55
target_xfer_memory (0x100004ac, xxx, 4, read, xxx) = 4, bytes = 94 21
ff e0
target_xfer_memory (0x100004b0, xxx, 4, read, xxx) = 4, bytes = 7c 08
02 a6
target_xfer_memory (0x100004b4, xxx, 4, read, xxx) = 4, bytes = 93 e1
00 1c
target_xfer_memory (0x100004b8, xxx, 4, read, xxx) = 4, bytes = 90 01
00 24
target_xfer_memory (0x100004bc, xxx, 4, read, xxx) = 4, bytes = 7c 3f
0b 78
target_xfer_memory (0x100004c0, xxx, 4, read, xxx) = 4, bytes = 3d 20
10 01
target_fetch_registers (r1) = ffffdbe0 0xffffdbe0 4294958048
target_xfer_memory (0xffffdbe0, xxx, 4, read, xxx) = 4, bytes = ff ff
dc 00
target_fetch_registers (r31) = ffffdbe0 0xffffdbe0 4294958048
target_terminal_inferior ()
target_resume (10456, step, SIGALRM)
target_wait (-1, status) = 10456,   status->kind = stopped, signal =
SIGTRAP
target_fetch_registers (pc) = 10000484 0x10000484 268436612

Notice how the resume/step/sigalarm stopped at 0x10000484 and not
0x10000480.

I think 64-bit PPC has the same problem.


Comment 16 Ernie Petrides 2004-10-28 23:43:44 UTC
The patch in comment #12 has just been committed to the RHEL3 U4
patch pool this evening (in kernel version 2.4.21-23.EL).  The
additional siginfo problem will be fixed in U5.


Comment 17 James Laska 2004-10-29 17:47:30 UTC
ernie: it sounds as if there are 2 issues gathered in this one bug.  Would it
make sense to move the siginfo problem into a seperate bug targetted for a
RHEL3-U5 Blocker list?

Comment 18 Ernie Petrides 2004-10-29 23:44:11 UTC
James, that's probably a good idea.


Comment 19 Ernie Petrides 2004-11-08 23:30:01 UTC
James/Andrew/David, is there a new bugzilla for the ppc64 siginfo problems?

Comment 20 David Woodhouse 2004-11-08 23:32:17 UTC
Not AFAIK; Paulus fixed them before Andrew had a chance to track them
down and make a properly coherent report.

Comment 22 David Woodhouse 2004-12-03 22:24:57 UTC
The original bug is fixed; The second bug isn't but that should really
be filed separately.

Comment 23 Ernie Petrides 2004-12-03 23:48:38 UTC
This bug report is considered fully resolved in U4 and will be closed
when the U4 advisory is pushed on RHN.  I'm removing it from the U5
blocker list.  The ppc64 siginfo rework was committed to 2.4.21-24.EL.

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