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