10236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj 20236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj#undef _GNU_SOURCE 30236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj#define _GNU_SOURCE 1 40236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj 50236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj#include <signal.h> 60236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj#include <stdio.h> 70236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj#include <sys/ucontext.h> 80236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj 90236a00b0bf7085bbcaf7c14aa69083efe78f033sewardjstatic char* eip_at_sig = NULL; 100236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj 110236a00b0bf7085bbcaf7c14aa69083efe78f033sewardjstatic void int_handler(int signum, siginfo_t *si, void *uc_arg) 120236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj{ 130236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj ucontext_t *uc = (ucontext_t *)uc_arg; 140236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj /* Note that uc->uc_mcontext is an embedded struct, not a pointer */ 150236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj mcontext_t *mc = &(uc->uc_mcontext); 160236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj void *pc = (void*)mc->gregs[REG_EIP]; 170236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj printf("in int_handler, EIP is ...\n"); 180236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj eip_at_sig = pc; 190236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj} 200236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj 210236a00b0bf7085bbcaf7c14aa69083efe78f033sewardjstatic void register_handler(int sig, void *handler) 220236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj{ 230236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj struct sigaction sa; 240236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj sa.sa_flags = SA_RESTART | SA_SIGINFO; 250236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj sigfillset(&sa.sa_mask); 260236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj sa.sa_sigaction = handler; 270236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj sigaction(sig, &sa, NULL); 280236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj} 290236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj 300236a00b0bf7085bbcaf7c14aa69083efe78f033sewardjint main(void) { 310236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj char *intaddr = NULL; 320236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj puts("main"); 330236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj register_handler(SIGTRAP, int_handler); 340236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj asm volatile( 350236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj "movl $zz_int, %%edx\n" 360236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj "mov %%edx, %0\n" 370236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj "zz_int:\n" 380236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj "int $3\n" 390236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj : /* no outputs */ 400236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj : "m" (intaddr) /* input: address of var to store target addr to */ 410236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj : /* clobbers */ "edx" 420236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj ); 430236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj /* intaddr is the address of the int 3 insn. eip_at_sig is the PC 440236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj after the exception, which should be the next insn along. 450236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj Hence: */ 460236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj if (intaddr != NULL && eip_at_sig != NULL 470236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj && eip_at_sig == intaddr+1) 480236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj printf("PASS\n"); 490236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj else 500236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj printf("FAIL\n"); 510236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj return 0; 520236a00b0bf7085bbcaf7c14aa69083efe78f033sewardj} 53