1c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// RUN: %clang_esan_wset -O0 %s -o %t 2>&1
2c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// RUN: %run %t 2>&1 | FileCheck %s
3c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
4c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <assert.h>
5c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <setjmp.h>
6c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <signal.h>
7c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <stdio.h>
8c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <stdlib.h>
9c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <sys/mman.h>
10c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
11c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarsigjmp_buf mark;
12c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
13c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic void SignalHandler(int Sig) {
14c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (Sig == SIGSEGV) {
15c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    fprintf(stderr, "Handling SIGSEGV for signal\n");
16c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    siglongjmp(mark, 1);
17c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
18c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  exit(1);
19c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
20c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
21c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstatic void SigactionHandler(int Sig, siginfo_t *Info, void *Ctx) {
22c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (Sig == SIGSEGV) {
23c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    fprintf(stderr, "Handling SIGSEGV for sigaction\n");
24c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    siglongjmp(mark, 1);
25c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  }
26c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  exit(1);
27c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
28c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
29c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarint main(int argc, char **argv) {
30c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  __sighandler_t Prior = signal(SIGSEGV, SignalHandler);
31c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  assert(Prior == SIG_DFL);
32c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (sigsetjmp(mark, 1) == 0)
33c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    *((volatile int *)(ssize_t)argc) = 42; // Raise SIGSEGV
34c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  fprintf(stderr, "Past longjmp for signal\n");
35c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
36c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Prior = signal(SIGSEGV, SIG_DFL);
37c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  assert(Prior == SignalHandler);
38c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
39c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  struct sigaction SigAct;
40c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  SigAct.sa_sigaction = SigactionHandler;
41c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  int Res = sigfillset(&SigAct.sa_mask);
42c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  assert(Res == 0);
43c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  SigAct.sa_flags = SA_SIGINFO;
44c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Res = sigaction(SIGSEGV, &SigAct, NULL);
45c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  assert(Res == 0);
46c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
47c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (sigsetjmp(mark, 1) == 0)
48c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    *((volatile int *)(ssize_t)argc) = 42; // Raise SIGSEGV
49c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  fprintf(stderr, "Past longjmp for sigaction\n");
50c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
51c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Res = sigaction(SIGSEGV, NULL, &SigAct);
52c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  assert(Res == 0);
53c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  assert(SigAct.sa_sigaction == SigactionHandler);
54c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
55c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Test blocking SIGSEGV and raising a shadow fault.
56c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  sigset_t Set;
57c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  sigemptyset(&Set);
58c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  sigaddset(&Set, SIGSEGV);
59c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Res = sigprocmask(SIG_BLOCK, &Set, NULL);
60c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Make a large enough mapping that its start point will be before any
61c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // prior library-region shadow access.
62c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  char *buf = (char *)mmap(0, 640*1024, PROT_READ | PROT_WRITE,
63c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
64c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  buf[0] = 4;
65c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  munmap(buf, 640*1024);
66c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  fprintf(stderr, "Past blocked-SIGSEGV shadow fault\n");
67c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
68c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return 0;
69c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
70c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// CHECK:      Handling SIGSEGV for signal
71c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// CHECK-NEXT: Past longjmp for signal
72c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// CHECK-NEXT: Handling SIGSEGV for sigaction
73c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// CHECK-NEXT: Past longjmp for sigaction
74c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// CHECK-NEXT: Past blocked-SIGSEGV shadow fault
75c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// CHECK:      {{.*}} EfficiencySanitizer: the total working set size: {{[0-9]+}} Bytes ({{[0-9][0-9]}} cache lines)
76