1// Check that if LSan finds that SP doesn't point into thread stack (e.g.
2// if swapcontext is used), LSan will not hit the guard page.
3// RUN: %clang_lsan %s -o %t && %run %t
4// Missing 'getcontext' and 'makecontext' on Android.
5// UNSUPPORTED: android
6
7#include <errno.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <pthread.h>
12#include <ucontext.h>
13
14pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
15pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
16int ctxfunc_started = 0;
17
18static void die(const char* msg, int err) {
19 if (err == 0)
20 err = errno;
21 fprintf(stderr, format: "%s: %s\n", msg, strerror(errnum: err));
22 exit(EXIT_FAILURE);
23}
24
25static void ctxfunc() {
26 pthread_mutex_lock(mutex: &mutex);
27 ctxfunc_started = 1;
28 // printf("ctxfunc\n");
29 pthread_cond_signal(cond: &cond);
30 pthread_mutex_unlock(mutex: &mutex);
31 // Leave this context alive when the program exits.
32 for (;;);
33}
34
35static void* thread(void* arg) {
36 (void)arg;
37 ucontext_t ctx;
38 void* stack;
39
40 if (getcontext(ucp: &ctx) < 0)
41 die(msg: "getcontext", err: 0);
42 stack = malloc(size: 1 << 12);
43 if (stack == NULL)
44 die(msg: "malloc", err: 0);
45 ctx.uc_stack.ss_sp = stack;
46 ctx.uc_stack.ss_size = 1 << 12;
47 makecontext(ucp: &ctx, func: ctxfunc, argc: 0);
48 setcontext(&ctx);
49 die(msg: "setcontext", err: 0);
50 return NULL;
51}
52
53int main() {
54 pthread_t tid;
55 int i;
56
57 pthread_mutex_lock(mutex: &mutex);
58 i = pthread_create(newthread: &tid, NULL, start_routine: thread, NULL);
59 if (i != 0)
60 die(msg: "pthread_create", err: i);
61 while (!ctxfunc_started) pthread_cond_wait(cond: &cond, mutex: &mutex);
62 pthread_mutex_unlock(mutex: &mutex);
63 return 0;
64}
65

source code of compiler-rt/test/lsan/TestCases/Linux/guard-page.c