1 #include <stddef.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <sys/mman.h> 5 6 #define DEFINE_ASM(_name, _code) \ 7 extern const char _name[]; \ 8 extern const char _name ## _end[]; \ 9 asm(" .globl " #_name "\n" \ 10 #_name ":\n" \ 11 " " _code "\n" \ 12 " .globl " #_name "_end\n" \ 13 #_name "_end:\n"); 14 15 DEFINE_ASM(br_r14, "br %r14"); 16 DEFINE_ASM(brasl_r0, "brasl %r0,.-0x100000000"); 17 DEFINE_ASM(brcl_0xf, "brcl 0xf,.-0x100000000"); 18 19 struct test { 20 const char *code; 21 const char *code_end; 22 }; 23 24 static const struct test tests[] = { 25 { 26 .code = brasl_r0, 27 .code_end = brasl_r0_end, 28 }, 29 { 30 .code = brcl_0xf, 31 .code_end = brcl_0xf_end, 32 }, 33 }; 34 35 int main(void) 36 { 37 unsigned char *buf; 38 size_t length = 0; 39 size_t i; 40 41 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 42 size_t test_length = 0x100000000 + (tests[i].code_end - tests[i].code); 43 44 if (test_length > length) { 45 length = test_length; 46 } 47 } 48 49 buf = mmap(NULL, length, PROT_READ | PROT_WRITE | PROT_EXEC, 50 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); 51 if (buf == MAP_FAILED) { 52 perror("SKIP: mmap() failed"); 53 return 0; 54 } 55 56 memcpy(buf, br_r14, br_r14_end - br_r14); 57 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 58 void (*code)(void) = (void *)(buf + 0x100000000); 59 60 memcpy(code, tests[i].code, tests[i].code_end - tests[i].code); 61 code(); 62 memset(code, 0, tests[i].code_end - tests[i].code); 63 } 64 65 munmap(buf, length); 66 67 return 0; 68 } 69