Files
clang-p2996/compiler-rt/test/msan/Linux/swapcontext_annotation.cpp
Justin Cady 1d3ef5f122 [MSAN] Add fiber switching APIs
Add functions exposed via the MSAN interface to enable MSAN within
binaries that perform manual stack switching (e.g. through using fibers
or coroutines).

This functionality is analogous to the fiber APIs available for ASAN and TSAN.

Fixes google/sanitizers#1232

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D86471
2020-08-27 19:30:40 -07:00

69 lines
2.1 KiB
C++

// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <unistd.h>
#include <sanitizer/msan_interface.h>
namespace {
const int kStackSize = 1 << 20;
char fiber_stack[kStackSize] = {};
ucontext_t main_ctx;
ucontext_t fiber_ctx;
void fiber() {
printf("%s: entering fiber\n", __FUNCTION__);
// This fiber was switched into from main. Verify the details of main's stack
// have been populated by MSAN.
const void *previous_stack_bottom = nullptr;
size_t previous_stack_size = 0;
__msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);
assert(previous_stack_bottom != nullptr);
assert(previous_stack_size != 0);
printf("%s: implicitly swapcontext to main\n", __FUNCTION__);
__msan_start_switch_fiber(previous_stack_bottom, previous_stack_size);
}
} // namespace
// Set up a fiber, switch to it, and switch back, invoking __msan_*_switch_fiber
// functions along the way. At each step, validate the correct stack addresses and
// sizes are returned from those functions.
int main(int argc, char **argv) {
if (getcontext(&fiber_ctx) == -1) {
perror("getcontext");
_exit(1);
}
fiber_ctx.uc_stack.ss_sp = fiber_stack;
fiber_ctx.uc_stack.ss_size = sizeof(fiber_stack);
fiber_ctx.uc_link = &main_ctx;
makecontext(&fiber_ctx, fiber, 0);
// Tell MSAN a fiber switch is about to occur, then perform the switch
printf("%s: swapcontext to fiber\n", __FUNCTION__);
__msan_start_switch_fiber(fiber_stack, kStackSize);
if (swapcontext(&main_ctx, &fiber_ctx) == -1) {
perror("swapcontext");
_exit(1);
}
// The fiber switched to above now switched back here. Tell MSAN that switch
// is complete and verify the fiber details return by MSAN are correct.
const void *previous_stack_bottom = nullptr;
size_t previous_stack_size = 0;
__msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);
assert(previous_stack_bottom == fiber_stack);
assert(previous_stack_size == kStackSize);
printf("%s: exiting\n", __FUNCTION__);
return 0;
}