CMakeLists.txt revision 8c6e4855ac47415f1f2863690860f24213638cb5
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  -Werror=sign-compare
40  -g
41  -O2)
42if(SUPPORTS_NO_VARIADIC_MACROS_FLAG)
43  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -Wno-variadic-macros)
44endif()
45
46# Use -D instead of definitions to please custom compile command.
47list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
48  -DASAN_HAS_BLACKLIST=1
49  -DASAN_HAS_EXCEPTIONS=1
50  -DASAN_UAR=0)
51if(ANDROID)
52  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
53    -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0
54    -DASAN_NEEDS_SEGV=0)
55else()
56  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
57    -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=1
58    -DASAN_NEEDS_SEGV=1)
59endif()
60
61set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
62set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
63  ${ASAN_UNITTEST_COMMON_CFLAGS}
64  -fsanitize=address
65  "-fsanitize-blacklist=${ASAN_BLACKLIST_FILE}"
66  -mllvm -asan-stack=1
67  -mllvm -asan-globals=1
68  -mllvm -asan-mapping-scale=0        # default will be used
69  -mllvm -asan-mapping-offset-log=-1  # default will be used
70)
71if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
72  list(APPEND ASAN_UNITTEST_INSTRUMENTED_CFLAGS
73    -fsanitize-address-zero-base-shadow)
74endif()
75
76# Unit tests require libstdc++.
77set(ASAN_UNITTEST_COMMON_LINKFLAGS -lstdc++)
78# Unit tests on Mac depend on Foundation.
79if(APPLE)
80  list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -framework Foundation)
81endif()
82if(ASAN_TESTS_USE_ZERO_BASE_SHADOW)
83  list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -pie)
84endif()
85
86set(ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS
87  ${ASAN_UNITTEST_COMMON_LINKFLAGS})
88# On Android, we link with ASan runtime manually. On other platforms we depend
89# on Clang driver behavior, passing -fsanitize=address flag.
90if(NOT ANDROID)
91  list(APPEND ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS -fsanitize=address)
92endif()
93
94set(ASAN_UNITTEST_NOINST_LINKFLAGS
95  ${ASAN_UNITTEST_COMMON_LINKFLAGS}
96  -ldl -lm)
97if(NOT ANDROID)
98  list(APPEND ASAN_UNITTEST_NOINST_LINKFLAGS -lpthread)
99endif()
100
101# Compile source for the given architecture, using compiler
102# options in ${ARGN}, and add it to the object list.
103macro(asan_compile obj_list source arch)
104  get_filename_component(basename ${source} NAME)
105  set(output_obj "${obj_list}.${basename}.${arch}.o")
106  get_target_flags_for_arch(${arch} TARGET_CFLAGS)
107  clang_compile(${output_obj} ${source}
108                CFLAGS ${ARGN} ${TARGET_CFLAGS}
109                DEPS gtest asan_runtime_libraries
110                           ${ASAN_UNITTEST_HEADERS}
111                           ${ASAN_BLACKLIST_FILE})
112  list(APPEND ${obj_list} ${output_obj})
113endmacro()
114
115# Link ASan unit test for a given architecture from a set
116# of objects in with given linker flags.
117macro(add_asan_test test_suite test_name arch)
118  parse_arguments(TEST "OBJECTS;LINKFLAGS" "WITH_TEST_RUNTIME" ${ARGN})
119  get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
120  set(TEST_DEPS asan_runtime_libraries ${TEST_OBJECTS})
121  if(TEST_WITH_TEST_RUNTIME)
122    list(APPEND TEST_DEPS ${ASAN_TEST_RUNTIME})
123    list(APPEND TEST_OBJECTS lib${ASAN_TEST_RUNTIME}.a)
124  endif()
125  add_compiler_rt_test(${test_suite} ${test_name}
126                       OBJECTS ${TEST_OBJECTS}
127                       DEPS ${TEST_DEPS}
128                       LINK_FLAGS ${TEST_LINKFLAGS}
129                                  ${TARGET_LINK_FLAGS})
130endmacro()
131
132# Main AddressSanitizer unit tests.
133add_custom_target(AsanUnitTests)
134set_target_properties(AsanUnitTests PROPERTIES FOLDER "ASan unit tests")
135# ASan benchmarks (not actively used now).
136add_custom_target(AsanBenchmarks)
137set_target_properties(AsanBenchmarks PROPERTIES FOLDER "Asan benchmarks")
138
139set(ASAN_NOINST_TEST_SOURCES
140  ${COMPILER_RT_GTEST_SOURCE}
141  asan_fake_stack_test.cc
142  asan_noinst_test.cc
143  asan_test_main.cc)
144
145set(ASAN_INST_TEST_SOURCES
146  ${COMPILER_RT_GTEST_SOURCE}
147  asan_globals_test.cc
148  asan_interface_test.cc
149  asan_test.cc
150  asan_oob_test.cc
151  asan_mem_test.cc
152  asan_str_test.cc
153  asan_test_main.cc)
154if(APPLE)
155  list(APPEND ASAN_INST_TEST_SOURCES asan_mac_test.cc)
156endif()
157
158set(ASAN_BENCHMARKS_SOURCES
159  ${COMPILER_RT_GTEST_SOURCE}
160  asan_benchmarks_test.cc)  
161
162# Adds ASan unit tests and benchmarks for architecture.
163macro(add_asan_tests_for_arch arch)
164  # Instrumented tests.
165  set(ASAN_INST_TEST_OBJECTS)
166  foreach(src ${ASAN_INST_TEST_SOURCES})
167    asan_compile(ASAN_INST_TEST_OBJECTS ${src} ${arch}
168                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
169  endforeach()
170  if (APPLE)
171    # Add Mac-specific helper.
172    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test_helpers.mm ${arch}
173                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -ObjC)
174  endif()
175  add_asan_test(AsanUnitTests "Asan-${arch}-Test" ${arch}
176                OBJECTS ${ASAN_INST_TEST_OBJECTS}
177                LINKFLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS})
178
179  # Add static ASan runtime that will be linked with uninstrumented tests.
180  set(ASAN_TEST_RUNTIME RTAsanTest.${arch})
181  if(APPLE)
182    set(ASAN_TEST_RUNTIME_OBJECTS
183      $<TARGET_OBJECTS:RTAsan.osx>
184      $<TARGET_OBJECTS:RTInterception.osx>
185      $<TARGET_OBJECTS:RTSanitizerCommon.osx>
186      $<TARGET_OBJECTS:RTLSanCommon.osx>)
187  else()
188    set(ASAN_TEST_RUNTIME_OBJECTS
189      $<TARGET_OBJECTS:RTAsan.${arch}>
190      $<TARGET_OBJECTS:RTInterception.${arch}>
191      $<TARGET_OBJECTS:RTLSanCommon.${arch}>
192      $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
193      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
194  endif()
195  add_library(${ASAN_TEST_RUNTIME} STATIC ${ASAN_TEST_RUNTIME_OBJECTS})
196  set_target_properties(${ASAN_TEST_RUNTIME} PROPERTIES
197    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
198  # Uninstrumented tests.
199  set(ASAN_NOINST_TEST_OBJECTS)
200  foreach(src ${ASAN_NOINST_TEST_SOURCES})
201    asan_compile(ASAN_NOINST_TEST_OBJECTS ${src} ${arch}
202                 ${ASAN_UNITTEST_COMMON_CFLAGS})
203  endforeach()
204  add_asan_test(AsanUnitTests "Asan-${arch}-Noinst-Test" ${arch}
205                OBJECTS ${ASAN_NOINST_TEST_OBJECTS}
206                LINKFLAGS ${ASAN_UNITTEST_NOINST_LINKFLAGS}
207                WITH_TEST_RUNTIME)
208
209  # Benchmarks.
210  set(ASAN_BENCHMARKS_OBJECTS)
211  foreach(src ${ASAN_BENCHMARKS_SOURCES})
212    asan_compile(ASAN_BENCHMARKS_OBJECTS ${src} ${arch}
213                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
214  endforeach()
215  add_asan_test(AsanBenchmarks "Asan-${arch}-Benchmark" ${arch}
216                OBJECTS ${ASAN_BENCHMARKS_OBJECTS}
217                LINKFLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS})
218endmacro()
219
220if(COMPILER_RT_CAN_EXECUTE_TESTS)
221  foreach(arch ${ASAN_SUPPORTED_ARCH})
222    add_asan_tests_for_arch(${arch})
223  endforeach()
224endif()
225
226if(ANDROID)
227  # We assume that unit tests on Android are built in a build
228  # tree with fresh Clang as a host compiler.
229  
230  # Test w/o ASan instrumentation. Link it with ASan statically.
231  add_executable(AsanNoinstTest
232    $<TARGET_OBJECTS:RTAsan.arm.android>
233    $<TARGET_OBJECTS:RTInterception.arm.android>
234    $<TARGET_OBJECTS:RTSanitizerCommon.arm.android>
235    ${COMPILER_RT_GTEST_SOURCE}
236    ${ASAN_NOINST_TEST_SOURCES})
237  set_target_compile_flags(AsanNoinstTest ${ASAN_UNITTEST_COMMON_CFLAGS})
238  set_target_link_flags(AsanNoinstTest ${ASAN_UNITTEST_NOINST_LINKFLAGS})
239
240  # Test with ASan instrumentation. Link with ASan dynamic runtime.
241  add_executable(AsanTest
242    ${COMPILER_RT_GTEST_SOURCE}
243    ${ASAN_INST_TEST_SOURCES})
244  set_target_compile_flags(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
245  set_target_link_flags(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_LINKFLAGS})
246  target_link_libraries(AsanTest clang_rt.asan-arm-android)
247
248  # Setup correct output directory and link flags.
249  set_target_properties(AsanNoinstTest AsanTest PROPERTIES
250    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
251  # Add unit test to test suite.
252  add_dependencies(AsanUnitTests AsanNoinstTest AsanTest)
253endif()
254