| 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 | |