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