aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/ptrace.c
diff options
context:
space:
mode:
authorBodo Stroesser <bstroesser@fujitsu-siemens.com>2005-09-03 18:57:20 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:20 -0400
commit1b38f0064e4e0b9ec626e39f0740b1cf2e295743 (patch)
treeb5e3af88b23bd47d91c4745a3e0c61512f58ff21 /arch/i386/kernel/ptrace.c
parentc8c86cecd1d1a2722acb28a01d1babf7b6993697 (diff)
[PATCH] Uml support: add PTRACE_SYSEMU_SINGLESTEP option to i386
This patch implements the new ptrace option PTRACE_SYSEMU_SINGLESTEP, which can be used by UML to singlestep a process: it will receive SINGLESTEP interceptions for normal instructions and syscalls, but syscall execution will be skipped just like with PTRACE_SYSEMU. Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com> Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/ptrace.c')
-rw-r--r--arch/i386/kernel/ptrace.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 18642f05dde1..3196ba50fcd5 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -547,11 +547,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
547 wake_up_process(child); 547 wake_up_process(child);
548 break; 548 break;
549 549
550 case PTRACE_SYSEMU_SINGLESTEP: /* Same as SYSEMU, but singlestep if not syscall */
550 case PTRACE_SINGLESTEP: /* set the trap flag. */ 551 case PTRACE_SINGLESTEP: /* set the trap flag. */
551 ret = -EIO; 552 ret = -EIO;
552 if (!valid_signal(data)) 553 if (!valid_signal(data))
553 break; 554 break;
554 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 555
556 if (request == PTRACE_SYSEMU_SINGLESTEP)
557 set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
558 else
559 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
560
555 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 561 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
556 set_singlestep(child); 562 set_singlestep(child);
557 child->exit_code = data; 563 child->exit_code = data;
@@ -686,7 +692,10 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
686__attribute__((regparm(3))) 692__attribute__((regparm(3)))
687int do_syscall_trace(struct pt_regs *regs, int entryexit) 693int do_syscall_trace(struct pt_regs *regs, int entryexit)
688{ 694{
689 int is_sysemu, is_singlestep, ret = 0; 695 int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU), ret = 0;
696 /* With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP */
697 int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
698
690 /* do the secure computing check first */ 699 /* do the secure computing check first */
691 secure_computing(regs->orig_eax); 700 secure_computing(regs->orig_eax);
692 701
@@ -696,8 +705,11 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
696 if (!(current->ptrace & PT_PTRACED)) 705 if (!(current->ptrace & PT_PTRACED))
697 goto out; 706 goto out;
698 707
699 is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); 708 /* If a process stops on the 1st tracepoint with SYSCALL_TRACE
700 is_singlestep = test_thread_flag(TIF_SINGLESTEP); 709 * and then is resumed with SYSEMU_SINGLESTEP, it will come in
710 * here. We have to check this and return */
711 if (is_sysemu && entryexit)
712 return 0;
701 713
702 /* Fake a debug trap */ 714 /* Fake a debug trap */
703 if (is_singlestep) 715 if (is_singlestep)
@@ -728,6 +740,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
728 if (ret == 0) 740 if (ret == 0)
729 return 0; 741 return 0;
730 742
743 regs->orig_eax = -1; /* force skip of syscall restarting */
731 if (unlikely(current->audit_context)) 744 if (unlikely(current->audit_context))
732 audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax); 745 audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
733 return 1; 746 return 1;