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
11namespace {
12
13const int kStackSize = 1 << 20;
14char fiber_stack[kStackSize] = {};
15
16ucontext_t main_ctx;
17ucontext_t fiber_ctx;
18
19void fiber() {
20 printf(format: "%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(bottom_old: &previous_stack_bottom, size_old: &previous_stack_size);
27 assert(previous_stack_bottom != nullptr);
28 assert(previous_stack_size != 0);
29
30 printf(format: "%s: implicitly swapcontext to main\n", __FUNCTION__);
31 __msan_start_switch_fiber(bottom: previous_stack_bottom, size: 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.
39int main(int argc, char **argv) {
40 if (getcontext(ucp: &fiber_ctx) == -1) {
41 perror(s: "getcontext");
42 _exit(status: 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(ucp: &fiber_ctx, func: fiber, argc: 0);
48
49 // Tell MSAN a fiber switch is about to occur, then perform the switch
50 printf(format: "%s: swapcontext to fiber\n", __FUNCTION__);
51 __msan_start_switch_fiber(bottom: fiber_stack, size: kStackSize);
52 if (swapcontext(oucp: &main_ctx, ucp: &fiber_ctx) == -1) {
53 perror(s: "swapcontext");
54 _exit(status: 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(bottom_old: &previous_stack_bottom, size_old: &previous_stack_size);
62 assert(previous_stack_bottom == fiber_stack);
63 assert(previous_stack_size == kStackSize);
64
65 printf(format: "%s: exiting\n", __FUNCTION__);
66
67 return 0;
68}
69

source code of compiler-rt/test/msan/Linux/swapcontext_annotation.cpp