diff options
author | Oleg Nesterov <oleg@redhat.com> | 2009-12-15 19:47:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:08 -0500 |
commit | 7f38551fc3ff0e17a38d6f3f0f8831380a88f3cc (patch) | |
tree | 80a2618da48e46c3918a15cbd72bf2149fe2bd75 | |
parent | 2f0edac5555983dc28033acce8a355f588fd01b2 (diff) |
ptrace: x86: implement user_single_step_siginfo()
Suggested by Roland.
Implement user_single_step_siginfo() for x86. Extract this code from
send_sigtrap().
Since x86 calls tracehook_report_syscall_exit(step => 0) the new helper is
not used yet.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Roland McGrath <roland@redhat.com>
Cc: <linux-arch@vger.kernel.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/x86/include/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 30 |
2 files changed, 23 insertions, 9 deletions
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 3d11fd0f44c5..9d369f680321 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h | |||
@@ -292,6 +292,8 @@ extern void user_enable_block_step(struct task_struct *); | |||
292 | #define arch_has_block_step() (boot_cpu_data.x86 >= 6) | 292 | #define arch_has_block_step() (boot_cpu_data.x86 >= 6) |
293 | #endif | 293 | #endif |
294 | 294 | ||
295 | #define ARCH_HAS_USER_SINGLE_STEP_INFO | ||
296 | |||
295 | struct user_desc; | 297 | struct user_desc; |
296 | extern int do_get_thread_area(struct task_struct *p, int idx, | 298 | extern int do_get_thread_area(struct task_struct *p, int idx, |
297 | struct user_desc __user *info); | 299 | struct user_desc __user *info); |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 7079ddaf0731..77b60085a810 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -1676,21 +1676,33 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
1676 | #endif | 1676 | #endif |
1677 | } | 1677 | } |
1678 | 1678 | ||
1679 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, | 1679 | static void fill_sigtrap_info(struct task_struct *tsk, |
1680 | int error_code, int si_code) | 1680 | struct pt_regs *regs, |
1681 | int error_code, int si_code, | ||
1682 | struct siginfo *info) | ||
1681 | { | 1683 | { |
1682 | struct siginfo info; | ||
1683 | |||
1684 | tsk->thread.trap_no = 1; | 1684 | tsk->thread.trap_no = 1; |
1685 | tsk->thread.error_code = error_code; | 1685 | tsk->thread.error_code = error_code; |
1686 | 1686 | ||
1687 | memset(&info, 0, sizeof(info)); | 1687 | memset(info, 0, sizeof(*info)); |
1688 | info.si_signo = SIGTRAP; | 1688 | info->si_signo = SIGTRAP; |
1689 | info.si_code = si_code; | 1689 | info->si_code = si_code; |
1690 | info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL; | ||
1691 | } | ||
1692 | |||
1693 | void user_single_step_siginfo(struct task_struct *tsk, | ||
1694 | struct pt_regs *regs, | ||
1695 | struct siginfo *info) | ||
1696 | { | ||
1697 | fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); | ||
1698 | } | ||
1690 | 1699 | ||
1691 | /* User-mode ip? */ | 1700 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
1692 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; | 1701 | int error_code, int si_code) |
1702 | { | ||
1703 | struct siginfo info; | ||
1693 | 1704 | ||
1705 | fill_sigtrap_info(tsk, regs, error_code, si_code, &info); | ||
1694 | /* Send us the fake SIGTRAP */ | 1706 | /* Send us the fake SIGTRAP */ |
1695 | force_sig_info(SIGTRAP, &info, tsk); | 1707 | force_sig_info(SIGTRAP, &info, tsk); |
1696 | } | 1708 | } |