1// Test __msan_set_indirect_call_wrapper.
2
3// RUN: %clangxx_msan -mllvm -msan-wrap-indirect-calls=__msan_wrap_indirect_call \
4// RUN:     -mllvm -msan-wrap-indirect-calls-fast=0 \
5// RUN:     -O0 -g -rdynamic -Wl,--defsym=__executable_start=0 %s -o %t && %run %t
6
7// This test disables -msan-wrap-indirect-calls-fast, otherwise indirect calls
8// inside the same module are short-circuited and are never seen by the wrapper.
9
10#include <assert.h>
11#include <pthread.h>
12#include <stdio.h>
13#include <stdint.h>
14
15extern "C" void __msan_set_indirect_call_wrapper(uintptr_t);
16
17bool done_f, done_g;
18
19void f(void) {
20  assert(!done_g);
21  done_f = true;
22}
23
24void g(void) {
25  assert(done_f);
26  done_g = true;
27}
28
29typedef void (*Fn)(void);
30extern "C" Fn my_wrapper(Fn target) {
31  if (target == f) return g;
32  return target;
33}
34
35int main(void) {
36  volatile Fn fp;
37  fp = &f;
38  fp();
39  __msan_set_indirect_call_wrapper((uintptr_t)my_wrapper);
40  fp();
41  return !(done_f && done_g);
42}
43