1// REQUIRES: native-run
2// RUN: %clang_builtins %s %librt -o %t && %run_nomprotect %t
3// REQUIRES: librt_has_enable_execute_stack
4
5#include <stdio.h>
6#include <string.h>
7#include <stdint.h>
8extern void __clear_cache(void* start, void* end);
9extern void __enable_execute_stack(void* addr);
10
11typedef int (*pfunc)(void);
12
13#ifdef __arm64ec__
14// On ARM64EC, we need the x86_64 version of this function, but the compiler
15// would normally generate the AArch64 variant, so we hardcode it here.
16static char func1[] = {
17 0xb8, 0x01, 0x00, 0x00, 0x00, // movl $0x1, %eax
18 0xc3 // retq
19};
20static char func2[] = {
21 0xb8, 0x02, 0x00, 0x00, 0x00, // movl $0x2, %eax
22 0xc3 // retq
23};
24#else
25// Make these static to avoid ILT jumps for incremental linking on Windows.
26static int func1() { return 1; }
27static int func2() { return 2; }
28#endif
29
30void *__attribute__((noinline))
31memcpy_f(void *dst, const void *src, size_t n) {
32// ARM and MIPS naturally align functions, but use the LSB for ISA selection
33// (THUMB, MIPS16/uMIPS respectively). Ensure that the ISA bit is ignored in
34// the memcpy
35#if defined(__arm__) || defined(__mips__)
36 return (void *)((uintptr_t)memcpy(dst, (void *)((uintptr_t)src & ~1), n) |
37 ((uintptr_t)src & 1));
38#else
39 return memcpy(dest: dst, src: (void *)((uintptr_t)src), n: n);
40#endif
41}
42
43int main()
44{
45#if defined(__ve__)
46 unsigned char execution_buffer[128] __attribute__((__aligned__(8)));
47#else
48 unsigned char execution_buffer[128];
49#endif
50 // mark stack page containing execution_buffer to be executable
51 __enable_execute_stack(addr: execution_buffer);
52
53 // verify you can copy and execute a function
54 pfunc f1 = (pfunc)memcpy_f(dst: execution_buffer, src: func1, n: 128);
55 __clear_cache(start: execution_buffer, end: &execution_buffer[128]);
56 printf(format: "f1: %p\n", f1);
57 if ((*f1)() != 1)
58 return 1;
59
60 // verify you can overwrite a function with another
61 pfunc f2 = (pfunc)memcpy_f(dst: execution_buffer, src: func2, n: 128);
62 __clear_cache(start: execution_buffer, end: &execution_buffer[128]);
63 if ((*f2)() != 2)
64 return 1;
65
66 return 0;
67}
68

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of compiler-rt/test/builtins/Unit/enable_execute_stack_test.c