[compiler-rt] r329614 - shadowcallstack: Make runtime tests compatible with aarch64.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 9 13:18:10 PDT 2018


Author: pcc
Date: Mon Apr  9 13:18:10 2018
New Revision: 329614

URL: http://llvm.org/viewvc/llvm-project?rev=329614&view=rev
Log:
shadowcallstack: Make runtime tests compatible with aarch64.

Differential Revision: https://reviews.llvm.org/D45303

Added:
    compiler-rt/trunk/test/shadowcallstack/libc_support.h
    compiler-rt/trunk/test/shadowcallstack/overflow-aarch64.c
    compiler-rt/trunk/test/shadowcallstack/overflow-x86_64.c
Modified:
    compiler-rt/trunk/cmake/config-ix.cmake
    compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt
    compiler-rt/trunk/test/shadowcallstack/init.c
    compiler-rt/trunk/test/shadowcallstack/lit.cfg
    compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in
    compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h
    compiler-rt/trunk/test/shadowcallstack/overflow.c

Modified: compiler-rt/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/cmake/config-ix.cmake (original)
+++ compiler-rt/trunk/cmake/config-ix.cmake Mon Apr  9 13:18:10 2018
@@ -219,6 +219,7 @@ set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
 else()
 set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
 endif()
+set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${X86_64} ${ARM64})
 
 if(APPLE)
   include(CompilerRTDarwinUtils)
@@ -429,6 +430,9 @@ if(APPLE)
   list_intersect(XRAY_SUPPORTED_ARCH
     ALL_XRAY_SUPPORTED_ARCH
     SANITIZER_COMMON_SUPPORTED_ARCH)
+  list_intersect(SHADOWCALLSTACK_SUPPORTED_ARCH
+    ALL_SHADOWCALLSTACK_SUPPORTED_ARCH
+    SANITIZER_COMMON_SUPPORTED_ARCH)
 
 else()
   # Architectures supported by compiler-rt libraries.
@@ -455,6 +459,8 @@ else()
   filter_available_targets(ESAN_SUPPORTED_ARCH ${ALL_ESAN_SUPPORTED_ARCH})
   filter_available_targets(SCUDO_SUPPORTED_ARCH ${ALL_SCUDO_SUPPORTED_ARCH})
   filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
+  filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH
+    ${ALL_SHADOWCALLSTACK_SUPPORTED_ARCH})
 endif()
 
 if (MSVC)
@@ -612,3 +618,10 @@ if (COMPILER_RT_HAS_SANITIZER_COMMON AND
 else()
   set(COMPILER_RT_HAS_FUZZER FALSE)
 endif()
+
+if (COMPILER_RT_HAS_SANITIZER_COMMON AND SHADOWCALLSTACK_SUPPORTED_ARCH AND
+    OS_NAME MATCHES "Linux|Android")
+  set(COMPILER_RT_HAS_SHADOWCALLSTACK TRUE)
+else()
+  set(COMPILER_RT_HAS_SHADOWCALLSTACK FALSE)
+endif()

Modified: compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt (original)
+++ compiler-rt/trunk/test/shadowcallstack/CMakeLists.txt Mon Apr  9 13:18:10 2018
@@ -1,13 +1,21 @@
+set(TEST_ARCH ${SHADOWCALLSTACK_SUPPORTED_ARCH})
+
 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
-  )
+foreach(arch ${SHADOWCALLSTACK_SUPPORTED_ARCH})
+  set(SANITIZER_COMMON_TEST_TARGET_ARCH ${arch})
+  get_test_cc_for_arch(${arch}
+    SHADOWSTACK_TEST_TARGET_CC SHADOWSTACK_TEST_TARGET_CFLAGS)
+  configure_lit_site_cfg(
+    ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+    ${CMAKE_CURRENT_BINARY_DIR}/${arch}/lit.site.cfg)
+  list(APPEND SHADOWCALLSTACK_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${arch})
+endforeach()
 
 add_lit_testsuite(check-shadowcallstack "Running the ShadowCallStack tests"
-  ${CMAKE_CURRENT_BINARY_DIR})
+  ${SHADOWCALLSTACK_TESTSUITES}
+  DEPENDS ${SANITIZER_COMMON_LIT_TEST_DEPS})
 set_target_properties(check-shadowcallstack PROPERTIES FOLDER "Compiler-RT Misc")

Modified: compiler-rt/trunk/test/shadowcallstack/init.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/init.c?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/init.c (original)
+++ compiler-rt/trunk/test/shadowcallstack/init.c Mon Apr  9 13:18:10 2018
@@ -6,11 +6,15 @@
 
 // Basic smoke test for the runtime
 
+#include "libc_support.h"
+
 #ifdef INCLUDE_RUNTIME
 #include "minimal_runtime.h"
+#else
+#define scs_main main
 #endif
 
-int main(int argc, char **argv) {
-  printf("In main.\n");
+int scs_main(void) {
+  scs_fputs_stdout("In main.\n");
   return 0;
 }

Added: compiler-rt/trunk/test/shadowcallstack/libc_support.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/libc_support.h?rev=329614&view=auto
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/libc_support.h (added)
+++ compiler-rt/trunk/test/shadowcallstack/libc_support.h Mon Apr  9 13:18:10 2018
@@ -0,0 +1,41 @@
+// This header provides replacements for certain libc functions. It is necessary
+// in order to safely run the tests on aarch64, because the system libc might
+// not have been compiled with -ffixed-x18.
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef __aarch64__
+
+size_t scs_strlen(const char *p) {
+  size_t retval = 0;
+  while (*p++)
+    retval++;
+  return retval;
+}
+
+// We mark this function as noinline to make sure that its callers do not
+// become leaf functions as a result of inlining. This is because we want to
+// make sure that we generate the correct code for non-leaf functions.
+
+__attribute__((noinline)) void scs_fputs_stdout(const char *p) {
+  __asm__ __volatile__(
+      "mov x0, #1\n"  // stdout
+      "mov x1, %0\n"
+      "mov x2, %1\n"
+      "mov x8, #64\n"  // write
+      "svc #0\n" ::"r"(p),
+      "r"(scs_strlen(p))
+      : "x0", "x1", "x2", "x8");
+}
+
+#else
+
+__attribute__((noinline)) void scs_fputs_stdout(const char *p) {
+  fputs(p, stdout);
+}
+
+#endif

Modified: compiler-rt/trunk/test/shadowcallstack/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/lit.cfg?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/lit.cfg (original)
+++ compiler-rt/trunk/test/shadowcallstack/lit.cfg Mon Apr  9 13:18:10 2018
@@ -12,8 +12,12 @@ config.test_source_root = os.path.dirnam
 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 ") )
+config.substitutions.append( ("%clang_noscs ", config.clang + ' -O0 -fno-sanitize=shadow-call-stack ' + config.target_cflags + ' ') )
 
-if config.host_os not in ['Linux'] or config.target_arch != 'x86_64':
+scs_arch_cflags = config.target_cflags
+if config.target_arch == 'aarch64':
+  scs_arch_cflags += ' -ffixed-x18 '
+config.substitutions.append( ("%clang_scs ", config.clang + ' -O0 -fsanitize=shadow-call-stack ' + scs_arch_cflags + ' ') )
+
+if config.host_os not in ['Linux'] or config.target_arch not in ['x86_64', 'aarch64']:
    config.unsupported = True

Modified: compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in (original)
+++ compiler-rt/trunk/test/shadowcallstack/lit.site.cfg.in Mon Apr  9 13:18:10 2018
@@ -1,5 +1,10 @@
 @LIT_SITE_CFG_IN_HEADER@
 
+# Tool-specific config options.
+config.name_suffix = "@SHADOWCALLSTACK_TEST_CONFIG_SUFFIX@"
+config.target_cflags = "@SHADOWCALLSTACK_TEST_TARGET_CFLAGS@"
+config.target_arch = "@SHADOWCALLSTACK_TEST_TARGET_ARCH@"
+
 # Load common config for all compiler-rt lit tests.
 lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
 

Modified: compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h (original)
+++ compiler-rt/trunk/test/shadowcallstack/minimal_runtime.h Mon Apr  9 13:18:10 2018
@@ -1,15 +1,18 @@
 // 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.
+// minimal runtime to allocate a shadow call stack and assign an
+// architecture-specific register to point at it.
 
 #pragma once
 
+#ifdef __x86_64__
 #include <asm/prctl.h>
+int arch_prctl(int code, void *addr);
+#endif
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
 
-int arch_prctl(int code, void *addr);
+#include "libc_support.h"
 
 __attribute__((no_sanitize("shadow-call-stack")))
 static void __shadowcallstack_init() {
@@ -18,9 +21,23 @@ static void __shadowcallstack_init() {
   if (stack == MAP_FAILED)
     abort();
 
+#if defined(__x86_64__)
   if (arch_prctl(ARCH_SET_GS, stack))
     abort();
+#elif defined(__aarch64__)
+  __asm__ __volatile__("mov x18, %0" ::"r"(stack));
+#else
+#error Unsupported platform
+#endif
 }
 
-__attribute__((section(".preinit_array"), used))
-    void (*__shadowcallstack_preinit)(void) = __shadowcallstack_init;
+int scs_main(void);
+
+__attribute__((no_sanitize("shadow-call-stack"))) int main(void) {
+  __shadowcallstack_init();
+
+  // We can't simply return scs_main() because scs_main might have corrupted our
+  // return address for testing purposes (see overflow.c), so we need to exit
+  // ourselves.
+  exit(scs_main());
+}

Added: compiler-rt/trunk/test/shadowcallstack/overflow-aarch64.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/overflow-aarch64.c?rev=329614&view=auto
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/overflow-aarch64.c (added)
+++ compiler-rt/trunk/test/shadowcallstack/overflow-aarch64.c Mon Apr  9 13:18:10 2018
@@ -0,0 +1,5 @@
+// See overflow.c for a description.
+
+// REQUIRES: aarch64-target-arch
+// RUN: %clang_scs %S/overflow.c -o %t -DITERATIONS=12
+// RUN: %run %t | FileCheck %S/overflow.c

Added: compiler-rt/trunk/test/shadowcallstack/overflow-x86_64.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/overflow-x86_64.c?rev=329614&view=auto
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/overflow-x86_64.c (added)
+++ compiler-rt/trunk/test/shadowcallstack/overflow-x86_64.c Mon Apr  9 13:18:10 2018
@@ -0,0 +1,5 @@
+// See overflow.c for a description.
+
+// REQUIRES: x86_64-target-arch
+// RUN: %clang_scs %S/overflow.c -o %t -DITERATIONS=12
+// RUN: not --crash %run %t

Modified: compiler-rt/trunk/test/shadowcallstack/overflow.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/shadowcallstack/overflow.c?rev=329614&r1=329613&r2=329614&view=diff
==============================================================================
--- compiler-rt/trunk/test/shadowcallstack/overflow.c (original)
+++ compiler-rt/trunk/test/shadowcallstack/overflow.c Mon Apr  9 13:18:10 2018
@@ -1,13 +1,20 @@
-// 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
 
+// RUN: %clang_noscs %s -o %t -DITERATIONS=3
+// RUN: %run %t | FileCheck %s
+// RUN: %clang_noscs %s -o %t -DITERATIONS=12
+// RUN: %run %t | FileCheck -check-prefix=OVERFLOW_SUCCESS %s
+
+// RUN: %clang_scs %s -o %t -DITERATIONS=3
+// RUN: %run %t | FileCheck %s
+
+// The behavioral check for SCS + overflow lives in the tests overflow-x86_64.c
+// and overflow-aarch64.c. This is because the expected behavior is different
+// between the two platforms. On x86_64 we crash because the comparison between
+// the shadow call stack and the regular stack fails. On aarch64 there is no
+// comparison, we just load the return address from the shadow call stack. So we
+// just expect not to see the output from print_and_exit.
+
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -16,21 +23,17 @@
 void print_and_exit(void) {
 // CHECK-NOT: Stack overflow successful.
 // OVERFLOW_SUCCESS: Stack overflow successful.
-  printf("Stack overflow successful.\n");
+  scs_fputs_stdout("Stack overflow successful.\n");
   exit(0);
 }
 
-int main(int argc, char **argv)
+int scs_main(void)
 {
-  if (argc != 2)
-    exit(1);
-
   void *addrs[4];
-  const int iterations = atoi(argv[1]);
-  for (int i = 0; i < iterations; i++)
+  for (int i = 0; i < ITERATIONS; i++)
     addrs[i] = &print_and_exit;
 
-  printf("Returning.\n");
+  scs_fputs_stdout("Returning.\n");
 
   return 0;
 }




More information about the llvm-commits mailing list