• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 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/chrome_build.gni")
6import("//build/config/chromecast_build.gni")
7import("//build/config/sanitizers/sanitizers.gni")
8import("//build/toolchain/toolchain.gni")
9
10# Contains the dependencies needed for sanitizers to link into executables and
11# shared_libraries. Unconditionally depend upon this target as it is empty if
12# |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false.
13group("deps") {
14  deps = [
15    ":deps_no_options",
16  ]
17  if (using_sanitizer) {
18    public_configs = [
19      ":sanitizer_options_link_helper",
20
21      # Even when a target removes default_sanitizer_flags, it may be depending
22      # on a library that did not remove default_sanitizer_flags. Thus, we need
23      # to add the ldflags here as well as in default_sanitizer_flags.
24      ":default_sanitizer_ldflags",
25    ]
26    deps += [ ":options_sources" ]
27  }
28}
29
30group("deps_no_options") {
31  if (using_sanitizer) {
32    public_configs = [
33      # Even when a target removes default_sanitizer_flags, it may be depending
34      # on a library that did not remove default_sanitizer_flags. Thus, we need
35      # to add the ldflags here as well as in default_sanitizer_flags.
36      ":default_sanitizer_ldflags",
37    ]
38    deps = []
39    if (use_prebuilt_instrumented_libraries) {
40      deps += [ "//third_party/instrumented_libraries:deps" ]
41    }
42    if (use_custom_libcxx) {
43      deps += [ "//buildtools/third_party/libc++:libcxx_proxy" ]
44    }
45    if (is_mac) {
46      data_deps = [
47        ":copy_asan_runtime",
48      ]
49    }
50  }
51}
52
53if (is_mac) {
54  copy("copy_asan_runtime") {
55    sources = [
56      "//third_party/llvm-build/Release+Asserts/lib/clang/$clang_version/lib/darwin/libclang_rt.asan_osx_dynamic.dylib",
57    ]
58    outputs = [
59      "$root_out_dir/{{source_file_part}}",
60    ]
61  }
62}
63
64config("sanitizer_options_link_helper") {
65  if (is_mac) {
66    ldflags = [ "-Wl,-U,_sanitizer_options_link_helper" ]
67  } else if (!is_win) {
68    ldflags = [ "-Wl,-u_sanitizer_options_link_helper" ]
69  }
70}
71
72static_library("options_sources") {
73  # This is a static_library instead of a source_set, as it shouldn't be
74  # unconditionally linked into targets.
75  visibility = [
76    ":deps",
77    "//:gn_visibility",
78  ]
79  sources = [
80    "//build/sanitizers/sanitizer_options.cc",
81  ]
82
83  # Don't compile this target with any sanitizer code. It can be called from
84  # the sanitizer runtimes, so instrumenting these functions could cause
85  # recursive calls into the runtime if there is an error.
86  configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
87
88  if (is_asan) {
89    sources += [ "//build/sanitizers/asan_suppressions.cc" ]
90  }
91
92  if (is_lsan) {
93    sources += [ "//build/sanitizers/lsan_suppressions.cc" ]
94  }
95
96  if (is_tsan) {
97    sources += [ "//build/sanitizers/tsan_suppressions.cc" ]
98  }
99}
100
101# Applies linker flags necessary when either :deps or :default_sanitizer_flags
102# are used.
103config("default_sanitizer_ldflags") {
104  visibility = [
105    ":default_sanitizer_flags",
106    ":deps",
107  ]
108
109  if (is_posix) {
110    ldflags = []
111    if (is_asan) {
112      ldflags += [ "-fsanitize=address" ]
113    }
114    if (is_lsan) {
115      ldflags += [ "-fsanitize=leak" ]
116    }
117    if (is_tsan) {
118      ldflags += [ "-fsanitize=thread" ]
119    }
120    if (is_msan) {
121      ldflags += [ "-fsanitize=memory" ]
122    }
123    if (is_ubsan || is_ubsan_security) {
124      ldflags += [ "-fsanitize=undefined" ]
125    }
126    if (is_ubsan_vptr) {
127      ldflags += [ "-fsanitize=vptr" ]
128    }
129
130    if (is_cfi && !is_nacl) {
131      ldflags += [
132        "-fsanitize=cfi-vcall",
133        "-fsanitize=cfi-derived-cast",
134        "-fsanitize=cfi-unrelated-cast",
135      ]
136      if (use_cfi_diag) {
137        ldflags += [
138          "-fno-sanitize-trap=cfi",
139          "-fsanitize-recover=cfi",
140        ]
141      }
142    }
143  }
144}
145
146config("common_sanitizer_flags") {
147  cflags = []
148  cflags_cc = []
149
150  # Sanitizers need line table info for stack traces. They don't need type info
151  # or variable info, so we can leave that out to speed up the build.
152  if (using_sanitizer) {
153    assert(is_clang, "sanitizers only supported with clang")
154    cflags += [ "-gline-tables-only" ]
155  }
156
157  # Common options for AddressSanitizer, LeakSanitizer, ThreadSanitizer,
158  # MemorySanitizer and non-official CFI builds.
159  if (using_sanitizer || (is_cfi && !is_official_build)) {
160    if (is_posix) {
161      cflags += [ "-fno-omit-frame-pointer" ]
162    } else {
163      cflags += [ "/Oy-" ]
164    }
165  }
166
167  if (use_custom_libcxx) {
168    prefix = "//buildtools/third_party"
169    include = "trunk/include"
170    cflags_cc += [
171      "-nostdinc++",
172      "-isystem" + rebase_path("$prefix/libc++/$include", root_build_dir),
173      "-isystem" + rebase_path("$prefix/libc++abi/$include", root_build_dir),
174    ]
175  }
176}
177
178config("asan_flags") {
179  cflags = []
180  if (is_asan) {
181    cflags += [ "-fsanitize=address" ]
182    if (is_win) {
183      cflags += [ "-fsanitize-blacklist=" +
184                  rebase_path("//tools/memory/asan/blacklist_win.txt",
185                              root_build_dir) ]
186    } else {
187      # TODO(rnk): Remove this as discussed in http://crbug.com/427202.
188      cflags +=
189          [ "-fsanitize-blacklist=" +
190            rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir) ]
191    }
192    if (is_android) {
193      # Android build relies on -Wl,--gc-sections removing unreachable code.
194      # ASan instrumentation for globals inhibits this and results in a
195      # library with unresolvable relocations.
196      # TODO(eugenis): find a way to reenable this.
197      cflags += [
198        "-mllvm",
199        "-asan-globals=0",
200      ]
201    } else if (is_mac) {
202      # http://crbug.com/352073
203      cflags += [
204        "-mllvm",
205        "-asan-globals=0",
206      ]
207      # TODO(GYP): deal with mac_bundles.
208    } else if (is_win) {
209      assert(target_cpu == "x86", "WinASan is 32-bit only currently")
210      if (is_component_build) {
211        libs = [
212          "clang_rt.asan_dynamic-i386.lib",
213          "clang_rt.asan_dynamic_runtime_thunk-i386.lib",
214        ]
215      } else {
216        # TODO(rnk): DLLs in the non-component build should link against
217        # clang_rt.asan_dll_thunk-i386.lib instead.
218        libs = [ "clang_rt.asan-i386.lib" ]
219      }
220    }
221  }
222}
223
224config("cfi_flags") {
225  cflags = []
226  if (is_cfi && !is_nacl) {
227    cfi_blacklist_path =
228        rebase_path("//tools/cfi/blacklist.txt", root_build_dir)
229    cflags += [
230      "-fsanitize=cfi-vcall",
231      "-fsanitize=cfi-derived-cast",
232      "-fsanitize=cfi-unrelated-cast",
233      "-fsanitize-blacklist=$cfi_blacklist_path",
234    ]
235
236    if (use_cfi_diag) {
237      cflags += [
238        "-fno-sanitize-trap=cfi",
239        "-fsanitize-recover=cfi",
240        "-fno-inline-functions",
241        "-fno-inline",
242        "-fno-omit-frame-pointer",
243        "-O1",
244      ]
245    } else {
246      defines = [ "CFI_ENFORCEMENT" ]
247    }
248  }
249}
250
251config("coverage_flags") {
252  cflags = []
253
254  if (use_sanitizer_coverage) {
255    cflags += [
256      "-fsanitize-coverage=$sanitizer_coverage_flags",
257      "-mllvm",
258      "-sanitizer-coverage-prune-blocks=1",
259    ]
260    if (target_cpu == "arm") {
261      # http://crbug.com/517105
262      cflags += [
263        "-mllvm",
264        "-sanitizer-coverage-block-threshold=0",
265      ]
266    }
267    defines = [ "SANITIZER_COVERAGE" ]
268  }
269}
270
271config("lsan_flags") {
272  if (is_lsan) {
273    cflags = [ "-fsanitize=leak" ]
274  }
275}
276
277config("msan_flags") {
278  if (is_msan) {
279    assert(is_linux, "msan only supported on linux x86_64")
280    msan_blacklist_path =
281        rebase_path("//tools/msan/blacklist.txt", root_build_dir)
282    cflags = [
283      "-fsanitize=memory",
284      "-fsanitize-memory-track-origins=$msan_track_origins",
285      "-fsanitize-blacklist=$msan_blacklist_path",
286    ]
287  }
288}
289
290config("tsan_flags") {
291  if (is_tsan) {
292    assert(is_linux, "tsan only supported on linux x86_64")
293    tsan_blacklist_path =
294        rebase_path("//tools/memory/tsan_v2/ignores.txt", root_build_dir)
295    cflags = [
296      "-fsanitize=thread",
297      "-fsanitize-blacklist=$tsan_blacklist_path",
298    ]
299  }
300}
301
302config("ubsan_flags") {
303  cflags = []
304  if (is_ubsan) {
305    ubsan_blacklist_path =
306        rebase_path("//tools/ubsan/blacklist.txt", root_build_dir)
307    cflags += [
308      # Yasm dies with an "Illegal instruction" error when bounds checking is
309      # enabled. See http://crbug.com/489901
310      # "-fsanitize=bounds",
311      "-fsanitize=float-divide-by-zero",
312      "-fsanitize=integer-divide-by-zero",
313      "-fsanitize=null",
314      "-fsanitize=object-size",
315      "-fsanitize=return",
316      "-fsanitize=returns-nonnull-attribute",
317      "-fsanitize=shift-exponent",
318      "-fsanitize=signed-integer-overflow",
319      "-fsanitize=unreachable",
320      "-fsanitize=vla-bound",
321      "-fsanitize-blacklist=$ubsan_blacklist_path",
322    ]
323
324    # Chromecast ubsan builds fail to compile with these
325    # experimental flags, so only add them to non-chromecast ubsan builds.
326    if (!is_chromecast) {
327      cflags += [
328        # Employ the experimental PBQP register allocator to avoid slow
329        # compilation on files with too many basic blocks.
330        # See http://crbug.com/426271.
331        "-mllvm",
332        "-regalloc=pbqp",
333
334        # Speculatively use coalescing to slightly improve the code generated
335        # by PBQP regallocator. May increase compile time.
336        "-mllvm",
337        "-pbqp-coalescing",
338      ]
339    }
340  }
341}
342
343config("ubsan_no_recover") {
344  if (is_ubsan_no_recover) {
345    cflags = [ "-fno-sanitize-recover=undefined" ]
346  }
347}
348
349config("ubsan_security_flags") {
350  if (is_ubsan_security) {
351    ubsan_blacklist_path =
352        rebase_path("//tools/ubsan/blacklist.txt", root_build_dir)
353    cflags = [
354      "-fsanitize=signed-integer-overflow,shift",
355      "-fsanitize-blacklist=$ubsan_blacklist_path",
356    ]
357  }
358}
359
360config("ubsan_vptr_flags") {
361  if (is_ubsan_vptr) {
362    ubsan_vptr_blacklist_path =
363        rebase_path("//tools/ubsan/vptr_blacklist.txt", root_build_dir)
364    cflags = [
365      "-fsanitize=vptr",
366      "-fsanitize-blacklist=$ubsan_vptr_blacklist_path",
367    ]
368  }
369}
370
371all_sanitizer_configs = [
372  ":common_sanitizer_flags",
373  ":coverage_flags",
374  ":default_sanitizer_ldflags",
375  ":asan_flags",
376  ":cfi_flags",
377  ":lsan_flags",
378  ":msan_flags",
379  ":tsan_flags",
380  ":ubsan_flags",
381  ":ubsan_no_recover",
382  ":ubsan_security_flags",
383  ":ubsan_vptr_flags",
384]
385
386# This config is applied by default to all targets. It sets the compiler flags
387# for sanitizer usage, or, if no sanitizer is set, does nothing.
388#
389# This needs to be in a separate config so that targets can opt out of
390# sanitizers (by removing the config) if they desire. Even if a target
391# removes this config, executables & shared libraries should still depend on
392# :deps if any of their dependencies have not opted out of sanitizers.
393# Keep this list in sync with default_sanitizer_flags_but_ubsan_vptr.
394config("default_sanitizer_flags") {
395  configs = all_sanitizer_configs
396}
397
398# This config is equivalent to default_sanitizer_flags, but excludes ubsan_vptr.
399# This allows to selectively disable ubsan_vptr, when needed. In particular,
400# if some third_party code is required to be compiled without rtti, which
401# is a requirement for ubsan_vptr.
402config("default_sanitizer_flags_but_ubsan_vptr") {
403  configs = all_sanitizer_configs - [ ":ubsan_vptr_flags" ]
404}
405
406config("default_sanitizer_flags_but_coverage") {
407  configs = all_sanitizer_configs - [ ":coverage_flags" ]
408}
409