1 // REQUIRES: native-run
2 // UNSUPPORTED: arm, aarch64
3 // RUN: %clang_builtins %s %librt -o %t && %run %t
4 // REQUIRES: librt_has_clear_cache
5 //===-- clear_cache_test.c - Test clear_cache -----------------------------===//
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 //===----------------------------------------------------------------------===//
25 extern void __clear_cache(void* start
, void* end
);
27 typedef int (*pfunc
)(void);
29 // Make these static to avoid ILT jumps for incremental linking on Windows.
30 static int func1() { return 1; }
31 static int func2() { return 2; }
33 void __attribute__((noinline
))
34 memcpy_f(void *dst
, const void *src
, size_t n
) {
35 // ARM and MIPS nartually align functions, but use the LSB for ISA selection
36 // (THUMB, MIPS16/uMIPS respectively). Ensure that the ISA bit is ignored in
38 #if defined(__arm__) || defined(__mips__)
39 memcpy(dst
, (void *)((uintptr_t)src
& ~1), n
);
41 memcpy(dst
, (void *)((uintptr_t)src
), n
);
45 // Realign the 'dst' pointer as if it has been returned by memcpy() above.
46 // We need to split it because we're using two mappings for the same area.
47 void *__attribute__((noinline
))
48 realign_f(void *dst
, const void *src
, size_t n
) {
49 #if defined(__arm__) || defined(__mips__)
50 return (void *)((uintptr_t)dst
| ((uintptr_t)src
& 1));
58 const int kSize
= 128;
59 #if defined(__NetBSD__)
60 // we need to create separate RW and RX mappings to satisfy MPROTECT
61 uint8_t *write_buffer
= mmap(0, kSize
,
62 PROT_MPROTECT(PROT_READ
| PROT_WRITE
|
64 MAP_ANON
| MAP_PRIVATE
, -1, 0);
65 if (write_buffer
== MAP_FAILED
)
67 uint8_t *execution_buffer
= mremap(write_buffer
, kSize
, NULL
, kSize
,
69 if (execution_buffer
== MAP_FAILED
)
72 if (mprotect(write_buffer
, kSize
, PROT_READ
| PROT_WRITE
) == -1)
74 if (mprotect(execution_buffer
, kSize
, PROT_READ
| PROT_EXEC
) == -1)
76 #elif !defined(_WIN32)
77 uint8_t *execution_buffer
= mmap(0, kSize
,
78 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
79 MAP_ANON
| MAP_PRIVATE
, -1, 0);
80 if (execution_buffer
== MAP_FAILED
)
82 uint8_t *write_buffer
= execution_buffer
;
84 HANDLE mapping
= CreateFileMapping(INVALID_HANDLE_VALUE
, NULL
,
85 PAGE_EXECUTE_READWRITE
, 0, kSize
, NULL
);
89 uint8_t* execution_buffer
= MapViewOfFile(
90 mapping
, FILE_MAP_ALL_ACCESS
| FILE_MAP_EXECUTE
, 0, 0, 0);
91 if (execution_buffer
== NULL
)
93 uint8_t *write_buffer
= execution_buffer
;
96 // verify you can copy and execute a function
97 memcpy_f(write_buffer
, func1
, kSize
);
98 pfunc f1
= (pfunc
)realign_f(execution_buffer
, func1
, kSize
);
99 __clear_cache(execution_buffer
, execution_buffer
+ kSize
);
103 // verify you can overwrite a function with another
104 memcpy_f(write_buffer
, func2
, kSize
);
105 pfunc f2
= (pfunc
)realign_f(execution_buffer
, func2
, kSize
);
106 __clear_cache(execution_buffer
, execution_buffer
+ kSize
);