From 7555f5ed1f0b76ef3ff0b0550f1d62a2203c69d3 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 18 Nov 2014 10:33:15 +0000 Subject: [PATCH] [msan] Remove MSanDR and supporting code. MSanDR is a dynamic instrumentation tool that can instrument the code (prebuilt libraries and such) that could not be instrumented at compile time. This code is unused (to the best of our knowledge) and unmaintained, and starting to bit-rot. llvm-svn: 222232 --- compiler-rt/lib/CMakeLists.txt | 1 - compiler-rt/lib/asan/asan_interceptors.h | 2 +- compiler-rt/lib/asan/asan_malloc_win.cc | 2 +- compiler-rt/lib/asan/asan_new_delete.cc | 2 +- compiler-rt/lib/asan/asan_win_dll_thunk.cc | 2 +- compiler-rt/lib/lsan/lsan_interceptors.cc | 2 +- compiler-rt/lib/msan/msan.cc | 54 +- compiler-rt/lib/msan/msan.h | 3 - compiler-rt/lib/msan/msan_interceptors.cc | 46 +- compiler-rt/lib/msan/msan_interface_internal.h | 19 - compiler-rt/lib/msan/msan_new_delete.cc | 2 +- compiler-rt/lib/msan/msan_thread.cc | 2 +- compiler-rt/lib/msan/tests/msan_loadable.cc | 18 - compiler-rt/lib/msan/tests/msan_test.cc | 62 +- compiler-rt/lib/msandr/CMakeLists.txt | 26 - compiler-rt/lib/msandr/README.txt | 40 - compiler-rt/lib/msandr/msandr.cc | 900 --------------------- .../lib/sanitizer_common/sanitizer_common.h | 17 - .../sanitizer_common_interceptors.inc | 18 +- .../lib/sanitizer_common/sanitizer_interception.h | 25 - .../sanitizer_common/sanitizer_linux_libcdep.cc | 12 +- compiler-rt/test/msan/wrap_indirect_calls.cc | 64 -- .../test/msan/wrap_indirect_calls/caller.cc | 51 -- .../test/msan/wrap_indirect_calls/lit.local.cfg | 3 - compiler-rt/test/msan/wrap_indirect_calls/one.cc | 3 - compiler-rt/test/msan/wrap_indirect_calls/two.cc | 11 - .../test/msan/wrap_indirect_calls/wrapper.cc | 11 - compiler-rt/test/msan/wrap_indirect_calls2.cc | 42 - .../test/msan/wrap_indirect_calls_in_rtl.cc | 77 -- 29 files changed, 37 insertions(+), 1480 deletions(-) delete mode 100644 compiler-rt/lib/msandr/CMakeLists.txt delete mode 100644 compiler-rt/lib/msandr/README.txt delete mode 100644 compiler-rt/lib/msandr/msandr.cc delete mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_interception.h delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls.cc delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls/caller.cc delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls/lit.local.cfg delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls/one.cc delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls/two.cc delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls/wrapper.cc delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls2.cc delete mode 100644 compiler-rt/test/msan/wrap_indirect_calls_in_rtl.cc diff --git a/compiler-rt/lib/CMakeLists.txt b/compiler-rt/lib/CMakeLists.txt index 934c5b7..6929e68 100644 --- a/compiler-rt/lib/CMakeLists.txt +++ b/compiler-rt/lib/CMakeLists.txt @@ -25,7 +25,6 @@ endif() if(COMPILER_RT_HAS_MSAN) add_subdirectory(msan) - add_subdirectory(msandr) endif() if(COMPILER_RT_HAS_PROFILE) diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 55460c2..ee3b82a 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -15,7 +15,7 @@ #define ASAN_INTERCEPTORS_H #include "asan_internal.h" -#include "sanitizer_common/sanitizer_interception.h" +#include "interception/interception.h" #include "sanitizer_common/sanitizer_platform_interceptors.h" // Use macro to describe if specific function should be diff --git a/compiler-rt/lib/asan/asan_malloc_win.cc b/compiler-rt/lib/asan/asan_malloc_win.cc index 8c1c448..c99e312 100644 --- a/compiler-rt/lib/asan/asan_malloc_win.cc +++ b/compiler-rt/lib/asan/asan_malloc_win.cc @@ -19,7 +19,7 @@ #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_stack.h" -#include "sanitizer_common/sanitizer_interception.h" +#include "interception/interception.h" #include diff --git a/compiler-rt/lib/asan/asan_new_delete.cc b/compiler-rt/lib/asan/asan_new_delete.cc index 2427602..e48bdaf 100644 --- a/compiler-rt/lib/asan/asan_new_delete.cc +++ b/compiler-rt/lib/asan/asan_new_delete.cc @@ -16,7 +16,7 @@ #include "asan_internal.h" #include "asan_stack.h" -#include "sanitizer_common/sanitizer_interception.h" +#include "interception/interception.h" #include diff --git a/compiler-rt/lib/asan/asan_win_dll_thunk.cc b/compiler-rt/lib/asan/asan_win_dll_thunk.cc index dff6e18..b38a2d1 100644 --- a/compiler-rt/lib/asan/asan_win_dll_thunk.cc +++ b/compiler-rt/lib/asan/asan_win_dll_thunk.cc @@ -21,7 +21,7 @@ // simplifies the build procedure. #ifdef ASAN_DLL_THUNK #include "asan_init_version.h" -#include "sanitizer_common/sanitizer_interception.h" +#include "interception/interception.h" // ---------- Function interception helper functions and macros ----------- {{{1 extern "C" { diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cc b/compiler-rt/lib/lsan/lsan_interceptors.cc index 484f578..b01bbf8 100644 --- a/compiler-rt/lib/lsan/lsan_interceptors.cc +++ b/compiler-rt/lib/lsan/lsan_interceptors.cc @@ -12,11 +12,11 @@ // //===----------------------------------------------------------------------===// +#include "interception/interception.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" -#include "sanitizer_common/sanitizer_interception.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index b232834..09622c4 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -34,8 +34,6 @@ using namespace __sanitizer; static THREADLOCAL int msan_expect_umr = 0; static THREADLOCAL int msan_expected_umr_found = 0; -static bool msan_running_under_dr; - // Function argument shadow. Each argument starts at the next available 8-byte // aligned address. SANITIZER_INTERFACE_ATTRIBUTE @@ -63,7 +61,6 @@ SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __msan_origin_tls; static THREADLOCAL int is_in_symbolizer; -static THREADLOCAL int is_in_loader; extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins; @@ -79,14 +76,6 @@ void EnterSymbolizer() { ++is_in_symbolizer; } void ExitSymbolizer() { --is_in_symbolizer; } bool IsInSymbolizer() { return is_in_symbolizer; } -void EnterLoader() { ++is_in_loader; } -void ExitLoader() { --is_in_loader; } - -extern "C" { -SANITIZER_INTERFACE_ATTRIBUTE -bool __msan_is_in_loader() { return is_in_loader; } -} - static Flags msan_flags; Flags *flags() { @@ -394,7 +383,7 @@ void __msan_init() { __msan_clear_on_return(); if (__msan_get_track_origins()) VPrintf(1, "msan_track_origins\n"); - if (!InitShadow(/* prot1 */ !msan_running_under_dr, /* prot2 */ true, + if (!InitShadow(/* prot1 */ true, /* prot2 */ true, /* map_shadow */ true, __msan_get_track_origins())) { Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); @@ -498,40 +487,13 @@ int __msan_set_poison_in_malloc(int do_poison) { return old; } -int __msan_has_dynamic_component() { - return msan_running_under_dr; -} +int __msan_has_dynamic_component() { return false; } NOINLINE void __msan_clear_on_return() { __msan_param_tls[0] = 0; } -static void* get_tls_base() { - u64 p; - asm("mov %%fs:0, %0" - : "=r"(p) ::); - return (void*)p; -} - -int __msan_get_retval_tls_offset() { - // volatile here is needed to avoid UB, because the compiler thinks that we - // are doing address arithmetics on unrelated pointers, and takes some - // shortcuts - volatile sptr retval_tls_p = (sptr)&__msan_retval_tls; - volatile sptr tls_base_p = (sptr)get_tls_base(); - return retval_tls_p - tls_base_p; -} - -int __msan_get_param_tls_offset() { - // volatile here is needed to avoid UB, because the compiler thinks that we - // are doing address arithmetics on unrelated pointers, and takes some - // shortcuts - volatile sptr param_tls_p = (sptr)&__msan_param_tls; - volatile sptr tls_base_p = (sptr)get_tls_base(); - return param_tls_p - tls_base_p; -} - void __msan_partial_poison(const void* data, void* shadow, uptr size) { internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size); } @@ -657,18 +619,6 @@ void __msan_set_death_callback(void (*callback)(void)) { death_callback = callback; } -void *__msan_wrap_indirect_call(void *target) { - return IndirectExternCall(target); -} - -void __msan_dr_is_initialized() { - msan_running_under_dr = true; -} - -void __msan_set_indirect_call_wrapper(uptr wrapper) { - SetIndirectCallWrapper(wrapper); -} - #if !SANITIZER_SUPPORTS_WEAK_HOOKS extern "C" { SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h index 892cf04..f01940b 100644 --- a/compiler-rt/lib/msan/msan.h +++ b/compiler-rt/lib/msan/msan.h @@ -65,9 +65,6 @@ struct SymbolizerScope { ~SymbolizerScope() { ExitSymbolizer(); } }; -void EnterLoader(); -void ExitLoader(); - void MsanDie(); void PrintWarning(uptr pc, uptr bp); void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin); diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index 1c7a812..aa6b1ff 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -15,6 +15,7 @@ // sanitizer_common/sanitizer_common_interceptors.h //===----------------------------------------------------------------------===// +#include "interception/interception.h" #include "msan.h" #include "msan_chained_origin_depot.h" #include "msan_origin.h" @@ -25,7 +26,6 @@ #include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_interception.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_linux.h" @@ -315,11 +315,8 @@ INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) { INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { ENSURE_MSAN_INITED(); char *res = REAL(gcvt)(number, ndigit, buf); - // DynamoRio tool will take care of unpoisoning gcvt result for us. - if (!__msan_has_dynamic_component()) { - SIZE_T n = REAL(strlen)(buf); - __msan_unpoison(buf, n + 1); - } + SIZE_T n = REAL(strlen)(buf); + __msan_unpoison(buf, n + 1); return res; } @@ -349,9 +346,7 @@ INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \ ENSURE_MSAN_INITED(); \ ret_type res = REAL(func)(__VA_ARGS__); \ - if (!__msan_has_dynamic_component()) { \ - __msan_unpoison(endptr, sizeof(*endptr)); \ - } \ + __msan_unpoison(endptr, sizeof(*endptr)); \ return res; #define INTERCEPTOR_STRTO(ret_type, func) \ @@ -408,7 +403,7 @@ INTERCEPTOR_STRTO_BASE_LOC(unsigned long long, __strtoull_internal) // NOLINT INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) { ENSURE_MSAN_INITED(); int res = REAL(vswprintf)(str, size, format, ap); - if (res >= 0 && !__msan_has_dynamic_component()) { + if (res >= 0) { __msan_unpoison(str, 4 * (res + 1)); } return res; @@ -575,21 +570,16 @@ INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) { ENSURE_MSAN_INITED(); char *res = REAL(fcvt)(x, a, b, c); - if (!__msan_has_dynamic_component()) { - __msan_unpoison(b, sizeof(*b)); - __msan_unpoison(c, sizeof(*c)); - if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); - } + __msan_unpoison(b, sizeof(*b)); + __msan_unpoison(c, sizeof(*c)); + if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); return res; } INTERCEPTOR(char *, getenv, char *name) { ENSURE_MSAN_INITED(); char *res = REAL(getenv)(name); - if (!__msan_has_dynamic_component()) { - if (res) - __msan_unpoison(res, REAL(strlen)(res) + 1); - } + if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); return res; } @@ -927,17 +917,15 @@ static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, } dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; UnpoisonParam(3); - return IndirectExternCall(cbdata->callback)(info, size, cbdata->data); + return cbdata->callback(info, size, cbdata->data); } INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { ENSURE_MSAN_INITED(); - EnterLoader(); dl_iterate_phdr_data cbdata; cbdata.callback = callback; cbdata.data = data; int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); - ExitLoader(); return res; } @@ -977,7 +965,7 @@ static void SignalHandler(int signo) { typedef void (*signal_cb)(int x); signal_cb cb = (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); - IndirectExternCall(cb)(signo); + cb(signo); } static void SignalAction(int signo, void *si, void *uc) { @@ -990,7 +978,7 @@ static void SignalAction(int signo, void *si, void *uc) { typedef void (*sigaction_cb)(int, void *, void *); sigaction_cb cb = (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); - IndirectExternCall(cb)(signo, si, uc); + cb(signo, si, uc); } INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act, @@ -1118,7 +1106,7 @@ struct MSanAtExitRecord { void MSanAtExitWrapper(void *arg) { UnpoisonParam(1); MSanAtExitRecord *r = (MSanAtExitRecord *)arg; - IndirectExternCall(r->func)(r->arg); + r->func(r->arg); InternalFree(r); } @@ -1228,12 +1216,8 @@ int OnExit() { } while (false) // FIXME #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() -#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) \ - if (!__msan_has_dynamic_component() && map) { \ - /* If msandr didn't clear the shadow before the initializers ran, we do */ \ - /* it ourselves afterwards. */ \ - ForEachMappedRegion((link_map *)map, __msan_unpoison); \ - } +#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) \ + if (map) ForEachMappedRegion((link_map *)map, __msan_unpoison); #include "sanitizer_common/sanitizer_common_interceptors.inc" diff --git a/compiler-rt/lib/msan/msan_interface_internal.h b/compiler-rt/lib/msan/msan_interface_internal.h index 401d6f9..8641f81 100644 --- a/compiler-rt/lib/msan/msan_interface_internal.h +++ b/compiler-rt/lib/msan/msan_interface_internal.h @@ -122,16 +122,6 @@ void __msan_dump_shadow(const void *x, uptr size); SANITIZER_INTERFACE_ATTRIBUTE int __msan_has_dynamic_component(); -// Returns x such that %fs:x is the first byte of __msan_retval_tls. -SANITIZER_INTERFACE_ATTRIBUTE -int __msan_get_retval_tls_offset(); -SANITIZER_INTERFACE_ATTRIBUTE -int __msan_get_param_tls_offset(); - -// For intercepting mmap from ld.so in msandr. -SANITIZER_INTERFACE_ATTRIBUTE -bool __msan_is_in_loader(); - // For testing. SANITIZER_INTERFACE_ATTRIBUTE u32 __msan_get_umr_origin(); @@ -162,15 +152,6 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_unaligned_store64(uu64 *p, u64 x); SANITIZER_INTERFACE_ATTRIBUTE -void __msan_dr_is_initialized(); - -SANITIZER_INTERFACE_ATTRIBUTE -void *__msan_wrap_indirect_call(void *target); - -SANITIZER_INTERFACE_ATTRIBUTE -void __msan_set_indirect_call_wrapper(uptr wrapper); - -SANITIZER_INTERFACE_ATTRIBUTE void __msan_set_death_callback(void (*callback)(void)); } // extern "C" diff --git a/compiler-rt/lib/msan/msan_new_delete.cc b/compiler-rt/lib/msan/msan_new_delete.cc index 3bae49c..9a8e56e 100644 --- a/compiler-rt/lib/msan/msan_new_delete.cc +++ b/compiler-rt/lib/msan/msan_new_delete.cc @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "msan.h" -#include "sanitizer_common/sanitizer_interception.h" +#include "interception/interception.h" #if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE diff --git a/compiler-rt/lib/msan/msan_thread.cc b/compiler-rt/lib/msan/msan_thread.cc index 5fe99f6..2a1e05a 100644 --- a/compiler-rt/lib/msan/msan_thread.cc +++ b/compiler-rt/lib/msan/msan_thread.cc @@ -73,7 +73,7 @@ thread_return_t MsanThread::ThreadStart() { return 0; } - thread_return_t res = IndirectExternCall(start_routine_)(arg_); + thread_return_t res = start_routine_(arg_); return res; } diff --git a/compiler-rt/lib/msan/tests/msan_loadable.cc b/compiler-rt/lib/msan/tests/msan_loadable.cc index db3bf48..06e880f 100644 --- a/compiler-rt/lib/msan/tests/msan_loadable.cc +++ b/compiler-rt/lib/msan/tests/msan_loadable.cc @@ -20,24 +20,6 @@ static void *dso_global; // No name mangling. extern "C" { -__attribute__((constructor)) -void loadable_module_init(void) { - if (!__msan_has_dynamic_component()) - return; - // The real test is that this compare should not make an uninit. - if (dso_global == NULL) - dso_global = malloc(4); -} - -__attribute__((destructor)) -void loadable_module_fini(void) { - if (!__msan_has_dynamic_component()) - return; - free(dso_global); - // *Don't* overwrite it with NULL! That would unpoison it, but our test - // relies on reloading at the same address and keeping the poison. -} - void **get_dso_global() { return &dso_global; } diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index c91fb0d..12012a0 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -251,7 +251,6 @@ TEST(MemorySanitizer, ArgTest) { TEST(MemorySanitizer, CallAndRet) { - if (!__msan_has_dynamic_component()) return; ReturnPoisoned(); ReturnPoisoned(); ReturnPoisoned(); @@ -494,14 +493,12 @@ TEST(MemorySanitizer, DynMem) { static char *DynRetTestStr; TEST(MemorySanitizer, DynRet) { - if (!__msan_has_dynamic_component()) return; ReturnPoisoned(); EXPECT_NOT_POISONED(clearenv()); } TEST(MemorySanitizer, DynRet1) { - if (!__msan_has_dynamic_component()) return; ReturnPoisoned(); } @@ -1452,13 +1449,8 @@ void TestOverlapMemmove() { x[2] = 0; memmove(x, x + 1, (size - 1) * sizeof(T)); EXPECT_NOT_POISONED(x[1]); - if (!__msan_has_dynamic_component()) { - // FIXME: under DR we will lose this information - // because accesses in memmove will unpoisin the shadow. - // We need to use our own memove implementation instead of libc's. - EXPECT_POISONED(x[0]); - EXPECT_POISONED(x[2]); - } + EXPECT_POISONED(x[0]); + EXPECT_POISONED(x[2]); delete [] x; } @@ -3732,56 +3724,6 @@ TEST(VectorMaddTest, mmx_pmadd_wd) { } #endif // defined(__clang__) -TEST(MemorySanitizerDr, StoreInDSOTest) { - if (!__msan_has_dynamic_component()) return; - char* s = new char[10]; - dso_memfill(s, 9); - EXPECT_NOT_POISONED(s[5]); - EXPECT_POISONED(s[9]); -} - -int return_poisoned_int() { - return ReturnPoisoned(); -} - -TEST(MemorySanitizerDr, ReturnFromDSOTest) { - if (!__msan_has_dynamic_component()) return; - EXPECT_NOT_POISONED(dso_callfn(return_poisoned_int)); -} - -NOINLINE int TrashParamTLS(long long x, long long y, long long z) { //NOLINT - EXPECT_POISONED(x); - EXPECT_POISONED(y); - EXPECT_POISONED(z); - return 0; -} - -static int CheckParamTLS(long long x, long long y, long long z) { //NOLINT - EXPECT_NOT_POISONED(x); - EXPECT_NOT_POISONED(y); - EXPECT_NOT_POISONED(z); - return 0; -} - -TEST(MemorySanitizerDr, CallFromDSOTest) { - if (!__msan_has_dynamic_component()) return; - S8* x = GetPoisoned(); - S8* y = GetPoisoned(); - S8* z = GetPoisoned(); - EXPECT_NOT_POISONED(TrashParamTLS(*x, *y, *z)); - EXPECT_NOT_POISONED(dso_callfn1(CheckParamTLS)); -} - -static void StackStoreInDSOFn(int* x, int* y) { - EXPECT_NOT_POISONED(*x); - EXPECT_NOT_POISONED(*y); -} - -TEST(MemorySanitizerDr, StackStoreInDSOTest) { - if (!__msan_has_dynamic_component()) return; - dso_stack_store(StackStoreInDSOFn, 1); -} - TEST(MemorySanitizerOrigins, SetGet) { EXPECT_EQ(TrackingOrigins(), __msan_get_track_origins()); if (!TrackingOrigins()) return; diff --git a/compiler-rt/lib/msandr/CMakeLists.txt b/compiler-rt/lib/msandr/CMakeLists.txt deleted file mode 100644 index 5a96a9d..0000000 --- a/compiler-rt/lib/msandr/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ - -if(DynamoRIO_DIR AND DrMemoryFramework_DIR) - set(CMAKE_COMPILER_IS_GNUCC 1) - find_package(DynamoRIO) - find_package(DrMemoryFramework) - - set(arch "x86_64") - add_library(clang_rt.msandr-${arch} SHARED msandr.cc) - configure_DynamoRIO_client(clang_rt.msandr-${arch}) - - function(append_target_cflags tgt cflags) - get_property(old_cflags TARGET clang_rt.msandr-${arch} PROPERTY COMPILE_FLAGS) - set_property(TARGET clang_rt.msandr-${arch} PROPERTY COMPILE_FLAGS "${old_cflags} ${cflags}") - endfunction(append_target_cflags) - - append_target_cflags(clang_rt.msandr-${arch} "-Wno-c++11-extensions") - - use_DynamoRIO_extension(clang_rt.msandr-${arch} drutil) - use_DynamoRIO_extension(clang_rt.msandr-${arch} drmgr) - use_DynamoRIO_extension(clang_rt.msandr-${arch} drsyscall) - - set_target_properties(clang_rt.msandr-${arch} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) - install(TARGETS clang_rt.msandr-${arch} - LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) -endif() diff --git a/compiler-rt/lib/msandr/README.txt b/compiler-rt/lib/msandr/README.txt deleted file mode 100644 index 81a87c6..0000000 --- a/compiler-rt/lib/msandr/README.txt +++ /dev/null @@ -1,40 +0,0 @@ -Experimental DynamoRIO-MSAN plugin (codename "MSanDR"). -Supports Linux/x86_64 only. - -Building: - 1. First, download and build DynamoRIO: - (svn co https://dynamorio.googlecode.com/svn/trunk dr && \ - cd dr && mkdir build && cd build && \ - cmake -DDR_EXT_DRMGR_STATIC=ON -DDR_EXT_DRSYMS_STATIC=ON \ - -DDR_EXT_DRUTIL_STATIC=ON -DDR_EXT_DRWRAP_STATIC=ON \ - -DDR_EXT_DRX_STATIC=ON .. && \ - make -j10 && make install) - - 2. Download and build DrMemory (for DrSyscall extension) - (svn co http://drmemory.googlecode.com/svn/trunk/ drmemory && \ - cd drmemory && mkdir build && cd build && \ - cmake -DDynamoRIO_DIR=`pwd`/../../dr/exports/cmake .. && \ - make -j10 && make install) - - NOTE: The line above will build a shared DrSyscall library in a non-standard - location. This will require the use of LD_LIBRARY_PATH when running MSanDR. - To build a static DrSyscall library (and link it into MSanDR), add - -DDR_EXT_DRSYSCALL_STATIC=ON to the CMake invocation above, but - beware: DrSyscall is LGPL. - - 3. Now, build LLVM with two extra CMake flags: - -DDynamoRIO_DIR=/exports/cmake - -DDrMemoryFramework_DIR=/exports64/drmf - - This will build a lib/clang/$VERSION/lib/linux/libclang_rt.msandr-x86_64.so - -Running: - /exports/bin64/drrun -c lib/clang/$VERSION/lib/linux/libclang_rt.msandr-x86_64.so -- test_binary - -MSan unit tests contain several tests for MSanDR (use MemorySanitizerDr.* gtest filter). - -Debugging: - Add -DCMAKE_BUILD_TYPE=Debug to the first and/or second cmake invocation(s). - Add -debug -v to drrun invocation line (right before -c). - Add -checklevel 1 to drrun (as the first argument) to make debug DR faster. - diff --git a/compiler-rt/lib/msandr/msandr.cc b/compiler-rt/lib/msandr/msandr.cc deleted file mode 100644 index 5159ddb..0000000 --- a/compiler-rt/lib/msandr/msandr.cc +++ /dev/null @@ -1,900 +0,0 @@ -//===-- msandr.cc ---------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of MemorySanitizer. -// -// DynamoRio client for MemorySanitizer. -// -// MemorySanitizer requires that all program code is instrumented. Any memory -// store that can turn an uninitialized value into an initialized value must be -// observed by the tool, otherwise we risk reporting a false UMR. -// -// This also includes any libraries that the program depends on. -// -// In the case when rebuilding all program dependencies with MemorySanitizer is -// problematic, an experimental MSanDR tool (the code you are currently looking -// at) can be used. It is a DynamoRio-based tool that uses dynamic -// instrumentation to -// * Unpoison all memory stores. -// * Unpoison TLS slots used by MemorySanitizer to pass function arguments and -// return value shadow on anything that looks like a function call or a return -// from a function. -// -// This tool does not detect the use of uninitialized values in uninstrumented -// libraries. It merely gets rid of false positives by marking all data that -// passes through uninstrumented code as fully initialized. -//===----------------------------------------------------------------------===// - -#include -#include -#include -#include - -#include -#include /* for SYS_mmap */ - -#include - -// XXX: it seems setting macro in CMakeLists.txt does not work, -// so manually set it here now. - -// Building msandr client for running in DynamoRIO hybrid mode, -// which allows some module running natively. -// TODO: turn it on by default when hybrid is stable enough -// #define MSANDR_NATIVE_EXEC - -#ifndef MSANDR_NATIVE_EXEC -#include -#include -#include -#include -#endif - -#define TESTALL(mask, var) (((mask) & (var)) == (mask)) -#define TESTANY(mask, var) (((mask) & (var)) != 0) - -#define CHECK_IMPL(condition, file, line) \ - do { \ - if (!(condition)) { \ - dr_printf("Check failed: `%s`\nat %s:%d\n", #condition, file, line); \ - dr_abort(); \ - } \ - } while (0) // TODO: stacktrace - -#define CHECK(condition) CHECK_IMPL(condition, __FILE__, __LINE__) - -#define VERBOSITY 0 - -// Building msandr client for standalone test that does not need to -// run with msan build executables. Disable by default. -// #define MSANDR_STANDALONE_TEST - -#define NUM_TLS_RETVAL 1 -#define NUM_TLS_PARAM 6 - -#ifdef MSANDR_STANDALONE_TEST -// For testing purpose, we map app to shadow memory at [0x100000, 0x20000). -// Normally, the app starts at 0x400000: -// 00400000-004e0000 r-xp 00000000 fc:00 524343 /bin/bash -// so there should be no problem. -# define SHADOW_MEMORY_BASE ((void *)0x100000) -# define SHADOW_MEMORY_SIZE (0x100000) -# define SHADOW_MEMORY_MASK (SHADOW_MEMORY_SIZE - 4 /* to avoid overflow */) -#else -// shadow memory range [0x200000000000, 0x400000000000) -// assuming no app memory below 0x200000000000 -# define SHADOW_MEMORY_MASK 0x3fffffffffffULL -#endif /* MSANDR_STANDALONE_TEST */ - -typedef void *(*WrapperFn)(void *); -extern "C" void __msan_set_indirect_call_wrapper(WrapperFn wrapper); -extern "C" void __msan_dr_is_initialized(); - -namespace { - -int msan_retval_tls_offset; -int msan_param_tls_offset; - -#ifndef MSANDR_NATIVE_EXEC -class ModuleData { -public: - ModuleData(); - ModuleData(const module_data_t *info); - // Yes, we want default copy, assign, and dtor semantics. - -public: - app_pc start_; - app_pc end_; - // Full path to the module. - std::string path_; - module_handle_t handle_; - bool should_instrument_; - bool executed_; -}; - -// A vector of loaded modules sorted by module bounds. We lookup the current PC -// in here from the bb event. This is better than an rb tree because the lookup -// is faster and the bb event occurs far more than the module load event. -std::vector g_module_list; - -ModuleData::ModuleData() - : start_(NULL), end_(NULL), path_(""), handle_(NULL), - should_instrument_(false), executed_(false) { -} - -ModuleData::ModuleData(const module_data_t *info) - : start_(info->start), end_(info->end), path_(info->full_path), - handle_(info->handle), - // We'll check the black/white lists later and adjust this. - should_instrument_(true), executed_(false) { -} -#endif /* !MSANDR_NATIVE_EXEC */ - -int(*__msan_get_retval_tls_offset)(); -int(*__msan_get_param_tls_offset)(); -void (*__msan_unpoison)(void *base, size_t size); -bool (*__msan_is_in_loader)(); - -#ifdef MSANDR_STANDALONE_TEST -uint mock_msan_retval_tls_offset; -uint mock_msan_param_tls_offset; -static int mock_msan_get_retval_tls_offset() { - return (int)mock_msan_retval_tls_offset; -} - -static int mock_msan_get_param_tls_offset() { - return (int)mock_msan_param_tls_offset; -} - -static void mock_msan_unpoison(void *base, size_t size) { - /* do nothing */ -} - -static bool mock_msan_is_in_loader() { - return false; -} -#endif /* MSANDR_STANDALONE_TEST */ - -static generic_func_t LookupCallback(module_data_t *app, const char *name) { -#ifdef MSANDR_STANDALONE_TEST - if (strcmp("__msan_get_retval_tls_offset", name) == 0) { - return (generic_func_t)mock_msan_get_retval_tls_offset; - } else if (strcmp("__msan_get_param_tls_offset", name) == 0) { - return (generic_func_t)mock_msan_get_param_tls_offset; - } else if (strcmp("__msan_unpoison", name) == 0) { - return (generic_func_t)mock_msan_unpoison; - } else if (strcmp("__msan_is_in_loader", name) == 0) { - return (generic_func_t)mock_msan_is_in_loader; - } - CHECK(false); - return NULL; -#else /* !MSANDR_STANDALONE_TEST */ - generic_func_t callback = dr_get_proc_address(app->handle, name); - if (callback == NULL) { - dr_printf("Couldn't find `%s` in %s\n", name, app->full_path); - CHECK(callback); - } - return callback; -#endif /* !MSANDR_STANDALONE_TEST */ -} - -void InitializeMSanCallbacks() { - module_data_t *app = dr_lookup_module_by_name(dr_get_application_name()); - if (!app) { - dr_printf("%s - oops, dr_lookup_module_by_name failed!\n", - dr_get_application_name()); - CHECK(app); - } - - __msan_get_retval_tls_offset = (int (*)()) - LookupCallback(app, "__msan_get_retval_tls_offset"); - __msan_get_param_tls_offset = (int (*)()) - LookupCallback(app, "__msan_get_param_tls_offset"); - __msan_unpoison = (void(*)(void *, size_t)) - LookupCallback(app, "__msan_unpoison"); - __msan_is_in_loader = (bool (*)()) - LookupCallback(app, "__msan_is_in_loader"); - - dr_free_module_data(app); -} - -// FIXME: Handle absolute addresses and PC-relative addresses. -// FIXME: Handle TLS accesses via FS or GS. DR assumes all other segments have -// a zero base anyway. -bool OperandIsInteresting(opnd_t opnd) { - return (opnd_is_base_disp(opnd) && opnd_get_segment(opnd) != DR_SEG_FS && - opnd_get_segment(opnd) != DR_SEG_GS); -} - -bool WantToInstrument(instr_t *instr) { - // TODO: skip push instructions? - switch (instr_get_opcode(instr)) { - // FIXME: support the instructions excluded below: - case OP_rep_cmps: - // f3 a6 rep cmps %ds:(%rsi) %es:(%rdi) %rsi %rdi %rcx -> %rsi %rdi %rcx - return false; - } - - // Labels appear due to drutil_expand_rep_string() - if (instr_is_label(instr)) - return false; - - CHECK(instr_ok_to_mangle(instr) == true); - - if (instr_writes_memory(instr)) { - for (int d = 0; d < instr_num_dsts(instr); d++) { - opnd_t op = instr_get_dst(instr, d); - if (OperandIsInteresting(op)) - return true; - } - } - - return false; -} - -#define PRE(at, what) instrlist_meta_preinsert(bb, at, INSTR_CREATE_##what); -#define PREF(at, what) instrlist_meta_preinsert(bb, at, what); - -void InstrumentMops(void *drcontext, instrlist_t *bb, instr_t *instr, opnd_t op, - bool is_write) { - bool need_to_restore_eflags = false; - uint flags = instr_get_arith_flags(instr); - // TODO: do something smarter with flags and spills in general? - // For example, spill them only once for a sequence of instrumented - // instructions that don't change/read flags. - - if (!TESTALL(EFLAGS_WRITE_6, flags) || TESTANY(EFLAGS_READ_6, flags)) { - if (VERBOSITY > 1) - dr_printf("Spilling eflags...\n"); - need_to_restore_eflags = true; - // TODO: Maybe sometimes don't need to 'seto'. - // TODO: Maybe sometimes don't want to spill XAX here? - // TODO: No need to spill XAX here if XAX is not used in the BB. - dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); - dr_save_arith_flags_to_xax(drcontext, bb, instr); - dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_3); - dr_restore_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); - } - -#if 0 - dr_printf("==DRMSAN== DEBUG: %d %d %d %d %d %d\n", - opnd_is_memory_reference(op), opnd_is_base_disp(op), - opnd_is_base_disp(op) ? opnd_get_index(op) : -1, - opnd_is_far_memory_reference(op), opnd_is_reg_pointer_sized(op), - opnd_is_base_disp(op) ? opnd_get_disp(op) : -1); -#endif - - reg_id_t R1; - bool address_in_R1 = false; - if (opnd_is_base_disp(op) && opnd_get_index(op) == DR_REG_NULL && - opnd_get_disp(op) == 0) { - // If this is a simple access with no offset or index, we can just use the - // base for R1. - address_in_R1 = true; - R1 = opnd_get_base(op); - } else { - // Otherwise, we need to compute the addr into R1. - // TODO: reuse some spare register? e.g. r15 on x64 - // TODO: might be used as a non-mem-ref register? - R1 = DR_REG_XAX; - } - CHECK(reg_is_pointer_sized(R1)); // otherwise R2 may be wrong. - - // Pick R2 from R8 to R15. - // It's OK if the instr uses R2 elsewhere, since we'll restore it before instr. - reg_id_t R2; - for (R2 = DR_REG_R8; R2 <= DR_REG_R15; R2++) { - if (!opnd_uses_reg(op, R2)) - break; - } - CHECK((R2 <= DR_REG_R15) && R1 != R2); - - // Save the current values of R1 and R2. - dr_save_reg(drcontext, bb, instr, R1, SPILL_SLOT_1); - // TODO: Something smarter than spilling a "fixed" register R2? - dr_save_reg(drcontext, bb, instr, R2, SPILL_SLOT_2); - - if (!address_in_R1) - CHECK(drutil_insert_get_mem_addr(drcontext, bb, instr, op, R1, R2)); - PRE(instr, mov_imm(drcontext, opnd_create_reg(R2), - OPND_CREATE_INT64(SHADOW_MEMORY_MASK))); - PRE(instr, and(drcontext, opnd_create_reg(R1), opnd_create_reg(R2))); -#ifdef MSANDR_STANDALONE_TEST - PRE(instr, add(drcontext, opnd_create_reg(R1), - OPND_CREATE_INT32(SHADOW_MEMORY_BASE))); -#endif - // There is no mov_st of a 64-bit immediate, so... - opnd_size_t op_size = opnd_get_size(op); - CHECK(op_size != OPSZ_NA); - uint access_size = opnd_size_in_bytes(op_size); - if (access_size <= 4 || op_size == OPSZ_PTR /* x64 support sign extension */) { - instr_t *label = INSTR_CREATE_label(drcontext); - opnd_t immed; - if (op_size == OPSZ_PTR || op_size == OPSZ_4) - immed = OPND_CREATE_INT32(0); - else - immed = opnd_create_immed_int((ptr_int_t) 0, op_size); - // we check if target is 0 before write to reduce unnecessary memory stores. - PRE(instr, cmp(drcontext, - opnd_create_base_disp(R1, DR_REG_NULL, 0, 0, op_size), - immed)); - PRE(instr, jcc(drcontext, OP_je, opnd_create_instr(label))); - PRE(instr, mov_st(drcontext, - opnd_create_base_disp(R1, DR_REG_NULL, 0, 0, op_size), - immed)); - PREF(instr, label); - } else { - // FIXME: tail? - for (uint ofs = 0; ofs < access_size; ofs += 4) { - instr_t *label = INSTR_CREATE_label(drcontext); - opnd_t immed = OPND_CREATE_INT32(0); - PRE(instr, cmp(drcontext, OPND_CREATE_MEM32(R1, ofs), immed)); - PRE(instr, jcc(drcontext, OP_je, opnd_create_instr(label))); - PRE(instr, mov_st(drcontext, OPND_CREATE_MEM32(R1, ofs), immed)); - PREF(instr, label) - } - } - - // Restore the registers and flags. - dr_restore_reg(drcontext, bb, instr, R1, SPILL_SLOT_1); - dr_restore_reg(drcontext, bb, instr, R2, SPILL_SLOT_2); - - // TODO: move aflags save/restore to per instr instead of per opnd - if (need_to_restore_eflags) { - if (VERBOSITY > 1) - dr_printf("Restoring eflags\n"); - // TODO: Check if it's reverse to the dr_restore_reg above and optimize. - dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); - dr_restore_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_3); - dr_restore_arith_flags_from_xax(drcontext, bb, instr); - dr_restore_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); - } - - // The original instruction is left untouched. The above instrumentation is just - // a prefix. -} - -void InstrumentReturn(void *drcontext, instrlist_t *bb, instr_t *instr) { -#ifdef MSANDR_STANDALONE_TEST - PRE(instr, - mov_st(drcontext, - opnd_create_far_base_disp(DR_SEG_GS /* DR's TLS */, - DR_REG_NULL, DR_REG_NULL, - 0, msan_retval_tls_offset, - OPSZ_PTR), - OPND_CREATE_INT32(0))); -#else /* !MSANDR_STANDALONE_TEST */ -# ifdef MSANDR_NATIVE_EXEC - /* For optimized native exec, -mangle_app_seg and -private_loader are turned off, - * so we can reference msan_retval_tls_offset directly. - */ - PRE(instr, - mov_st(drcontext, - opnd_create_far_base_disp(DR_SEG_FS, DR_REG_NULL, DR_REG_NULL, 0, - msan_retval_tls_offset, OPSZ_PTR), - OPND_CREATE_INT32(0))); -# else /* !MSANDR_NATIVE_EXEC */ - /* XXX: the code below only works if -mangle_app_seg and -private_loader, - * which is turned off for optimized native exec - */ - dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); - - // Clobbers nothing except xax. - bool res = - dr_insert_get_seg_base(drcontext, bb, instr, DR_SEG_FS, DR_REG_XAX); - CHECK(res); - - // TODO: unpoison more bytes? - PRE(instr, - mov_st(drcontext, OPND_CREATE_MEM64(DR_REG_XAX, msan_retval_tls_offset), - OPND_CREATE_INT32(0))); - - dr_restore_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); -# endif /* !MSANDR_NATIVE_EXEC */ - // The original instruction is left untouched. The above instrumentation is just - // a prefix. -#endif /* !MSANDR_STANDALONE_TEST */ -} - -void InstrumentIndirectBranch(void *drcontext, instrlist_t *bb, - instr_t *instr) { -#ifdef MSANDR_STANDALONE_TEST - for (int i = 0; i < NUM_TLS_PARAM; ++i) { - PRE(instr, - mov_st(drcontext, - opnd_create_far_base_disp(DR_SEG_GS /* DR's TLS */, - DR_REG_NULL, DR_REG_NULL, - 0, - msan_param_tls_offset + - i * sizeof(void *), - OPSZ_PTR), - OPND_CREATE_INT32(0))); - } -#else /* !MSANDR_STANDALONE_TEST */ -# ifdef MSANDR_NATIVE_EXEC - for (int i = 0; i < NUM_TLS_PARAM; ++i) { - PRE(instr, - mov_st(drcontext, - opnd_create_far_base_disp(DR_SEG_FS, DR_REG_NULL, DR_REG_NULL, 0, - msan_param_tls_offset + i*sizeof(void*), - OPSZ_PTR), - OPND_CREATE_INT32(0))); - } -# else /* !MSANDR_NATIVE_EXEC */ - /* XXX: the code below only works if -mangle_app_seg and -private_loader, - * which is turned off for optimized native exec - */ - dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); - - // Clobbers nothing except xax. - bool res = - dr_insert_get_seg_base(drcontext, bb, instr, DR_SEG_FS, DR_REG_XAX); - CHECK(res); - - // TODO: unpoison more bytes? - for (int i = 0; i < NUM_TLS_PARAM; ++i) { - PRE(instr, - mov_st(drcontext, OPND_CREATE_MEMPTR(DR_REG_XAX, msan_param_tls_offset + - i * sizeof(void *)), - OPND_CREATE_INT32(0))); - } - - dr_restore_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1); -# endif /* !MSANDR_NATIVE_EXEC */ - // The original instruction is left untouched. The above instrumentation is just - // a prefix. -#endif /* !MSANDR_STANDALONE_TEST */ -} - -#ifndef MSANDR_NATIVE_EXEC -// For use with binary search. Modules shouldn't overlap, so we shouldn't have -// to look at end_. If that can happen, we won't support such an application. -bool ModuleDataCompareStart(const ModuleData &left, const ModuleData &right) { - return left.start_ < right.start_; -} - -// Look up the module containing PC. Should be relatively fast, as its called -// for each bb instrumentation. -ModuleData *LookupModuleByPC(app_pc pc) { - ModuleData fake_mod_data; - fake_mod_data.start_ = pc; - std::vector::iterator it = - lower_bound(g_module_list.begin(), g_module_list.end(), fake_mod_data, - ModuleDataCompareStart); - // if (it == g_module_list.end()) - // return NULL; - if (it == g_module_list.end() || pc < it->start_) - --it; - CHECK(it->start_ <= pc); - if (pc >= it->end_) { - // We're past the end of this module. We shouldn't be in the next module, - // or lower_bound lied to us. - ++it; - CHECK(it == g_module_list.end() || pc < it->start_); - return NULL; - } - - // OK, we found the module. - return &*it; -} - -bool ShouldInstrumentNonModuleCode() { return true; } - -bool ShouldInstrumentModule(ModuleData *mod_data) { - // TODO(rnk): Flags for blacklist would get wired in here. - generic_func_t p = - dr_get_proc_address(mod_data->handle_, "__msan_track_origins"); - return !p; -} - -bool ShouldInstrumentPc(app_pc pc, ModuleData **pmod_data) { - ModuleData *mod_data = LookupModuleByPC(pc); - if (pmod_data) - *pmod_data = mod_data; - if (mod_data != NULL) { - // This module is on a blacklist. - if (!mod_data->should_instrument_) { - return false; - } - } else if (!ShouldInstrumentNonModuleCode()) { - return false; - } - return true; -} -#endif /* !MSANDR_NATIVE_CLIENT */ - -// TODO(rnk): Make sure we instrument after __msan_init. -dr_emit_flags_t -event_basic_block_app2app(void *drcontext, void *tag, instrlist_t *bb, - bool for_trace, bool translating) { -#ifndef MSANDR_NATIVE_EXEC - app_pc pc = dr_fragment_app_pc(tag); - if (ShouldInstrumentPc(pc, NULL)) - CHECK(drutil_expand_rep_string(drcontext, bb)); -#else /* MSANDR_NATIVE_EXEC */ - CHECK(drutil_expand_rep_string(drcontext, bb)); -#endif /* MSANDR_NATIVE_EXEC */ - return DR_EMIT_PERSISTABLE; -} - -dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, - bool for_trace, bool translating) { - app_pc pc = dr_fragment_app_pc(tag); -#ifndef MSANDR_NATIVE_EXEC - ModuleData *mod_data; - - if (!ShouldInstrumentPc(pc, &mod_data)) - return DR_EMIT_PERSISTABLE; - - if (VERBOSITY > 1) - dr_printf("============================================================\n"); - if (VERBOSITY > 0) { - std::string mod_path = (mod_data ? mod_data->path_ : ""); - if (mod_data && !mod_data->executed_) { - mod_data->executed_ = true; // Nevermind this race. - dr_printf("Executing from new module: %s\n", mod_path.c_str()); - } - dr_printf("BB to be instrumented: %p [from %s]; translating = %s\n", pc, - mod_path.c_str(), translating ? "true" : "false"); - if (mod_data) { - // Match standard sanitizer trace format for free symbols. - // #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) - dr_printf(" #0 %p (%s+%p)\n", pc, mod_data->path_.c_str(), - pc - mod_data->start_); - } - } -#endif /* !MSANDR_NATIVE_EXEC */ - - if (VERBOSITY > 1) { - instrlist_disassemble(drcontext, pc, bb, STDOUT); - instr_t *instr; - for (instr = instrlist_first(bb); instr; instr = instr_get_next(instr)) { - dr_printf("opcode: %d\n", instr_get_opcode(instr)); - } - } - - for (instr_t *i = instrlist_first(bb); i != NULL; i = instr_get_next(i)) { - int opcode = instr_get_opcode(i); - if (opcode == OP_ret || opcode == OP_ret_far) { - InstrumentReturn(drcontext, bb, i); - continue; - } - - // These instructions hopefully cover all cases where control is transferred - // to a function in a different module (we only care about calls into - // compiler-instrumented modules). - // * call_ind is used for normal indirect calls. - // * jmp_ind is used for indirect tail calls, and calls through PLT (PLT - // stub includes a jump to an address from GOT). - if (opcode == OP_call_ind || opcode == OP_call_far_ind || - opcode == OP_jmp_ind || opcode == OP_jmp_far_ind) { - InstrumentIndirectBranch(drcontext, bb, i); - continue; - } - - if (!WantToInstrument(i)) - continue; - - if (VERBOSITY > 1) { - app_pc orig_pc = dr_fragment_app_pc(tag); - uint flags = instr_get_arith_flags(i); - dr_printf("+%d -> to be instrumented! [opcode=%d, flags = 0x%08X]\n", - instr_get_app_pc(i) - orig_pc, instr_get_opcode(i), flags); - } - - if (instr_writes_memory(i)) { - // Instrument memory writes - // bool instrumented_anything = false; - for (int d = 0; d < instr_num_dsts(i); d++) { - opnd_t op = instr_get_dst(i, d); - if (!OperandIsInteresting(op)) - continue; - - // CHECK(!instrumented_anything); - // instrumented_anything = true; - InstrumentMops(drcontext, bb, i, op, true); - break; // only instrumenting the first dst - } - } - } - -// TODO: optimize away redundant restore-spill pairs? - - if (VERBOSITY > 1) { - pc = dr_fragment_app_pc(tag); - dr_printf("\nFinished instrumenting dynamorio_basic_block(PC=" PFX ")\n", pc); - instrlist_disassemble(drcontext, pc, bb, STDOUT); - } - return DR_EMIT_PERSISTABLE; -} - -#ifndef MSANDR_NATIVE_EXEC -void event_module_load(void *drcontext, const module_data_t *info, - bool loaded) { - // Insert the module into the list while maintaining the ordering. - ModuleData mod_data(info); - std::vector::iterator it = - upper_bound(g_module_list.begin(), g_module_list.end(), mod_data, - ModuleDataCompareStart); - it = g_module_list.insert(it, mod_data); - // Check if we should instrument this module. - it->should_instrument_ = ShouldInstrumentModule(&*it); - dr_module_set_should_instrument(info->handle, it->should_instrument_); - - if (VERBOSITY > 0) - dr_printf("==DRMSAN== Loaded module: %s [%p...%p], instrumentation is %s\n", - info->full_path, info->start, info->end, - it->should_instrument_ ? "on" : "off"); -} - -void event_module_unload(void *drcontext, const module_data_t *info) { - if (VERBOSITY > 0) - dr_printf("==DRMSAN== Unloaded module: %s [%p...%p]\n", info->full_path, - info->start, info->end); - - // Remove the module from the list. - ModuleData mod_data(info); - std::vector::iterator it = - lower_bound(g_module_list.begin(), g_module_list.end(), mod_data, - ModuleDataCompareStart); - // It's a bug if we didn't actually find the module. - CHECK(it != g_module_list.end() && it->start_ == mod_data.start_ && - it->end_ == mod_data.end_ && it->path_ == mod_data.path_); - g_module_list.erase(it); -} -#endif /* !MSANDR_NATIVE_EXEC */ - -void event_exit() { - // Clean up so DR doesn't tell us we're leaking memory. - drsys_exit(); - drutil_exit(); - drmgr_exit(); - -#ifdef MSANDR_STANDALONE_TEST - /* free tls */ - bool res; - res = dr_raw_tls_cfree(msan_retval_tls_offset, NUM_TLS_RETVAL); - CHECK(res); - res = dr_raw_tls_cfree(msan_param_tls_offset, NUM_TLS_PARAM); - CHECK(res); - /* we do not bother to free the shadow memory */ -#endif /* !MSANDR_STANDALONE_TEST */ - if (VERBOSITY > 0) - dr_printf("==DRMSAN== DONE\n"); -} - -bool event_filter_syscall(void *drcontext, int sysnum) { - // FIXME: only intercept syscalls with memory effects. - return true; /* intercept everything */ -} - -bool drsys_iter_memarg_cb(drsys_arg_t *arg, void *user_data) { - CHECK(arg->valid); - - if (arg->pre) - return true; - if (!TESTANY(DRSYS_PARAM_OUT, arg->mode)) - return true; - - size_t sz = arg->size; - - if (sz > 0xFFFFFFFF) { - drmf_status_t res; - drsys_syscall_t *syscall = (drsys_syscall_t *)user_data; - const char *name; - res = drsys_syscall_name(syscall, &name); - CHECK(res == DRMF_SUCCESS); - - dr_printf("SANITY: syscall '%s' arg %d writes %llu bytes memory?!" - " Clipping to %llu.\n", - name, arg->ordinal, (unsigned long long) sz, - (unsigned long long)(sz & 0xFFFFFFFF)); - } - - if (VERBOSITY > 0) { - drmf_status_t res; - drsys_syscall_t *syscall = (drsys_syscall_t *)user_data; - const char *name; - res = drsys_syscall_name(syscall, &name); - CHECK(res == DRMF_SUCCESS); - dr_printf("drsyscall: syscall '%s' arg %d wrote range [%p, %p)\n", - name, arg->ordinal, arg->start_addr, - (char *)arg->start_addr + sz); - } - - // We don't switch to the app context because __msan_unpoison() doesn't need - // TLS segments. - __msan_unpoison(arg->start_addr, sz); - - return true; /* keep going */ -} - -bool event_pre_syscall(void *drcontext, int sysnum) { - drsys_syscall_t *syscall; - drsys_sysnum_t sysnum_full; - bool known; - drsys_param_type_t ret_type; - drmf_status_t res; - const char *name; - - res = drsys_cur_syscall(drcontext, &syscall); - CHECK(res == DRMF_SUCCESS); - - res = drsys_syscall_number(syscall, &sysnum_full); - CHECK(res == DRMF_SUCCESS); - CHECK(sysnum == sysnum_full.number); - - res = drsys_syscall_is_known(syscall, &known); - CHECK(res == DRMF_SUCCESS); - - res = drsys_syscall_name(syscall, &name); - CHECK(res == DRMF_SUCCESS); - - res = drsys_syscall_return_type(syscall, &ret_type); - CHECK(res == DRMF_SUCCESS); - CHECK(ret_type != DRSYS_TYPE_INVALID); - CHECK(!known || ret_type != DRSYS_TYPE_UNKNOWN); - - res = drsys_iterate_memargs(drcontext, drsys_iter_memarg_cb, NULL); - CHECK(res == DRMF_SUCCESS); - - return true; -} - -static bool IsInLoader(void *drcontext) { - // TODO: This segment swap is inefficient. DR should just let us query the - // app segment base, which it has. Alternatively, if we disable - // -mangle_app_seg, then we won't need the swap. - bool need_swap = !dr_using_app_state(drcontext); - if (need_swap) - dr_switch_to_app_state(drcontext); - bool is_in_loader = __msan_is_in_loader(); - if (need_swap) - dr_switch_to_dr_state(drcontext); - return is_in_loader; -} - -void event_post_syscall(void *drcontext, int sysnum) { - drsys_syscall_t *syscall; - drsys_sysnum_t sysnum_full; - bool success = false; - drmf_status_t res; - - res = drsys_cur_syscall(drcontext, &syscall); - CHECK(res == DRMF_SUCCESS); - - res = drsys_syscall_number(syscall, &sysnum_full); - CHECK(res == DRMF_SUCCESS); - CHECK(sysnum == sysnum_full.number); - - res = drsys_syscall_succeeded(syscall, dr_syscall_get_result(drcontext), - &success); - CHECK(res == DRMF_SUCCESS); - - if (success) { - res = - drsys_iterate_memargs(drcontext, drsys_iter_memarg_cb, (void *)syscall); - CHECK(res == DRMF_SUCCESS); - } - - // Our normal mmap interceptor can't intercept calls from the loader itself. - // This means we don't clear the shadow for calls to dlopen. For now, we - // solve this by intercepting mmap from ld.so here, but ideally we'd have a - // solution that doesn't rely on msandr. - // - // Be careful not to intercept maps done by the msan rtl. Otherwise we end up - // unpoisoning vast regions of memory and OOMing. - // TODO: __msan_unpoison() could "flush" large regions of memory like tsan - // does instead of doing a large memset. However, we need the memory to be - // zeroed, where as tsan does not, so plain madvise is not enough. - if (success && (sysnum == SYS_mmap IF_NOT_X64(|| sysnum == SYS_mmap2))) { - if (IsInLoader(drcontext)) { - app_pc base = (app_pc)dr_syscall_get_result(drcontext); - ptr_uint_t size; - drmf_status_t res = drsys_pre_syscall_arg(drcontext, 1, &size); - CHECK(res == DRMF_SUCCESS); - if (VERBOSITY > 0) - dr_printf("unpoisoning for dlopen: [%p-%p]\n", base, base + size); - // We don't switch to the app context because __msan_unpoison() doesn't - // need TLS segments. - __msan_unpoison(base, size); - } - } -} - -} // namespace - -DR_EXPORT void dr_init(client_id_t id) { - drmf_status_t res; - - drmgr_init(); - drutil_init(); - -#ifndef MSANDR_NATIVE_EXEC - // We should use drconfig to ignore these applications. - std::string app_name = dr_get_application_name(); - // This blacklist will still run these apps through DR's code cache. On the - // other hand, we are able to follow children of these apps. - // FIXME: Once DR has detach, we could just detach here. Alternatively, - // if DR had a fork or exec hook to let us decide there, that would be nice. - // FIXME: make the blacklist cmd-adjustable. - if (app_name == "python" || app_name == "python2.7" || app_name == "bash" || - app_name == "sh" || app_name == "true" || app_name == "exit" || - app_name == "yes" || app_name == "echo") - return; -#endif /* !MSANDR_NATIVE_EXEC */ - - drsys_options_t ops; - memset(&ops, 0, sizeof(ops)); - ops.struct_size = sizeof(ops); - ops.analyze_unknown_syscalls = false; - - res = drsys_init(id, &ops); - CHECK(res == DRMF_SUCCESS); - - dr_register_filter_syscall_event(event_filter_syscall); - drmgr_register_pre_syscall_event(event_pre_syscall); - drmgr_register_post_syscall_event(event_post_syscall); - res = drsys_filter_all_syscalls(); - CHECK(res == DRMF_SUCCESS); - -#ifdef MSANDR_STANDALONE_TEST - reg_id_t reg_seg; - /* alloc tls */ - if (!dr_raw_tls_calloc(®_seg, &mock_msan_retval_tls_offset, NUM_TLS_RETVAL, 0)) - CHECK(false); - CHECK(reg_seg == DR_SEG_GS /* x64 only! */); - if (!dr_raw_tls_calloc(®_seg, &mock_msan_param_tls_offset, NUM_TLS_PARAM, 0)) - CHECK(false); - CHECK(reg_seg == DR_SEG_GS /* x64 only! */); - /* alloc shadow memory */ - if (mmap(SHADOW_MEMORY_BASE, SHADOW_MEMORY_SIZE, PROT_READ|PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0) != SHADOW_MEMORY_BASE) { - CHECK(false); - } -#endif /* MSANDR_STANDALONE_TEST */ - InitializeMSanCallbacks(); - - // FIXME: the shadow is initialized earlier when DR calls one of our wrapper - // functions. This may change one day. - // TODO: make this more robust. - - void *drcontext = dr_get_current_drcontext(); - - dr_switch_to_app_state(drcontext); - msan_retval_tls_offset = __msan_get_retval_tls_offset(); - msan_param_tls_offset = __msan_get_param_tls_offset(); - dr_switch_to_dr_state(drcontext); - if (VERBOSITY > 0) { - dr_printf("__msan_retval_tls offset: %d\n", msan_retval_tls_offset); - dr_printf("__msan_param_tls offset: %d\n", msan_param_tls_offset); - } - - // Standard DR events. - dr_register_exit_event(event_exit); - - drmgr_priority_t priority = { - sizeof(priority), /* size of struct */ - "msandr", /* name of our operation */ - NULL, /* optional name of operation we should precede */ - NULL, /* optional name of operation we should follow */ - 0 - }; /* numeric priority */ - - drmgr_register_bb_app2app_event(event_basic_block_app2app, &priority); - drmgr_register_bb_instru2instru_event(event_basic_block, &priority); -#ifndef MSANDR_NATIVE_EXEC - drmgr_register_module_load_event(event_module_load); - drmgr_register_module_unload_event(event_module_unload); -#endif /* MSANDR_NATIVE_EXEC */ - __msan_dr_is_initialized(); - __msan_set_indirect_call_wrapper(dr_app_handle_mbr_target); - if (VERBOSITY > 0) - dr_printf("==MSANDR== Starting!\n"); -} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index d1e9d36..c1e2101 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -523,23 +523,6 @@ const uptr kPthreadDestructorIterations = 0; // Callback type for iterating over a set of memory ranges. typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg); -#if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !defined(SANITIZER_GO) -extern uptr indirect_call_wrapper; -void SetIndirectCallWrapper(uptr wrapper); - -template -F IndirectExternCall(F f) { - typedef F (*WrapF)(F); - return indirect_call_wrapper ? ((WrapF)indirect_call_wrapper)(f) : f; -} -#else -INLINE void SetIndirectCallWrapper(uptr wrapper) {} -template -F IndirectExternCall(F f) { - return f; -} -#endif - #if SANITIZER_ANDROID // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 4fb0111..274e87c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -1442,30 +1442,30 @@ static THREADLOCAL __sanitizer_glob_t *pglob_copy; static void wrapped_gl_closedir(void *dir) { COMMON_INTERCEPTOR_UNPOISON_PARAM(1); - IndirectExternCall(pglob_copy->gl_closedir)(dir); + pglob_copy->gl_closedir(dir); } static void *wrapped_gl_readdir(void *dir) { COMMON_INTERCEPTOR_UNPOISON_PARAM(1); - return IndirectExternCall(pglob_copy->gl_readdir)(dir); + return pglob_copy->gl_readdir(dir); } static void *wrapped_gl_opendir(const char *s) { COMMON_INTERCEPTOR_UNPOISON_PARAM(1); COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1); - return IndirectExternCall(pglob_copy->gl_opendir)(s); + return pglob_copy->gl_opendir(s); } static int wrapped_gl_lstat(const char *s, void *st) { COMMON_INTERCEPTOR_UNPOISON_PARAM(2); COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1); - return IndirectExternCall(pglob_copy->gl_lstat)(s, st); + return pglob_copy->gl_lstat(s, st); } static int wrapped_gl_stat(const char *s, void *st) { COMMON_INTERCEPTOR_UNPOISON_PARAM(2); COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1); - return IndirectExternCall(pglob_copy->gl_stat)(s, st); + return pglob_copy->gl_stat(s, st); } INTERCEPTOR(int, glob, const char *pattern, int flags, @@ -2633,7 +2633,7 @@ static THREADLOCAL scandir_compar_f scandir_compar; static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) { COMMON_INTERCEPTOR_UNPOISON_PARAM(1); COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen); - return IndirectExternCall(scandir_filter)(dir); + return scandir_filter(dir); } static int wrapped_scandir_compar(const struct __sanitizer_dirent **a, @@ -2643,7 +2643,7 @@ static int wrapped_scandir_compar(const struct __sanitizer_dirent **a, COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen); COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b)); COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen); - return IndirectExternCall(scandir_compar)(a, b); + return scandir_compar(a, b); } INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist, @@ -2685,7 +2685,7 @@ static THREADLOCAL scandir64_compar_f scandir64_compar; static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) { COMMON_INTERCEPTOR_UNPOISON_PARAM(1); COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen); - return IndirectExternCall(scandir64_filter)(dir); + return scandir64_filter(dir); } static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a, @@ -2695,7 +2695,7 @@ static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a, COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen); COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b)); COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen); - return IndirectExternCall(scandir64_compar)(a, b); + return scandir64_compar(a, b); } INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_interception.h b/compiler-rt/lib/sanitizer_common/sanitizer_interception.h deleted file mode 100644 index b63462d..0000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_interception.h +++ /dev/null @@ -1,25 +0,0 @@ -//===-- sanitizer_interception.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Common macro definitions for interceptors. -// Always use this headers instead of interception/interception.h. -// -//===----------------------------------------------------------------------===// -#ifndef SANITIZER_INTERCEPTION_H -#define SANITIZER_INTERCEPTION_H - -#include "interception/interception.h" -#include "sanitizer_common.h" - -#if SANITIZER_LINUX && !defined(SANITIZER_GO) -#undef REAL -#define REAL(x) IndirectExternCall(__interception::PTR_TO_REAL(x)) -#endif - -#endif // SANITIZER_INTERCEPTION_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 3387680..2ca55b4 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -128,7 +128,7 @@ bool SetEnv(const char *name, const char *value) { setenv_ft setenv_f; CHECK_EQ(sizeof(setenv_f), sizeof(f)); internal_memcpy(&setenv_f, &f, sizeof(f)); - return IndirectExternCall(setenv_f)(name, value, 1) == 0; + return setenv_f(name, value, 1) == 0; } bool SanitizerSetThreadName(const char *name) { @@ -173,7 +173,7 @@ void InitTlsSize() { CHECK_NE(get_tls, 0); size_t tls_size = 0; size_t tls_align = 0; - IndirectExternCall(get_tls)(&tls_size, &tls_align); + get_tls(&tls_size, &tls_align); g_tls_size = tls_size; #endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID } @@ -408,14 +408,6 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules, } #endif // SANITIZER_ANDROID -uptr indirect_call_wrapper; - -void SetIndirectCallWrapper(uptr wrapper) { - CHECK(!indirect_call_wrapper); - CHECK(wrapper); - indirect_call_wrapper = wrapper; -} - void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { // Some kinds of sandboxes may forbid filesystem access, so we won't be able // to read the file mappings from /proc/self/maps. Luckily, neither the diff --git a/compiler-rt/test/msan/wrap_indirect_calls.cc b/compiler-rt/test/msan/wrap_indirect_calls.cc deleted file mode 100644 index be17bd8..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Test indirect call wrapping in MemorySanitizer. - -// RUN: %clangxx_msan -O0 %p/wrap_indirect_calls/two.cc -fPIC -shared -o %t-two-so.so -// RUN: %clangxx_msan -O0 %p/wrap_indirect_calls/wrapper.cc -fPIC -shared -o %t-wrapper-so.so - -// Disable fast path. - -// RUN: %clangxx_msan -O0 %p/wrap_indirect_calls/caller.cc %p/wrap_indirect_calls/one.cc %s \ -// RUN: %t-two-so.so %t-wrapper-so.so \ -// RUN: -mllvm -msan-wrap-indirect-calls=wrapper \ -// RUN: -mllvm -msan-wrap-indirect-calls-fast=0 \ -// RUN: -DSLOW=1 \ -// RUN: -Wl,--defsym=__executable_start=0 -o %t -// RUN: %run %t - -// Enable fast path, call from executable, -O0. - -// RUN: %clangxx_msan -O0 %p/wrap_indirect_calls/caller.cc %p/wrap_indirect_calls/one.cc %s \ -// RUN: %t-two-so.so %t-wrapper-so.so \ -// RUN: -mllvm -msan-wrap-indirect-calls=wrapper \ -// RUN: -mllvm -msan-wrap-indirect-calls-fast=1 \ -// RUN: -DSLOW=0 \ -// RUN: -Wl,--defsym=__executable_start=0 -o %t -// RUN: %run %t - -// Enable fast path, call from executable, -O3. - -// RUN: %clangxx_msan -O3 %p/wrap_indirect_calls/caller.cc %p/wrap_indirect_calls/one.cc %s \ -// RUN: %t-two-so.so %t-wrapper-so.so \ -// RUN: -mllvm -msan-wrap-indirect-calls=wrapper \ -// RUN: -mllvm -msan-wrap-indirect-calls-fast=1 \ -// RUN: -DSLOW=0 \ -// RUN: -Wl,--defsym=__executable_start=0 -o %t -// RUN: %run %t - -// Enable fast path, call from DSO, -O0. - -// RUN: %clangxx_msan -O0 %p/wrap_indirect_calls/caller.cc %p/wrap_indirect_calls/one.cc -shared \ -// RUN: %t-two-so.so %t-wrapper-so.so \ -// RUN: -mllvm -msan-wrap-indirect-calls=wrapper \ -// RUN: -mllvm -msan-wrap-indirect-calls-fast=1 \ -// RUN: -DSLOW=0 \ -// RUN: -Wl,--defsym=__executable_start=0 -o %t-caller-so.so -// RUN: %clangxx_msan -O0 %s %t-caller-so.so %t-two-so.so %t-wrapper-so.so -o %t -// RUN: %run %t - -// Enable fast path, call from DSO, -O3. - -// RUN: %clangxx_msan -O3 %p/wrap_indirect_calls/caller.cc %p/wrap_indirect_calls/one.cc -shared \ -// RUN: %t-two-so.so %t-wrapper-so.so \ -// RUN: -mllvm -msan-wrap-indirect-calls=wrapper \ -// RUN: -mllvm -msan-wrap-indirect-calls-fast=1 \ -// RUN: -DSLOW=0 \ -// RUN: -Wl,--defsym=__executable_start=0 -o %t-caller-so.so -// RUN: %clangxx_msan -O3 %s %t-caller-so.so %t-two-so.so %t-wrapper-so.so -o %t -// RUN: %run %t - -// The actual test is in multiple files in wrap_indirect_calls/ directory. -void run_test(); - -int main() { - run_test(); - return 0; -} diff --git a/compiler-rt/test/msan/wrap_indirect_calls/caller.cc b/compiler-rt/test/msan/wrap_indirect_calls/caller.cc deleted file mode 100644 index a0af8b7..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls/caller.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Indirectly call a bunch of functions. - -#include - -extern int cnt; - -typedef int (*F)(int, int); - -// A function in the same object. -int f_local(int x, int y) { - return x + y; -} - -// A function in another object. -int f_other_object(int x, int y); - -// A function in another DSO. -int f_dso(int x, int y); - -// A function in another DSO that is replaced by the wrapper. -int f_replaced(int x, int y); - -void run_test(void) { - int x; - int expected_cnt = 0; - volatile F f; - - if (SLOW) ++expected_cnt; - f = &f_local; - x = f(1, 2); - assert(x == 3); - assert(cnt == expected_cnt); - - if (SLOW) ++expected_cnt; - f = &f_other_object; - x = f(2, 3); - assert(x == 6); - assert(cnt == expected_cnt); - - ++expected_cnt; - f = &f_dso; - x = f(2, 3); - assert(x == 7); - assert(cnt == expected_cnt); - - ++expected_cnt; - f = &f_replaced; - x = f(2, 3); - assert(x == 11); - assert(cnt == expected_cnt); -} diff --git a/compiler-rt/test/msan/wrap_indirect_calls/lit.local.cfg b/compiler-rt/test/msan/wrap_indirect_calls/lit.local.cfg deleted file mode 100644 index 5e01230..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls/lit.local.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Sources in this directory are used by tests in parent directory. - -config.suffixes = [] diff --git a/compiler-rt/test/msan/wrap_indirect_calls/one.cc b/compiler-rt/test/msan/wrap_indirect_calls/one.cc deleted file mode 100644 index ab7bf41..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls/one.cc +++ /dev/null @@ -1,3 +0,0 @@ -int f_other_object(int x, int y) { - return x * y; -} diff --git a/compiler-rt/test/msan/wrap_indirect_calls/two.cc b/compiler-rt/test/msan/wrap_indirect_calls/two.cc deleted file mode 100644 index c939a99..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls/two.cc +++ /dev/null @@ -1,11 +0,0 @@ -int f_dso(int x, int y) { - return 2 * x + y; -} - -int f_replaced(int x, int y) { - return x + y + 5; -} - -int f_replacement(int x, int y) { - return x + y + 6; -} diff --git a/compiler-rt/test/msan/wrap_indirect_calls/wrapper.cc b/compiler-rt/test/msan/wrap_indirect_calls/wrapper.cc deleted file mode 100644 index 8fcd0c6..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls/wrapper.cc +++ /dev/null @@ -1,11 +0,0 @@ -int f_replaced(int x, int y); -int f_replacement(int x, int y); - -int cnt; - -extern "C" void *wrapper(void *p) { - ++cnt; - if (p == (void *)f_replaced) - return (void *)f_replacement; - return p; -} diff --git a/compiler-rt/test/msan/wrap_indirect_calls2.cc b/compiler-rt/test/msan/wrap_indirect_calls2.cc deleted file mode 100644 index fb4e6c7..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls2.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Test __msan_set_indirect_call_wrapper. - -// RUN: %clangxx_msan -mllvm -msan-wrap-indirect-calls=__msan_wrap_indirect_call \ -// RUN: -mllvm -msan-wrap-indirect-calls-fast=0 \ -// RUN: -O0 -g -rdynamic -Wl,--defsym=__executable_start=0 %s -o %t && %run %t - -// This test disables -msan-wrap-indirect-calls-fast, otherwise indirect calls -// inside the same module are short-circuited and are never seen by the wrapper. - -#include -#include -#include -#include - -extern "C" void __msan_set_indirect_call_wrapper(uintptr_t); - -bool done_f, done_g; - -void f(void) { - assert(!done_g); - done_f = true; -} - -void g(void) { - assert(done_f); - done_g = true; -} - -typedef void (*Fn)(void); -extern "C" Fn my_wrapper(Fn target) { - if (target == f) return g; - return target; -} - -int main(void) { - volatile Fn fp; - fp = &f; - fp(); - __msan_set_indirect_call_wrapper((uintptr_t)my_wrapper); - fp(); - return !(done_f && done_g); -} diff --git a/compiler-rt/test/msan/wrap_indirect_calls_in_rtl.cc b/compiler-rt/test/msan/wrap_indirect_calls_in_rtl.cc deleted file mode 100644 index 58e8004..0000000 --- a/compiler-rt/test/msan/wrap_indirect_calls_in_rtl.cc +++ /dev/null @@ -1,77 +0,0 @@ -// 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 -#include -#include -#include -#include -#include -#include - -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; -} -- 2.7.4