1 /* This changes the definition of ucontext_t */
2 #define _XOPEN_SOURCE 1
10 #define offsetof(type, fld) ((unsigned long)&((type *)0)->fld)
11 #define stringify(x) #x
13 static int verbose
= 0;
15 #define _ASSERT_OP(a, op, b) \
17 unsigned long long _a = (unsigned long long)(a); \
18 unsigned long long _b = (unsigned long long)(b); \
20 fprintf(stderr, "%s:%d: ASSERT(" stringify(a) \
21 " " stringify(op) " " stringify(b) ")\n", \
22 __FILE__, __LINE__); \
24 fprintf(stderr, "%s:%d: FAILED ASSERT((" stringify(a) \
25 "=0x%016llx) " stringify(op) " (" stringify(b) "=0x%016llx))\n", \
26 __FILE__, __LINE__, _a, _b); \
30 #define ASSERT_EQ(a, b) _ASSERT_OP(a, ==, b)
31 #define ASSERT_NE(a, b) _ASSERT_OP(a, !=, b)
32 #define ASSERT_LTE(a, b) _ASSERT_OP(a, <=, b)
33 #define ASSERT_GTE(a, b) _ASSERT_OP(a, >=, b)
37 fprintf(stderr, "%s:%d: ASSERT(" stringify(e) ")\n", \
38 __FILE__, __LINE__); \
40 fprintf(stderr, "%s:%d: FAILED ASSERT(" stringify(e) ")\n", \
41 __FILE__, __LINE__); \
47 static bool using_int3
= false;
48 static volatile int sig_count
= 0;
49 static volatile int ran_after_fault
= 0;
50 static void *top_of_stack
;
51 static void *bottom_of_stack
;
53 void this_function_halts(unsigned long long a0
, unsigned long long a1
,
54 unsigned long long a2
, unsigned long long a3
,
55 unsigned long long a4
, unsigned long long a5
)
58 bottom_of_stack
= &foo
;
60 /* Set up registers with known values which will be tested in the signal handler */
61 __asm__
volatile("movq $0xfeed01010101cafe,%rax");
62 __asm__
volatile("movq $0xfeed02020202cafe,%rbx");
63 __asm__
volatile("movq $0xfeed03030303cafe,%r10");
64 __asm__
volatile("movq $0xfeed04040404cafe,%r11");
65 __asm__
volatile("movq $0xfeed05050505cafe,%r12");
66 __asm__
volatile("movq $0xfeed06060606cafe,%r13");
67 __asm__
volatile("movq $0xfeed07070707cafe,%r14");
68 __asm__
volatile("movq $0xfeed08080808cafe,%r15");
69 __asm__
volatile("hlt");
73 void this_function_int3s(unsigned long long a0
, unsigned long long a1
,
74 unsigned long long a2
, unsigned long long a3
,
75 unsigned long long a4
, unsigned long long a5
)
78 bottom_of_stack
= &foo
;
80 /* Set up registers with known values which will be tested in the signal handler */
81 __asm__
volatile("movq $0xfeed01010101cafe,%rax");
82 __asm__
volatile("movq $0xfeed02020202cafe,%rbx");
83 __asm__
volatile("movq $0xfeed03030303cafe,%r10");
84 __asm__
volatile("movq $0xfeed04040404cafe,%r11");
85 __asm__
volatile("movq $0xfeed05050505cafe,%r12");
86 __asm__
volatile("movq $0xfeed06060606cafe,%r13");
87 __asm__
volatile("movq $0xfeed07070707cafe,%r14");
88 __asm__
volatile("movq $0xfeed08080808cafe,%r15");
89 __asm__
volatile("int $3");
95 handle_signal(int sig
, siginfo_t
*si
, void *vuc
)
97 ucontext_t
*uc
= (ucontext_t
*)vuc
;
101 fprintf(stderr
, "handle_signal\n");
106 ASSERT(sig_count
== 1);
108 int expected_sig
= (using_int3
? SIGTRAP
: SIGSEGV
);
109 ASSERT_EQ(sig
, expected_sig
);
112 ASSERT_NE(uc
->uc_mcontext
, NULL
);
114 /* Test that the siginfo is set up right for this signal */
115 ASSERT_EQ(si
->si_signo
, expected_sig
);
116 ASSERT_EQ(si
->si_errno
, 0);
117 int expected_code
= (using_int3
? 1 : 0);
118 ASSERT_EQ(si
->si_code
, expected_code
);
119 ASSERT_EQ(si
->si_pid
, 0);
120 ASSERT_EQ(si
->si_uid
, 0);
121 ASSERT_EQ(si
->si_status
, 0);
122 ASSERT_EQ(si
->si_addr
, 0);
123 ASSERT_EQ(si
->si_band
, 0);
125 /* Test that RAX is saved to the signal ucontext */
126 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__rax
, 0xfeed01010101cafe);
128 /* Test that the registers used to pass the 1st 6
129 * function arguments were saved in the signal ucontext */
130 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__rdi
, 0xbabe01010101cedeULL
);
131 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__rsi
, 0xbabe02020202cedeULL
);
132 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__rdx
, 0xbabe03030303cedeULL
);
133 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__rcx
, 0xbabe04040404cedeULL
);
134 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r8
, 0xbabe05050505cedeULL
);
135 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r9
, 0xbabe06060606cedeULL
);
137 /* Test that the saved RBP and RSP point into roughly the right
138 * part of the stack */
139 ASSERT_GTE(uc
->uc_mcontext
->__ss
.__rbp
, bottom_of_stack
);
140 ASSERT_LTE(uc
->uc_mcontext
->__ss
.__rbp
, top_of_stack
);
141 ASSERT_GTE(uc
->uc_mcontext
->__ss
.__rsp
, bottom_of_stack
);
142 ASSERT_LTE(uc
->uc_mcontext
->__ss
.__rsp
, top_of_stack
);
144 /* Test that the saved RIP points into roughly the
145 * right part of the text segment */
146 char *calling_fn
= (using_int3
? (char *)&this_function_int3s
: (char *)&this_function_halts
);
147 ASSERT_GTE(uc
->uc_mcontext
->__ss
.__rip
, calling_fn
);
148 ASSERT_LTE(uc
->uc_mcontext
->__ss
.__rip
, calling_fn
+400);
150 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__rbx
, 0xfeed02020202cafe);
151 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r10
, 0xfeed03030303cafe);
152 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r11
, 0xfeed04040404cafe);
153 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r12
, 0xfeed05050505cafe);
154 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r13
, 0xfeed06060606cafe);
155 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r14
, 0xfeed07070707cafe);
156 ASSERT_EQ(uc
->uc_mcontext
->__ss
.__r15
, 0xfeed08080808cafe);
158 printf(" RFLAGS 0x%016llx\n", (unsigned long long)uc->uc_mcontext->__ss.__rflags);
162 * Test that the RIP is restored from the signal ucontext;
163 * this should skip past the HLT/INT instruction and
164 * allow execution to continue back out to main()
168 fprintf(stderr
, "Setting up to return past the HLT\n");
171 uc
->uc_mcontext
->__ss
.__rip
+= (using_int3
? 0 : 1);
175 fprintf(stderr
, "Returning from signal handler\n");
180 int main(int argc
, char **argv
)
183 struct sigaction act
;
185 top_of_stack
= (void *)&act
;
187 if (argc
> 1 && !strcmp(argv
[1], "--verbose"))
191 printf("Setting up signal handler\n");
192 memset(&act
, 0, sizeof(act
));
193 act
.sa_sigaction
= handle_signal
;
194 act
.sa_flags
|= SA_SIGINFO
;
195 if (RUNNING_ON_VALGRIND
)
197 r
= sigaction((using_int3
? SIGTRAP
: SIGSEGV
), &act
, NULL
);
202 fprintf(stderr
, "Calling function with a breakpoint insn in it\n");
206 this_function_int3s(0xbabe01010101cedeULL
,
207 0xbabe02020202cedeULL
,
208 0xbabe03030303cedeULL
,
209 0xbabe04040404cedeULL
,
210 0xbabe05050505cedeULL
,
211 0xbabe06060606cedeULL
);
213 this_function_halts(0xbabe01010101cedeULL
,
214 0xbabe02020202cedeULL
,
215 0xbabe03030303cedeULL
,
216 0xbabe04040404cedeULL
,
217 0xbabe05050505cedeULL
,
218 0xbabe06060606cedeULL
);
219 ASSERT_EQ(ran_after_fault
, 1);
221 fprintf(stderr
, "PASS\n");