Commit 314508f7 by Nicolas Capens Committed by Nicolas Capens

Work around MemorySanitizer false-positive

The initialization of static thread-local data is not observed by MemorySanitizer when inside a shared library, leading to false-positive use-of-uninitialized-data errors: https://github.com/google/sanitizers/issues/1409 We work around this by assigning an initial value to it ourselves on first use. Note that since the flag to check whether this initialization has already been done is itself a static thread-local, we must suppress the MemorySanitizer check with a function attribute. Bug: b/191050320 Change-Id: I356a89f90ff099e08a12f5562e0545ed14d93ee3 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/55328Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@google.com>
parent 47c3ca02
...@@ -17,16 +17,56 @@ ...@@ -17,16 +17,56 @@
#include "Debug.hpp" #include "Debug.hpp"
namespace rr { // The CLANG_NO_SANITIZE_MEMORY macro suppresses MemorySanitizer checks for
// use-of-uninitialized-data. It is used to decorate functions with known
// false positives.
#ifdef __clang__
# define CLANG_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
#else
# define CLANG_NO_SANITIZE_MEMORY
#endif
namespace {
struct PragmaState
{
bool memorySanitizerInstrumentation;
};
// The initialization of static thread-local data is not observed by MemorySanitizer
// when inside a shared library, leading to false-positive use-of-uninitialized-data
// errors: https://github.com/google/sanitizers/issues/1409
// We work around this by assigning an initial value to it ourselves on first use.
// Note that since the flag to check whether this initialization has already been
// done is itself a static thread-local, we must suppress the MemorySanitizer check
// with a function attribute.
CLANG_NO_SANITIZE_MEMORY PragmaState &getPragmaState()
{
static thread_local bool initialized = false;
static thread_local PragmaState state;
if(!initialized)
{
state = {};
static thread_local bool memorySanitizerInstrumentation = false; initialized = true;
}
return state;
}
} // namespace
namespace rr {
void Pragma(PragmaBooleanOption option, bool enable) void Pragma(PragmaBooleanOption option, bool enable)
{ {
PragmaState &state = ::getPragmaState();
switch(option) switch(option)
{ {
case MemorySanitizerInstrumentation: case MemorySanitizerInstrumentation:
memorySanitizerInstrumentation = enable; state.memorySanitizerInstrumentation = enable;
break; break;
default: default:
UNSUPPORTED("Unknown pragma %d", int(option)); UNSUPPORTED("Unknown pragma %d", int(option));
...@@ -35,10 +75,12 @@ void Pragma(PragmaBooleanOption option, bool enable) ...@@ -35,10 +75,12 @@ void Pragma(PragmaBooleanOption option, bool enable)
bool getPragmaState(PragmaBooleanOption option) bool getPragmaState(PragmaBooleanOption option)
{ {
PragmaState &state = ::getPragmaState();
switch(option) switch(option)
{ {
case MemorySanitizerInstrumentation: case MemorySanitizerInstrumentation:
return memorySanitizerInstrumentation; return state.memorySanitizerInstrumentation;
default: default:
UNSUPPORTED("Unknown pragma %d", int(option)); UNSUPPORTED("Unknown pragma %d", int(option));
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment