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