10bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj 20bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj#undef _GNU_SOURCE 30bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj#define _GNU_SOURCE 1 40bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj 50bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj#include <signal.h> 60bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj#include <stdio.h> 70bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj#include <sys/ucontext.h> 80bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj 90bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardjstatic char* rip_at_sig = NULL; 100bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj 110bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardjstatic void int_handler(int signum, siginfo_t *si, void *uc_arg) 120bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj{ 130bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj ucontext_t *uc = (ucontext_t *)uc_arg; 140bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj /* Note that uc->uc_mcontext is an embedded struct, not a pointer */ 150bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj mcontext_t *mc = &(uc->uc_mcontext); 160bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj void *pc = (void*)mc->gregs[REG_RIP]; 170bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj printf("in int_handler, RIP is ...\n"); 180bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj rip_at_sig = pc; 190bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj} 200bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj 210bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardjstatic void register_handler(int sig, void *handler) 220bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj{ 230bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj struct sigaction sa; 240bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj sa.sa_flags = SA_RESTART | SA_SIGINFO; 250bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj sigfillset(&sa.sa_mask); 260bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj sa.sa_sigaction = handler; 270bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj sigaction(sig, &sa, NULL); 280bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj} 290bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj 300bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardjint main(void) { 310bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj char *intaddr = NULL; 320bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj puts("main"); 330bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj register_handler(SIGTRAP, int_handler); 340bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj asm volatile( 350bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj "movabsq $zz_int, %%rdx\n" 360bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj "mov %%rdx, %0\n" 370bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj "zz_int:\n" 380bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj "int $3\n" 390bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj : /* no outputs */ 400bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj : "m" (intaddr) /* input: address of var to store target addr to */ 410bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj : /* clobbers */ "rdx" 420bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj ); 430bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj /* intaddr is the address of the int 3 insn. rip_at_sig is the PC 440bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj after the exception, which should be the next insn along. 450bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj Hence: */ 460bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj if (intaddr != NULL && rip_at_sig != NULL 470bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj && rip_at_sig == intaddr+1) 480bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj printf("PASS\n"); 490bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj else 500bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj printf("FAIL\n"); 510bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj return 0; 520bfd9e6acef6d8c34e58646ece7c94967702c4d2sewardj} 53