From 6e6c1c3ef2dcf80a57c9853f74cb859c2419710f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 5 Jan 2015 21:54:50 +0000 Subject: [PATCH] tests: correct builtins test if built under -mthumb on ARM The clear_cache and enable_execute_stack tests attempt to memcpy the definition of a function into a buffer before executing the function. The problem with this approach is that on some targets (ARM with thumb mode compilation, MIPS with MIPS16 codegen or uMIPS), you would use a pointer which is incorrect (it would be off-by-one) due to the ISA selection being encoded into the address. This ensures that the function address is retrieved correctly in all cases. llvm-svn: 225215 --- .../test/builtins/Unit/clear_cache_test.c | 19 +++++++++++++----- .../builtins/Unit/enable_execute_stack_test.c | 20 +++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/compiler-rt/test/builtins/Unit/clear_cache_test.c b/compiler-rt/test/builtins/Unit/clear_cache_test.c index 3507fd80b288..3c893018545f 100644 --- a/compiler-rt/test/builtins/Unit/clear_cache_test.c +++ b/compiler-rt/test/builtins/Unit/clear_cache_test.c @@ -38,7 +38,18 @@ int func2() return 2; } - +void *__attribute__((noinline)) +memcpy_f(void *dst, const void *src, size_t n) { +// ARM and MIPS nartually align functions, but use the LSB for ISA selection +// (THUMB, MIPS16/uMIPS respectively). Ensure that the ISA bit is ignored in +// the memcpy +#if defined(__arm__) || defined(__mips__) + return (void *)((uintptr_t)memcpy(dst, (void *)((uintptr_t)src & ~1), n) | + ((uintptr_t)src & 1)); +#else + return memcpy(dst, (void *)((uintptr_t)src), n); +#endif +} unsigned char execution_buffer[128]; @@ -59,16 +70,14 @@ int main() return 1; // verify you can copy and execute a function - memcpy(execution_buffer, (void *)(uintptr_t)&func1, 128); + pfunc f1 = (pfunc)memcpy_f(execution_buffer, func1, 128); __clear_cache(execution_buffer, &execution_buffer[128]); - pfunc f1 = (pfunc)(uintptr_t)execution_buffer; if ((*f1)() != 1) return 1; // verify you can overwrite a function with another - memcpy(execution_buffer, (void *)(uintptr_t)&func2, 128); + pfunc f2 = (pfunc)memcpy_f(execution_buffer, func2, 128); __clear_cache(execution_buffer, &execution_buffer[128]); - pfunc f2 = (pfunc)(uintptr_t)execution_buffer; if ((*f2)() != 2) return 1; diff --git a/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c b/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c index c0f67b337939..38a142afb24d 100644 --- a/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c +++ b/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c @@ -45,8 +45,18 @@ int func2() return 2; } - - +void *__attribute__((noinline)) +memcpy_f(void *dst, const void *src, size_t n) { +// ARM and MIPS nartually align functions, but use the LSB for ISA selection +// (THUMB, MIPS16/uMIPS respectively). Ensure that the ISA bit is ignored in +// the memcpy +#if defined(__arm__) || defined(__mips__) + return (void *)((uintptr_t)memcpy(dst, (void *)((uintptr_t)src & ~1), n) | + ((uintptr_t)src & 1)); +#else + return memcpy(dst, (void *)((uintptr_t)src), n); +#endif +} int main() { @@ -55,16 +65,14 @@ int main() __enable_execute_stack(execution_buffer); // verify you can copy and execute a function - memcpy(execution_buffer, (void *)(uintptr_t)&func1, 128); + pfunc f1 = (pfunc)memcpy_f(execution_buffer, func1, 128); __clear_cache(execution_buffer, &execution_buffer[128]); - pfunc f1 = (pfunc)(uintptr_t)execution_buffer; if ((*f1)() != 1) return 1; // verify you can overwrite a function with another - memcpy(execution_buffer, (void *)(uintptr_t)&func2, 128); + pfunc f2 = (pfunc)memcpy_f(execution_buffer, func2, 128); __clear_cache(execution_buffer, &execution_buffer[128]); - pfunc f2 = (pfunc)(uintptr_t)execution_buffer; if ((*f2)() != 2) return 1;