• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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