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>
This commit is contained in:
parent
101d5b7137
commit
da654b74bd
|
@ -113,11 +113,6 @@ typedef struct siginfo {
|
||||||
#undef NSIGSEGV
|
#undef NSIGSEGV
|
||||||
#define NSIGSEGV 3
|
#define NSIGSEGV 3
|
||||||
|
|
||||||
/*
|
|
||||||
* SIGTRAP si_codes
|
|
||||||
*/
|
|
||||||
#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
|
|
||||||
#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */
|
|
||||||
#undef NSIGTRAP
|
#undef NSIGTRAP
|
||||||
#define NSIGTRAP 4
|
#define NSIGTRAP 4
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
|
|
||||||
#include <asm-generic/siginfo.h>
|
#include <asm-generic/siginfo.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* SIGTRAP si_codes
|
|
||||||
*/
|
|
||||||
#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
|
|
||||||
#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */
|
|
||||||
#undef NSIGTRAP
|
#undef NSIGTRAP
|
||||||
#define NSIGTRAP 4
|
#define NSIGTRAP 4
|
||||||
|
|
||||||
|
|
|
@ -1358,7 +1358,8 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
|
void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
|
int error_code, int si_code)
|
||||||
{
|
{
|
||||||
struct siginfo info;
|
struct siginfo info;
|
||||||
|
|
||||||
|
@ -1367,7 +1368,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
info.si_signo = SIGTRAP;
|
info.si_signo = SIGTRAP;
|
||||||
info.si_code = TRAP_BRKPT;
|
info.si_code = si_code;
|
||||||
|
|
||||||
/* User-mode ip? */
|
/* User-mode ip? */
|
||||||
info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL;
|
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)
|
||||||
*/
|
*/
|
||||||
if (test_thread_flag(TIF_SINGLESTEP) &&
|
if (test_thread_flag(TIF_SINGLESTEP) &&
|
||||||
tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
|
tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
|
||||||
send_sigtrap(current, regs, 0);
|
send_sigtrap(current, regs, 0, TRAP_BRKPT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -891,6 +891,7 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code)
|
||||||
{
|
{
|
||||||
struct task_struct *tsk = current;
|
struct task_struct *tsk = current;
|
||||||
unsigned int condition;
|
unsigned int condition;
|
||||||
|
int si_code;
|
||||||
|
|
||||||
trace_hardirqs_fixup();
|
trace_hardirqs_fixup();
|
||||||
|
|
||||||
|
@ -935,8 +936,9 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code)
|
||||||
goto clear_TF_reenable;
|
goto clear_TF_reenable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
si_code = get_si_code((unsigned long)condition);
|
||||||
/* Ok, finally something we can handle */
|
/* Ok, finally something we can handle */
|
||||||
send_sigtrap(tsk, regs, error_code);
|
send_sigtrap(tsk, regs, error_code, si_code);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable additional traps. They'll be re-enabled when
|
* Disable additional traps. They'll be re-enabled when
|
||||||
|
|
|
@ -941,7 +941,7 @@ asmlinkage void __kprobes do_debug(struct pt_regs *regs,
|
||||||
tsk->thread.error_code = error_code;
|
tsk->thread.error_code = error_code;
|
||||||
info.si_signo = SIGTRAP;
|
info.si_signo = SIGTRAP;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
info.si_code = TRAP_BRKPT;
|
info.si_code = get_si_code(condition);
|
||||||
info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
|
info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
|
||||||
force_sig_info(SIGTRAP, &info, tsk);
|
force_sig_info(SIGTRAP, &info, tsk);
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,8 @@ typedef struct siginfo {
|
||||||
*/
|
*/
|
||||||
#define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */
|
#define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */
|
||||||
#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
|
#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
|
||||||
|
#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
|
||||||
|
#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint/watchpoint */
|
||||||
#define NSIGTRAP 2
|
#define NSIGTRAP 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -3,11 +3,6 @@
|
||||||
|
|
||||||
#include <asm-generic/siginfo.h>
|
#include <asm-generic/siginfo.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* SIGTRAP si_codes
|
|
||||||
*/
|
|
||||||
#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
|
|
||||||
#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */
|
|
||||||
#undef NSIGTRAP
|
#undef NSIGTRAP
|
||||||
#define NSIGTRAP 4
|
#define NSIGTRAP 4
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
|
extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
int error_code);
|
int error_code, int si_code);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
|
void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
|
||||||
|
|
|
@ -36,6 +36,16 @@ void do_invalid_op(struct pt_regs *, long);
|
||||||
void do_general_protection(struct pt_regs *, long);
|
void do_general_protection(struct pt_regs *, long);
|
||||||
void do_nmi(struct pt_regs *, long);
|
void do_nmi(struct pt_regs *, long);
|
||||||
|
|
||||||
|
static inline int get_si_code(unsigned long condition)
|
||||||
|
{
|
||||||
|
if (condition & DR_STEP)
|
||||||
|
return TRAP_TRACE;
|
||||||
|
else if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3))
|
||||||
|
return TRAP_HWBKPT;
|
||||||
|
else
|
||||||
|
return TRAP_BRKPT;
|
||||||
|
}
|
||||||
|
|
||||||
extern int panic_on_unrecovered_nmi;
|
extern int panic_on_unrecovered_nmi;
|
||||||
extern int kstack_depth_to_print;
|
extern int kstack_depth_to_print;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue