1 | #include <signal.h> |
2 | #include <stdio.h> |
3 | #include <stdlib.h> |
4 | |
5 | void handler(int sig) { |
6 | // The kernel only changes a few registers so set them all to something other |
7 | // than the values in sigill() so that we can't fall back to real registers |
8 | // and still pass the test. |
9 | #define SETREG(N) "mov x" N ", #" N "+1\n\t" |
10 | asm volatile( |
11 | /* clang-format off */ |
12 | /* x0 is used for a parameter */ |
13 | SETREG("1" ) SETREG("2" ) SETREG("3" ) |
14 | SETREG("4" ) SETREG("5" ) SETREG("6" ) SETREG("7" ) |
15 | SETREG("8" ) SETREG("9" ) SETREG("10" ) SETREG("11" ) |
16 | SETREG("12" ) SETREG("13" ) SETREG("14" ) SETREG("15" ) |
17 | SETREG("16" ) SETREG("17" ) SETREG("18" ) SETREG("19" ) |
18 | SETREG("20" ) SETREG("21" ) SETREG("22" ) SETREG("23" ) |
19 | SETREG("24" ) SETREG("25" ) SETREG("26" ) SETREG("27" ) |
20 | SETREG("28" ) // fp/x29 needed for unwiding |
21 | SETREG("30" ) // 31 is xzr/sp |
22 | /* clang-format on */ |
23 | :: |
24 | : /* skipped x0 */ "x1" , "x2" , "x3" , "x4" , "x5" , "x6" , "x7" , "x8" , |
25 | "x9" , "x10" , "x11" , "x12" , "x13" , "x14" , "x15" , "x16" , "x17" , "x18" , |
26 | "x19" , "x20" , "x21" , "x22" , "x23" , "x24" , "x25" , "x26" , "x27" , |
27 | "x28" , |
28 | /* skipped fp/x29 */ "x30" ); |
29 | printf(format: "Set a breakpoint here.\n" ); |
30 | exit(status: 0); |
31 | } |
32 | |
33 | static void sigill() { |
34 | // Set all general registers to known values to check |
35 | // that the signal unwind plan sets their locations correctly. |
36 | #define SETREG(N) "mov x" N ", #" N "\n\t" |
37 | asm volatile( |
38 | /* clang-format off */ |
39 | SETREG("0" ) SETREG("1" ) SETREG("2" ) SETREG("3" ) |
40 | SETREG("4" ) SETREG("5" ) SETREG("6" ) SETREG("7" ) |
41 | SETREG("8" ) SETREG("9" ) SETREG("10" ) SETREG("11" ) |
42 | SETREG("12" ) SETREG("13" ) SETREG("14" ) SETREG("15" ) |
43 | SETREG("16" ) SETREG("17" ) SETREG("18" ) SETREG("19" ) |
44 | SETREG("20" ) SETREG("21" ) SETREG("22" ) SETREG("23" ) |
45 | SETREG("24" ) SETREG("25" ) SETREG("26" ) SETREG("27" ) |
46 | SETREG("28" ) SETREG("29" ) SETREG("30" ) /* 31 is xzr/sp */ |
47 | /* clang-format on */ |
48 | ".inst 0x00000000\n\t" // udf #0 (old binutils don't support udf) |
49 | :: |
50 | : "x0" , "x1" , "x2" , "x3" , "x4" , "x5" , "x6" , "x7" , "x8" , "x9" , "x10" , |
51 | "x11" , "x12" , "x13" , "x14" , "x15" , "x16" , "x17" , "x18" , "x19" , |
52 | "x20" , "x21" , "x22" , "x23" , "x24" , "x25" , "x26" , "x27" , "x28" , |
53 | "x29" , "x30" ); |
54 | } |
55 | |
56 | int main() { |
57 | if (signal(SIGILL, handler: handler) == SIG_ERR) { |
58 | perror(s: "signal" ); |
59 | return 1; |
60 | } |
61 | |
62 | sigill(); |
63 | return 2; |
64 | } |
65 | |