lkml.org 
[lkml]   [2003]   [Feb]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectPtrace 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/

    \
     
     \ /
      Last update: 2005-03-22 13:33    [W:0.034 / U:0.120 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site