Sanitizers (ASan/MSan/TSan)link
AddressSanitizer,
MemorySanitizer and
ThreadSanitizer are tools
provided by clang to detect certain classes of errors in C/C++ programs. They
consist of compiler instrumentation (so your program's executable code is
modified) and runtime libraries (so e.g. the malloc function may get
replaced).
They are abbreviated as "ASan", "MSan" and "TSan" respectively.
They all incur large overhead, so only enable them while debugging.
| Tool | Detects | Helps debug what? | Slowdown | Memory overhead | Android support |
|---|---|---|---|---|---|
| ASan | Out-of-bounds accesses, use-after-free, use-after-return, memory leaks | Crashes, non-deterministic results, memory leaks | 2x | 3x | Yes |
| MSan | Uninitialized memory reads | Non-deterministic results | 3x | ? | Yes |
| TSan | Data races | Many bugs in multi-thread code | 5x-15x | 5x-10x | No |
Note
See this documentation on leak detection. It is only enabled by default on some platforms.
Support status and how to enable each sanitizerlink
ASan (AddressSanitizer)link
Enabling ASan in the IREE build is a simple matter of setting the
IREE_ENABLE_ASAN CMake option:
cmake -DIREE_ENABLE_ASAN=ON ...
TSan (ThreadSanitizer)link
To enable TSan, at the moment, the following 3 CMake options must be set:
cmake \
-DIREE_ENABLE_TSAN=ON \
-DIREE_BYTECODE_MODULE_ENABLE_TSAN=ON \
-DIREE_BYTECODE_MODULE_FORCE_LLVM_SYSTEM_LINKER=ON \
-DIREE_BUILD_SAMPLES=OFF \
...
In practice, IREE_ENABLE_TSAN alone would be enough for many targets, but not
all. The problem is that a IREE runtime built with IREE_ENABLE_TSAN cannot
load a IREE compiled LLVM/CPU module unless the following flags were passed to
the IREE compiler: --iree-llvmcpu-sanitize=thread and
--iree-llvmcpu-link-embedded=false.
The CMake options IREE_BYTECODE_MODULE_ENABLE_TSAN and
IREE_BYTECODE_MODULE_FORCE_LLVM_SYSTEM_LINKER ensure that the above flags are
passed to the IREE compiler when building modules used in tests, benchmarks,
etc. (anything that internally uses the CMake iree_bytecode_module macro).
The CMake option IREE_BUILD_SAMPLES=OFF is needed because samples currently
assume that the embedded linker is
used, so they are incompatible with
IREE_BYTECODE_MODULE_FORCE_LLVM_SYSTEM_LINKER=ON.
At the moment, CMake logic heavy-handedly enforces that whenever
IREE_ENABLE_TSAN is set, these other two CMake variables are also set.
That ensures that all tests succeed: no test is expected to fail with TSan.
If you know what you're doing (i.e. if you are not building targets that
internally involve a LLVM/CPU iree_bytecode_module), feel free to locally
comment out the CMake error and only set IREE_ENABLE_TSAN. Also see a
past attempt to relax that CMake
validation.
MSan (MemorySanitizer)link
In theory that should be a simple matter of
-DIREE_ENABLE_MSAN=ON
However, that requires making and using a custom build of libc++ with MSan as explained in this documentation.
As of April 2022, all of IREE's tests succeeded with MSan on Linux/x86-64,
provided that the vulkan driver was disabled (due to lack of MSan
instrumentation in the NVIDIA Vulkan driver).
UBSan (UndefinedBehaviorSanitizer)link
Enabling UBSan in the IREE build is a simple matter of setting the
IREE_ENABLE_UBSAN CMake option:
cmake -DIREE_ENABLE_UBSAN=ON ...
Note that both ASan and UBSan can be enabled in the same build.
Symbolizing the reportslink
Desktop platformslink
On desktop platforms, getting nicely symbolized reports is covered in this
documentation.
The gist of it is make sure that llvm-symbolizer is in your PATH, or make
the ASAN_SYMBOLIZER_PATH environment variable point to it.
Androidlink
On Android it's more complicated due to
this Android NDK issue.
Fortunately, we have a script to perform the symbolization. Copy the raw output
from the sanitizer and feed it into the stdin of the
build_tools/scripts/android_symbolize.sh script, with the ANDROID_NDK
environment variable pointing to the NDK root directory, like this:
ANDROID_NDK=~/android-ndk-r21d ./build_tools/scripts/android_symbolize.sh < /tmp/asan.txt
Where /tmp/asan.txt is where you've pasted the raw sanitizer report.
Tip
This script will happily just echo any line that isn't a stack frame.
That means you can feed it the whole ASan report at once, and it will
output a symbolized version of it. DO NOT run it on a single stack at a
time! That is unlike the symbolizer tool that's being added in NDK r22, and
one of the reasons why we prefer to keep our own script. For more details
see
this comment.