Unpoison Reactor Call() arguments when MSan instrumentation is disabled
For MemorySanitizer builds which do not have Reactor routine
instrumentation enabled, mark all Call() arguments as initialized by
calling __msan_unpoison_param(). This prevents false positives.
Note that we also already unpoisoned all memory writes, when proper
instrumentation is not enabled. While it's preferable to set
REACTOR_ENABLE_MEMORY_SANITIZER_INSTRUMENTATION=1 to avoid the false
negatives caused by unpoisoning, it currently causes slowdowns which
result in timeouts.
Bug: b/187467599
Change-Id: I5fdcbceb5cd795f5e3684df0cdc1ba6c1bef06e9
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/54348
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Reactor/LLVMJIT.cpp b/src/Reactor/LLVMJIT.cpp
index 5c0f15d..2d9a801 100644
--- a/src/Reactor/LLVMJIT.cpp
+++ b/src/Reactor/LLVMJIT.cpp
@@ -548,6 +548,7 @@
// TODO(b/155148722): Remove when we no longer unpoison all writes.
# if !REACTOR_ENABLE_MEMORY_SANITIZER_INSTRUMENTATION
functions.try_emplace("msan_unpoison", reinterpret_cast<void *>(__msan_unpoison));
+ functions.try_emplace("msan_unpoison_param", reinterpret_cast<void *>(__msan_unpoison_param));
# endif
functions.try_emplace("emutls_get_address", reinterpret_cast<void *>(rr::getTLSAddress));
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 8564f8a..4d78d58 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -516,13 +516,13 @@
#if !__has_feature(memory_sanitizer)
// thread_local variables in shared libraries are initialized at load-time,
// but this is not observed by MemorySanitizer if the loader itself was not
- // instrumented, leading to false-positive unitialized variable errors.
+ // instrumented, leading to false-positive uninitialized variable errors.
ASSERT(jit == nullptr);
ASSERT(Variable::unmaterializedVariables == nullptr);
#endif
jit = new JITBuilder(Nucleus::getDefaultConfig());
- Variable::unmaterializedVariables = new Variable::UnmaterializedVariables{};
+ Variable::unmaterializedVariables = new Variable::UnmaterializedVariables();
}
Nucleus::~Nucleus()
@@ -3595,6 +3595,19 @@
Value *Call(RValue<Pointer<Byte>> fptr, Type *retTy, std::initializer_list<Value *> args, std::initializer_list<Type *> argTys)
{
+ // If this is a MemorySanitizer build, but Reactor routine instrumentation is not enabled,
+ // mark all call arguments as initialized by calling __msan_unpoison_param().
+ if(__has_feature(memory_sanitizer) && !REACTOR_ENABLE_MEMORY_SANITIZER_INSTRUMENTATION)
+ {
+ // void __msan_unpoison_param(size_t n)
+ auto voidTy = llvm::Type::getVoidTy(*jit->context);
+ auto sizetTy = llvm::IntegerType::get(*jit->context, sizeof(size_t) * 8);
+ auto funcTy = llvm::FunctionType::get(voidTy, { sizetTy }, false);
+ auto func = jit->module->getOrInsertFunction("__msan_unpoison_param", funcTy);
+
+ jit->builder->CreateCall(func, { llvm::ConstantInt::get(sizetTy, args.size()) });
+ }
+
RR_DEBUG_INFO_UPDATE_LOC();
llvm::SmallVector<llvm::Type *, 8> paramTys;
for(auto ty : argTys) { paramTys.push_back(T(ty)); }
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 301c6bd..8799eb8 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -929,7 +929,7 @@
#if !__has_feature(memory_sanitizer)
// thread_local variables in shared libraries are initialized at load-time,
// but this is not observed by MemorySanitizer if the loader itself was not
- // instrumented, leading to false-positive unitialized variable errors.
+ // instrumented, leading to false-positive uninitialized variable errors.
ASSERT(Variable::unmaterializedVariables == nullptr);
#endif
Variable::unmaterializedVariables = new Variable::UnmaterializedVariables{};