[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