[PATCH 51] implement PTRACE_SINGLESTEP/PTRACE_SINGLEBLOCK
Oleg Nesterov
oleg at redhat.com
Wed Sep 23 00:26:27 UTC 2009
Change ptrace_resume() path to pass the correct "action" argument
to utrace_control(), the current code always uses UTRACE_RESUME
while PTRACE_SINGLEXXX needs UTRACE_XXXSTEP.
Introduce ptrace_context->resume to remember this action, we have
to re-assert it from report_quiesce/report_signal callbacks.
The next patch changes ptrace_report_signal(UTRACE_SIGNAL_HANDLER).
---
kernel/ptrace.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
--- PU/kernel/ptrace.c~51_STEP_SIMPLE 2009-09-17 21:03:11.000000000 +0200
+++ PU/kernel/ptrace.c 2009-09-23 00:50:28.000000000 +0200
@@ -25,7 +25,7 @@
#include <linux/uaccess.h>
typedef void (*resume_func_t)(struct utrace_engine *,
- struct task_struct*, long);
+ struct task_struct*, long);
struct ptrace_event {
int ev_code;
@@ -42,6 +42,8 @@ struct ptrace_context {
struct ptrace_event ev_array[2];
unsigned int ev_first, ev_last;
+
+ enum utrace_resume_action resume;
};
static inline bool ev_empty(struct ptrace_context *context)
@@ -348,6 +350,7 @@ static u32 ptrace_report_signal(u32 acti
struct k_sigaction *return_ka)
{
struct ptrace_context *context = ptrace_context(engine);
+ enum utrace_resume_action resume = context->resume;
struct ptrace_event *ev;
if (!ev_empty(context)) {
@@ -362,27 +365,27 @@ static u32 ptrace_report_signal(u32 acti
WARN_ON(1);
case UTRACE_SIGNAL_REPORT:
if (!context->siginfo)
- return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
+ return resume | UTRACE_SIGNAL_IGN;
if (WARN_ON(context->siginfo != info))
- return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
+ return resume | UTRACE_SIGNAL_IGN;
context->siginfo = NULL;
if (!info->si_signo) // debugger cancelled sig
- return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
+ return resume | UTRACE_SIGNAL_IGN;
/*
* If the (new) signal is now blocked, requeue it.
*/
if (sigismember(&task->blocked, info->si_signo)) {
send_sig_info(info->si_signo, info, task);
- return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
+ return resume | UTRACE_SIGNAL_IGN;
}
spin_lock_irq(&task->sighand->siglock);
*return_ka = task->sighand->action[info->si_signo - 1];
spin_unlock_irq(&task->sighand->siglock);
- return UTRACE_RESUME | UTRACE_SIGNAL_DELIVER;
+ return resume | UTRACE_SIGNAL_DELIVER;
default:
WARN_ON(context->siginfo);
@@ -411,7 +414,7 @@ static u32 ptrace_report_quiesce(u32 act
return UTRACE_STOP;
}
- return UTRACE_RESUME;
+ return event ? UTRACE_RESUME : context->resume;
}
static void ptrace_release(void *data)
@@ -463,6 +466,8 @@ static int ptrace_attach_task(struct tas
if (unlikely(!context))
return -ENOMEM;
+ context->resume = UTRACE_RESUME;
+
engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE |
UTRACE_ATTACH_EXCLUSIVE |
UTRACE_ATTACH_MATCH_OPS,
@@ -924,6 +929,7 @@ static void ptrace_wake_up(struct utrace
static void do_ptrace_resume(struct utrace_engine *engine,
struct task_struct *tracee,
+ enum utrace_resume_action action,
long request, long data)
{
struct ptrace_context *context = ptrace_context(engine);
@@ -950,7 +956,8 @@ static void do_ptrace_resume(struct utra
}
}
- ptrace_wake_up(engine, tracee, UTRACE_RESUME);
+ context->resume = action;
+ ptrace_wake_up(engine, tracee, action);
}
static int ptrace_resume(struct utrace_engine *engine,
@@ -992,7 +999,7 @@ static int ptrace_resume(struct utrace_e
}
if (!ret)
- do_ptrace_resume(engine, child, request, data);
+ do_ptrace_resume(engine, child, action, request, data);
return ret;
}
More information about the utrace-devel
mailing list