1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import("//build/config/chrome_build.gni") 6import("//build/config/chromecast_build.gni") 7import("//build/config/sanitizers/sanitizers.gni") 8import("//build/toolchain/toolchain.gni") 9 10# Contains the dependencies needed for sanitizers to link into executables and 11# shared_libraries. Unconditionally depend upon this target as it is empty if 12# |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false. 13group("deps") { 14 deps = [ 15 ":deps_no_options", 16 ] 17 if (using_sanitizer) { 18 public_configs = [ 19 ":sanitizer_options_link_helper", 20 21 # Even when a target removes default_sanitizer_flags, it may be depending 22 # on a library that did not remove default_sanitizer_flags. Thus, we need 23 # to add the ldflags here as well as in default_sanitizer_flags. 24 ":default_sanitizer_ldflags", 25 ] 26 deps += [ ":options_sources" ] 27 } 28} 29 30group("deps_no_options") { 31 if (using_sanitizer) { 32 public_configs = [ 33 # Even when a target removes default_sanitizer_flags, it may be depending 34 # on a library that did not remove default_sanitizer_flags. Thus, we need 35 # to add the ldflags here as well as in default_sanitizer_flags. 36 ":default_sanitizer_ldflags", 37 ] 38 deps = [] 39 if (use_prebuilt_instrumented_libraries) { 40 deps += [ "//third_party/instrumented_libraries:deps" ] 41 } 42 if (use_custom_libcxx) { 43 deps += [ "//buildtools/third_party/libc++:libcxx_proxy" ] 44 } 45 if (is_mac) { 46 data_deps = [ 47 ":copy_asan_runtime", 48 ] 49 } 50 } 51} 52 53if (is_mac) { 54 copy("copy_asan_runtime") { 55 sources = [ 56 "//third_party/llvm-build/Release+Asserts/lib/clang/$clang_version/lib/darwin/libclang_rt.asan_osx_dynamic.dylib", 57 ] 58 outputs = [ 59 "$root_out_dir/{{source_file_part}}", 60 ] 61 } 62} 63 64config("sanitizer_options_link_helper") { 65 if (is_mac) { 66 ldflags = [ "-Wl,-U,_sanitizer_options_link_helper" ] 67 } else if (!is_win) { 68 ldflags = [ "-Wl,-u_sanitizer_options_link_helper" ] 69 } 70} 71 72static_library("options_sources") { 73 # This is a static_library instead of a source_set, as it shouldn't be 74 # unconditionally linked into targets. 75 visibility = [ 76 ":deps", 77 "//:gn_visibility", 78 ] 79 sources = [ 80 "//build/sanitizers/sanitizer_options.cc", 81 ] 82 83 # Don't compile this target with any sanitizer code. It can be called from 84 # the sanitizer runtimes, so instrumenting these functions could cause 85 # recursive calls into the runtime if there is an error. 86 configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ] 87 88 if (is_asan) { 89 sources += [ "//build/sanitizers/asan_suppressions.cc" ] 90 } 91 92 if (is_lsan) { 93 sources += [ "//build/sanitizers/lsan_suppressions.cc" ] 94 } 95 96 if (is_tsan) { 97 sources += [ "//build/sanitizers/tsan_suppressions.cc" ] 98 } 99} 100 101# Applies linker flags necessary when either :deps or :default_sanitizer_flags 102# are used. 103config("default_sanitizer_ldflags") { 104 visibility = [ 105 ":default_sanitizer_flags", 106 ":deps", 107 ] 108 109 if (is_posix) { 110 ldflags = [] 111 if (is_asan) { 112 ldflags += [ "-fsanitize=address" ] 113 } 114 if (is_lsan) { 115 ldflags += [ "-fsanitize=leak" ] 116 } 117 if (is_tsan) { 118 ldflags += [ "-fsanitize=thread" ] 119 } 120 if (is_msan) { 121 ldflags += [ "-fsanitize=memory" ] 122 } 123 if (is_ubsan || is_ubsan_security) { 124 ldflags += [ "-fsanitize=undefined" ] 125 } 126 if (is_ubsan_vptr) { 127 ldflags += [ "-fsanitize=vptr" ] 128 } 129 130 if (is_cfi && !is_nacl) { 131 ldflags += [ 132 "-fsanitize=cfi-vcall", 133 "-fsanitize=cfi-derived-cast", 134 "-fsanitize=cfi-unrelated-cast", 135 ] 136 if (use_cfi_diag) { 137 ldflags += [ 138 "-fno-sanitize-trap=cfi", 139 "-fsanitize-recover=cfi", 140 ] 141 } 142 } 143 } 144} 145 146config("common_sanitizer_flags") { 147 cflags = [] 148 cflags_cc = [] 149 150 # Sanitizers need line table info for stack traces. They don't need type info 151 # or variable info, so we can leave that out to speed up the build. 152 if (using_sanitizer) { 153 assert(is_clang, "sanitizers only supported with clang") 154 cflags += [ "-gline-tables-only" ] 155 } 156 157 # Common options for AddressSanitizer, LeakSanitizer, ThreadSanitizer, 158 # MemorySanitizer and non-official CFI builds. 159 if (using_sanitizer || (is_cfi && !is_official_build)) { 160 if (is_posix) { 161 cflags += [ "-fno-omit-frame-pointer" ] 162 } else { 163 cflags += [ "/Oy-" ] 164 } 165 } 166 167 if (use_custom_libcxx) { 168 prefix = "//buildtools/third_party" 169 include = "trunk/include" 170 cflags_cc += [ 171 "-nostdinc++", 172 "-isystem" + rebase_path("$prefix/libc++/$include", root_build_dir), 173 "-isystem" + rebase_path("$prefix/libc++abi/$include", root_build_dir), 174 ] 175 } 176} 177 178config("asan_flags") { 179 cflags = [] 180 if (is_asan) { 181 cflags += [ "-fsanitize=address" ] 182 if (is_win) { 183 cflags += [ "-fsanitize-blacklist=" + 184 rebase_path("//tools/memory/asan/blacklist_win.txt", 185 root_build_dir) ] 186 } else { 187 # TODO(rnk): Remove this as discussed in http://crbug.com/427202. 188 cflags += 189 [ "-fsanitize-blacklist=" + 190 rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir) ] 191 } 192 if (is_android) { 193 # Android build relies on -Wl,--gc-sections removing unreachable code. 194 # ASan instrumentation for globals inhibits this and results in a 195 # library with unresolvable relocations. 196 # TODO(eugenis): find a way to reenable this. 197 cflags += [ 198 "-mllvm", 199 "-asan-globals=0", 200 ] 201 } else if (is_mac) { 202 # http://crbug.com/352073 203 cflags += [ 204 "-mllvm", 205 "-asan-globals=0", 206 ] 207 # TODO(GYP): deal with mac_bundles. 208 } else if (is_win) { 209 assert(target_cpu == "x86", "WinASan is 32-bit only currently") 210 if (is_component_build) { 211 libs = [ 212 "clang_rt.asan_dynamic-i386.lib", 213 "clang_rt.asan_dynamic_runtime_thunk-i386.lib", 214 ] 215 } else { 216 # TODO(rnk): DLLs in the non-component build should link against 217 # clang_rt.asan_dll_thunk-i386.lib instead. 218 libs = [ "clang_rt.asan-i386.lib" ] 219 } 220 } 221 } 222} 223 224config("cfi_flags") { 225 cflags = [] 226 if (is_cfi && !is_nacl) { 227 cfi_blacklist_path = 228 rebase_path("//tools/cfi/blacklist.txt", root_build_dir) 229 cflags += [ 230 "-fsanitize=cfi-vcall", 231 "-fsanitize=cfi-derived-cast", 232 "-fsanitize=cfi-unrelated-cast", 233 "-fsanitize-blacklist=$cfi_blacklist_path", 234 ] 235 236 if (use_cfi_diag) { 237 cflags += [ 238 "-fno-sanitize-trap=cfi", 239 "-fsanitize-recover=cfi", 240 "-fno-inline-functions", 241 "-fno-inline", 242 "-fno-omit-frame-pointer", 243 "-O1", 244 ] 245 } else { 246 defines = [ "CFI_ENFORCEMENT" ] 247 } 248 } 249} 250 251config("coverage_flags") { 252 cflags = [] 253 254 if (use_sanitizer_coverage) { 255 cflags += [ 256 "-fsanitize-coverage=$sanitizer_coverage_flags", 257 "-mllvm", 258 "-sanitizer-coverage-prune-blocks=1", 259 ] 260 if (target_cpu == "arm") { 261 # http://crbug.com/517105 262 cflags += [ 263 "-mllvm", 264 "-sanitizer-coverage-block-threshold=0", 265 ] 266 } 267 defines = [ "SANITIZER_COVERAGE" ] 268 } 269} 270 271config("lsan_flags") { 272 if (is_lsan) { 273 cflags = [ "-fsanitize=leak" ] 274 } 275} 276 277config("msan_flags") { 278 if (is_msan) { 279 assert(is_linux, "msan only supported on linux x86_64") 280 msan_blacklist_path = 281 rebase_path("//tools/msan/blacklist.txt", root_build_dir) 282 cflags = [ 283 "-fsanitize=memory", 284 "-fsanitize-memory-track-origins=$msan_track_origins", 285 "-fsanitize-blacklist=$msan_blacklist_path", 286 ] 287 } 288} 289 290config("tsan_flags") { 291 if (is_tsan) { 292 assert(is_linux, "tsan only supported on linux x86_64") 293 tsan_blacklist_path = 294 rebase_path("//tools/memory/tsan_v2/ignores.txt", root_build_dir) 295 cflags = [ 296 "-fsanitize=thread", 297 "-fsanitize-blacklist=$tsan_blacklist_path", 298 ] 299 } 300} 301 302config("ubsan_flags") { 303 cflags = [] 304 if (is_ubsan) { 305 ubsan_blacklist_path = 306 rebase_path("//tools/ubsan/blacklist.txt", root_build_dir) 307 cflags += [ 308 # Yasm dies with an "Illegal instruction" error when bounds checking is 309 # enabled. See http://crbug.com/489901 310 # "-fsanitize=bounds", 311 "-fsanitize=float-divide-by-zero", 312 "-fsanitize=integer-divide-by-zero", 313 "-fsanitize=null", 314 "-fsanitize=object-size", 315 "-fsanitize=return", 316 "-fsanitize=returns-nonnull-attribute", 317 "-fsanitize=shift-exponent", 318 "-fsanitize=signed-integer-overflow", 319 "-fsanitize=unreachable", 320 "-fsanitize=vla-bound", 321 "-fsanitize-blacklist=$ubsan_blacklist_path", 322 ] 323 324 # Chromecast ubsan builds fail to compile with these 325 # experimental flags, so only add them to non-chromecast ubsan builds. 326 if (!is_chromecast) { 327 cflags += [ 328 # Employ the experimental PBQP register allocator to avoid slow 329 # compilation on files with too many basic blocks. 330 # See http://crbug.com/426271. 331 "-mllvm", 332 "-regalloc=pbqp", 333 334 # Speculatively use coalescing to slightly improve the code generated 335 # by PBQP regallocator. May increase compile time. 336 "-mllvm", 337 "-pbqp-coalescing", 338 ] 339 } 340 } 341} 342 343config("ubsan_no_recover") { 344 if (is_ubsan_no_recover) { 345 cflags = [ "-fno-sanitize-recover=undefined" ] 346 } 347} 348 349config("ubsan_security_flags") { 350 if (is_ubsan_security) { 351 ubsan_blacklist_path = 352 rebase_path("//tools/ubsan/blacklist.txt", root_build_dir) 353 cflags = [ 354 "-fsanitize=signed-integer-overflow,shift", 355 "-fsanitize-blacklist=$ubsan_blacklist_path", 356 ] 357 } 358} 359 360config("ubsan_vptr_flags") { 361 if (is_ubsan_vptr) { 362 ubsan_vptr_blacklist_path = 363 rebase_path("//tools/ubsan/vptr_blacklist.txt", root_build_dir) 364 cflags = [ 365 "-fsanitize=vptr", 366 "-fsanitize-blacklist=$ubsan_vptr_blacklist_path", 367 ] 368 } 369} 370 371all_sanitizer_configs = [ 372 ":common_sanitizer_flags", 373 ":coverage_flags", 374 ":default_sanitizer_ldflags", 375 ":asan_flags", 376 ":cfi_flags", 377 ":lsan_flags", 378 ":msan_flags", 379 ":tsan_flags", 380 ":ubsan_flags", 381 ":ubsan_no_recover", 382 ":ubsan_security_flags", 383 ":ubsan_vptr_flags", 384] 385 386# This config is applied by default to all targets. It sets the compiler flags 387# for sanitizer usage, or, if no sanitizer is set, does nothing. 388# 389# This needs to be in a separate config so that targets can opt out of 390# sanitizers (by removing the config) if they desire. Even if a target 391# removes this config, executables & shared libraries should still depend on 392# :deps if any of their dependencies have not opted out of sanitizers. 393# Keep this list in sync with default_sanitizer_flags_but_ubsan_vptr. 394config("default_sanitizer_flags") { 395 configs = all_sanitizer_configs 396} 397 398# This config is equivalent to default_sanitizer_flags, but excludes ubsan_vptr. 399# This allows to selectively disable ubsan_vptr, when needed. In particular, 400# if some third_party code is required to be compiled without rtti, which 401# is a requirement for ubsan_vptr. 402config("default_sanitizer_flags_but_ubsan_vptr") { 403 configs = all_sanitizer_configs - [ ":ubsan_vptr_flags" ] 404} 405 406config("default_sanitizer_flags_but_coverage") { 407 configs = all_sanitizer_configs - [ ":coverage_flags" ] 408} 409