Home | History | Annotate | Download | only in amd64-solaris
      1 /* Test if values in rax, rbx, rcx, rdx, rsi and rdi are correctly propagated
      2    into and out of a signal handler and also check that the same applies for
      3    uninitialised values and their origins. */
      4 
      5 #include <assert.h>
      6 #include <signal.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <unistd.h>
     10 #include <sys/regset.h>
     11 #include <sys/syscall.h>
     12 #include <sys/ucontext.h>
     13 
     14 static siginfo_t si;
     15 static ucontext_t uc;
     16 /* x0 is always zero, but is visible to Valgrind as uninitialised. */
     17 static long x0;
     18 
     19 void break_out(void);
     20 
     21 static void sighandler(int sig, siginfo_t *sip, void *arg)
     22 {
     23    ucontext_t *ucp = (ucontext_t *) arg;
     24 
     25    si = *sip;
     26    uc = *ucp;
     27 
     28    ucp->uc_mcontext.gregs[REG_RCX] = x0;
     29 
     30    /* Break out of the endless loop. */
     31    *(uintptr_t*)&ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t)break_out;
     32 }
     33 
     34 int main(void)
     35 {
     36    struct sigaction sa;
     37    long rax, rbx, rcx, rdx, rsi, rdi;
     38    long y0;
     39 
     40    /* Uninitialised, but we know px[0] is 0x0. */
     41    long *px = malloc(sizeof(*px));
     42    x0 = px[0];
     43 
     44    /* Uninitialised, but we know py[0] is 0x0. */
     45    long *py = malloc(sizeof(*py));
     46    y0 = py[0];
     47 
     48    sa.sa_sigaction = sighandler;
     49    sa.sa_flags = SA_SIGINFO;
     50    if (sigfillset(&sa.sa_mask)) {
     51       perror("sigfillset");
     52       return 1;
     53    }
     54    if (sigaction(SIGALRM, &sa, NULL)) {
     55       perror("sigaction");
     56       return 1;
     57    }
     58 
     59    alarm(2);
     60 
     61    __asm__ __volatile__(
     62       /* Set values in general purpose registers. */
     63       "movq   $0xf0, %%rax\n"
     64       "movq   %[y0], %%rbx\n"
     65       "movq   $0xf1, %%rcx\n"
     66       "movq   $0xf2, %%rdx\n"
     67       "movq   $0xf3, %%rsi\n"
     68       "movq   $0xf4, %%rdi\n"
     69 
     70       /* Loopity loop, this is where the SIGALRM is triggered. */
     71       "1:\n"
     72       "jmp    1b\n"
     73 
     74       "break_out:\n"
     75       : "=a" (rax), "=b" (rbx), "=c" (rcx), "=d" (rdx), "=S" (rsi),
     76         "=D" (rdi)
     77       : [y0] "m" (y0)
     78       : "cc", "memory");
     79 
     80    printf("Values in the signal handler:\n");
     81    printf("  rax=%#lx, rcx=%#lx, rdx=%#lx, rsi=%#lx, rdi=%#lx\n",
     82           uc.uc_mcontext.gregs[REG_RAX], uc.uc_mcontext.gregs[REG_RCX],
     83           uc.uc_mcontext.gregs[REG_RDX], uc.uc_mcontext.gregs[REG_RSI],
     84           uc.uc_mcontext.gregs[REG_RDI]);
     85    /* Check that rbx contains an uninitialised value (origin is py[0]). */
     86    if (uc.uc_mcontext.gregs[REG_RBX])
     87       assert(0);
     88 
     89    printf("Values after the return from the signal handler:\n");
     90    printf("  rax=%#lx, rdx=%#lx, rsi=%#lx, rdi=%#lx\n", rax, rdx, rsi, rdi);
     91    /* Check that rbx and rcx contain uninitialised values (origin is py[0]
     92       and px[0], respectively). */
     93    if (rbx || rcx)
     94       assert(0);
     95 
     96    return 0;
     97 }
     98 
     99