1# Copyright 2015 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/coverage/coverage.gni") 6import("//build/toolchain/toolchain.gni") 7 8declare_args() { 9 # Compile for Address Sanitizer to find memory bugs. 10 is_asan = false 11 12 # Customize asan detection. 13 asan_detector = false 14 15 # Compile for Leak Sanitizer to find leaks. 16 is_lsan = false 17 18 # Compile for Memory Sanitizer to find uninitialized reads. 19 is_msan = false 20 21 # Compile for Thread Sanitizer to find threading bugs. 22 is_tsan = false 23 24 # Compile for Undefined Behavior Sanitizer to find various types of 25 # undefined behavior (excludes vptr checks). 26 is_ubsan = false 27 28 # Halt the program if a problem is detected. 29 is_ubsan_no_recover = false 30 31 # Compile for Undefined Behavior Sanitizer's null pointer checks. 32 is_ubsan_null = false 33 34 # Compile for Undefined Behavior Sanitizer's vptr checks. 35 is_ubsan_vptr = false 36 37 # Compile with SafeStack shadow stack support. 38 is_safestack = false 39 40 # Track where uninitialized memory originates from. From fastest to slowest: 41 # 0 - no tracking, 1 - track only the initial allocation site, 2 - track the 42 # chain of stores leading from allocation site to use site. 43 msan_track_origins = 2 44 45 # Use dynamic libraries instrumented by one of the sanitizers instead of the 46 # standard system libraries. Set this flag to download prebuilt binaries from 47 # GCS. 48 use_prebuilt_instrumented_libraries = false 49 50 # Use dynamic libraries instrumented by one of the sanitizers instead of the 51 # standard system libraries. Set this flag to build the libraries from source. 52 use_locally_built_instrumented_libraries = false 53 54 # Compile with Control Flow Integrity to protect virtual calls and casts. 55 # See http://clang.llvm.org/docs/ControlFlowIntegrity.html 56 is_cfi = target_os == "linux" && !is_chromeos && target_cpu == "x64" && 57 is_official_build 58 59 # Enable checks for bad casts: derived cast and unrelated cast. 60 use_cfi_cast = false 61 62 # Enable checks for indirect function calls via a function pointer. 63 use_cfi_icall = target_os == "linux" && !is_chromeos && target_cpu == "x64" && 64 is_official_build 65 66 # Print detailed diagnostics when Control Flow Integrity detects a violation. 67 use_cfi_diag = false 68 69 # Let Control Flow Integrity continue execution instead of crashing when 70 # printing diagnostics (use_cfi_diag = true). 71 use_cfi_recover = false 72 73 # Compile for fuzzing with LLVM LibFuzzer. 74 # See http://www.chromium.org/developers/testing/libfuzzer 75 use_libfuzzer = false 76 77 # Compile for fuzzing with AFL. 78 use_afl = false 79 80 # Enables core ubsan security features. Will later be removed once it matches 81 # is_ubsan. 82 is_ubsan_security = false 83 84 # Compile for fuzzing with Dr. Fuzz 85 # See http://www.chromium.org/developers/testing/dr-fuzz 86 use_drfuzz = false 87 88 # Helper variable for testing builds with disabled libfuzzer. 89 # Not for client use. 90 disable_libfuzzer = false 91 92 # Optimize for coverage guided fuzzing (balance between speed and number of 93 # branches). Can be also used to remove non-determinism and other issues. 94 optimize_for_fuzzing = false 95 96 # Value for -fsanitize-coverage flag. Setting this causes 97 # use_sanitizer_coverage to be enabled. 98 # This flag is not used for libFuzzer (use_libfuzzer=true) unless we are on 99 # Mac. Instead, we use: 100 # -fsanitize=fuzzer-no-link 101 # Default value when unset and use_fuzzing_engine=true: 102 # trace-pc-guard 103 # Default value when unset and use_sanitizer_coverage=true: 104 # trace-pc-guard,indirect-calls 105 sanitizer_coverage_flags = "" 106} 107 108is_v8_host_toolchain = 109 current_toolchain == "//build/toolchain/linux:clang_x64_v8_arm64" || 110 current_toolchain == "//build/toolchain/linux:clang_x86_v8_arm" 111 112# Disable sanitizers for non-default toolchains. 113if (current_toolchain == host_toolchain || is_v8_host_toolchain) { 114 is_asan = false 115 is_cfi = false 116 is_lsan = false 117 is_msan = false 118 is_tsan = false 119 is_ubsan = false 120 is_ubsan_null = false 121 is_ubsan_no_recover = false 122 is_ubsan_security = false 123 is_ubsan_vptr = false 124 msan_track_origins = 0 125 sanitizer_coverage_flags = "" 126 use_afl = false 127 use_cfi_diag = false 128 use_cfi_recover = false 129 use_drfuzz = false 130 use_libfuzzer = false 131 use_prebuilt_instrumented_libraries = false 132 use_locally_built_instrumented_libraries = false 133 use_sanitizer_coverage = false 134} 135 136# Whether we are doing a fuzzer build. Normally this should be checked instead 137# of checking "use_libfuzzer || use_afl" because often developers forget to 138# check for "use_afl". 139use_fuzzing_engine = use_libfuzzer || use_afl 140 141# Args that are in turn dependent on other args must be in a separate 142# declare_args block. User overrides are only applied at the end of a 143# declare_args block. 144declare_args() { 145 use_sanitizer_coverage = 146 !use_clang_coverage && 147 (use_fuzzing_engine || sanitizer_coverage_flags != "") 148 149 # Detect overflow/underflow for global objects. 150 # 151 # Mac: http://crbug.com/352073 152 asan_globals = !is_mac 153} 154 155if (use_fuzzing_engine && sanitizer_coverage_flags == "") { 156 sanitizer_coverage_flags = "trace-pc-guard" 157} else if (use_sanitizer_coverage && sanitizer_coverage_flags == "") { 158 sanitizer_coverage_flags = "trace-pc-guard,indirect-calls" 159} 160 161# Whether we are linking against a debugging sanitizer runtime library. Among 162# other things, this changes the default symbol level and other settings in 163# order to prepare to create stack traces "live" using the sanitizer runtime. 164using_sanitizer = 165 is_asan || is_lsan || is_tsan || is_msan || is_ubsan || is_ubsan_null || 166 is_ubsan_vptr || is_ubsan_security || use_sanitizer_coverage || use_cfi_diag 167 168if (!is_ohos) { 169 using_sanitizer = false 170} 171 172assert(!using_sanitizer || is_clang, 173 "Sanitizers (is_*san) require setting is_clang = true in 'gn args'") 174 175assert(!is_cfi || is_clang, 176 "is_cfi requires setting is_clang = true in 'gn args'") 177 178assert(!is_safestack || is_clang, 179 "is_safestack requires setting is_clang = true in 'gn args'") 180 181prebuilt_instrumented_libraries_available = 182 is_msan && (msan_track_origins == 0 || msan_track_origins == 2) 183 184if (use_libfuzzer && is_linux) { 185 if (is_asan) { 186 # We do leak checking with libFuzzer on Linux. Set is_lsan for code that 187 # relies on LEAK_SANITIZER define to avoid false positives. 188 is_lsan = true 189 } 190 if (is_msan) { 191 use_prebuilt_instrumented_libraries = true 192 } 193} 194 195# MSan only links Chrome properly in release builds (brettw -- 9/1/2015). The 196# same is possibly true for the other non-ASan sanitizers. But regardless of 197# whether it links, one would normally never run a sanitizer in debug mode. 198# Running in debug mode probably indicates you forgot to set the "is_debug = 199# false" flag in the build args. ASan seems to run fine in debug mode. 200# 201# If you find a use-case where you want to compile a sanitizer in debug mode 202# and have verified it works, ask brettw and we can consider removing it from 203# this condition. We may also be able to find another way to enable your case 204# without having people accidentally get broken builds by compiling an 205# unsupported or unadvisable configurations. 206# 207# For one-off testing, just comment this assertion out. 208assert(!is_debug || !(is_msan || is_ubsan || is_ubsan_null || is_ubsan_vptr), 209 "Sanitizers should generally be used in release (set is_debug=false).") 210 211assert(!is_msan || (is_linux && current_cpu == "x64"), 212 "MSan currently only works on 64-bit Linux and ChromeOS builds.") 213 214assert(!is_lsan || is_asan, "is_lsan = true requires is_asan = true also.") 215 216# ASAN build on Windows is not working in debug mode. Intercepting memory 217# allocation functions is hard on Windows and not yet implemented in LLVM. 218assert(!is_win || !is_debug || !is_asan, 219 "ASan on Windows doesn't work in debug (set is_debug=false).") 220 221# Make sure that if we recover on detection (i.e. not crash), diagnostics are 222# printed. 223assert(!use_cfi_recover || use_cfi_diag, 224 "Only use CFI recovery together with diagnostics.") 225 226assert( 227 !(use_sanitizer_coverage && is_mac && target_os == "ios"), 228 "crbug.com/753445: use_sanitizer_coverage=true is not supported by the " + 229 "Chromium mac_clang_x64 toolchain on iOS distribution. Please set " + 230 "the argument value to false.") 231 232# Use these lists of configs to disable instrumenting code that is part of a 233# fuzzer, but which isn't being targeted (such as libprotobuf-mutator, *.pb.cc 234# and libprotobuf when they are built as part of a proto fuzzer). Adding or 235# removing these lists does not have any effect if use_libfuzzer or use_afl are 236# not passed as arguments to gn. 237not_fuzzed_remove_configs = [] 238not_fuzzed_remove_nonasan_configs = [] 239 240if (use_fuzzing_engine) { 241 # Removing coverage should always just work. 242 not_fuzzed_remove_configs += [ "//build/config/coverage:default_coverage" ] 243 not_fuzzed_remove_nonasan_configs += 244 [ "//build/config/coverage:default_coverage" ] 245 246 if (!is_msan) { 247 # Allow sanitizer instrumentation to be removed if we are not using MSan 248 # since binaries cannot be partially instrumented with MSan. 249 not_fuzzed_remove_configs += 250 [ "//build/config/sanitizers:default_sanitizer_flags" ] 251 252 # Certain parts of binaries must be instrumented with ASan if the rest of 253 # the binary is. For these, only remove non-ASan sanitizer instrumentation. 254 if (!is_asan) { 255 not_fuzzed_remove_nonasan_configs += 256 [ "//build/config/sanitizers:default_sanitizer_flags" ] 257 assert(not_fuzzed_remove_nonasan_configs == not_fuzzed_remove_configs) 258 } 259 } 260} 261 262template("ohos_sanitizer_config") { 263 config(target_name) { 264 forward_variables_from(invoker, [ "sanitize" ]) 265 if (defined(sanitize)) { 266 configs = [ "//build/config/sanitizers:sanitizer_trap_all_flags" ] 267 _mode = "release" 268 _debug = (defined(sanitize.debug) && sanitize.debug) || is_asan 269 if (_debug) { 270 _mode = "debug" 271 } 272 _cfi = defined(sanitize.cfi) && sanitize.cfi && !is_asan 273 if (_cfi) { 274 if (defined(sanitize.cfi_cross_dso) && sanitize.cfi_cross_dso) { 275 configs += [ "//build/config/sanitizers:cfi_cross_dso_" + _mode ] 276 } else { 277 configs += [ "//build/config/sanitizers:cfi_config_" + _mode ] 278 } 279 } 280 _scudo = defined(sanitize.scudo) && sanitize.scudo && !is_asan && !is_tsan 281 if (_scudo) { 282 configs += [ "//build/config/sanitizers:scudo_config" ] 283 } 284 _ubsan = defined(sanitize.ubsan) && sanitize.ubsan && !is_asan 285 if (_ubsan) { 286 configs += 287 [ "//build/config/sanitizers:undefined_behavior_sanitize_config_" + 288 _mode ] 289 } 290 _all_ubsan = defined(sanitize.all_ubsan) && sanitize.all_ubsan && !is_asan 291 if (_all_ubsan) { 292 configs += [ 293 "//build/config/sanitizers:all_undefined_behavior_sanitize_config_" + 294 _mode, 295 ] 296 } 297 _scs = defined(sanitize.scs) && sanitize.scs 298 if (_scs) { 299 configs += [ "//build/config/sanitizers:shadow_call_stack_config" ] 300 } 301 _boundary_sanitize = defined(sanitize.boundary_sanitize) && 302 sanitize.boundary_sanitize && !is_asan 303 if (_boundary_sanitize) { 304 configs += 305 [ "//build/config/sanitizers:boundary_sanitize_config_" + _mode ] 306 } 307 308 _integer_overflow = defined(sanitize.integer_overflow) && 309 sanitize.integer_overflow && !is_asan 310 _unsigned_integer_overflow = 311 defined(sanitize.unsigned_integer_overflow) && 312 sanitize.unsigned_integer_overflow && !is_asan 313 _signed_integer_overflow = defined(sanitize.signed_integer_overflow) && 314 sanitize.signed_integer_overflow && !is_asan 315 if (_unsigned_integer_overflow || _integer_overflow) { 316 configs += 317 [ "//build/config/sanitizers:unsigned_integer_overflow_config" ] 318 } 319 if (_signed_integer_overflow || _integer_overflow) { 320 configs += 321 [ "//build/config/sanitizers:signed_integer_overflow_config" ] 322 } 323 if (_integer_overflow || _unsigned_integer_overflow || 324 _signed_integer_overflow) { 325 configs += 326 [ "//build/config/sanitizers:common_integer_overflow_config_" + 327 _mode ] 328 } 329 330 if (defined(sanitize.blocklist)) { 331 cflags = [ "-fsanitize-blacklist=" + 332 rebase_path(get_path_info(sanitize.blocklist, "abspath"), 333 root_build_dir) ] 334 } 335 configs += [ "//build/config/sanitizers:compiler_rt_" + _mode ] 336 } 337 } 338} 339