1*1d3ef5f1SJustin Cady // RUN: %clangxx_msan -O0 %s -o %t && %run %t
2*1d3ef5f1SJustin Cady
3*1d3ef5f1SJustin Cady #include <assert.h>
4*1d3ef5f1SJustin Cady #include <stdio.h>
5*1d3ef5f1SJustin Cady #include <stdlib.h>
6*1d3ef5f1SJustin Cady #include <ucontext.h>
7*1d3ef5f1SJustin Cady #include <unistd.h>
8*1d3ef5f1SJustin Cady
9*1d3ef5f1SJustin Cady #include <sanitizer/msan_interface.h>
10*1d3ef5f1SJustin Cady
11*1d3ef5f1SJustin Cady namespace {
12*1d3ef5f1SJustin Cady
13*1d3ef5f1SJustin Cady const int kStackSize = 1 << 20;
14*1d3ef5f1SJustin Cady char fiber_stack[kStackSize] = {};
15*1d3ef5f1SJustin Cady
16*1d3ef5f1SJustin Cady ucontext_t main_ctx;
17*1d3ef5f1SJustin Cady ucontext_t fiber_ctx;
18*1d3ef5f1SJustin Cady
fiber()19*1d3ef5f1SJustin Cady void fiber() {
20*1d3ef5f1SJustin Cady printf("%s: entering fiber\n", __FUNCTION__);
21*1d3ef5f1SJustin Cady
22*1d3ef5f1SJustin Cady // This fiber was switched into from main. Verify the details of main's stack
23*1d3ef5f1SJustin Cady // have been populated by MSAN.
24*1d3ef5f1SJustin Cady const void *previous_stack_bottom = nullptr;
25*1d3ef5f1SJustin Cady size_t previous_stack_size = 0;
26*1d3ef5f1SJustin Cady __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);
27*1d3ef5f1SJustin Cady assert(previous_stack_bottom != nullptr);
28*1d3ef5f1SJustin Cady assert(previous_stack_size != 0);
29*1d3ef5f1SJustin Cady
30*1d3ef5f1SJustin Cady printf("%s: implicitly swapcontext to main\n", __FUNCTION__);
31*1d3ef5f1SJustin Cady __msan_start_switch_fiber(previous_stack_bottom, previous_stack_size);
32*1d3ef5f1SJustin Cady }
33*1d3ef5f1SJustin Cady
34*1d3ef5f1SJustin Cady } // namespace
35*1d3ef5f1SJustin Cady
36*1d3ef5f1SJustin Cady // Set up a fiber, switch to it, and switch back, invoking __msan_*_switch_fiber
37*1d3ef5f1SJustin Cady // functions along the way. At each step, validate the correct stack addresses and
38*1d3ef5f1SJustin Cady // sizes are returned from those functions.
main(int argc,char ** argv)39*1d3ef5f1SJustin Cady int main(int argc, char **argv) {
40*1d3ef5f1SJustin Cady if (getcontext(&fiber_ctx) == -1) {
41*1d3ef5f1SJustin Cady perror("getcontext");
42*1d3ef5f1SJustin Cady _exit(1);
43*1d3ef5f1SJustin Cady }
44*1d3ef5f1SJustin Cady fiber_ctx.uc_stack.ss_sp = fiber_stack;
45*1d3ef5f1SJustin Cady fiber_ctx.uc_stack.ss_size = sizeof(fiber_stack);
46*1d3ef5f1SJustin Cady fiber_ctx.uc_link = &main_ctx;
47*1d3ef5f1SJustin Cady makecontext(&fiber_ctx, fiber, 0);
48*1d3ef5f1SJustin Cady
49*1d3ef5f1SJustin Cady // Tell MSAN a fiber switch is about to occur, then perform the switch
50*1d3ef5f1SJustin Cady printf("%s: swapcontext to fiber\n", __FUNCTION__);
51*1d3ef5f1SJustin Cady __msan_start_switch_fiber(fiber_stack, kStackSize);
52*1d3ef5f1SJustin Cady if (swapcontext(&main_ctx, &fiber_ctx) == -1) {
53*1d3ef5f1SJustin Cady perror("swapcontext");
54*1d3ef5f1SJustin Cady _exit(1);
55*1d3ef5f1SJustin Cady }
56*1d3ef5f1SJustin Cady
57*1d3ef5f1SJustin Cady // The fiber switched to above now switched back here. Tell MSAN that switch
58*1d3ef5f1SJustin Cady // is complete and verify the fiber details return by MSAN are correct.
59*1d3ef5f1SJustin Cady const void *previous_stack_bottom = nullptr;
60*1d3ef5f1SJustin Cady size_t previous_stack_size = 0;
61*1d3ef5f1SJustin Cady __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);
62*1d3ef5f1SJustin Cady assert(previous_stack_bottom == fiber_stack);
63*1d3ef5f1SJustin Cady assert(previous_stack_size == kStackSize);
64*1d3ef5f1SJustin Cady
65*1d3ef5f1SJustin Cady printf("%s: exiting\n", __FUNCTION__);
66*1d3ef5f1SJustin Cady
67*1d3ef5f1SJustin Cady return 0;
68*1d3ef5f1SJustin Cady }
69