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