From 1669ce53e2ff7b49a60d0230866d3faee5f45573 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Sat, 18 Jan 2003 10:40:18 -0500 Subject: 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. --- include/linux/ptrace.h | 2 ++ include/linux/sched.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index c6de3a4ea70a..b56bbe7ca800 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -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 --git a/include/linux/sched.h b/include/linux/sched.h index 15a951d2d27e..a325e5a8c645 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -400,6 +400,7 @@ struct task_struct { 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); -- cgit v1.2.3 From 45c1a159b85b3b30afd26a77b4be312226bba416 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Thu, 6 Feb 2003 04:32:29 -0500 Subject: Add PTRACE_O_TRACEVFORKDONE and PTRACE_O_TRACEEXIT facilities. --- include/linux/ptrace.h | 4 ++++ include/linux/sched.h | 2 ++ kernel/exit.c | 3 +++ kernel/fork.c | 6 ++++-- kernel/ptrace.c | 13 ++++++++++++- 5 files changed, 25 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index b56bbe7ca800..706b420fb5c9 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -35,12 +35,16 @@ #define PTRACE_O_TRACEVFORK 0x00000004 #define PTRACE_O_TRACECLONE 0x00000008 #define PTRACE_O_TRACEEXEC 0x00000010 +#define PTRACE_O_TRACEVFORKDONE 0x00000020 +#define PTRACE_O_TRACEEXIT 0x00000040 /* Wait extended result codes for the above trace options. */ #define PTRACE_EVENT_FORK 1 #define PTRACE_EVENT_VFORK 2 #define PTRACE_EVENT_CLONE 3 #define PTRACE_EVENT_EXEC 4 +#define PTRACE_EVENT_VFORK_DONE 5 +#define PTRACE_EVENT_EXIT 6 #include #include diff --git a/include/linux/sched.h b/include/linux/sched.h index a325e5a8c645..c424a353a748 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -441,6 +441,8 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PT_TRACE_VFORK 0x00000020 #define PT_TRACE_CLONE 0x00000040 #define PT_TRACE_EXEC 0x00000080 +#define PT_TRACE_VFORK_DONE 0x00000100 +#define PT_TRACE_EXIT 0x00000200 #if CONFIG_SMP extern void set_cpus_allowed(task_t *p, unsigned long new_mask); diff --git a/kernel/exit.c b/kernel/exit.c index 03801540a5e6..5cb58a1d2075 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -653,6 +653,9 @@ NORET_TYPE void do_exit(long code) profile_exit_task(tsk); + if (unlikely(current->ptrace & PT_TRACE_EXIT)) + ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP); + fake_volatile: acct_process(code); __exit_mm(tsk); diff --git a/kernel/fork.c b/kernel/fork.c index 347f957b080e..3da82d978812 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1046,9 +1046,11 @@ struct task_struct *do_fork(unsigned long clone_flags, ptrace_notify ((trace << 8) | SIGTRAP); } - if (clone_flags & CLONE_VFORK) + if (clone_flags & CLONE_VFORK) { wait_for_completion(&vfork); - else + if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) + ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); + } else /* * Let the child process run first, to avoid most of the * COW overhead when the child exec()s afterwards. diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 9f3769bfdc7e..14d158864d9e 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -277,9 +277,20 @@ static int ptrace_setoptions(struct task_struct *child, long data) else child->ptrace &= ~PT_TRACE_EXEC; + if (data & PTRACE_O_TRACEVFORKDONE) + child->ptrace |= PT_TRACE_VFORK_DONE; + else + child->ptrace &= ~PT_TRACE_VFORK_DONE; + + if (data & PTRACE_O_TRACEEXIT) + child->ptrace |= PT_TRACE_EXIT; + else + child->ptrace &= ~PT_TRACE_EXIT; + if ((data & (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE - | PTRACE_O_TRACEEXEC)) + | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT + | PTRACE_O_TRACEVFORKDONE)) != data) return -EINVAL; -- cgit v1.2.3