forked from OSchip/llvm-project
78 lines
1.9 KiB
C++
78 lines
1.9 KiB
C++
// Test indirect call wrapping in MemorySanitizer runtime.
|
|
|
|
// RUN: %clangxx_msan -O0 -g -rdynamic %s -o %t && %run %t
|
|
// RUN: %clangxx_msan -O2 -g -rdynamic %s -o %t && %run %t
|
|
|
|
#include <assert.h>
|
|
#include <dlfcn.h>
|
|
#include <math.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <sys/time.h>
|
|
|
|
extern "C" void __msan_set_indirect_call_wrapper(uintptr_t);
|
|
|
|
bool pthread_create_done;
|
|
|
|
void *ThreadFn(void *) {
|
|
printf("bad threadfn\n");
|
|
return 0;
|
|
}
|
|
|
|
void *ThreadFn2(void *) {
|
|
printf("good threadfn\n");
|
|
pthread_create_done = true;
|
|
return 0;
|
|
}
|
|
|
|
int my_gettimeofday(struct timeval *p, void *q) {
|
|
p->tv_sec = 1;
|
|
p->tv_usec = 2;
|
|
return 42;
|
|
}
|
|
|
|
double my_lgamma(double x) {
|
|
return x;
|
|
}
|
|
|
|
uintptr_t real_gettimeofday;
|
|
uintptr_t real_lgamma;
|
|
|
|
extern "C" uintptr_t my_wrapper(uintptr_t f) {
|
|
if (f == (uintptr_t)ThreadFn) return (uintptr_t)&ThreadFn2;
|
|
if (f == real_gettimeofday) return (uintptr_t)my_gettimeofday;
|
|
if (f == real_lgamma) return (uintptr_t)my_lgamma;
|
|
return f;
|
|
}
|
|
|
|
int main(void) {
|
|
real_gettimeofday = (uintptr_t)dlsym(RTLD_NEXT, "gettimeofday");
|
|
real_lgamma = (uintptr_t)dlsym(RTLD_NEXT, "lgamma");
|
|
|
|
__msan_set_indirect_call_wrapper((uintptr_t)my_wrapper);
|
|
|
|
// ThreadFn is called indirectly from a wrapper function in MSan rtl and
|
|
// is subject to indirect call wrapping (it could be an native-to-translated
|
|
// edge).
|
|
pthread_t t;
|
|
pthread_create(&t, 0, ThreadFn, 0);
|
|
pthread_join(t, 0);
|
|
assert(pthread_create_done);
|
|
|
|
// gettimeofday is intercepted in msan_interceptors.cc and the real one (from
|
|
// libc) is called indirectly.
|
|
struct timeval tv;
|
|
int res = gettimeofday(&tv, NULL);
|
|
assert(tv.tv_sec == 1);
|
|
assert(tv.tv_usec == 2);
|
|
assert(res == 42);
|
|
|
|
// lgamma is intercepted in sanitizer_common_interceptors.inc and is also
|
|
// called indirectly.
|
|
double dres = lgamma(1.1);
|
|
assert(dres == 1.1);
|
|
|
|
return 0;
|
|
}
|