Skip to content
  • Chuck Ebbert's avatar
    [PATCH] i386: fix singlestep through an int80 syscall · 635cf99a
    Chuck Ebbert authored
    
    
    Using PTRACE_SINGLESTEP on a child that does an int80 syscall misses the
    SIGTRAP that should be delivered upon syscall exit.  Fix that by setting
    TIF_SINGLESTEP when entering the kernel via int80 with TF set.
    
    /* Test whether singlestep through an int80 syscall works.
     */
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/ptrace.h>
    #include <sys/wait.h>
    #include <sys/mman.h>
    #include <asm/user.h>
    
    static int child, status;
    static struct user_regs_struct regs;
    
    static void do_child()
    {
    	ptrace(PTRACE_TRACEME, 0, 0, 0);
    	kill(getpid(), SIGUSR1);
    	asm ("int $0x80" : : "a" (20)); /* getpid */
    }
    
    static void do_parent()
    {
    	unsigned long eip, expected = 0;
    again:
    	waitpid(child, &status, 0);
    	if (WIFEXITED(status) || WIFSIGNALED(status))
    		return;
    
    	if (WIFSTOPPED(status)) {
    		ptrace(PTRACE_GETREGS, child, 0, &regs);
    		eip = regs.eip;
    		if (expected)
    			fprintf(stderr, "child stop @ %08x, expected %08x %s\n",
    					eip, expected,
    					eip == expected ? "" : " <== ERROR");
    
    		if (*(unsigned short *)eip == 0x80cd) {
    			fprintf(stderr, "int 0x80 at %08x\n", (unsigned int)eip);
    			expected = eip + 2;
    		} else
    			expected = 0;
    
    		ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
    	}
    	goto again;
    }
    
    int main(int argc, char * const argv[])
    {
    	child = fork();
    	if (child)
    		do_parent();
    	else
    		do_child();
    	return 0;
    }
    
    Signed-off-by: default avatarChuck Ebbert <76306.1226@compuserve.com>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    635cf99a