Skip to content

Commit

Permalink
Merge branch 'x86/tracehook' into x86-v28-for-linus-phase1
Browse files Browse the repository at this point in the history
Conflicts:
	arch/x86/kernel/signal_64.c

Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Ingo Molnar committed Oct 6, 2008
2 parents 0962f40 + 4ab4ba3 commit b159d7a
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 66 deletions.
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ config X86
select HAVE_FTRACE
select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
select HAVE_ARCH_KGDB if !X86_VOYAGER
select HAVE_ARCH_TRACEHOOK
select HAVE_GENERIC_DMA_COHERENT if X86_32
select HAVE_EFFICIENT_UNALIGNED_ACCESS

Expand Down
34 changes: 6 additions & 28 deletions arch/x86/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/regset.h>
#include <linux/tracehook.h>
#include <linux/user.h>
#include <linux/elf.h>
#include <linux/security.h>
Expand Down Expand Up @@ -1469,30 +1470,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
force_sig_info(SIGTRAP, &info, tsk);
}

static void syscall_trace(struct pt_regs *regs)
{
if (!(current->ptrace & PT_PTRACED))
return;

#if 0
printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
current->comm,
regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0),
current_thread_info()->flags, current->ptrace);
#endif

ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (current->exit_code) {
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
}

#ifdef CONFIG_X86_32
# define IS_IA32 1
Expand Down Expand Up @@ -1526,8 +1503,9 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs)
if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
ret = -1L;

if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
syscall_trace(regs);
if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
tracehook_report_syscall_entry(regs))
ret = -1L;

if (unlikely(current->audit_context)) {
if (IS_IA32)
Expand All @@ -1553,7 +1531,7 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);

if (test_thread_flag(TIF_SYSCALL_TRACE))
syscall_trace(regs);
tracehook_report_syscall_exit(regs, 0);

/*
* If TIF_SYSCALL_EMU is set, we only get here because of
Expand All @@ -1569,6 +1547,6 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs)
* system call instruction.
*/
if (test_thread_flag(TIF_SINGLESTEP) &&
(current->ptrace & PT_PTRACED))
tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
send_sigtrap(current, regs, 0);
}
11 changes: 9 additions & 2 deletions arch/x86/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/tracehook.h>
#include <linux/elf.h>
#include <linux/smp.h>
#include <linux/mm.h>
Expand Down Expand Up @@ -559,8 +560,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* handler too.
*/
regs->flags &= ~X86_EFLAGS_TF;
if (test_thread_flag(TIF_SINGLESTEP))
ptrace_notify(SIGTRAP);

spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
Expand All @@ -569,6 +568,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);

tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));

return 0;
}

Expand Down Expand Up @@ -662,5 +664,10 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);

if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}

clear_thread_flag(TIF_IRET);
}
49 changes: 14 additions & 35 deletions arch/x86/kernel/signal_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/personality.h>
Expand All @@ -26,6 +27,7 @@
#include <asm/proto.h>
#include <asm/ia32_unistd.h>
#include <asm/mce.h>
#include <asm/syscall.h>
#include <asm/syscalls.h>
#include "sigframe.h"

Expand Down Expand Up @@ -355,35 +357,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return -EFAULT;
}

/*
* Return -1L or the syscall number that @regs is executing.
*/
static long current_syscall(struct pt_regs *regs)
{
/*
* We always sign-extend a -1 value being set here,
* so this is always either -1L or a syscall number.
*/
return regs->orig_ax;
}

/*
* Return a value that is -EFOO if the system call in @regs->orig_ax
* returned an error. This only works for @regs from @current.
*/
static long current_syscall_ret(struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
if (test_thread_flag(TIF_IA32))
/*
* Sign-extend the value so (int)-EFOO becomes (long)-EFOO
* and will match correctly in comparisons.
*/
return (int) regs->ax;
#endif
return regs->ax;
}

/*
* OK, we're invoking a handler
*/
Expand All @@ -395,9 +368,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
int ret;

/* Are we from a system call? */
if (current_syscall(regs) >= 0) {
if (syscall_get_nr(current, regs) >= 0) {
/* If so, check system call restarting.. */
switch (current_syscall_ret(regs)) {
switch (syscall_get_error(current, regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
regs->ax = -EINTR;
Expand Down Expand Up @@ -454,15 +427,16 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* handler too.
*/
regs->flags &= ~X86_EFLAGS_TF;
if (test_thread_flag(TIF_SINGLESTEP))
ptrace_notify(SIGTRAP);

spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);

tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}

return ret;
Expand Down Expand Up @@ -519,9 +493,9 @@ static void do_signal(struct pt_regs *regs)
}

/* Did we come from a system call? */
if (current_syscall(regs) >= 0) {
if (syscall_get_nr(current, regs) >= 0) {
/* Restart the system call - no handlers present */
switch (current_syscall_ret(regs)) {
switch (syscall_get_error(current, regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
Expand Down Expand Up @@ -559,6 +533,11 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);

if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}
}

void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
Expand Down
5 changes: 5 additions & 0 deletions include/asm-x86/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ static inline unsigned long frame_pointer(struct pt_regs *regs)
return regs->bp;
}

static inline unsigned long user_stack_pointer(struct pt_regs *regs)
{
return regs->sp;
}

/*
* These are defined as per linux/ptrace.h, which see.
*/
Expand Down
Loading

0 comments on commit b159d7a

Please sign in to comment.