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
This commit is contained in:
Saleem Abdulrasool 2015-01-05 21:54:50 +00:00
parent 9187711f08
commit 6e6c1c3ef2
2 changed files with 28 additions and 11 deletions

View File

@ -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;

View File

@ -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;