diff options
author | Srinivasa Ds <srinivasa@in.ibm.com> | 2008-09-23 05:53:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-23 07:26:52 -0400 |
commit | da654b74bda14c45a7d98c731bf3c1a43b6b74e2 (patch) | |
tree | e3cc6f1a1f7300c07e59c9091cd2ede0c5da8d4d /arch/x86 | |
parent | 101d5b713700b902b1c200cdd1925c3cb7d34567 (diff) |
signals: demultiplexing SIGTRAP signal
Currently a SIGTRAP can denote any one of below reasons.
- Breakpoint hit
- H/W debug register hit
- Single step
- Signal sent through kill() or rasie()
Architectures like powerpc/parisc provides infrastructure to demultiplex
SIGTRAP signal by passing down the information for receiving SIGTRAP through
si_code of siginfot_t structure. Here is an attempt is generalise this
infrastructure by extending it to x86 and x86_64 archs.
Signed-off-by: Srinivasa DS <srinivasa@in.ibm.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: akpm@linux-foundation.org
Cc: paulus@samba.org
Cc: linuxppc-dev@ozlabs.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/ptrace.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/traps_32.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/traps_64.c | 2 |
3 files changed, 8 insertions, 5 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 9e43a48ad6e0..bf45cdf1aaca 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -1358,7 +1358,8 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
1358 | #endif | 1358 | #endif |
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | 1361 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
1362 | int error_code, int si_code) | ||
1362 | { | 1363 | { |
1363 | struct siginfo info; | 1364 | struct siginfo info; |
1364 | 1365 | ||
@@ -1367,7 +1368,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | |||
1367 | 1368 | ||
1368 | memset(&info, 0, sizeof(info)); | 1369 | memset(&info, 0, sizeof(info)); |
1369 | info.si_signo = SIGTRAP; | 1370 | info.si_signo = SIGTRAP; |
1370 | info.si_code = TRAP_BRKPT; | 1371 | info.si_code = si_code; |
1371 | 1372 | ||
1372 | /* User-mode ip? */ | 1373 | /* User-mode ip? */ |
1373 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; | 1374 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; |
@@ -1454,5 +1455,5 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) | |||
1454 | */ | 1455 | */ |
1455 | if (test_thread_flag(TIF_SINGLESTEP) && | 1456 | if (test_thread_flag(TIF_SINGLESTEP) && |
1456 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) | 1457 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) |
1457 | send_sigtrap(current, regs, 0); | 1458 | send_sigtrap(current, regs, 0, TRAP_BRKPT); |
1458 | } | 1459 | } |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index da5a5964fccb..0429c5de5ea9 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
@@ -891,6 +891,7 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
891 | { | 891 | { |
892 | struct task_struct *tsk = current; | 892 | struct task_struct *tsk = current; |
893 | unsigned int condition; | 893 | unsigned int condition; |
894 | int si_code; | ||
894 | 895 | ||
895 | trace_hardirqs_fixup(); | 896 | trace_hardirqs_fixup(); |
896 | 897 | ||
@@ -935,8 +936,9 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
935 | goto clear_TF_reenable; | 936 | goto clear_TF_reenable; |
936 | } | 937 | } |
937 | 938 | ||
939 | si_code = get_si_code((unsigned long)condition); | ||
938 | /* Ok, finally something we can handle */ | 940 | /* Ok, finally something we can handle */ |
939 | send_sigtrap(tsk, regs, error_code); | 941 | send_sigtrap(tsk, regs, error_code, si_code); |
940 | 942 | ||
941 | /* | 943 | /* |
942 | * Disable additional traps. They'll be re-enabled when | 944 | * Disable additional traps. They'll be re-enabled when |
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 56d6f1147785..011d8e1fac6e 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c | |||
@@ -941,7 +941,7 @@ asmlinkage void __kprobes do_debug(struct pt_regs *regs, | |||
941 | tsk->thread.error_code = error_code; | 941 | tsk->thread.error_code = error_code; |
942 | info.si_signo = SIGTRAP; | 942 | info.si_signo = SIGTRAP; |
943 | info.si_errno = 0; | 943 | info.si_errno = 0; |
944 | info.si_code = TRAP_BRKPT; | 944 | info.si_code = get_si_code(condition); |
945 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; | 945 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; |
946 | force_sig_info(SIGTRAP, &info, tsk); | 946 | force_sig_info(SIGTRAP, &info, tsk); |
947 | 947 | ||