Skip to content

Commit aa9d74c

Browse files
committed
[asan] Android test runner for ASan lit tests.
This change replaces 32- and 64- bit config.in-s with a single config template that is used to generate both 32 and 64 bits configs as well as the new arm-android config. Arm-android config is special because it can run tests on a remote device over adb (android debug bridge). We replace %clang with a script that run the compiler, upload the result to the device, and replaces it with another script. The second script runs the binary on the device and delivers stdout/stderr/exitcode back. llvm-svn: 201394
1 parent a6b264b commit aa9d74c

File tree

9 files changed

+207
-72
lines changed

9 files changed

+207
-72
lines changed

compiler-rt/CMakeLists.txt

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,25 @@ macro(test_target_arch arch)
9999
endif()
100100
endmacro()
101101

102-
if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
103-
if (NOT MSVC)
104-
test_target_arch(x86_64 ${TARGET_64_BIT_CFLAGS})
102+
if(ANDROID_COMMON_FLAGS)
103+
test_target_arch(arm_android "${ANDROID_COMMON_FLAGS}")
104+
else()
105+
if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
106+
if (NOT MSVC)
107+
test_target_arch(x86_64 ${TARGET_64_BIT_CFLAGS})
108+
endif()
109+
test_target_arch(i386 ${TARGET_32_BIT_CFLAGS})
110+
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC")
111+
test_target_arch(powerpc64 ${TARGET_64_BIT_CFLAGS})
112+
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "ARM")
113+
test_target_arch(arm "")
105114
endif()
106-
test_target_arch(i386 ${TARGET_32_BIT_CFLAGS})
107-
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC")
108-
test_target_arch(powerpc64 ${TARGET_64_BIT_CFLAGS})
109-
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "ARM")
110-
test_target_arch(arm "")
111115
endif()
112116

113117
# We only support running instrumented tests when we're not cross compiling
114-
# and target a unix-like system. On Android we define the rules for building
115-
# unit tests, but don't execute them.
116-
if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX AND NOT ANDROID)
118+
# and target a unix-like system. We can run tests on Android even when we are
119+
# cross-compiling.
120+
if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX) OR ANDROID)
117121
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON)
118122
else()
119123
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF)
@@ -230,12 +234,15 @@ filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
230234

231235
add_subdirectory(include)
232236

233-
set(SANITIZER_COMMON_LIT_TEST_DEPS
234-
clang clang-headers FileCheck count not llvm-nm llvm-symbolizer
235-
compiler-rt-headers)
236-
# Check code style when running lit tests for sanitizers.
237-
if(UNIX)
238-
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS SanitizerLintCheck)
237+
# When ANDROID, we build tests with the host compiler (i.e. CMAKE_C_COMPILER),
238+
# and run tests with tools from the host toolchain.
239+
if (NOT ANDROID)
240+
set(SANITIZER_COMMON_LIT_TEST_DEPS
241+
clang clang-headers FileCheck count not llvm-nm llvm-symbolizer
242+
compiler-rt-headers)
243+
if(UNIX)
244+
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS SanitizerLintCheck)
245+
endif()
239246
endif()
240247

241248
add_subdirectory(lib)

compiler-rt/lib/asan/lit_tests/64bitConfig/lit.site.cfg.in

Lines changed: 0 additions & 12 deletions
This file was deleted.

compiler-rt/lib/asan/lit_tests/CMakeLists.txt

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,59 @@
11
set(ASAN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
22
set(ASAN_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/..)
33

4-
configure_lit_site_cfg(
5-
${CMAKE_CURRENT_SOURCE_DIR}/64bitConfig/lit.site.cfg.in
6-
${CMAKE_CURRENT_BINARY_DIR}/64bitConfig/lit.site.cfg
7-
)
8-
9-
configure_lit_site_cfg(
10-
${CMAKE_CURRENT_SOURCE_DIR}/32bitConfig/lit.site.cfg.in
11-
${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg
12-
)
13-
14-
configure_lit_site_cfg(
15-
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
16-
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
17-
)
18-
194
if(COMPILER_RT_CAN_EXECUTE_TESTS)
205
set(ASAN_TESTSUITES)
21-
if(CAN_TARGET_i386)
22-
list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig)
6+
7+
if(CAN_TARGET_arm_android)
8+
# This is only true if we are cross-compiling.
9+
# Build all tests with host compiler and use host tools.
10+
set(ASAN_TEST_TARGET_CC ${CMAKE_C_COMPILER})
11+
get_filename_component(ASAN_TEST_LLVM_TOOLS_DIR ${CMAKE_C_COMPILER} PATH)
12+
set(ASAN_TEST_CONFIG_SUFFIX "-arm-android")
13+
set(ASAN_TEST_BITS "32")
14+
get_target_flags_for_arch(arm_android ASAN_TEST_TARGET_CFLAGS)
15+
configure_lit_site_cfg(
16+
${CMAKE_CURRENT_SOURCE_DIR}/GenericConfig/lit.site.cfg.in
17+
${CMAKE_CURRENT_BINARY_DIR}/ARMAndroidConfig/lit.site.cfg
18+
)
19+
list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/ARMAndroidConfig)
2320
endif()
21+
2422
if(CAN_TARGET_x86_64 OR CAN_TARGET_powerpc64)
23+
set(ASAN_TEST_CONFIG_SUFFIX "64")
24+
set(ASAN_TEST_BITS "64")
25+
set(ASAN_TEST_TARGET_CFLAGS ${TARGET_64_BIT_CFLAGS})
26+
configure_lit_site_cfg(
27+
${CMAKE_CURRENT_SOURCE_DIR}/GenericConfig/lit.site.cfg.in
28+
${CMAKE_CURRENT_BINARY_DIR}/64bitConfig/lit.site.cfg
29+
)
2530
list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig)
2631
endif()
32+
33+
if(CAN_TARGET_i386)
34+
set(ASAN_TEST_CONFIG_SUFFIX "32")
35+
set(ASAN_TEST_BITS "32")
36+
set(ASAN_TEST_TARGET_CFLAGS ${TARGET_32_BIT_CFLAGS})
37+
configure_lit_site_cfg(
38+
${CMAKE_CURRENT_SOURCE_DIR}/GenericConfig/lit.site.cfg.in
39+
${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg
40+
)
41+
list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig)
42+
endif()
43+
44+
configure_lit_site_cfg(
45+
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
46+
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
47+
)
48+
2749
# Run ASan tests only if we're sure we may produce working binaries.
2850
set(ASAN_TEST_DEPS
2951
${SANITIZER_COMMON_LIT_TEST_DEPS}
3052
asan_runtime_libraries)
3153
set(ASAN_TEST_PARAMS
3254
asan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
33-
if(LLVM_INCLUDE_TESTS)
55+
# FIXME: support unit test in the android test runner
56+
if(LLVM_INCLUDE_TESTS AND NOT CAN_TARGET_arm_android)
3457
list(APPEND ASAN_TEST_DEPS AsanUnitTests)
3558
list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
3659
endif()

compiler-rt/lib/asan/lit_tests/32bitConfig/lit.site.cfg.in renamed to compiler-rt/lib/asan/lit_tests/GenericConfig/lit.site.cfg.in

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
## Autogenerated by LLVM/Clang configuration.
22
# Do not edit!
33

4-
# Load common config for all compiler-rt lit tests.
5-
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/lib/lit.common.configured")
6-
74
# Tool-specific config options.
5+
config.name_suffix = "@ASAN_TEST_CONFIG_SUFFIX@"
86
config.asan_source_dir = "@ASAN_SOURCE_DIR@"
9-
config.bits = "32"
7+
config.target_cflags = "@ASAN_TEST_TARGET_CFLAGS@"
8+
config.clang = "@ASAN_TEST_TARGET_CC@"
9+
config.llvm_tools_dir = "@ASAN_TEST_LLVM_TOOLS_DIR@"
10+
config.bits = "@ASAN_TEST_BITS@"
11+
config.android = "@CAN_TARGET_arm_android@"
12+
13+
# Load common config for all compiler-rt lit tests.
14+
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/lib/lit.common.configured")
1015

1116
# Load tool-specific config that would do the real work.
1217
lit_config.load_config(config, "@ASAN_SOURCE_DIR@/lit_tests/lit.cfg")
13-
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import os, subprocess, tempfile
2+
import time
3+
4+
ANDROID_TMPDIR = '/data/local/tmp/Output'
5+
ADB = os.environ.get('ADB', 'adb')
6+
7+
verbose = False
8+
if os.environ.get('ANDROID_RUN_VERBOSE') == '1':
9+
verbose = True
10+
11+
def adb(args):
12+
if verbose:
13+
print args
14+
devnull = open(os.devnull, 'w')
15+
return subprocess.call([ADB] + args, stdout=devnull, stderr=subprocess.STDOUT)
16+
17+
def pull_from_device(path):
18+
tmp = tempfile.mktemp()
19+
adb(['pull', path, tmp])
20+
text = open(tmp, 'r').read()
21+
os.unlink(tmp)
22+
return text
23+
24+
def push_to_device(path):
25+
# Workaround for https://code.google.com/p/android/issues/detail?id=65857
26+
dst_path = os.path.join(ANDROID_TMPDIR, os.path.basename(path))
27+
tmp_path = dst_path + '.push'
28+
adb(['push', path, tmp_path])
29+
adb(['shell', 'cp "%s" "%s" 2>&1' % (tmp_path, dst_path)])
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/python
2+
3+
import os, sys, subprocess
4+
from android_common import *
5+
6+
7+
here = os.path.abspath(os.path.dirname(sys.argv[0]))
8+
android_run = os.path.join(here, 'android_run.py')
9+
10+
output = None
11+
output_type = 'executable'
12+
13+
args = sys.argv[1:]
14+
while args:
15+
arg = args.pop(0)
16+
if arg == '-shared':
17+
output_type = 'shared'
18+
elif arg == '-c':
19+
output_type = 'object'
20+
elif arg == '-o':
21+
output = args.pop(0)
22+
23+
if output == None:
24+
print "No output file name!"
25+
sys.exit(1)
26+
27+
ret = subprocess.call(sys.argv[1:])
28+
if ret != 0:
29+
sys.exit(ret)
30+
31+
if output_type in ['executable', 'shared']:
32+
push_to_device(output)
33+
34+
if output_type == 'executable':
35+
os.rename(output, output + '.real')
36+
os.symlink(android_run, output)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/python
2+
3+
import os, sys, subprocess, tempfile
4+
from android_common import *
5+
6+
ANDROID_TMPDIR = '/data/local/tmp/Output'
7+
8+
here = os.path.abspath(os.path.dirname(sys.argv[0]))
9+
device_binary = os.path.join(ANDROID_TMPDIR, os.path.basename(sys.argv[0]))
10+
11+
def build_env():
12+
args = []
13+
# Android linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir.
14+
args.append('LD_LIBRARY_PATH=%s:%s' %
15+
(ANDROID_TMPDIR, os.environ.get('LD_LIBRARY_PATH', '')))
16+
for (key, value) in os.environ.items():
17+
if key in ['ASAN_OPTIONS']:
18+
args.append('%s="%s"' % (key, value))
19+
return ' '.join(args)
20+
21+
device_env = build_env()
22+
device_args = ' '.join(sys.argv[1:]) # FIXME: escape?
23+
device_stdout = device_binary + '.stdout'
24+
device_stderr = device_binary + '.stderr'
25+
device_exitcode = device_binary + '.exitcode'
26+
ret = adb(['shell', 'cd %s && %s %s %s >%s 2>%s ; echo $? >%s' %
27+
(ANDROID_TMPDIR, device_env, device_binary, device_args,
28+
device_stdout, device_stderr, device_exitcode)])
29+
if ret != 0:
30+
sys.exit(ret)
31+
32+
sys.stdout.write(pull_from_device(device_stdout))
33+
sys.stderr.write(pull_from_device(device_stderr))
34+
sys.exit(int(pull_from_device(device_exitcode)))

compiler-rt/lib/asan/lit_tests/lit.cfg

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def get_required_attr(config, attr_name):
1414
return attr_value
1515

1616
# Setup config name.
17-
config.name = 'AddressSanitizer' + config.bits
17+
config.name = 'AddressSanitizer' + config.name_suffix
1818

1919
# Setup source root.
2020
config.test_source_root = os.path.dirname(__file__)
@@ -53,23 +53,32 @@ if llvm_src_root is None:
5353

5454
# Setup default compiler flags used with -fsanitize=address option.
5555
# FIXME: Review the set of required flags and check if it can be reduced.
56-
bits_cflag = " -m" + config.bits
56+
target_cflags = " " + config.target_cflags
5757
clang_asan_cflags = (" -fsanitize=address"
5858
+ " -mno-omit-leaf-frame-pointer"
5959
+ " -fno-omit-frame-pointer"
6060
+ " -fno-optimize-sibling-calls"
6161
+ " -g"
62-
+ bits_cflag)
62+
+ target_cflags)
6363
clang_asan_cxxflags = " --driver-mode=g++" + clang_asan_cflags
64-
config.substitutions.append( ("%clang ", " " + config.clang + bits_cflag + " "))
65-
config.substitutions.append( ("%clangxx ", (" " + config.clang +
64+
65+
if config.android == "TRUE":
66+
config.available_features.add('android')
67+
clang_wrapper = os.path.join(config.asan_source_dir, "lit_tests",
68+
"android_commands", "android_compile.py") + " "
69+
else:
70+
clang_wrapper = ""
71+
72+
config.substitutions.append( ("%clang ", " " + clang_wrapper + config.clang + target_cflags + " "))
73+
config.substitutions.append( ("%clangxx ", (" " + clang_wrapper + config.clang +
6674
" --driver-mode=g++" +
67-
bits_cflag + " ")) )
68-
config.substitutions.append( ("%clang_asan ", (" " + config.clang + " " +
75+
target_cflags + " ")) )
76+
config.substitutions.append( ("%clang_asan ", (" " + clang_wrapper + config.clang + " " +
6977
clang_asan_cflags + " ")) )
70-
config.substitutions.append( ("%clangxx_asan ", (" " + config.clang + " " +
78+
config.substitutions.append( ("%clangxx_asan ", (" " + clang_wrapper + config.clang + " " +
7179
clang_asan_cxxflags + " ")) )
7280

81+
7382
# Setup path to asan_symbolize.py script.
7483
asan_source_dir = get_required_attr(config, "asan_source_dir")
7584
asan_symbolize = os.path.join(asan_source_dir, "scripts", "asan_symbolize.py")

compiler-rt/lib/lit.common.configured.in

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
## Autogenerated by LLVM/Clang configuration.
22
# Do not edit!
33

4+
# Set attribute value if it is unset.
5+
def set_default(attr, value):
6+
if not getattr(config, attr, None):
7+
setattr(config, attr, value)
8+
49
# Generic config options for all compiler-rt lit tests.
5-
config.target_triple = "@TARGET_TRIPLE@"
6-
config.host_arch = "@HOST_ARCH@"
7-
config.host_os = "@HOST_OS@"
8-
config.llvm_build_mode = "@LLVM_BUILD_MODE@"
9-
config.llvm_src_root = "@LLVM_SOURCE_DIR@"
10-
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
11-
config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@"
12-
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
13-
config.clang = "@LLVM_BINARY_DIR@/bin/clang"
14-
config.compiler_rt_arch = "@COMPILER_RT_SUPPORTED_ARCH@"
15-
config.python_executable = "@PYTHON_EXECUTABLE@"
16-
config.compiler_rt_debug = @COMPILER_RT_DEBUG_PYBOOL@
10+
set_default("target_triple", "@TARGET_TRIPLE@")
11+
set_default("host_arch", "@HOST_ARCH@")
12+
set_default("host_os", "@HOST_OS@")
13+
set_default("llvm_build_mode", "@LLVM_BUILD_MODE@")
14+
set_default("llvm_src_root", "@LLVM_SOURCE_DIR@")
15+
set_default("llvm_obj_root", "@LLVM_BINARY_DIR@")
16+
set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@")
17+
set_default("llvm_tools_dir", "@LLVM_TOOLS_DIR@")
18+
set_default("clang", "@LLVM_BINARY_DIR@/bin/clang")
19+
set_default("compiler_rt_arch", "@COMPILER_RT_SUPPORTED_ARCH@")
20+
set_default("python_executable", "@PYTHON_EXECUTABLE@")
21+
set_default("compiler_rt_debug", @COMPILER_RT_DEBUG_PYBOOL@)
1722

1823
# LLVM tools dir can be passed in lit parameters, so try to
1924
# apply substitution.

0 commit comments

Comments
 (0)