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