mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-03 16:13:44 +00:00
shadowcallstack: Make runtime tests compatible with aarch64.
Differential Revision: https://reviews.llvm.org/D45303 llvm-svn: 329614
This commit is contained in:
parent
d9e96741c4
commit
6662e9890b
@ -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 FUZZER_SUPPORTED_ARCH 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()
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
|
41
compiler-rt/test/shadowcallstack/libc_support.h
Normal file
41
compiler-rt/test/shadowcallstack/libc_support.h
Normal file
@ -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
|
@ -12,8 +12,12 @@ config.test_source_root = os.path.dirname(__file__)
|
||||
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
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
5
compiler-rt/test/shadowcallstack/overflow-aarch64.c
Normal file
5
compiler-rt/test/shadowcallstack/overflow-aarch64.c
Normal file
@ -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
|
5
compiler-rt/test/shadowcallstack/overflow-x86_64.c
Normal file
5
compiler-rt/test/shadowcallstack/overflow-x86_64.c
Normal file
@ -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
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user