1*1d9ac91bSRichard Henderson /*
2*1d9ac91bSRichard Henderson * Branch target identification, basic notskip cases.
3*1d9ac91bSRichard Henderson */
4*1d9ac91bSRichard Henderson
5*1d9ac91bSRichard Henderson #include <stdio.h>
6*1d9ac91bSRichard Henderson #include <signal.h>
7*1d9ac91bSRichard Henderson #include <string.h>
8*1d9ac91bSRichard Henderson #include <unistd.h>
9*1d9ac91bSRichard Henderson #include <sys/mman.h>
10*1d9ac91bSRichard Henderson
11*1d9ac91bSRichard Henderson #ifndef PROT_BTI
12*1d9ac91bSRichard Henderson #define PROT_BTI 0x10
13*1d9ac91bSRichard Henderson #endif
14*1d9ac91bSRichard Henderson
skip2_sigill(int sig,siginfo_t * info,void * vuc)15*1d9ac91bSRichard Henderson static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
16*1d9ac91bSRichard Henderson {
17*1d9ac91bSRichard Henderson ucontext_t *uc = vuc;
18*1d9ac91bSRichard Henderson uc->uc_mcontext.pc += 8;
19*1d9ac91bSRichard Henderson uc->uc_mcontext.pstate = 1;
20*1d9ac91bSRichard Henderson }
21*1d9ac91bSRichard Henderson
22*1d9ac91bSRichard Henderson #define NOP "nop"
23*1d9ac91bSRichard Henderson #define BTI_N "hint #32"
24*1d9ac91bSRichard Henderson #define BTI_C "hint #34"
25*1d9ac91bSRichard Henderson #define BTI_J "hint #36"
26*1d9ac91bSRichard Henderson #define BTI_JC "hint #38"
27*1d9ac91bSRichard Henderson
28*1d9ac91bSRichard Henderson #define BTYPE_1(DEST) \
29*1d9ac91bSRichard Henderson "mov x1, #1\n\t" \
30*1d9ac91bSRichard Henderson "adr x16, 1f\n\t" \
31*1d9ac91bSRichard Henderson "br x16\n" \
32*1d9ac91bSRichard Henderson "1: " DEST "\n\t" \
33*1d9ac91bSRichard Henderson "mov x1, #0"
34*1d9ac91bSRichard Henderson
35*1d9ac91bSRichard Henderson #define BTYPE_2(DEST) \
36*1d9ac91bSRichard Henderson "mov x1, #1\n\t" \
37*1d9ac91bSRichard Henderson "adr x16, 1f\n\t" \
38*1d9ac91bSRichard Henderson "blr x16\n" \
39*1d9ac91bSRichard Henderson "1: " DEST "\n\t" \
40*1d9ac91bSRichard Henderson "mov x1, #0"
41*1d9ac91bSRichard Henderson
42*1d9ac91bSRichard Henderson #define BTYPE_3(DEST) \
43*1d9ac91bSRichard Henderson "mov x1, #1\n\t" \
44*1d9ac91bSRichard Henderson "adr x15, 1f\n\t" \
45*1d9ac91bSRichard Henderson "br x15\n" \
46*1d9ac91bSRichard Henderson "1: " DEST "\n\t" \
47*1d9ac91bSRichard Henderson "mov x1, #0"
48*1d9ac91bSRichard Henderson
49*1d9ac91bSRichard Henderson #define TEST(WHICH, DEST, EXPECT) \
50*1d9ac91bSRichard Henderson WHICH(DEST) "\n" \
51*1d9ac91bSRichard Henderson ".if " #EXPECT "\n\t" \
52*1d9ac91bSRichard Henderson "eor x1, x1," #EXPECT "\n" \
53*1d9ac91bSRichard Henderson ".endif\n\t" \
54*1d9ac91bSRichard Henderson "add x0, x0, x1\n\t"
55*1d9ac91bSRichard Henderson
56*1d9ac91bSRichard Henderson asm("\n"
57*1d9ac91bSRichard Henderson "test_begin:\n\t"
58*1d9ac91bSRichard Henderson BTI_C "\n\t"
59*1d9ac91bSRichard Henderson "mov x2, x30\n\t"
60*1d9ac91bSRichard Henderson "mov x0, #0\n\t"
61*1d9ac91bSRichard Henderson
62*1d9ac91bSRichard Henderson TEST(BTYPE_1, NOP, 1)
63*1d9ac91bSRichard Henderson TEST(BTYPE_1, BTI_N, 1)
64*1d9ac91bSRichard Henderson TEST(BTYPE_1, BTI_C, 0)
65*1d9ac91bSRichard Henderson TEST(BTYPE_1, BTI_J, 0)
66*1d9ac91bSRichard Henderson TEST(BTYPE_1, BTI_JC, 0)
67*1d9ac91bSRichard Henderson
68*1d9ac91bSRichard Henderson TEST(BTYPE_2, NOP, 1)
69*1d9ac91bSRichard Henderson TEST(BTYPE_2, BTI_N, 1)
70*1d9ac91bSRichard Henderson TEST(BTYPE_2, BTI_C, 0)
71*1d9ac91bSRichard Henderson TEST(BTYPE_2, BTI_J, 1)
72*1d9ac91bSRichard Henderson TEST(BTYPE_2, BTI_JC, 0)
73*1d9ac91bSRichard Henderson
74*1d9ac91bSRichard Henderson TEST(BTYPE_3, NOP, 1)
75*1d9ac91bSRichard Henderson TEST(BTYPE_3, BTI_N, 1)
76*1d9ac91bSRichard Henderson TEST(BTYPE_3, BTI_C, 1)
77*1d9ac91bSRichard Henderson TEST(BTYPE_3, BTI_J, 0)
78*1d9ac91bSRichard Henderson TEST(BTYPE_3, BTI_JC, 0)
79*1d9ac91bSRichard Henderson
80*1d9ac91bSRichard Henderson "ret x2\n"
81*1d9ac91bSRichard Henderson "test_end:"
82*1d9ac91bSRichard Henderson );
83*1d9ac91bSRichard Henderson
main()84*1d9ac91bSRichard Henderson int main()
85*1d9ac91bSRichard Henderson {
86*1d9ac91bSRichard Henderson struct sigaction sa;
87*1d9ac91bSRichard Henderson void *tb, *te;
88*1d9ac91bSRichard Henderson
89*1d9ac91bSRichard Henderson void *p = mmap(0, getpagesize(),
90*1d9ac91bSRichard Henderson PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
91*1d9ac91bSRichard Henderson MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
92*1d9ac91bSRichard Henderson if (p == MAP_FAILED) {
93*1d9ac91bSRichard Henderson perror("mmap");
94*1d9ac91bSRichard Henderson return 1;
95*1d9ac91bSRichard Henderson }
96*1d9ac91bSRichard Henderson
97*1d9ac91bSRichard Henderson memset(&sa, 0, sizeof(sa));
98*1d9ac91bSRichard Henderson sa.sa_sigaction = skip2_sigill;
99*1d9ac91bSRichard Henderson sa.sa_flags = SA_SIGINFO;
100*1d9ac91bSRichard Henderson if (sigaction(SIGILL, &sa, NULL) < 0) {
101*1d9ac91bSRichard Henderson perror("sigaction");
102*1d9ac91bSRichard Henderson return 1;
103*1d9ac91bSRichard Henderson }
104*1d9ac91bSRichard Henderson
105*1d9ac91bSRichard Henderson /*
106*1d9ac91bSRichard Henderson * ??? With "extern char test_begin[]", some compiler versions
107*1d9ac91bSRichard Henderson * will use :got references, and some linker versions will
108*1d9ac91bSRichard Henderson * resolve this reference to a static symbol incorrectly.
109*1d9ac91bSRichard Henderson * Bypass this error by using a pc-relative reference directly.
110*1d9ac91bSRichard Henderson */
111*1d9ac91bSRichard Henderson asm("adr %0, test_begin; adr %1, test_end" : "=r"(tb), "=r"(te));
112*1d9ac91bSRichard Henderson
113*1d9ac91bSRichard Henderson memcpy(p, tb, te - tb);
114*1d9ac91bSRichard Henderson
115*1d9ac91bSRichard Henderson return ((int (*)(void))p)();
116*1d9ac91bSRichard Henderson }
117