llvm-project/compiler-rt/test/builtins/Unit/enable_execute_stack_test.c
Reid Kleckner 8c78ca2e8f [builtins] Get the builtins tests passing on Windows
Many things were broken:

- We stopped building most builtins on Windows in r261432 for reasons
  that are not at all clear to me. This essentially reverts that patch.

- Fix %librt to expand to clang_rt.builtins-$arch.lib on Windows instead
  of libclang_rt.builtins-$arch.a.

- Fix memory protection tests (trampoline, enable executable, clear
  cache) on Windows. One issue was that the MSVC incremental linker
  generates ILT thunks for functions with external linkage, so memcpying
  the functions into the executable stack buffer wasn't working. You
  can't memcpy an RIP-relative jump without fixing up the offset.

- Disable tests that rely on C99 complex library functions when using
  the MSVC CRT, which isn't compatible with clang's C99 _Complex.

In theory, these could all be separate patches, but it would not green
the tests, so let's try for it all at once. Hopefully this fixes the
clang-x64-ninja-win7 bot.

llvm-svn: 299780
2017-04-07 16:35:09 +00:00

59 lines
1.8 KiB
C

// REQUIRES: native-run
// RUN: %clang_builtins %s %librt -o %t && %run %t
//===-- enable_execute_stack_test.c - Test __enable_execute_stack ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdio.h>
#include <string.h>
#include <stdint.h>
extern void __clear_cache(void* start, void* end);
extern void __enable_execute_stack(void* addr);
typedef int (*pfunc)(void);
// Make these static to avoid ILT jumps for incremental linking on Windows.
static int func1() { return 1; }
static 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()
{
unsigned char execution_buffer[128];
// mark stack page containing execution_buffer to be executable
__enable_execute_stack(execution_buffer);
// verify you can copy and execute a function
pfunc f1 = (pfunc)memcpy_f(execution_buffer, func1, 128);
__clear_cache(execution_buffer, &execution_buffer[128]);
printf("f1: %p\n", f1);
if ((*f1)() != 1)
return 1;
// verify you can overwrite a function with another
pfunc f2 = (pfunc)memcpy_f(execution_buffer, func2, 128);
__clear_cache(execution_buffer, &execution_buffer[128]);
if ((*f2)() != 2)
return 1;
return 0;
}