1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef _GNU_SOURCE 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE 1 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <signal.h> 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/ucontext.h> 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char* eip_at_sig = NULL; 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void int_handler(int signum, siginfo_t *si, void *uc_arg) 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ucontext_t *uc = (ucontext_t *)uc_arg; 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that uc->uc_mcontext is an embedded struct, not a pointer */ 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mcontext_t *mc = &(uc->uc_mcontext); 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *pc = (void*)mc->gregs[REG_EIP]; 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("in int_handler, EIP is ...\n"); 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eip_at_sig = pc; 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void register_handler(int sig, void *handler) 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct sigaction sa; 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_flags = SA_RESTART | SA_SIGINFO; 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigfillset(&sa.sa_mask); 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_sigaction = handler; 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sigaction(sig, &sa, NULL); 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(void) { 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *intaddr = NULL; 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown puts("main"); 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register_handler(SIGTRAP, int_handler); 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asm volatile( 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "movl $zz_int, %%edx\n" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "mov %%edx, %0\n" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "zz_int:\n" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "int $3\n" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : /* no outputs */ 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : "m" (intaddr) /* input: address of var to store target addr to */ 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : /* clobbers */ "edx" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* intaddr is the address of the int 3 insn. eip_at_sig is the PC 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown after the exception, which should be the next insn along. 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence: */ 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (intaddr != NULL && eip_at_sig != NULL 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && eip_at_sig == intaddr+1) 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("PASS\n"); 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("FAIL\n"); 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 53