1# Copyright 2015 The Chromium Authors 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/chromeos/args.gni") 8import("//build/config/chromeos/ui_mode.gni") 9import("//build/config/profiling/profiling.gni") 10import("//build/toolchain/toolchain.gni") 11 12declare_args() { 13 # Compile for Address Sanitizer to find memory bugs. 14 is_asan = false 15 16 # Compile for Hardware-Assisted Address Sanitizer to find memory bugs 17 # (android/arm64 only). 18 # See http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html 19 is_hwasan = false 20 21 # Compile for Leak Sanitizer to find leaks. 22 is_lsan = false 23 24 # Compile for Memory Sanitizer to find uninitialized reads. 25 is_msan = false 26 27 # Compile for Thread Sanitizer to find threading bugs. 28 is_tsan = false 29 30 # Compile for Undefined Behaviour Sanitizer to find various types of 31 # undefined behaviour (excludes vptr checks). 32 is_ubsan = false 33 34 # Halt the program if a problem is detected. 35 is_ubsan_no_recover = 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 build the libraries from source. 44 use_locally_built_instrumented_libraries = false 45 46 # Compile with Control Flow Integrity to protect virtual calls and casts. 47 # See http://clang.llvm.org/docs/ControlFlowIntegrity.html 48 # 49 # TODO(pcc): Remove this flag if/when CFI is enabled in all official builds. 50 is_cfi = is_official_build && is_clang && 51 ((target_os == "linux" && target_cpu == "x64") || 52 (is_chromeos && is_chromeos_device)) 53 54 # Enable checks for indirect function calls via a function pointer. 55 # TODO(pcc): remove this when we're ready to add these checks by default. 56 # https://crbug.com/701919 57 use_cfi_icall = 58 target_os == "linux" && target_cpu == "x64" && is_official_build 59 60 # Print detailed diagnostics when Control Flow Integrity detects a violation. 61 use_cfi_diag = false 62 63 # Let Control Flow Integrity continue execution instead of crashing when 64 # printing diagnostics (use_cfi_diag = true). 65 use_cfi_recover = false 66 67 # Compile for fuzzing with LLVM LibFuzzer. 68 # See http://www.chromium.org/developers/testing/libfuzzer 69 use_libfuzzer = false 70 71 # Compile for fuzzing with centipede. 72 # See https://github.com/google/centipede 73 use_centipede = false 74 75 # Compile for fuzzing with AFL. 76 use_afl = false 77 78 # Compile for fuzzing with an external engine (e.g., Grammarinator). 79 use_external_fuzzing_engine = false 80 81 # Enables core ubsan security features. Will later be removed once it matches 82 # is_ubsan. 83 is_ubsan_security = 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). Instead, we use: 96 # -fsanitize=fuzzer-no-link 97 # Default value when unset and use_fuzzing_engine=true: 98 # trace-pc-guard 99 # Default value when unset and use_sanitizer_coverage=true: 100 # trace-pc-guard,indirect-calls 101 sanitizer_coverage_flags = "" 102 103 # When enabled, only relevant sanitizer defines are set, but compilation 104 # happens with no extra flags. This is useful when in component build 105 # enabling sanitizers only in some of the components. 106 use_sanitizer_configs_without_instrumentation = false 107 108 # When true, seed corpora archives are built. 109 archive_seed_corpus = true 110} 111 112declare_args() { 113 # Enable checks for bad casts: derived cast and unrelated cast. 114 # TODO(krasin): remove this, when we're ready to add these checks by default. 115 # https://crbug.com/626794 116 use_cfi_cast = is_cfi && is_chromeos 117 118 # Compile for Undefined Behaviour Sanitizer's vptr checks. 119 is_ubsan_vptr = is_ubsan_security 120} 121 122assert(!is_hwasan || (target_os == "android" && target_cpu == "arm64"), 123 "HWASan only supported on Android ARM64 builds.") 124 125# Disable sanitizers for non-target toolchains. 126if (!is_a_target_toolchain || toolchain_disables_sanitizers) { 127 is_asan = false 128 is_cfi = false 129 is_hwasan = false 130 is_lsan = false 131 is_msan = false 132 is_tsan = false 133 is_ubsan = false 134 is_ubsan_no_recover = false 135 is_ubsan_security = false 136 is_ubsan_vptr = false 137 msan_track_origins = 0 138 sanitizer_coverage_flags = "" 139 use_afl = false 140 use_centipede = false 141 use_cfi_diag = false 142 use_cfi_recover = false 143 use_libfuzzer = false 144 use_locally_built_instrumented_libraries = false 145 use_sanitizer_coverage = false 146} else if (current_cpu != "arm64") { 147 is_hwasan = false 148} 149 150# Use dynamic libraries instrumented by one of the sanitizers instead of the 151# standard system libraries. We have instrumented system libraries for msan, 152# which requires them to prevent false positives. 153# TODO(thakis): Maybe remove this variable. 154use_prebuilt_instrumented_libraries = is_msan 155 156# Whether we are doing a fuzzer build. Normally this should be checked instead 157# of checking "use_libfuzzer || use_afl" because often developers forget to 158# check for "use_afl", and "use_centipede" is new. 159use_fuzzing_engine = 160 use_libfuzzer || use_afl || use_centipede || use_external_fuzzing_engine 161 162# Whether the current fuzzing engine supports libprotobuf_mutator. Right now 163# this is just libfuzzer, but others are likely to support this in future, 164# so it's preferable to check this. 165use_fuzzing_engine_with_lpm = use_libfuzzer || use_centipede 166 167# Whether the fuzzing engine supports fuzzers which supply their own 168# "main" function. 169fuzzing_engine_supports_custom_main = use_libfuzzer || use_centipede 170 171# Args that are in turn dependent on other args must be in a separate 172# declare_args block. User overrides are only applied at the end of a 173# declare_args block. 174declare_args() { 175 # Generates an owners file for each fuzzer test. 176 # TODO(crbug.com/1194183): Remove this arg when finding OWNERS is faster. 177 generate_fuzzer_owners = use_fuzzing_engine 178 179 use_sanitizer_coverage = 180 !use_clang_coverage && 181 (use_fuzzing_engine || sanitizer_coverage_flags != "") 182 183 # https://crbug.com/1002058: Code coverage works inside the sandbox via the 184 # help of several helper IPCs. Unfortunately, the sandbox-only path does not 185 # work well for fuzzing builds. Since fuzzing builds already disable the 186 # sandbox when dumping coverage, limit the sandbox-only path to non-fuzzing 187 # builds. 188 # Everything is IPC on Fuchsia, so this workaround for code coverage inside 189 # the sandbox does not apply. 190 use_clang_profiling_inside_sandbox = 191 use_clang_profiling && !use_fuzzing_engine && !is_fuchsia 192} 193 194if (use_fuzzing_engine && sanitizer_coverage_flags == "") { 195 sanitizer_coverage_flags = "trace-pc-guard" 196 if (use_centipede) { 197 # Centipede's minimal flags are listed in //third_party/centipede/src/clang-flags.txt. 198 # But, for users like Chromium using an up-to-date clang, we can also 199 # enable extra optional types of coverage which may make Centipede more 200 # effective. This list is not currently documented and has been derived 201 # from discussion with centipede creators (though one is warned about at 202 # https://github.com/google/centipede/blob/main/centipede_callbacks.cc#L68) 203 sanitizer_coverage_flags = sanitizer_coverage_flags + 204 ",pc-table,trace-cmp,control-flow,trace-loads" 205 } 206} else if (use_sanitizer_coverage && sanitizer_coverage_flags == "") { 207 sanitizer_coverage_flags = "trace-pc-guard,indirect-calls" 208} 209 210# Whether we are linking against a sanitizer runtime library. Among other 211# things, this changes the default symbol level and other settings in order to 212# prepare to create stack traces "live" using the sanitizer runtime. 213using_sanitizer = 214 is_asan || is_hwasan || is_lsan || is_tsan || is_msan || is_ubsan || 215 is_ubsan_vptr || is_ubsan_security || use_sanitizer_coverage || use_cfi_diag 216 217assert(!using_sanitizer || is_clang, 218 "Sanitizers (is_*san) require setting is_clang = true in 'gn args'") 219 220assert(!is_cfi || is_clang, 221 "is_cfi requires setting is_clang = true in 'gn args'") 222 223prebuilt_instrumented_libraries_available = 224 is_msan && (msan_track_origins == 0 || msan_track_origins == 2) 225 226if (use_libfuzzer && (is_linux || is_chromeos)) { 227 if (is_asan) { 228 # We do leak checking with libFuzzer on Linux. Set is_lsan for code that 229 # relies on LEAK_SANITIZER define to avoid false positives. 230 is_lsan = true 231 } 232} 233 234# MSan only links Chrome properly in release builds (brettw -- 9/1/2015). The 235# same is possibly true for the other non-ASan sanitizers. But regardless of 236# whether it links, one would normally never run a sanitizer in debug mode. 237# Running in debug mode probably indicates you forgot to set the "is_debug = 238# false" flag in the build args. ASan seems to run fine in debug mode. 239# 240# If you find a use-case where you want to compile a sanitizer in debug mode 241# and have verified it works, ask brettw and we can consider removing it from 242# this condition. We may also be able to find another way to enable your case 243# without having people accidentally get broken builds by compiling an 244# unsupported or unadvisable configurations. 245# 246# For one-off testing, just comment this assertion out. 247assert(!is_debug || !(is_msan || is_ubsan || is_ubsan_vptr), 248 "Sanitizers should generally be used in release (set is_debug=false).") 249 250assert(!is_msan || ((is_linux || is_chromeos) && current_cpu == "x64"), 251 "MSan currently only works on 64-bit Linux and ChromeOS builds.") 252 253assert(!is_lsan || is_asan, "is_lsan = true requires is_asan = true also.") 254 255# ASAN build on Windows is not working in debug mode. Intercepting memory 256# allocation functions is hard on Windows and not yet implemented in LLVM. 257assert(!is_win || !is_debug || !is_asan, 258 "ASan on Windows doesn't work in debug (set is_debug=false).") 259 260# libFuzzer targets can fail to build or behave incorrectly when built without 261# ASAN on Windows. 262assert(!is_win || !use_libfuzzer || is_asan, 263 "use_libfuzzer on Windows requires setting is_asan = true") 264 265# Make sure that if we recover on detection (i.e. not crash), diagnostics are 266# printed. 267assert(!use_cfi_recover || use_cfi_diag, 268 "Only use CFI recovery together with diagnostics.") 269 270# TODO(crbug.com/753445): the use_sanitizer_coverage arg is currently 271# not supported by the Chromium mac_clang_x64 toolchain on iOS distribution. 272# The coverage works with iOS toolchain but it is broken when the mac 273# toolchain is used as a secondary one on iOS distribution. E.g., it should be 274# possible to build the "net" target for iOS with the sanitizer coverage 275# enabled. 276assert( 277 !(use_sanitizer_coverage && is_mac && target_os == "ios"), 278 "crbug.com/753445: use_sanitizer_coverage=true is not supported by the " + 279 "Chromium mac_clang_x64 toolchain on iOS distribution. Please set " + 280 "the argument value to false.") 281 282# Use these lists of configs to disable instrumenting code that is part of a 283# fuzzer, but which isn't being targeted (such as libprotobuf-mutator, *.pb.cc 284# and libprotobuf when they are built as part of a proto fuzzer). Adding or 285# removing these lists does not have any effect if use_libfuzzer or use_afl are 286# not passed as arguments to gn. 287not_fuzzed_remove_configs = [] 288not_fuzzed_remove_nonasan_configs = [] 289 290if (use_fuzzing_engine) { 291 # Removing coverage should always just work. 292 not_fuzzed_remove_configs += [ "//build/config/coverage:default_coverage" ] 293 not_fuzzed_remove_nonasan_configs += 294 [ "//build/config/coverage:default_coverage" ] 295 296 if (!is_msan) { 297 # Allow sanitizer instrumentation to be removed if we are not using MSan 298 # since binaries cannot be partially instrumented with MSan. 299 not_fuzzed_remove_configs += 300 [ "//build/config/sanitizers:default_sanitizer_flags" ] 301 302 # Certain parts of binaries must be instrumented with ASan if the rest of 303 # the binary is. For these, only remove non-ASan sanitizer instrumentation. 304 if (!is_asan) { 305 not_fuzzed_remove_nonasan_configs += 306 [ "//build/config/sanitizers:default_sanitizer_flags" ] 307 308 assert(not_fuzzed_remove_nonasan_configs == not_fuzzed_remove_configs) 309 } 310 } 311} 312 313# Options common to different fuzzer engines. 314# Engine should be compiled without coverage (infinite loop in trace_cmp). 315fuzzing_engine_remove_configs = [ 316 "//build/config/coverage:default_coverage", 317 "//build/config/sanitizers:default_sanitizer_flags", 318] 319 320# Add any sanitizer flags back. In MSAN builds, instrumenting libfuzzer with 321# MSAN is necessary since all parts of the binary need to be instrumented for it 322# to work. ASAN builds are more subtle: libfuzzer depends on features from the 323# C++ STL. If it were not instrumented, templates would be insantiated without 324# ASAN from libfuzzer and with ASAN in other TUs. The linker might merge 325# instrumented template instantiations with non-instrumented ones (which could 326# have a different ABI) in the final binary, which is problematic for TUs 327# expecting one particular ABI (https://crbug.com/915422). The other sanitizers 328# are added back for the same reason. 329fuzzing_engine_add_configs = 330 [ "//build/config/sanitizers:default_sanitizer_flags_but_coverage" ] 331