-
Notifications
You must be signed in to change notification settings - Fork 5
/
SanitizeTargets.cmake
148 lines (139 loc) · 7.27 KB
/
SanitizeTargets.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Runtime analysis using Clang sanitization flags.
option(SWIFT_SANITIZE_ADDRESS "Enable address sanitizer." OFF)
option(SWIFT_SANITIZE_LEAK "Enable leak sanitizer." OFF)
option(SWIFT_SANITIZE_MEMORY "Enable memory sanitizer." OFF)
option(SWIFT_SANITIZE_THREAD "Enable thread sanitizer." OFF)
option(SWIFT_SANITIZE_UNDEFINED "Enable undefined behavior sanitizer." OFF)
option(SWIFT_SANITIZE_DATAFLOW "Enable dataflow sanitizer." OFF)
option(SWIFT_SANITIZE_DISABLE_SUPPRESSION "Disable suppression of checks." OFF)
if (SWIFT_SANITIZE_ADDRESS OR
SWIFT_SANITIZE_LEAK OR
SWIFT_SANITIZE_MEMORY OR
SWIFT_SANITIZE_THREAD OR
SWIFT_SANITIZE_UNDEFINED OR
SWIFT_SANITIZE_DATAFLOW)
set(_SWIFT_SANITIZE TRUE)
else ()
set(_SWIFT_SANITIZE FALSE)
endif()
# Some of these options can't be used simultaneously.
#
if (SWIFT_SANITIZE_ADDRESS AND SWIFT_SANITIZE_MEMORY )
message(WARNING "Can't -fsanitize address/memory simultaneously.")
endif ()
if (SWIFT_SANITIZE_MEMORY AND SWIFT_SANITIZE_THREAD )
message(WARNING "Can't -fsanitize memory/thread simultaneously.")
endif ()
if (SWIFT_SANITIZE_ADDRESS AND SWIFT_SANITIZE_THREAD )
message(WARNING "Can't -fsanitize address/thread simultaneously.")
endif ()
# Instantiate C/C++ and C++-specific flags.
#
set(SWIFT_SANITIZE_FLAGS "")
# Dispatch sanitizer options based on compiler.
#
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# See http://clang.llvm.org/docs and
# http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
# for more details.
set(SWIFT_SANITIZE_FLAGS "-g -fno-omit-frame-pointer -Wno-error=disabled-optimization")
if (SWIFT_SANITIZE_ADDRESS)
message(STATUS "Enabling address sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=address")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fno-optimize-sibling-calls")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-address-use-after-scope")
elseif (SWIFT_SANITIZE_MEMORY)
message(STATUS "Enabling memory sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=memory")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fno-optimize-sibling-calls")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-memory-track-origins=2")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-memory-use-after-dtor")
elseif (SWIFT_SANITIZE_THREAD)
message(STATUS "Enabling thread sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=thread")
endif ()
if (SWIFT_SANITIZE_LEAK)
message(STATUS "Enabling leak sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=leak")
endif ()
if (SWIFT_SANITIZE_UNDEFINED)
message(STATUS "Enabling undefined behavior sanitizer.")
# The `vptr` sanitizer won't work with `-fno-rtti`.
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=undefined -fno-sanitize=vptr")
endif ()
if (_SWIFT_SANITIZE)
# Suppression files are supported at build time only by clang, not GCC.
if (NOT DEFINED SWIFT_SANITIZE_SUPPRESSION_FILE)
if (EXISTS "${PROJECT_ROOT}/sanitizers.supp")
set(SWIFT_SANITIZE_SUPPRESSION_FILE "${PROJECT_ROOT}/sanitizers.supp")
endif()
endif ()
endif()
# According to the clang docs, we have to pass this file at build
# time; the sanitizers that support runtime suppression can only use
# it for third-party code that's not been built with sanitizer support
# (https://clang.llvm.org/docs/AddressSanitizer.html#suppressing-errors-in-recompiled-code-ignorelist).
# We build all our code, including third-party libraries, so we cannot
# simply pass a file in an environment variable
# (https://clang.llvm.org/docs/AddressSanitizer.html#suppressing-reports-in-external-libraries).
#
# The docs for the sanitizers don't seem to be complete or maintained,
# though, nor is behavior consistent between different sanitizers, so
# this theory could all be wrong!
#
# TODO(@peddie): I'm not sure how to make all targets that use this
# depend on the suppression file contents.
if (_SWIFT_SANITIZE AND NOT SWIFT_SANITIZE_DISABLE_SUPPRESSION AND (DEFINED SWIFT_SANITIZE_SUPPRESSION_FILE))
message(STATUS "Building with sanitizer ignore list ${SWIFT_SANITIZE_SUPPRESSION_FILE}")
message(" Note that this file is NOT CORRECTLY TRACKED as a dependency; if you modify its contents, you will have to force recompilation some other way.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-ignorelist=${SWIFT_SANITIZE_SUPPRESSION_FILE}")
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8)
# See: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
#
# We seem to need `-fuse-ld=gold` on Travis.
set(SWIFT_SANITIZE_FLAGS "-g3 -fno-omit-frame-pointer")
if (SWIFT_SANITIZE_ADDRESS)
message(STATUS "Enabling address sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=address")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-address-use-after-scope")
elseif (SWIFT_SANITIZE_MEMORY)
message(STATUS "Enabling memory sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=memory")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-memory-track-origins=2")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-memory-use-after-dtor")
elseif (SWIFT_SANITIZE_THREAD)
message(STATUS "Enabling thread sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=thread")
elseif (SWIFT_SANITIZE_LEAK)
message(STATUS "Enabling leak sanitizer.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=leak")
endif ()
if (SWIFT_SANITIZE_UNDEFINED)
message(STATUS "Enabling undefined behavior sanitizer.")
# TODO(@peddie): how can we pass `-fno-sanitize=vptr` only when
# RTTI is disabled? Albatross unit tests, for example, use RTTI.
#
# The `vptr` sanitizer won't work with `-fno-rtti`.
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize=undefined -fno-sanitize=vptr")
endif ()
if (_SWIFT_SANITIZE)
if(DEFINED SWIFT_SANITIZE_SUPPRESSION_FILE)
message(WARNING "You are compiling with GCC, which does not support masking of sanitizer issues via `-fsanitize-ignorelist=`.")
message(WARNING "If you don't want the issues in ${SWIFT_SANITIZE_SUPPRESSION_FILE} to be flagged, please build with clang instead.")
endif()
endif()
else ()
message(FATAL_ERROR "Oh noes! We don't support your compiler.")
endif ()
if (_SWIFT_SANITIZE)
message(STATUS "Enabling runtime analysis sanitizers!")
message(" Consider the appropriate runtime options for your sanitizer(s):")
message(" https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags")
message(" https://github.com/google/sanitizers/wiki/SanitizerCommonFlags")
message(" e.g.: ASAN_OPTIONS=check_initialization_order=true:detect_stack_use_after_return=true:strict_string_checks=true:halt_on_error=false")
message(" You may also specify SWIFT_SANITIZE_SUPPRESSION_FILE to mask known errors.")
set(SWIFT_SANITIZE_FLAGS "${SWIFT_SANITIZE_FLAGS} -fsanitize-recover=all")
endif ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SWIFT_SANITIZE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SWIFT_SANITIZE_FLAGS}")