1 // REQUIRES: native-run
2 // UNSUPPORTED: target={{(arm|aarch64).*}}
3 // RUN: %clang_builtins %s %librt -o %t && %run %t
4 // REQUIRES: librt_has_clear_cache
17 extern void __clear_cache(void* start
, void* end
);
19 typedef int (*pfunc
)(void);
21 // Make these static to avoid ILT jumps for incremental linking on Windows.
22 static int func1() { return 1; }
23 static int func2() { return 2; }
25 void __attribute__((noinline
))
26 memcpy_f(void *dst
, const void *src
, size_t n
) {
27 // ARM and MIPS naturally align functions, but use the LSB for ISA selection
28 // (THUMB, MIPS16/uMIPS respectively). Ensure that the ISA bit is ignored in
30 #if defined(__arm__) || defined(__mips__)
31 memcpy(dst
, (void *)((uintptr_t)src
& ~1), n
);
33 memcpy(dst
, (void *)((uintptr_t)src
), n
);
37 // Realign the 'dst' pointer as if it has been returned by memcpy() above.
38 // We need to split it because we're using two mappings for the same area.
39 void *__attribute__((noinline
))
40 realign_f(void *dst
, const void *src
, size_t n
) {
41 #if defined(__arm__) || defined(__mips__)
42 return (void *)((uintptr_t)dst
| ((uintptr_t)src
& 1));
50 const int kSize
= 128;
51 #if defined(__NetBSD__)
52 // we need to create separate RW and RX mappings to satisfy MPROTECT
53 uint8_t *write_buffer
= mmap(0, kSize
,
54 PROT_MPROTECT(PROT_READ
| PROT_WRITE
|
56 MAP_ANON
| MAP_PRIVATE
, -1, 0);
57 if (write_buffer
== MAP_FAILED
)
59 uint8_t *execution_buffer
= mremap(write_buffer
, kSize
, NULL
, kSize
,
61 if (execution_buffer
== MAP_FAILED
)
64 if (mprotect(write_buffer
, kSize
, PROT_READ
| PROT_WRITE
) == -1)
66 if (mprotect(execution_buffer
, kSize
, PROT_READ
| PROT_EXEC
) == -1)
68 #elif !defined(_WIN32)
69 uint8_t *execution_buffer
= mmap(0, kSize
,
70 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
71 MAP_ANON
| MAP_PRIVATE
, -1, 0);
72 if (execution_buffer
== MAP_FAILED
)
74 uint8_t *write_buffer
= execution_buffer
;
76 HANDLE mapping
= CreateFileMapping(INVALID_HANDLE_VALUE
, NULL
,
77 PAGE_EXECUTE_READWRITE
, 0, kSize
, NULL
);
81 uint8_t* execution_buffer
= MapViewOfFile(
82 mapping
, FILE_MAP_ALL_ACCESS
| FILE_MAP_EXECUTE
, 0, 0, 0);
83 if (execution_buffer
== NULL
)
85 uint8_t *write_buffer
= execution_buffer
;
88 // verify you can copy and execute a function
89 memcpy_f(write_buffer
, func1
, kSize
);
90 pfunc f1
= (pfunc
)realign_f(execution_buffer
, func1
, kSize
);
91 __clear_cache(execution_buffer
, execution_buffer
+ kSize
);
95 // verify you can overwrite a function with another
96 memcpy_f(write_buffer
, func2
, kSize
);
97 pfunc f2
= (pfunc
)realign_f(execution_buffer
, func2
, kSize
);
98 __clear_cache(execution_buffer
, execution_buffer
+ kSize
);