1# Testing rules for AddressSanitizer.
2#
3# These are broken into two buckets. One set of tests directly interacts with
4# the runtime library and checks its functionality. These are the
5# no-instrumentation tests.
6#
7# Another group of tests relies upon the ability to compile the test with
8# address sanitizer instrumentation pass. These tests form "integration" tests
9# and have some elements of version skew -- they test the *host* compiler's
10# instrumentation against the just-built runtime library.
11
12include(CheckCXXCompilerFlag)
13include(CompilerRTCompile)
14
15include_directories(..)
16include_directories(../..)
17
18# Use zero-based shadow on Android.
19if(ANDROID)
20  set(ASAN_TESTS_USE_ZERO_BASE_SHADOW TRUE)
21else()
22  set(ASAN_TESTS_USE_ZERO_BASE_SHADOW FALSE)
23endif()
24
25set(ASAN_UNITTEST_HEADERS
26  asan_mac_test.h
27  asan_test_config.h
28  asan_test_utils.h)
29
30set(ASAN_UNITTEST_COMMON_CFLAGS
31  ${COMPILER_RT_GTEST_INCLUDE_CFLAGS}
32  -I${COMPILER_RT_SOURCE_DIR}/include
33  -I${COMPILER_RT_SOURCE_DIR}/lib
34  -I${COMPILER_RT_SOURCE_DIR}/lib/asan
35  -I${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/tests
36  -Wall
37  -Wno-format
38  -Werror
39  -g
40  -O2
41)
42
43if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
44  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -fPIE)
45endif()
46if(SUPPORTS_NO_VARIADIC_MACROS_FLAG)
47  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -Wno-variadic-macros)
48endif()
49
50# Use -D instead of definitions to please custom compile command.
51list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
52  -DASAN_HAS_BLACKLIST=1
53  -DASAN_HAS_EXCEPTIONS=1
54  -DASAN_UAR=0)
55if(ANDROID)
56  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
57    -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0
58    -DASAN_NEEDS_SEGV=0)
59else()
60  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
61    -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=1
62    -DASAN_NEEDS_SEGV=1)
63endif()
64
65set(ASAN_LINK_FLAGS)
66if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
67  list(APPEND ASAN_LINK_FLAGS -pie)
68endif()
69# On Android, we link with ASan runtime manually. On other platforms we depend
70# on Clang driver behavior, passing -fsanitize=address flag.
71if(NOT ANDROID)
72  list(APPEND ASAN_LINK_FLAGS -fsanitize=address)
73endif()
74# Unit tests on Mac depend on Foundation.
75if(APPLE)
76  list(APPEND ASAN_LINK_FLAGS -framework Foundation)
77endif()
78# Unit tests require libstdc++.
79list(APPEND ASAN_LINK_FLAGS -lstdc++)
80
81set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
82
83set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
84  ${ASAN_UNITTEST_COMMON_CFLAGS}
85  -fsanitize=address
86  "-fsanitize-blacklist=${ASAN_BLACKLIST_FILE}"
87  -mllvm -asan-stack=1
88  -mllvm -asan-globals=1
89  -mllvm -asan-mapping-scale=0        # default will be used
90  -mllvm -asan-mapping-offset-log=-1  # default will be used
91  -mllvm -asan-use-after-return=0
92)
93if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
94  list(APPEND ASAN_UNITTEST_INSTRUMENTED_CFLAGS
95    -fsanitize-address-zero-base-shadow)
96endif()
97
98# Compile source for the given architecture, using compiler
99# options in ${ARGN}, and add it to the object list.
100macro(asan_compile obj_list source arch)
101  get_filename_component(basename ${source} NAME)
102  set(output_obj "${basename}.${arch}.o")
103  get_target_flags_for_arch(${arch} TARGET_CFLAGS)
104  clang_compile(${output_obj} ${source}
105                CFLAGS ${ARGN} ${TARGET_CFLAGS}
106                DEPS gtest ${ASAN_RUNTIME_LIBRARIES}
107                           ${ASAN_UNITTEST_HEADERS}
108                           ${ASAN_BLACKLIST_FILE})
109  list(APPEND ${obj_list} ${output_obj})
110endmacro()
111
112# Link ASan unit test for a given architecture from a set
113# of objects in ${ARGN}.
114macro(add_asan_test test_suite test_name arch)
115  get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
116  add_compiler_rt_test(${test_suite} ${test_name}
117                       OBJECTS ${ARGN}
118                       DEPS ${ASAN_RUNTIME_LIBRARIES} ${ARGN}
119                       LINK_FLAGS ${ASAN_LINK_FLAGS}
120                                  ${TARGET_LINK_FLAGS})
121endmacro()
122
123# Main AddressSanitizer unit tests.
124add_custom_target(AsanUnitTests)
125set_target_properties(AsanUnitTests PROPERTIES FOLDER "ASan unit tests")
126# ASan benchmarks (not actively used now).
127add_custom_target(AsanBenchmarks)
128set_target_properties(AsanBenchmarks PROPERTIES FOLDER "Asan benchmarks")
129
130set(ASAN_NOINST_TEST_SOURCES
131  asan_noinst_test.cc
132  asan_test_main.cc)
133set(ASAN_INST_TEST_SOURCES
134  asan_globals_test.cc
135  asan_test.cc
136  asan_oob_test.cc
137  asan_mem_test.cc
138  asan_str_test.cc)
139
140# Adds ASan unit tests and benchmarks for architecture.
141macro(add_asan_tests_for_arch arch)
142  # Build gtest instrumented with ASan.
143  set(ASAN_INST_GTEST)
144  asan_compile(ASAN_INST_GTEST ${COMPILER_RT_GTEST_SOURCE} ${arch} 
145                               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
146  # Instrumented tests.
147  set(ASAN_INST_TEST_OBJECTS)
148  foreach(src ${ASAN_INST_TEST_SOURCES})
149    asan_compile(ASAN_INST_TEST_OBJECTS ${src} ${arch}
150                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
151  endforeach()
152  # Add Mac-specific tests.
153  if (APPLE)
154    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test.cc ${arch}
155                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
156    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test_helpers.mm ${arch}
157                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -ObjC)
158  endif()
159  # Uninstrumented tests.
160  set(ASAN_NOINST_TEST_OBJECTS)
161  foreach(src ${ASAN_NOINST_TEST_SOURCES})
162    asan_compile(ASAN_NOINST_TEST_OBJECTS ${src} ${arch}
163                 ${ASAN_UNITTEST_COMMON_CFLAGS})
164  endforeach()
165  # Link everything together.
166  add_asan_test(AsanUnitTests "Asan-${arch}-Test" ${arch}
167                ${ASAN_NOINST_TEST_OBJECTS}
168                ${ASAN_INST_TEST_OBJECTS} ${ASAN_INST_GTEST})
169
170  # Instrumented benchmarks.
171  set(ASAN_BENCHMARKS_OBJECTS)
172  asan_compile(ASAN_BENCHMARKS_OBJECTS asan_benchmarks_test.cc ${arch}
173               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
174  # Link benchmarks.
175  add_asan_test(AsanBenchmarks "Asan-${arch}-Benchmark" ${arch}
176                ${ASAN_BENCHMARKS_OBJECTS} ${ASAN_INST_GTEST})
177endmacro()
178
179if(COMPILER_RT_CAN_EXECUTE_TESTS)
180  foreach(arch ${ASAN_SUPPORTED_ARCH})
181    add_asan_tests_for_arch(${arch})
182  endforeach()
183endif()
184
185if(ANDROID)
186  # We assume that unit tests on Android are built in a build
187  # tree with fresh Clang as a host compiler.
188  add_library(asan_noinst_test OBJECT ${ASAN_NOINST_TEST_SOURCES})
189  set_target_compile_flags(asan_noinst_test ${ASAN_UNITTEST_COMMON_CFLAGS})
190  add_library(asan_inst_test OBJECT
191              ${ASAN_INST_TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE})  
192  set_target_compile_flags(asan_inst_test ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
193  add_executable(AsanTest
194    $<TARGET_OBJECTS:asan_noinst_test>
195    $<TARGET_OBJECTS:asan_inst_test>
196  )
197  # Setup correct output directory and link flags.
198  set_target_properties(AsanTest PROPERTIES
199    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
200  set_target_link_flags(AsanTest ${ASAN_LINK_FLAGS})
201  target_link_libraries(AsanTest clang_rt.asan-arm-android)
202  # Add unit test to test suite.
203  add_dependencies(AsanUnitTests AsanTest)
204endif()
205