Index: compiler-rt/trunk/test/CMakeLists.txt =================================================================== --- compiler-rt/trunk/test/CMakeLists.txt +++ compiler-rt/trunk/test/CMakeLists.txt @@ -78,6 +78,9 @@ if(COMPILER_RT_BUILD_XRAY) compiler_rt_test_runtime(xray) endif() + # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests + # include their own minimal runtime + add_subdirectory(shadowcallstack) endif() if(COMPILER_RT_STANDALONE_BUILD) Index: compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt =================================================================== --- compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt +++ compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SHADOWCALLSTACK_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(SHADOWCALLSTACK_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +set(SHADOWCALLSTACK_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ) + +add_lit_testsuite(check-shadowcallstack "Running the ShadowCallStack tests" + ${CMAKE_CURRENT_BINARY_DIR}) +set_target_properties(check-shadowcallstack PROPERTIES FOLDER "Compiler-RT Misc") Index: compiler-rt/trunk/test/shadowcallstack/init.c =================================================================== --- compiler-rt/trunk/test/shadowcallstack/init.c +++ compiler-rt/trunk/test/shadowcallstack/init.c @@ -0,0 +1,16 @@ +// RUN: %clang_scs -D INCLUDE_RUNTIME %s -o %t +// RUN: %run %t + +// RUN: %clang_scs %s -o %t +// RUN: not --crash %run %t + +// Basic smoke test for the runtime + +#ifdef INCLUDE_RUNTIME +#include "minimal_runtime.h" +#endif + +int main(int argc, char **argv) { + printf("In main.\n"); + return 0; +} Index: compiler-rt/trunk/test/shadowcallstack/lit.cfg =================================================================== --- compiler-rt/trunk/test/shadowcallstack/lit.cfg +++ compiler-rt/trunk/test/shadowcallstack/lit.cfg @@ -0,0 +1,19 @@ +# -*- Python -*- + +import os + +# Setup config name. +config.name = 'ShadowCallStack' + +# Setup source root. +config.test_source_root = os.path.dirname(__file__) + +# Test suffixes. +config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test'] + +# Add clang substitutions. +config.substitutions.append( ("%clang_noscs ", config.clang + " -O0 -fno-sanitize=shadow-call-stack ") ) +config.substitutions.append( ("%clang_scs ", config.clang + " -O0 -fsanitize=shadow-call-stack ") ) + +if config.host_os not in ['Linux'] or config.target_arch != 'x86_64': + config.unsupported = True Index: compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in =================================================================== --- compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in +++ compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in @@ -0,0 +1,7 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@SHADOWCALLSTACK_LIT_SOURCE_DIR@/lit.cfg") Index: compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h =================================================================== --- compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h +++ compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h @@ -0,0 +1,26 @@ +// A shadow call stack runtime is not yet included with compiler-rt, provide a +// minimal runtime to allocate a shadow call stack and assign %gs to point at +// it. + +#pragma once + +#include +#include +#include +#include + +int arch_prctl(int code, void *addr); + +__attribute__((no_sanitize("shadow-call-stack"))) +static void __shadowcallstack_init() { + void *stack = mmap(NULL, 8192, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (stack == MAP_FAILED) + abort(); + + if (arch_prctl(ARCH_SET_GS, stack)) + abort(); +} + +__attribute__((section(".preinit_array"), used)) + void (*__shadowcallstack_preinit)(void) = __shadowcallstack_init; Index: compiler-rt/trunk/test/shadowcallstack/overflow.c =================================================================== --- compiler-rt/trunk/test/shadowcallstack/overflow.c +++ compiler-rt/trunk/test/shadowcallstack/overflow.c @@ -0,0 +1,36 @@ +// RUN: %clang_noscs %s -o %t +// RUN: %run %t 3 | FileCheck %s +// RUN: %run %t 12 | FileCheck -check-prefix=OVERFLOW_SUCCESS %s + +// RUN: %clang_scs %s -o %t +// RUN: %run %t 3 | FileCheck %s +// RUN: not --crash %run %t 12 + +// Test that a stack overflow fails as expected + +#include +#include + +#include "minimal_runtime.h" + +void print_and_exit(void) { +// CHECK-NOT: Stack overflow successful. +// OVERFLOW_SUCCESS: Stack overflow successful. + printf("Stack overflow successful.\n"); + exit(0); +} + +int main(int argc, char **argv) +{ + if (argc != 2) + exit(1); + + void *addrs[4]; + const int iterations = atoi(argv[1]); + for (int i = 0; i < iterations; i++) + addrs[i] = &print_and_exit; + + printf("Returning.\n"); + + return 0; +}