115 lines · cpp
1// RUN: %clangxx -std=c++11 %s -o %t2// RUN: %env_asan_opts=handle_segv=1 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s3// RUN: %env_asan_opts=handle_segv=2 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s4 5// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_HANDLER %s -o %t6// RUN: %env_asan_opts=handle_segv=0 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HANDLER7// RUN: %env_asan_opts=handle_segv=1 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s8// RUN: %env_asan_opts=handle_segv=2 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s9 10// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_ACTION %s -o %t11// RUN: %env_asan_opts=handle_segv=0 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-ACTION12// RUN: %env_asan_opts=handle_segv=1 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s13// RUN: %env_asan_opts=handle_segv=2 LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s14 15// REQUIRES: asan-dynamic-runtime16 17// This way of setting LD_PRELOAD does not work with Android test runner.18// REQUIRES: !android19 20// Issue #109573: Cannot use syscall(__NR_rt_sigaction) on Linux/sparc64.21// XFAIL: target={{sparc.*-.*-linux.*}}22 23#include <assert.h>24#include <signal.h>25#include <stdio.h>26#include <stdlib.h>27#include <string.h>28#include <sys/syscall.h>29#include <unistd.h>30 31const char *handler = nullptr;32void SigHandler(int signum) { handler = "TestSigHandler"; }33void SigAction(int, siginfo_t *, void *) { handler = "TestSigAction"; }34 35struct KernelSigaction {36 37#if defined(__mips__)38 unsigned long flags;39 __sighandler_t handler;40#else41 __sighandler_t handler;42 unsigned long flags;43#endif44 void (*restorer)();45 char unused[1024];46};47 48#if defined(__x86_64__)49extern "C" void restorer();50asm("restorer:mov $15,%rax\nsyscall");51#endif52 53int InternalSigaction(int sig, KernelSigaction *act, KernelSigaction *oact) {54 if (act) {55#if defined(__x86_64__)56 act->flags |= 0x04000000;57 act->restorer = &restorer;58#endif59 }60 return syscall(__NR_rt_sigaction, sig, act, oact, NSIG / 8);61}62 63struct KernelSigaction pre_asan = {};64 65static void Init() {66 int res = InternalSigaction(SIGSEGV, nullptr, &pre_asan);67 assert(res >= 0);68 assert(pre_asan.handler == SIG_DFL || pre_asan.handler == SIG_IGN);69#if defined(TEST_INSTALL_SIG_HANDLER)70 pre_asan = {};71 pre_asan.handler = &SigHandler;72 res = InternalSigaction(SIGSEGV, &pre_asan, nullptr);73 assert(res >= 0);74#elif defined(TEST_INSTALL_SIG_ACTION)75 pre_asan = {};76 pre_asan.flags = SA_SIGINFO | SA_NODEFER;77 pre_asan.handler = (__sighandler_t)&SigAction;78 res = InternalSigaction(SIGSEGV, &pre_asan, nullptr);79 assert(res >= 0);80#endif81}82 83__attribute__((section(".preinit_array"), used))84void (*__local_test_preinit)(void) = Init;85 86bool ExpectUserHandler() {87#if defined(TEST_INSTALL_SIG_HANDLER) || defined(TEST_INSTALL_SIG_ACTION)88 return !strcmp(getenv("ASAN_OPTIONS"), "handle_segv=0");89#endif90 return false;91}92 93int main(int argc, char *argv[]) {94 KernelSigaction post_asan = {};95 InternalSigaction(SIGSEGV, nullptr, &post_asan);96 97 assert(post_asan.handler != SIG_DFL);98 assert(post_asan.handler != SIG_IGN);99 assert(ExpectUserHandler() ==100 (post_asan.handler == pre_asan.handler));101 102 raise(SIGSEGV);103 printf("%s\n", handler);104 return 1;105}106 107// CHECK-NOT: TestSig108// CHECK: AddressSanitizer:DEADLYSIGNAL109 110// CHECK-HANDLER-NOT: AddressSanitizer:DEADLYSIGNAL111// CHECK-HANDLER: TestSigHandler112 113// CHECK-ACTION-NOT: AddressSanitizer:DEADLYSIGNAL114// CHECK-ACTION: TestSigAction115