Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | Date | Thu, 6 Feb 2003 17:41:32 -0500 | From | Daniel Jacobowitz <> | Subject | Ptrace updates: PTRACE_GETSIGINFO [2/5] |
| |
This patch adds PTRACE_GETSIGINFO and PTRACE_SETSIGINFO, as suggested by someone on linux-kernel (discussion between Andi Kleen and Roland McGrath, I think). You can use these to query the information about a signal or forge it, which is useful if (for instance) a debugger needs to queue a signal for later delivery.
This implements the feature for all architectures which use the generic get_signal_to_deliver. Doing it for the rest is straightforward.
# -------------------------------------------- # 03/01/18 drow@nevyn.them.org 1.958 # Add PTRACE_GETSIGINFO and PTRACE_SETSIGINFO # # These new ptrace commands allow a debugger to control signals more precisely; # for instance, store a signal and deliver it later, as if it had come from the # original outside process or in response to the same faulting memory access. # --------------------------------------------
diff -Nru a/include/linux/ptrace.h b/include/linux/ptrace.h --- a/include/linux/ptrace.h Thu Feb 6 16:57:36 2003 +++ b/include/linux/ptrace.h Thu Feb 6 16:57:36 2003 @@ -26,6 +26,8 @@ /* 0x4200-0x4300 are reserved for architecture-independent additions. */ #define PTRACE_SETOPTIONS 0x4200 #define PTRACE_GETEVENTMSG 0x4201 +#define PTRACE_GETSIGINFO 0x4202 +#define PTRACE_SETSIGINFO 0x4203 /* options set using PTRACE_SETOPTIONS */ #define PTRACE_O_TRACESYSGOOD 0x00000001 diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Thu Feb 6 16:57:36 2003 +++ b/include/linux/sched.h Thu Feb 6 16:57:36 2003 @@ -400,6 +400,7 @@ struct backing_dev_info *backing_dev_info; unsigned long ptrace_message; + siginfo_t *last_siginfo; /* For ptrace use. */ }; extern void __put_task_struct(struct task_struct *tsk); diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c --- a/kernel/ptrace.c Thu Feb 6 16:57:36 2003 +++ b/kernel/ptrace.c Thu Feb 6 16:57:36 2003 @@ -286,6 +286,23 @@ return 0; } +static int ptrace_getsiginfo(struct task_struct *child, long data) +{ + if (child->last_siginfo == NULL) + return -EINVAL; + return copy_siginfo_to_user ((siginfo_t *) data, child->last_siginfo); +} + +static int ptrace_setsiginfo(struct task_struct *child, long data) +{ + if (child->last_siginfo == NULL) + return -EINVAL; + if (copy_from_user (child->last_siginfo, (siginfo_t *) data, + sizeof (siginfo_t)) != 0) + return -EFAULT; + return 0; +} + int ptrace_request(struct task_struct *child, long request, long addr, long data) { @@ -300,6 +317,12 @@ break; case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned long *) data); + break; + case PTRACE_GETSIGINFO: + ret = ptrace_getsiginfo(child, data); + break; + case PTRACE_SETSIGINFO: + ret = ptrace_setsiginfo(child, data); break; default: break; diff -Nru a/kernel/signal.c b/kernel/signal.c --- a/kernel/signal.c Thu Feb 6 16:57:36 2003 +++ b/kernel/signal.c Thu Feb 6 16:57:36 2003 @@ -1244,10 +1244,13 @@ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; + current->last_siginfo = info; set_current_state(TASK_STOPPED); notify_parent(current, SIGCHLD); schedule(); + current->last_siginfo = NULL; + /* We're back. Did the debugger cancel the sig? */ signr = current->exit_code; if (signr == 0) @@ -1258,7 +1261,10 @@ if (signr == SIGSTOP) continue; - /* Update the siginfo structure. Is this good? */ + /* Update the siginfo structure if the signal has + changed. If the debugger wanted something + specific in the siginfo structure then it should + have updated *info via PTRACE_SETSIGINFO. */ if (signr != info->si_signo) { info->si_signo = signr; info->si_errno = 0; -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| ![\](/images/icornerr.gif) |