On Wed, 29 Dec 2004, Linus Torvalds wrote: > On Wed, 29 Dec 2004, Jesse Allen wrote: > > > > > > So instead of removing the setting of TIF_SINGLESTEP in set_singlestep(), > > > can you test whether removing the _testing_ of it in do_syscall_trace() > > > makes things happier for you? Hmm? > > > > > > > Yes, doing that does work. But I still have to remove the conditional > > TF clear. Here's the diff now to show you. > > Ok. That's a good piece of information. > > I don't actually understand why do_syscall_trace() does that > TIF_SINGLESTEP test in the first place, since the ptrace_notify() should > happen as part of the _normal_ TIF_SINGLESTEP handling, afaiks. No > apparent need to do it in syscall tracing, and do_syscall_trace() does > that bogus fake signal sending. > > Hmm.. That TF_SINGLESTEP test was added by Davide Libenzi in August, and I > think Davide had some test for exactly this. Davide? Can you recall why > you did this in the system call tracing code, rather than depend on the > regular TIF_SINGLESTEP handling in arch/i386/kernel/signal.c: > do_notify_resume()?
That test went in to be able to have ptrace single step, to see even the instruction following the #int instruction (this was the target of the patch itself). I just verified that, in 2.6.8 that does not have such test anymore, the single-step-after-int capability is lost. Below I inlining a simple test program (that I already sent you time ago) to test this. In my 2.6.8 I get this output: waiting ... done: pid=21398 status=1407 sig=5 EIP=0x080485d5 waiting ... done: pid=21398 status=1407 sig=5 EIP=0x080485da waiting ... done: pid=21398 status=1407 sig=5 EIP=0x080485df waiting ... done: pid=21398 status=1407 sig=5 EIP=0x080485d5 waiting ... done: pid=21398 status=1407 sig=5 EIP=0x080485da waiting ... done: pid=21398 status=1407 sig=5 EIP=0x080485df in front of this code: 80485d5: b8 14 00 00 00 mov $0x14,%eax 80485da: cd 80 int $0x80 80485dc: 89 45 ec mov %eax,0xffffffec(%ebp) 80485df: eb f4 jmp 80485d5 <main+0x85> You can see that the "mov %eax,0xffffffec(%ebp)" instruction at 0x80485dc is not seen by ptrace single step. With the test in place, it will show up again in your traces. - Davide #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <linux/user.h> #include <linux/unistd.h> int main(int ac, char **av) { int i, status, res; long start, end; pid_t cpid, pid; struct user_regs_struct ur; struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); printf("nargs=%d\n", ac); if (ac == 1) goto tracer; printf("arg=%s\n", av[1]); loop: __asm__ volatile ("int $0x80" : "=a" (res) : "0" (__NR_getpid)); goto loop; endloop: exit(0); tracer: if ((cpid = fork()) != 0) goto parent; printf("child=%d\n", getpid()); ptrace(PTRACE_TRACEME, 0, NULL, NULL); execl(av[0], av[0], "child", NULL); exit(0); parent: start = (long) &&loop; end = (long) &&endloop; printf("pchild=%d\n", cpid); for (;;) { pid = wait(&status); if (pid != cpid) continue; res = WSTOPSIG(status); if (ptrace(PTRACE_GETREGS, pid, NULL, &ur)) { printf("[%d] error: ptrace(PTRACE_GETREGS, %d)\n", pid, pid); return 1; } if (ptrace(PTRACE_SINGLESTEP, pid, NULL, res != SIGTRAP ? res: 0)) { perror("ptrace(PTRACE_SINGLESTEP)"); return 1; } if (ur.eip >= start && ur.eip <= end) break; } for (i = 0; i < 15; i++) { printf("waiting ...\n"); pid = wait(&status); printf("done: pid=%d status=%d\n", pid, status); if (pid != cpid) continue; res = WSTOPSIG(status); printf("sig=%d\n", res); if (ptrace(PTRACE_GETREGS, pid, NULL, &ur)) { printf("[%d] error: ptrace(PTRACE_GETREGS, %d)\n", pid, pid); return 1; } printf("EIP=0x%08x\n", ur.eip); if (ptrace(PTRACE_SINGLESTEP, pid, NULL, res != SIGTRAP ? res: 0)) { perror("ptrace(PTRACE_SINGLESTEP)"); return 1; } } if (ptrace(PTRACE_CONT, cpid, NULL, SIGKILL)) { perror("ptrace(PTRACE_SINGLESTEP)"); return 1; } return 0; }