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