Commit 2fc7d762 authored by Linus Torvalds's avatar Linus Torvalds Committed by Linus Torvalds

x86: clean up ptrace single-stepping, make PT_DTRACE exact.

(This makes the naming of "DTRACE" purely historical, since
on x86 it now means "single step in progress").
parent 6cff2b97
......@@ -138,6 +138,28 @@ static unsigned long getreg(struct task_struct *child,
return retval;
}
static void set_singlestep(struct task_struct *child)
{
long eflags;
set_tsk_thread_flag(child, TIF_SINGLESTEP);
eflags = get_stack_long(child, EFL_OFFSET);
put_stack_long(child, EFL_OFFSET, eflags | TRAP_FLAG);
child->ptrace |= PT_DTRACE;
}
static void clear_singlestep(struct task_struct *child)
{
if (child->ptrace & PT_DTRACE) {
long eflags;
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
eflags = get_stack_long(child, EFL_OFFSET);
put_stack_long(child, EFL_OFFSET, eflags & ~TRAP_FLAG);
child->ptrace &= ~PT_DTRACE;
}
}
/*
* Called by kernel/ptrace.c when detaching..
*
......@@ -145,11 +167,7 @@ static unsigned long getreg(struct task_struct *child,
*/
void ptrace_disable(struct task_struct *child)
{
long tmp;
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
clear_singlestep(child);
}
/*
......@@ -388,10 +406,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
long tmp;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: /* restart after signal. */
ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
......@@ -401,56 +417,39 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else {
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
}
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET,tmp);
/* make sure the single step bit is not set. */
clear_singlestep(child);
wake_up_process(child);
ret = 0;
break;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
long tmp;
case PTRACE_KILL:
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
clear_singlestep(child);
wake_up_process(child);
break;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
case PTRACE_SINGLESTEP: /* set the trap flag. */
ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
if ((child->ptrace & PT_DTRACE) == 0) {
/* Spurious delayed TF traps may occur */
child->ptrace |= PT_DTRACE;
}
tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
set_tsk_thread_flag(child, TIF_SINGLESTEP);
set_singlestep(child);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}
case PTRACE_DETACH:
/* detach a process that was attached. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment