gn build: Add check-hwasan target.

The Android sanitizer tests are currently some of the most difficult
to run correctly, requiring at least 3 build directories which have
to be configured in just the right way and built in the correct order
(see e.g. [1] and the functions that it calls).

This patch adds a check-hwasan target which greatly simplifies running
the hwasan tests for gn users, taking advantage of its support for
multiple toolchains. With this the tests can be run simply by setting
an NDK path and running "ninja check-hwasan" with a compatible Android
device connected. The Linux/x86_64 and Android/aarch64 targets are
tested in parallel.

[1] https://github.com/llvm/llvm-zorg/blob/master/zorg/buildbot/builders/sanitizers/buildbot_android.sh

Differential Revision: https://reviews.llvm.org/D56713

llvm-svn: 351277
This commit is contained in:
Peter Collingbourne 2019-01-16 00:15:25 +00:00
parent f510bc7972
commit 32c46f7274
6 changed files with 231 additions and 14 deletions

View File

@ -5,24 +5,11 @@ import("//llvm/utils/gn/build/toolchain/compiler.gni")
group("default") {
deps = [
"//clang/test",
"//compiler-rt/test/hwasan",
"//lld/test",
"//llvm/test",
]
# FIXME: This should be a dependency of a test target instead of being
# depended on from here.
if (android_ndk_path != "") {
android_aarch64_toolchain =
"//llvm/utils/gn/build/toolchain:stage2_android_aarch64"
deps += [
"//compiler-rt/lib/hwasan:hwasan_shared($android_aarch64_toolchain)",
"//llvm/tools/llvm-symbolizer($android_aarch64_toolchain)",
]
}
if (host_cpu == "x64" && host_os == "linux") {
deps += [ "//compiler-rt/lib/hwasan:hwasan_shared(//llvm/utils/gn/build/toolchain:stage2_unix)" ]
}
testonly = true
}

View File

@ -0,0 +1,26 @@
import("//clang/resource_dir.gni")
copy("include") {
sources = [
"sanitizer/allocator_interface.h",
"sanitizer/asan_interface.h",
"sanitizer/common_interface_defs.h",
"sanitizer/coverage_interface.h",
"sanitizer/dfsan_interface.h",
"sanitizer/esan_interface.h",
"sanitizer/hwasan_interface.h",
"sanitizer/linux_syscall_hooks.h",
"sanitizer/lsan_interface.h",
"sanitizer/msan_interface.h",
"sanitizer/netbsd_syscall_hooks.h",
"sanitizer/scudo_interface.h",
"sanitizer/tsan_interface.h",
"sanitizer/tsan_interface_atomic.h",
"xray/xray_interface.h",
"xray/xray_log_interface.h",
"xray/xray_records.h",
]
outputs = [
"$clang_resource_dir/include/{{source_target_relative}}",
]
}

View File

@ -0,0 +1,10 @@
import("//clang/resource_dir.gni")
copy("blacklist") {
sources = [
"cfi_blacklist.txt",
]
outputs = [
"$clang_resource_dir/share/{{source_target_relative}}",
]
}

View File

@ -0,0 +1,79 @@
import("//compiler-rt/target.gni")
import("//compiler-rt/test/test.gni")
import("//llvm/triples.gni")
import("//llvm/utils/gn/build/toolchain/compiler.gni")
import("//llvm/utils/gn/build/write_cmake_config.gni")
import("//llvm/version.gni")
write_cmake_config("lit_common_configured") {
input = "lit.common.configured.in"
output = "$target_gen_dir/lit.common.configured"
values = [
"LIT_SITE_CFG_IN_HEADER=## Autogenerated from $input, do not edit",
"COMPILER_RT_DEFAULT_TARGET_TRIPLE=$llvm_current_triple",
"COMPILER_RT_DEFAULT_TARGET_ARCH=$crt_current_target_arch",
"COMPILER_RT_TEST_COMPILER_CFLAGS=$target_flags_string",
"LLVM_BUILD_MODE=.",
"LLVM_MAIN_SRC_DIR=" + rebase_path("//llvm"),
"LLVM_BINARY_DIR=" + rebase_path(root_build_dir),
"COMPILER_RT_SOURCE_DIR=" + rebase_path("//compiler-rt"),
# This is only used by tsan to find the path to an instrumented libc++.
# Since we don't currently support running the tsan tests, leave it empty
# for now. Eventually it should probably be replaced with some mechanism
# where the libraries are found in a toolchain dir.
"COMPILER_RT_BINARY_DIR=",
# We don't currently support the multiarch runtime layout.
"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR_PYBOOL=False",
"LLVM_TOOLS_DIR=" + rebase_path("$root_build_dir/bin"),
"LLVM_LIBRARY_OUTPUT_INTDIR=" + rebase_path("$root_build_dir/lib"),
"GOLD_EXECUTABLE=ld",
"COMPILER_RT_RESOLVED_TEST_COMPILER=" +
rebase_path("$root_build_dir/bin/clang"),
"COMPILER_RT_TEST_COMPILER_ID=Clang",
"PYTHON_EXECUTABLE=$python_path",
"COMPILER_RT_DEBUG_PYBOOL=False",
"COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR=" +
rebase_path(crt_current_out_dir),
"COMPILER_RT_EMULATOR=",
"COMPILER_RT_ASAN_SHADOW_SCALE=",
"SANITIZER_CAN_USE_CXXABI_PYBOOL=True",
"COMPILER_RT_HAS_LLD_PYBOOL=True",
"HAVE_RPC_XDR_H=0",
"ANDROID_SERIAL_FOR_TESTING=$android_serial_for_testing",
]
if (host_cpu == "x64") {
values += [ "HOST_ARCH=x86_64" ]
} else {
assert(false, "unimplemented host_cpu " + host_cpu)
}
if (host_os == "mac") {
values += [ "HOST_OS=Darwin" ]
} else if (host_os == "linux") {
values += [ "HOST_OS=Linux" ]
} else if (host_os == "win") {
values += [ "HOST_OS=Windows" ]
} else {
assert(false, "unsupported host_os " + host_os)
}
if (current_os != "win" || llvm_enable_dia_sdk) {
values += [ "CAN_SYMBOLIZE=1" ]
} else {
values += [ "CAN_SYMBOLIZE=0" ]
}
if (current_os == "android") {
values += [ "ANDROID_PYBOOL=True" ]
} else {
values += [ "ANDROID_PYBOOL=False" ]
}
}

View File

@ -0,0 +1,99 @@
import("//compiler-rt/target.gni")
import("//compiler-rt/test/test.gni")
import("//llvm/utils/gn/build/toolchain/compiler.gni")
import("//llvm/utils/gn/build/write_cmake_config.gni")
import("//llvm/version.gni")
write_cmake_config("lit_site_cfg") {
input = "lit.site.cfg.in"
output = "$target_gen_dir/lit.site.cfg"
values = [
"LIT_SITE_CFG_IN_HEADER=## Autogenerated from $input, do not edit",
"HWASAN_TEST_CONFIG_SUFFIX=-$crt_current_target",
"HWASAN_TEST_TARGET_CFLAGS=$target_flags_string",
"HWASAN_TEST_TARGET_ARCH=$crt_current_target_arch",
"COMPILER_RT_BINARY_DIR=" + rebase_path("$root_gen_dir/compiler-rt"),
"HWASAN_LIT_SOURCE_DIR=" + rebase_path("."),
]
if (current_os == "android") {
values += [ "HWASAN_ANDROID_FILES_TO_PUSH=[\"" + rebase_path(
"$crt_current_out_dir/libclang_rt.hwasan-$crt_current_target.so") + "\", \"" + rebase_path(
"$root_out_dir/bin/llvm-symbolizer") + "\"]" ]
} else {
values += [ "HWASAN_ANDROID_FILES_TO_PUSH=[]" ]
}
}
if (current_toolchain != host_toolchain) {
group("hwasan_toolchain") {
deps = [
":lit_site_cfg",
"//compiler-rt/include($host_toolchain)",
"//compiler-rt/lib/cfi:blacklist($host_toolchain)",
"//compiler-rt/lib/hwasan:hwasan_shared",
"//compiler-rt/test:lit_common_configured",
"//llvm/utils/FileCheck($host_toolchain)",
"//llvm/utils/llvm-lit($host_toolchain)",
"//llvm/utils/not($host_toolchain)",
]
# FIXME: Make the host use the stage2 llvm-symbolizer as well, for
# consistency. Currently lit.common.cfg sets up the sanitizer runtime to
# look for llvm-symbolizer in llvm_tools_dir, and also looks there for
# other tools which are built with the host toolchain.
if (current_os == host_os && current_cpu == host_cpu) {
deps += [ "//llvm/tools/llvm-symbolizer($host_toolchain)" ]
} else {
deps += [ "//llvm/tools/llvm-symbolizer" ]
}
}
}
supported_toolchains = []
if (host_os == "linux" && host_cpu == "x64") {
supported_toolchains += [ "//llvm/utils/gn/build/toolchain:stage2_unix" ]
}
if (android_ndk_path != "") {
supported_toolchains +=
[ "//llvm/utils/gn/build/toolchain:stage2_android_aarch64" ]
}
group("hwasan") {
deps = []
foreach(toolchain, supported_toolchains) {
deps += [ ":hwasan_toolchain($toolchain)" ]
}
}
if (supported_toolchains != []) {
action("check-hwasan") {
script = "$root_build_dir/bin/llvm-lit"
if (host_os == "win") {
script += ".py"
}
args = [ "-sv" ]
foreach(toolchain, supported_toolchains) {
args += [ rebase_path(
get_label_info(":lit_site_cfg($toolchain)", "target_gen_dir"),
root_build_dir) ]
}
outputs = [
"$target_gen_dir/run-lit", # Non-existing, so that ninja runs it each time.
]
# Since check-hwasan is always dirty, //:default doesn't depend on it so that
# it's not part of the default ninja target. Hence, check-hwasan shouldn't
# have any deps except :hwasan. so that the default target is sure to build
# all the deps.
deps = [
":hwasan",
]
testonly = true
pool = "//:console"
}
}

View File

@ -0,0 +1,16 @@
import("//llvm/utils/gn/build/toolchain/target_flags.gni")
declare_args() {
# Specifies the serial number of the Android device to be used for testing.
android_serial_for_testing = ""
}
target_flags_string = ""
foreach(flag,
target_flags + target_cflags + target_ldflags + [ "-fuse-ld=lld" ]) {
if (target_flags_string != "") {
target_flags_string += " "
}
target_flags_string += flag
}