MSAN, ASAN, & TSAN
Testing Skia with memory, address, and thread santizers.
Compiling Skia with ASAN, UBSAN, or TSAN can be done with the latest version of Clang.
- UBSAN works on Linux, Mac, Android, and Windows, though some checks are platform-specific.
- ASAN works on Linux, Mac, Android, and Windows.
- TSAN works on Linux and Mac.
- MSAN works on Linux[1].
We find that testing sanitizer builds with libc++ uncovers more issues than with the system-provided C++ standard library, which is usually libstdc++. libc++ proactively hooks into sanitizers to help their analyses. We ship a copy of libc++ with our Linux toolchain in /lib.
[1]To compile and run with MSAN, an MSAN-instrumented version of libc++ is needed. It’s generally easiest to run one of the following 2 steps to build/download a recent version of Clang and the instrumented libc++, located in /msan.
Downloading Clang binaries (Googlers Only)
This requires gsutil, part of the gcloud sdk.
gcloud auth application-default login
CLANGDIR="${HOME}/clang"
./bin/sk asset download clang_linux $CLANGDIR
Building Clang binaries from scratch (Other users)
CLANGDIR="${HOME}/clang"
python3 tools/git-sync-deps
CC= CXX= infra/bots/assets/clang_linux/create.py -t "$CLANGDIR"
Configure and Compile Skia with MSAN
CLANGDIR="${HOME}/clang"
mkdir -p out/msan
cat > out/msan/args.gn <<- EOF
cc = "${CLANGDIR}/bin/clang"
cxx = "${CLANGDIR}/bin/clang++"
extra_cflags = [ "-B${CLANGDIR}/bin" ]
extra_ldflags = [
"-B${CLANGDIR}/bin",
"-fuse-ld=lld",
"-L${CLANGDIR}/msan",
"-Wl,-rpath,${CLANGDIR}/msan" ]
sanitize = "MSAN"
skia_use_fontconfig = false
EOF
python3 tools/git-sync-deps
bin/gn gen out/msan
ninja -C out/msan
When running dm under MSAN, you’ll want to include --nogpu because MSAN won’t have
instrumented driver memory and such and will flag unrelated issues.
Symbolizing MSAN Traces
By default, MSan will print hexadecimal addresses in stack traces. To see function names and line
numbers, you must provide the path to llvm-symbolizer via an environment variable.
CLANGDIR="${HOME}/clang"
export MSAN_SYMBOLIZER_PATH="${CLANGDIR}/bin/llvm-symbolizer"
./out/msan/dm ...
Stack Overflow during MSAN Reporting
If you encounter a stack overflow (segfault) while MSAN is trying to report an error, it is likely
because libunwind was itself instrumented with MSAN. This causes infinite recursion during
stack unwinding.
While our toolchain build script has been updated to fix this, you may need to apply a workaround to an existing toolchain:
- Locate the
msandirectory in your clang asset (e.g.,~/clang/msan). - Delete the instrumented unwinder files:
rm ~/clang/msan/libunwind.so* ~/clang/msan/libunwind.a - Force a relink of your binary (e.g.,
rm out/msan/dm && ninja -C out/msan dm).
This will force the loader to use the system’s uninstrumented libunwind.
Configure and Compile Skia with ASAN
CLANGDIR="${HOME}/clang"
mkdir -p out/asan
cat > out/asan/args.gn <<- EOF
cc = "${CLANGDIR}/bin/clang"
cxx = "${CLANGDIR}/bin/clang++"
sanitize = "ASAN"
extra_ldflags = [ "-fuse-ld=lld", "-Wl,-rpath,${CLANGDIR}/lib/x86_64-unknown-linux-gnu" ]
EOF
python3 tools/git-sync-deps
bin/gn gen out/asan
ninja -C out/asan
Configure and Compile Skia with TSAN
CLANGDIR="${HOME}/clang"
mkdir -p out/tsan
cat > out/tsan/args.gn <<- EOF
cc = "${CLANGDIR}/bin/clang"
cxx = "${CLANGDIR}/bin/clang++"
sanitize = "TSAN"
is_debug = false
extra_ldflags = [ "-Wl,-rpath,${CLANGDIR}/lib" ]
EOF
python3 tools/git-sync-deps
bin/gn gen out/tsan
ninja -C out/tsan