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