diff --git a/compiler-rt/test/sanitizer_common/android_commands/android_common.py b/compiler-rt/test/sanitizer_common/android_commands/android_common.py --- a/compiler-rt/test/sanitizer_common/android_commands/android_common.py +++ b/compiler-rt/test/sanitizer_common/android_commands/android_common.py @@ -34,6 +34,20 @@ os.unlink(tmpname) return ret +def device_file_exists(path): + ret = 255 + devnull = open(os.devnull, 'w') + ret = subprocess.call([ADB, "shell", "test", "-x", path], stdout=devnull, stderr=devnull) + + devnull.close() + if ret == 0: + return True + elif ret == 1: + return False + else: + print "adb connection failed" + return False + def pull_from_device(path): tmp = tempfile.mktemp() adb(['pull', path, tmp], 5, 60) diff --git a/compiler-rt/test/sanitizer_common/android_commands/android_run.py b/compiler-rt/test/sanitizer_common/android_commands/android_run.py --- a/compiler-rt/test/sanitizer_common/android_commands/android_run.py +++ b/compiler-rt/test/sanitizer_common/android_commands/android_run.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import os, signal, sys, subprocess, tempfile +import os, signal, sys, subprocess, tempfile, re from android_common import * ANDROID_TMPDIR = '/data/local/tmp/Output' @@ -8,12 +8,20 @@ device_binary = host_to_device_path(sys.argv[0]) def build_env(): + symbolizer_path = "{}/llvm-symbolizer".format(ANDROID_TMPDIR) + has_symbolizer = device_file_exists(symbolizer_path) + args = [] # Android linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir. args.append('LD_LIBRARY_PATH=%s' % (ANDROID_TMPDIR,)) for (key, value) in os.environ.items(): if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or key.endswith('SAN_OPTIONS'): - args.append('%s="%s"' % (key, value.replace('"', '\\"'))) + val = value.replace('"', '\\"') + val = re.sub( + r"external_symbolizer_path=(\'.*?\'|\".*?\"|.*?)(:|$)", + "external_symbolizer_path=\"{}\"\\2".format(symbolizer_path) if has_symbolizer else "", + val) + args.append('%s="%s"' % (key, val)) return ' '.join(args) is_64bit = (subprocess.check_output(['file', sys.argv[0] + '.real']).find('64-bit') != -1) diff --git a/compiler-rt/test/sanitizer_common/lit.common.cfg.py b/compiler-rt/test/sanitizer_common/lit.common.cfg.py --- a/compiler-rt/test/sanitizer_common/lit.common.cfg.py +++ b/compiler-rt/test/sanitizer_common/lit.common.cfg.py @@ -43,6 +43,13 @@ # which does not work for abort()-terminated programs. default_tool_options += ['abort_on_error=0'] +# If the user has a poisoned *SAN_SYMBOLIZER_PATH (like what's setup by +# build/envsetup.sh on Android), then they can end up with an out-of-date +# symbolizer for the tests. Ensure they get the one from the recent build tree. +symbolizer_path = os.path.join(config.binary_path, "bin", "llvm-symbolizer") +if os.path.exists(symbolizer_path): + default_tool_options += ['external_symbolizer_path=' + symbolizer_path] + default_tool_options_str = ':'.join(default_tool_options) if default_tool_options_str: config.environment[tool_options] = default_tool_options_str diff --git a/compiler-rt/test/sanitizer_common/lit.site.cfg.py.in b/compiler-rt/test/sanitizer_common/lit.site.cfg.py.in --- a/compiler-rt/test/sanitizer_common/lit.site.cfg.py.in +++ b/compiler-rt/test/sanitizer_common/lit.site.cfg.py.in @@ -5,6 +5,7 @@ config.tool_name = "@SANITIZER_COMMON_LIT_TEST_MODE@" config.target_cflags = "@SANITIZER_COMMON_TEST_TARGET_CFLAGS@" config.target_arch = "@SANITIZER_COMMON_TEST_TARGET_ARCH@" +config.binary_path = "@LLVM_BINARY_DIR@" # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")