Sanitizer support
Sanitizers может быть использован в пользовательских сборках Julia, чтобы упростить обнаружение определенных видов ошибок в внутреннем C/C++ коде Julia.
Address Sanitizer: easy build
Из исходного кода Julia вы должны иметь возможность собрать версию, поддерживающую санитацию адресов в Julia и LLVM, следующим образом:
$ mkdir /tmp/julia
$ contrib/asan/build.sh /tmp/julia/
Здесь мы выбрали /tmp/julia
в качестве каталога сборки, но вы можете выбрать любой другой. После сборки запустите нагрузку, которую вы хотите протестировать, с помощью /tmp/julia/julia
. Ошибки памяти приведут к сбоям.
Если вам требуется настройка или дополнительные детали, смотрите документацию ниже.
General considerations
Использование санитайзеров Clang очевидно требует от вас использования Clang (USECLANG=1
), но есть еще один нюанс: большинство санитайзеров требуют библиотеку времени выполнения, предоставляемую компилятором хоста, в то время как инструментированный код, сгенерированный JIT Julia, зависит от функциональности этой библиотеки. Это подразумевает, что версия LLVM вашего компилятора хоста должна совпадать с версией библиотеки LLVM, используемой в Julia.
Простое решение состоит в том, чтобы создать отдельную папку сборки для предоставления соответствующего инструментария, собрав с помощью BUILD_LLVM_CLANG=1
. Затем вы можете ссылаться на этот инструментарий из другой папки сборки, указав USECLANG=1
, переопределив переменные CC
и CXX
.
Ошибки санитайзеров возникают, когда они обнаруживают, что общая библиотека открывается с использованием RTLD_DEEPBIND
(ссылка: google/sanitizers#611). Поскольку libblastrampoline по умолчанию использует RTLD_DEEPBIND
, нам необходимо установить переменную окружения LBT_USE_RTLD_DEEPBIND=0
при использовании санитайзера.
Чтобы использовать один из санитайзеров, установите SANITIZE=1
, а затем соответствующий флаг для выбранного вами санитайзера.
На macOS это может потребовать дополнительных флагов для работы. В целом, это может выглядеть так, плюс один или несколько флагов SANITIZE_*
, перечисленных ниже:
make -C deps USE_BINARYBUILDER_LLVM=0 LLVM_VER=svn stage-llvm
make -C src SANITIZE=1 USECLANG=1 \
CC=~+/deps/scratch/llvm-svn/build_Release/bin/clang \
CXX=~+/deps/scratch/llvm-svn/build_Release/bin/clang++ \
CPPFLAGS="-isysroot $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" \
CXXFLAGS="-isystem $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1"
(или поместите их в ваш Make.user
, чтобы вам не нужно было помнить их каждый раз).
Address Sanitizer (ASAN)
Для обнаружения или отладки ошибок памяти вы можете использовать Clang's address sanitizer (ASAN). Компилируя с SANITIZE_ADDRESS=1
, вы включаете ASAN для компилятора Julia и его сгенерированного кода. Кроме того, вы можете указать LLVM_SANITIZE=1
, чтобы санировать библиотеку LLVM. Обратите внимание, что эти параметры влекут за собой высокие затраты на производительность и память. Например, использование ASAN для Julia и LLVM делает testall1
в 8-10 раз медленнее, при этом используя в 20 раз больше памяти (это можно уменьшить соответственно до фактора 3 и 4, используя параметры, описанные ниже).
По умолчанию Julia устанавливает флаг ASAN allow_user_segv_handler=1
, который необходим для правильной работы доставки сигналов. Вы можете определить другие параметры, используя переменную окружения ASAN_OPTIONS
, в этом случае вам нужно будет повторить ранее упомянутый параметр по умолчанию. Например, использование памяти можно уменьшить, указав fast_unwind_on_malloc=0
и malloc_context_size=2
, ценой точности обратного вызова. На данный момент Julia также устанавливает detect_leaks=0
, но это следует удалить в будущем.
Example setup
Step 1: Install toolchain
Проверьте рабочее дерево Git (или создайте каталог сборки вне дерева) по адресу $TOOLCHAIN_WORKTREE
и создайте файл конфигурации $TOOLCHAIN_WORKTREE/Make.user
с
USE_BINARYBUILDER_LLVM=1
BUILD_LLVM_CLANG=1
Запуск:
cd $TOOLCHAIN_WORKTREE
make -C deps install-llvm install-clang install-llvm-tools
установить двоичные файлы инструментов в $TOOLCHAIN_WORKTREE/usr/tools
Step 2: Build Julia with ASAN
Проверьте рабочее дерево Git (или создайте каталог сборки вне дерева) в $BUILD_WORKTREE
и создайте файл конфигурации $BUILD_WORKTREE/Make.user
с
TOOLCHAIN=$(TOOLCHAIN_WORKTREE)/usr/tools
# use our new toolchain
USECLANG=1
override CC=$(TOOLCHAIN)/clang
override CXX=$(TOOLCHAIN)/clang++
export ASAN_SYMBOLIZER_PATH=$(TOOLCHAIN)/llvm-symbolizer
USE_BINARYBUILDER_LLVM=1
override SANITIZE=1
override SANITIZE_ADDRESS=1
# make the GC use regular malloc/frees, which are hooked by ASAN
override WITH_GC_DEBUG_ENV=1
# default to a debug build for better line number reporting
override JULIA_BUILD_MODE=debug
# make ASAN consume less memory
export ASAN_OPTIONS=detect_leaks=0:fast_unwind_on_malloc=0:allow_user_segv_handler=1:malloc_context_size=2
JULIA_PRECOMPILE=1
# tell libblastrampoline to not use RTLD_DEEPBIND
export LBT_USE_RTLD_DEEPBIND=0
Запуск:
cd $BUILD_WORKTREE
make debug
собрать julia-debug
с ASAN.
Memory Sanitizer (MSAN)
For detecting use of uninitialized memory, you can use Clang's memory sanitizer (MSAN) by compiling with SANITIZE_MEMORY=1
.
Thread Sanitizer (TSAN)
Для отладки гонок данных и других проблем, связанных с потоками, вы можете использовать Clang's thread sanitizer (TSAN), скомпилировав с SANITIZE_THREAD=1
.