blob: d5535cb68c12581f90f822c71058ccdfb4c03ddc [file] [log] [blame]
Colin Cross16b23492016-01-06 14:41:07 -08001// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18 "fmt"
Colin Cross8ff9ef42017-05-08 13:44:11 -070019 "io"
Colin Cross16b23492016-01-06 14:41:07 -080020 "strings"
21
Colin Cross635c3b02016-05-18 15:37:25 -070022 "android/soong/android"
Evgenii Stepanovaf36db12016-08-15 14:18:24 -070023 "android/soong/cc/config"
Colin Cross16b23492016-01-06 14:41:07 -080024)
25
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -070026var (
27 // Any C flags added by sanitizer which libTooling tools may not
28 // understand also need to be added to ClangLibToolingUnknownCflags in
29 // cc/config/clang.go
Vishwath Mohanf3918d32017-02-14 07:59:33 -080030
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -070031 asanCflags = []string{"-fno-omit-frame-pointer"}
32 asanLdflags = []string{"-Wl,-u,__asan_preinit"}
33 asanLibs = []string{"libasan"}
34
Orion Hodson33c252c2017-10-31 17:37:33 +000035 cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fvisibility=default",
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -070036 "-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
Vishwath Mohanf3918d32017-02-14 07:59:33 -080037 // FIXME: revert the __cfi_check flag when clang is updated to r280031.
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -070038 cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
39 "-Wl,-plugin-opt,O1 -Wl,-export-dynamic-symbol=__cfi_check"}
Orion Hodson33c252c2017-10-31 17:37:33 +000040 cfiArflags = []string{"--plugin ${config.ClangBin}/../lib64/LLVMgold.so"}
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -070041
42 intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
Dan Willemsencbceaab2016-10-13 16:44:07 -070043)
44
Colin Cross16b23492016-01-06 14:41:07 -080045type sanitizerType int
46
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -070047func boolPtr(v bool) *bool {
48 if v {
49 return &v
50 } else {
51 return nil
52 }
53}
54
Colin Cross16b23492016-01-06 14:41:07 -080055const (
56 asan sanitizerType = iota + 1
57 tsan
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -070058 intOverflow
Colin Cross16b23492016-01-06 14:41:07 -080059)
60
61func (t sanitizerType) String() string {
62 switch t {
63 case asan:
64 return "asan"
65 case tsan:
66 return "tsan"
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -070067 case intOverflow:
68 return "intOverflow"
Colin Cross16b23492016-01-06 14:41:07 -080069 default:
70 panic(fmt.Errorf("unknown sanitizerType %d", t))
71 }
72}
73
74type SanitizeProperties struct {
75 // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
76 Sanitize struct {
77 Never bool `android:"arch_variant"`
78
79 // main sanitizers
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -070080 Address *bool `android:"arch_variant"`
81 Thread *bool `android:"arch_variant"`
Colin Cross16b23492016-01-06 14:41:07 -080082
83 // local sanitizers
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -070084 Undefined *bool `android:"arch_variant"`
85 All_undefined *bool `android:"arch_variant"`
86 Misc_undefined []string `android:"arch_variant"`
87 Coverage *bool `android:"arch_variant"`
88 Safestack *bool `android:"arch_variant"`
89 Cfi *bool `android:"arch_variant"`
90 Integer_overflow *bool `android:"arch_variant"`
Colin Cross16b23492016-01-06 14:41:07 -080091
Evgenii Stepanov1e405e12016-08-16 15:39:54 -070092 // Sanitizers to run in the diagnostic mode (as opposed to the release mode).
93 // Replaces abort() on error with a human-readable error message.
94 // Address and Thread sanitizers always run in diagnostic mode.
95 Diag struct {
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -070096 Undefined *bool `android:"arch_variant"`
97 Cfi *bool `android:"arch_variant"`
98 Integer_overflow *bool `android:"arch_variant"`
99 Misc_undefined []string `android:"arch_variant"`
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700100 }
101
102 // value to pass to -fsanitize-recover=
Colin Cross16b23492016-01-06 14:41:07 -0800103 Recover []string
104
105 // value to pass to -fsanitize-blacklist
106 Blacklist *string
107 } `android:"arch_variant"`
108
109 SanitizerEnabled bool `blueprint:"mutated"`
110 SanitizeDep bool `blueprint:"mutated"`
Vishwath Mohan1dd88392017-03-29 22:00:18 -0700111 InSanitizerDir bool `blueprint:"mutated"`
Colin Cross16b23492016-01-06 14:41:07 -0800112}
113
114type sanitize struct {
115 Properties SanitizeProperties
Colin Cross8ff9ef42017-05-08 13:44:11 -0700116
Jiyong Park27b188b2017-07-18 13:23:39 +0900117 runtimeLibrary string
118 androidMkRuntimeLibrary string
Colin Cross16b23492016-01-06 14:41:07 -0800119}
120
121func (sanitize *sanitize) props() []interface{} {
122 return []interface{}{&sanitize.Properties}
123}
124
125func (sanitize *sanitize) begin(ctx BaseModuleContext) {
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700126 s := &sanitize.Properties.Sanitize
127
Colin Cross16b23492016-01-06 14:41:07 -0800128 // Don't apply sanitizers to NDK code.
Jeff Gastonaf3cc2d2017-09-27 17:01:44 -0700129 if ctx.useSdk() {
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700130 s.Never = true
Colin Cross16b23492016-01-06 14:41:07 -0800131 }
132
133 // Never always wins.
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700134 if s.Never {
Colin Cross16b23492016-01-06 14:41:07 -0800135 return
136 }
137
Colin Cross16b23492016-01-06 14:41:07 -0800138 var globalSanitizers []string
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700139 var globalSanitizersDiag []string
140
Colin Cross16b23492016-01-06 14:41:07 -0800141 if ctx.clang() {
142 if ctx.Host() {
143 globalSanitizers = ctx.AConfig().SanitizeHost()
144 } else {
Colin Cross23ae82a2016-11-02 14:34:39 -0700145 arches := ctx.AConfig().SanitizeDeviceArch()
146 if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
147 globalSanitizers = ctx.AConfig().SanitizeDevice()
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700148 globalSanitizersDiag = ctx.AConfig().SanitizeDeviceDiag()
Colin Cross23ae82a2016-11-02 14:34:39 -0700149 }
Colin Cross16b23492016-01-06 14:41:07 -0800150 }
151 }
152
Colin Cross16b23492016-01-06 14:41:07 -0800153 if len(globalSanitizers) > 0 {
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000154 var found bool
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700155 if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil {
156 s.All_undefined = boolPtr(true)
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000157 }
Colin Cross16b23492016-01-06 14:41:07 -0800158
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700159 if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil {
160 s.Undefined = boolPtr(true)
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000161 }
162
Evgenii Stepanov774cb812016-12-28 15:52:54 -0800163 if found, globalSanitizers = removeFromList("address", globalSanitizers); found {
164 if s.Address == nil {
165 s.Address = boolPtr(true)
166 } else if *s.Address == false {
167 // Coverage w/o address is an error. If globalSanitizers includes both, and the module
168 // disables address, then disable coverage as well.
169 _, globalSanitizers = removeFromList("coverage", globalSanitizers)
170 }
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000171 }
172
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700173 if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
174 s.Thread = boolPtr(true)
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000175 }
176
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700177 if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found && s.Coverage == nil {
178 s.Coverage = boolPtr(true)
179 }
180
181 if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
182 s.Safestack = boolPtr(true)
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000183 }
184
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700185 if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil {
186 s.Cfi = boolPtr(true)
187 }
188
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700189 if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil {
Ivan Lozano5f595532017-07-13 14:46:05 -0700190 if !ctx.AConfig().IntegerOverflowDisabledForPath(ctx.ModuleDir()) {
191 s.Integer_overflow = boolPtr(true)
192 }
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700193 }
194
Evgenii Stepanov05bafd32016-07-07 17:38:41 +0000195 if len(globalSanitizers) > 0 {
196 ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
197 }
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700198
199 if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found &&
200 s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) {
201 s.Diag.Integer_overflow = boolPtr(true)
202 }
203
204 if len(globalSanitizersDiag) > 0 {
205 ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0])
206 }
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700207 }
Colin Cross3c344ef2016-07-18 15:44:56 -0700208
Evgenii Stepanova83fdac2017-01-31 18:37:30 -0800209 // CFI needs gold linker, and mips toolchain does not have one.
210 if !ctx.AConfig().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 {
Vishwath Mohan1b017a72017-01-19 13:54:55 -0800211 s.Cfi = nil
212 s.Diag.Cfi = nil
213 }
214
Vishwath Mohan6d67e6e2017-02-07 20:31:41 -0800215 // Also disable CFI for arm32 until b/35157333 is fixed.
216 if ctx.Arch().ArchType == android.Arm {
217 s.Cfi = nil
218 s.Diag.Cfi = nil
219 }
220
Vishwath Mohan8f4fdd82017-04-20 07:42:52 -0700221 // Also disable CFI if ASAN is enabled.
222 if Bool(s.Address) {
223 s.Cfi = nil
224 s.Diag.Cfi = nil
225 }
226
Colin Cross3c344ef2016-07-18 15:44:56 -0700227 if ctx.staticBinary() {
228 s.Address = nil
Colin Cross91169fe2016-08-11 15:54:20 -0700229 s.Coverage = nil
Colin Cross3c344ef2016-07-18 15:44:56 -0700230 s.Thread = nil
Colin Cross16b23492016-01-06 14:41:07 -0800231 }
232
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700233 if Bool(s.All_undefined) {
234 s.Undefined = nil
235 }
236
Evgenii Stepanov0a8a0d02016-05-12 13:54:53 -0700237 if !ctx.toolchain().Is64Bit() {
238 // TSAN and SafeStack are not supported on 32-bit architectures
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700239 s.Thread = nil
240 s.Safestack = nil
Colin Cross16b23492016-01-06 14:41:07 -0800241 // TODO(ccross): error for compile_multilib = "32"?
242 }
243
Evgenii Stepanov76cee232017-01-27 15:44:44 -0800244 if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700245 Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0) {
Colin Cross3c344ef2016-07-18 15:44:56 -0700246 sanitize.Properties.SanitizerEnabled = true
247 }
248
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700249 if Bool(s.Coverage) {
250 if !Bool(s.Address) {
Colin Cross16b23492016-01-06 14:41:07 -0800251 ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
252 }
253 }
254}
255
256func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps {
257 if !sanitize.Properties.SanitizerEnabled { // || c.static() {
258 return deps
259 }
260
261 if ctx.Device() {
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700262 if Bool(sanitize.Properties.Sanitize.Address) {
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -0700263 deps.StaticLibs = append(deps.StaticLibs, asanLibs...)
Colin Cross16b23492016-01-06 14:41:07 -0800264 }
265 }
266
267 return deps
268}
269
270func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
271 if !sanitize.Properties.SanitizerEnabled {
272 return flags
273 }
274
275 if !ctx.clang() {
276 ctx.ModuleErrorf("Use of sanitizers requires clang")
277 }
278
279 var sanitizers []string
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700280 var diagSanitizers []string
Colin Cross16b23492016-01-06 14:41:07 -0800281
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700282 if Bool(sanitize.Properties.Sanitize.All_undefined) {
Colin Cross16b23492016-01-06 14:41:07 -0800283 sanitizers = append(sanitizers, "undefined")
Colin Cross16b23492016-01-06 14:41:07 -0800284 } else {
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700285 if Bool(sanitize.Properties.Sanitize.Undefined) {
Colin Cross16b23492016-01-06 14:41:07 -0800286 sanitizers = append(sanitizers,
287 "bool",
288 "integer-divide-by-zero",
289 "return",
290 "returns-nonnull-attribute",
291 "shift-exponent",
292 "unreachable",
293 "vla-bound",
294 // TODO(danalbert): The following checks currently have compiler performance issues.
295 //"alignment",
296 //"bounds",
297 //"enum",
298 //"float-cast-overflow",
299 //"float-divide-by-zero",
300 //"nonnull-attribute",
301 //"null",
302 //"shift-base",
303 //"signed-integer-overflow",
304 // TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
305 // https://llvm.org/PR19302
306 // http://reviews.llvm.org/D6974
307 // "object-size",
308 )
309 }
310 sanitizers = append(sanitizers, sanitize.Properties.Sanitize.Misc_undefined...)
311 }
312
Ivan Lozano651275b2017-06-13 10:24:34 -0700313 if Bool(sanitize.Properties.Sanitize.Diag.Undefined) {
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700314 diagSanitizers = append(diagSanitizers, "undefined")
315 }
316
Ivan Lozano651275b2017-06-13 10:24:34 -0700317 diagSanitizers = append(diagSanitizers, sanitize.Properties.Sanitize.Diag.Misc_undefined...)
318
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700319 if Bool(sanitize.Properties.Sanitize.Address) {
Colin Cross635c3b02016-05-18 15:37:25 -0700320 if ctx.Arch().ArchType == android.Arm {
Colin Cross16b23492016-01-06 14:41:07 -0800321 // Frame pointer based unwinder in ASan requires ARM frame setup.
322 // TODO: put in flags?
323 flags.RequiredInstructionSet = "arm"
324 }
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -0700325 flags.CFlags = append(flags.CFlags, asanCflags...)
326 flags.LdFlags = append(flags.LdFlags, asanLdflags...)
Colin Cross16b23492016-01-06 14:41:07 -0800327
Colin Cross16b23492016-01-06 14:41:07 -0800328 if ctx.Host() {
329 // -nodefaultlibs (provided with libc++) prevents the driver from linking
330 // libraries needed with -fsanitize=address. http://b/18650275 (WAI)
Colin Cross16b23492016-01-06 14:41:07 -0800331 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-as-needed")
332 } else {
333 flags.CFlags = append(flags.CFlags, "-mllvm", "-asan-globals=0")
334 flags.DynamicLinker = "/system/bin/linker_asan"
335 if flags.Toolchain.Is64Bit() {
336 flags.DynamicLinker += "64"
337 }
338 }
339 sanitizers = append(sanitizers, "address")
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700340 diagSanitizers = append(diagSanitizers, "address")
Colin Cross16b23492016-01-06 14:41:07 -0800341 }
342
Yabin Cui6be405e2017-10-19 15:52:11 -0700343 if Bool(sanitize.Properties.Sanitize.Thread) {
344 sanitizers = append(sanitizers, "thread")
345 }
346
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700347 if Bool(sanitize.Properties.Sanitize.Coverage) {
Zach Riggle06bbd892017-08-21 17:12:32 -0400348 flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp")
Colin Cross16b23492016-01-06 14:41:07 -0800349 }
350
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700351 if Bool(sanitize.Properties.Sanitize.Safestack) {
Evgenii Stepanov0a8a0d02016-05-12 13:54:53 -0700352 sanitizers = append(sanitizers, "safe-stack")
353 }
354
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700355 if Bool(sanitize.Properties.Sanitize.Cfi) {
Evgenii Stepanov7ebf9fa2017-01-20 14:13:06 -0800356 if ctx.Arch().ArchType == android.Arm {
357 // __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
358 // to do this on a function basis, so force Thumb on the entire module.
359 flags.RequiredInstructionSet = "thumb"
Evgenii Stepanova83fdac2017-01-31 18:37:30 -0800360 // Workaround for b/33678192. CFI jumptables need Thumb2 codegen. Revert when
361 // Clang is updated past r290384.
362 flags.LdFlags = append(flags.LdFlags, "-march=armv7-a")
Evgenii Stepanov7ebf9fa2017-01-20 14:13:06 -0800363 }
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700364 sanitizers = append(sanitizers, "cfi")
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -0700365 flags.CFlags = append(flags.CFlags, cfiCflags...)
366 flags.LdFlags = append(flags.LdFlags, cfiLdflags...)
367 flags.ArFlags = append(flags.ArFlags, cfiArflags...)
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700368 if Bool(sanitize.Properties.Sanitize.Diag.Cfi) {
369 diagSanitizers = append(diagSanitizers, "cfi")
370 }
371 }
372
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700373 if Bool(sanitize.Properties.Sanitize.Integer_overflow) {
374 if !ctx.static() {
375 sanitizers = append(sanitizers, "unsigned-integer-overflow")
376 sanitizers = append(sanitizers, "signed-integer-overflow")
377 flags.CFlags = append(flags.CFlags, intOverflowCflags...)
378 if Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) {
379 diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
380 diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
381 }
382 }
383 }
384
Colin Cross16b23492016-01-06 14:41:07 -0800385 if len(sanitizers) > 0 {
386 sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
387 flags.CFlags = append(flags.CFlags, sanitizeArg)
388 if ctx.Host() {
389 flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
390 flags.LdFlags = append(flags.LdFlags, sanitizeArg)
Evgenii Stepanov76cee232017-01-27 15:44:44 -0800391 // Host sanitizers only link symbols in the final executable, so
392 // there will always be undefined symbols in intermediate libraries.
393 _, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
Colin Cross16b23492016-01-06 14:41:07 -0800394 } else {
Colin Cross263abbd2016-07-15 13:10:48 -0700395 flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
Colin Cross16b23492016-01-06 14:41:07 -0800396 }
397 }
398
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700399 if len(diagSanitizers) > 0 {
400 flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap="+strings.Join(diagSanitizers, ","))
401 }
402 // FIXME: enable RTTI if diag + (cfi or vptr)
403
Andreas Gampe97071162017-05-08 13:15:23 -0700404 if sanitize.Properties.Sanitize.Recover != nil {
405 flags.CFlags = append(flags.CFlags, "-fsanitize-recover="+
406 strings.Join(sanitize.Properties.Sanitize.Recover, ","))
407 }
408
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700409 // Link a runtime library if needed.
410 runtimeLibrary := ""
411 if Bool(sanitize.Properties.Sanitize.Address) {
412 runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain())
Yabin Cui6be405e2017-10-19 15:52:11 -0700413 } else if Bool(sanitize.Properties.Sanitize.Thread) {
414 runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700415 } else if len(diagSanitizers) > 0 {
416 runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
417 }
418
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700419 if runtimeLibrary != "" {
Jiyong Park27b188b2017-07-18 13:23:39 +0900420 // ASan runtime library must be the first in the link order.
Colin Cross8ff9ef42017-05-08 13:44:11 -0700421 flags.libFlags = append([]string{
422 "${config.ClangAsanLibDir}/" + runtimeLibrary + ctx.toolchain().ShlibSuffix(),
423 }, flags.libFlags...)
424 sanitize.runtimeLibrary = runtimeLibrary
Jiyong Park27b188b2017-07-18 13:23:39 +0900425
426 // When linking against VNDK, use the vendor variant of the runtime lib
427 sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
Jeff Gastonaf3cc2d2017-09-27 17:01:44 -0700428 if ctx.useVndk() {
Jiyong Park27b188b2017-07-18 13:23:39 +0900429 sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix
430 }
Evgenii Stepanov1e405e12016-08-16 15:39:54 -0700431 }
432
Colin Cross635c3b02016-05-18 15:37:25 -0700433 blacklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist)
Colin Cross16b23492016-01-06 14:41:07 -0800434 if blacklist.Valid() {
435 flags.CFlags = append(flags.CFlags, "-fsanitize-blacklist="+blacklist.String())
436 flags.CFlagsDeps = append(flags.CFlagsDeps, blacklist.Path())
437 }
438
439 return flags
440}
441
Colin Cross8ff9ef42017-05-08 13:44:11 -0700442func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
Colin Cross27a4b052017-08-10 16:32:23 -0700443 ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
Jiyong Park27b188b2017-07-18 13:23:39 +0900444 if sanitize.androidMkRuntimeLibrary != "" {
445 fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES += "+sanitize.androidMkRuntimeLibrary)
Colin Cross8ff9ef42017-05-08 13:44:11 -0700446 }
Colin Cross8ff9ef42017-05-08 13:44:11 -0700447 })
448}
449
Vishwath Mohan1dd88392017-03-29 22:00:18 -0700450func (sanitize *sanitize) inSanitizerDir() bool {
451 return sanitize.Properties.InSanitizerDir
Colin Cross30d5f512016-05-03 18:02:42 -0700452}
453
Orion Hodson33c252c2017-10-31 17:37:33 +0000454func (sanitize *sanitize) Sanitizer(t sanitizerType) bool {
455 if sanitize == nil {
456 return false
457 }
458
Vishwath Mohan95229302017-08-11 00:53:16 +0000459 switch t {
460 case asan:
Orion Hodson33c252c2017-10-31 17:37:33 +0000461 return Bool(sanitize.Properties.Sanitize.Address)
Vishwath Mohan95229302017-08-11 00:53:16 +0000462 case tsan:
Orion Hodson33c252c2017-10-31 17:37:33 +0000463 return Bool(sanitize.Properties.Sanitize.Thread)
Vishwath Mohan95229302017-08-11 00:53:16 +0000464 case intOverflow:
Orion Hodson33c252c2017-10-31 17:37:33 +0000465 return Bool(sanitize.Properties.Sanitize.Integer_overflow)
Vishwath Mohan95229302017-08-11 00:53:16 +0000466 default:
467 panic(fmt.Errorf("unknown sanitizerType %d", t))
468 }
469}
470
Colin Cross16b23492016-01-06 14:41:07 -0800471func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
472 switch t {
473 case asan:
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700474 sanitize.Properties.Sanitize.Address = boolPtr(b)
Colin Cross91169fe2016-08-11 15:54:20 -0700475 if !b {
476 sanitize.Properties.Sanitize.Coverage = nil
477 }
Colin Cross16b23492016-01-06 14:41:07 -0800478 case tsan:
Evgenii Stepanovfcfe56d2016-07-07 10:54:07 -0700479 sanitize.Properties.Sanitize.Thread = boolPtr(b)
Ivan Lozano0c3a1ef2017-06-28 09:10:48 -0700480 case intOverflow:
481 sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b)
Colin Cross16b23492016-01-06 14:41:07 -0800482 default:
483 panic(fmt.Errorf("unknown sanitizerType %d", t))
484 }
485 if b {
486 sanitize.Properties.SanitizerEnabled = true
487 }
488}
489
490// Propagate asan requirements down from binaries
Colin Cross635c3b02016-05-18 15:37:25 -0700491func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
492 return func(mctx android.TopDownMutatorContext) {
Orion Hodson33c252c2017-10-31 17:37:33 +0000493 if c, ok := mctx.Module().(*Module); ok && c.sanitize.Sanitizer(t) {
Colin Crossd11fcda2017-10-23 17:59:01 -0700494 mctx.VisitDepsDepthFirst(func(module android.Module) {
Orion Hodson33c252c2017-10-31 17:37:33 +0000495 if d, ok := mctx.Module().(*Module); ok && c.sanitize != nil &&
496 !c.sanitize.Properties.Sanitize.Never {
497 d.sanitize.Properties.SanitizeDep = true
Colin Cross16b23492016-01-06 14:41:07 -0800498 }
499 })
500 }
501 }
502}
503
Orion Hodson33c252c2017-10-31 17:37:33 +0000504// Create asan variants for modules that need them
Colin Cross635c3b02016-05-18 15:37:25 -0700505func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
506 return func(mctx android.BottomUpMutatorContext) {
Vishwath Mohane6153452017-08-11 00:52:44 +0000507 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
Orion Hodson33c252c2017-10-31 17:37:33 +0000508 if c.isDependencyRoot() && c.sanitize.Sanitizer(t) {
Colin Cross30d5f512016-05-03 18:02:42 -0700509 modules := mctx.CreateVariations(t.String())
510 modules[0].(*Module).sanitize.SetSanitizer(t, true)
Orion Hodson33c252c2017-10-31 17:37:33 +0000511 } else if c.sanitize.Properties.SanitizeDep {
Colin Crossb0f28952016-09-19 16:46:53 -0700512 modules := mctx.CreateVariations("", t.String())
513 modules[0].(*Module).sanitize.SetSanitizer(t, false)
514 modules[1].(*Module).sanitize.SetSanitizer(t, true)
515 modules[0].(*Module).sanitize.Properties.SanitizeDep = false
516 modules[1].(*Module).sanitize.Properties.SanitizeDep = false
Vishwath Mohane6153452017-08-11 00:52:44 +0000517 if mctx.Device() {
Orion Hodson33c252c2017-10-31 17:37:33 +0000518 modules[1].(*Module).sanitize.Properties.InSanitizerDir = true
Orion Hodsonda11d742017-10-31 17:31:00 +0000519 } else {
Orion Hodson33c252c2017-10-31 17:37:33 +0000520 modules[0].(*Module).Properties.PreventInstall = true
Vishwath Mohane6153452017-08-11 00:52:44 +0000521 }
Orion Hodsonda11d742017-10-31 17:31:00 +0000522 if mctx.AConfig().EmbeddedInMake() {
Orion Hodson33c252c2017-10-31 17:37:33 +0000523 modules[0].(*Module).Properties.HideFromMake = true
Orion Hodsonda11d742017-10-31 17:31:00 +0000524 }
Colin Cross16b23492016-01-06 14:41:07 -0800525 }
526 c.sanitize.Properties.SanitizeDep = false
527 }
528 }
529}