Bug 133782 - On PowerPC PTRACE_SINGLESTEP to deliver signal runs handler without single-step
On PowerPC PTRACE_SINGLESTEP to deliver signal runs handler without single-step
Status: CLOSED ERRATA
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: kernel (Show other bugs)
3.0
powerpc Linux
medium Severity medium
: ---
: ---
Assigned To: David Woodhouse
Brian Brock
:
Depends On:
Blocks: 116894 117972 127692
  Show dependency treegraph
 
Reported: 2004-09-27 09:08 EDT by Andrew Cagney
Modified: 2007-11-30 17:07 EST (History)
6 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2004-12-20 15:56:42 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Andrew Cagney 2004-09-27 09:08:45 EDT
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 15:30:09 EDT
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 18:01:58 EDT
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 19:43:44 EDT
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 13:47:30 EDT
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 19:44:11 EDT
James, that's probably a good idea.
Comment 19 Ernie Petrides 2004-11-08 18:30:01 EST
James/Andrew/David, is there a new bugzilla for the ppc64 siginfo problems?
Comment 20 David Woodhouse 2004-11-08 18:32:17 EST
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 17:24:57 EST
The original bug is fixed; The second bug isn't but that should really
be filed separately.
Comment 23 Ernie Petrides 2004-12-03 18:48:38 EST
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 15:56:42 EST
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.