Home | History | Annotate | Download | only in amd64-linux
      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 
      9 static char* rip_at_sig = NULL;
     10 
     11 static 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 
     21 static 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 
     30 int 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