-
Notifications
You must be signed in to change notification settings - Fork 0
/
setjmp.c
108 lines (92 loc) · 2.07 KB
/
setjmp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <setjmp.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifdef DEBUG
#if defined(__aarch64__)
#define asm_read_marker(marker) \
asm volatile ("ldr %0, [x28, #-8]" \
: "=r" (marker))
#define asm_read_rsp(rsp) \
asm volatile ("mov %0, x28" \
: "=r" (rsp))
#elif defined (__x86_64__)
#define asm_read_marker(marker) \
asm volatile ("movq (-8)(%%r15), %0" \
: "=r" (marker))
#define asm_read_rsp(rsp) \
asm volatile ("movq %%r15, %0" \
: "=r" (rsp))
#endif
#endif
static void first(void);
static void second(void);
static void third(void);
static jmp_buf env;
static int handled = 0;
int main (void) {
#ifdef DEBUG
unsigned long rsp;
unsigned long marker;
asm_read_rsp(rsp);
printf("(Main) RSP=0x%lx\n", rsp);
#endif
first();
if (handled != 2) {
fprintf(stderr, "main() failed: Not all setjmps succeeded.\n");
return 1;
}
printf("OK\n");
return 0;
}
static void first (void) {
#ifdef DEBUG
unsigned long rsp;
unsigned long marker;
asm_read_rsp(rsp);
asm_read_marker(marker);
printf("(First) RSP=0x%lx\n", rsp);
printf("(First) Marker=0x%lx\n", marker);
#endif
if (setjmp(env)) {
/* Handling longjmp() from second(). */
handled++;
} else {
second();
}
}
static void second (void) {
jmp_buf my_env;
#ifdef DEBUG
unsigned long rsp;
unsigned long marker;
asm_read_rsp(rsp);
asm_read_marker(marker);
printf("(Second) RSP=0x%lx\n", rsp);
printf("(Second) Marker=0x%lx\n", marker);
#endif
/* Saving env. */
memcpy(my_env, env, sizeof my_env);
switch (sigsetjmp(env, 1)) {
case 3:
/* Handling siglongjmp() from third(). */
handled++;
default:
/* Restoring env. */
memcpy(env, my_env, sizeof env);
/* Returning to first() with status 2. */
longjmp(env, 2);
case 0:
third();
}
}
static void third (void) {
#ifdef DEBUG
unsigned long rsp;
unsigned long marker;
asm_read_rsp(rsp);
printf("(Third) RSP=0x%lx\n", rsp);
#endif
/* Returning to second() with status 3. */
siglongjmp(env, 3);
}