2016-01-06 23:41:07 +01:00
|
|
|
// Copyright 2016 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package cc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-05-08 22:44:11 +02:00
|
|
|
"io"
|
2017-11-29 01:37:53 +01:00
|
|
|
"sort"
|
2016-01-06 23:41:07 +01:00
|
|
|
"strings"
|
2017-11-17 20:08:10 +01:00
|
|
|
"sync"
|
2016-01-06 23:41:07 +01:00
|
|
|
|
2018-06-21 22:03:07 +02:00
|
|
|
"github.com/google/blueprint"
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
"android/soong/android"
|
2016-08-15 23:18:24 +02:00
|
|
|
"android/soong/cc/config"
|
2016-01-06 23:41:07 +01:00
|
|
|
)
|
|
|
|
|
2017-06-15 23:45:18 +02:00
|
|
|
var (
|
|
|
|
// Any C flags added by sanitizer which libTooling tools may not
|
|
|
|
// understand also need to be added to ClangLibToolingUnknownCflags in
|
|
|
|
// cc/config/clang.go
|
|
|
|
|
|
|
|
asanCflags = []string{"-fno-omit-frame-pointer"}
|
|
|
|
asanLdflags = []string{"-Wl,-u,__asan_preinit"}
|
|
|
|
asanLibs = []string{"libasan"}
|
2017-02-14 16:59:33 +01:00
|
|
|
|
2018-12-08 00:33:24 +01:00
|
|
|
hwasanCflags = []string{"-mllvm", "-hwasan-with-ifunc=0", "-fno-omit-frame-pointer", "-Wno-frame-larger-than=", "-mllvm", "-hwasan-create-frame-descriptions=0"}
|
2018-08-03 01:19:13 +02:00
|
|
|
|
2017-11-01 10:20:21 +01:00
|
|
|
cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
|
2017-06-15 23:45:18 +02:00
|
|
|
"-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
|
2018-08-31 21:54:33 +02:00
|
|
|
// -flto and -fvisibility are required by clang when -fsanitize=cfi is
|
|
|
|
// used, but have no effect on assembly files
|
|
|
|
cfiAsflags = []string{"-flto", "-fvisibility=default"}
|
2017-06-15 23:45:18 +02:00
|
|
|
cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
|
2017-08-29 06:50:17 +02:00
|
|
|
"-Wl,-plugin-opt,O1"}
|
2018-08-03 01:19:13 +02:00
|
|
|
cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
|
|
|
|
cfiStaticLibsMutex sync.Mutex
|
|
|
|
hwasanStaticLibsMutex sync.Mutex
|
2017-06-28 18:10:48 +02:00
|
|
|
|
2018-11-30 00:12:51 +01:00
|
|
|
intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
|
2018-11-20 01:03:58 +01:00
|
|
|
|
|
|
|
// Pass -Xclang before -fsanitize-minimal-runtime to work around a driver
|
|
|
|
// check which rejects -fsanitize-minimal-runtime together with
|
|
|
|
// -fsanitize=shadow-call-stack even though this combination of flags
|
|
|
|
// is valid.
|
|
|
|
// TODO(pcc): Remove the -Xclang once LLVM r346526 is rolled into the compiler.
|
|
|
|
minimalRuntimeFlags = []string{"-Xclang", "-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
|
2018-10-08 18:29:39 +02:00
|
|
|
"-fno-sanitize-recover=integer,undefined"}
|
2018-10-04 03:22:57 +02:00
|
|
|
hwasanGlobalOptions = []string{"heap_history_size=4095"}
|
2016-10-14 01:44:07 +02:00
|
|
|
)
|
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
type sanitizerType int
|
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
func boolPtr(v bool) *bool {
|
|
|
|
if v {
|
|
|
|
return &v
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
const (
|
|
|
|
asan sanitizerType = iota + 1
|
2018-08-03 01:19:13 +02:00
|
|
|
hwasan
|
2016-01-06 23:41:07 +01:00
|
|
|
tsan
|
2017-06-28 18:10:48 +02:00
|
|
|
intOverflow
|
2017-11-01 10:20:21 +01:00
|
|
|
cfi
|
2018-11-20 01:03:58 +01:00
|
|
|
scs
|
2016-01-06 23:41:07 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func (t sanitizerType) String() string {
|
|
|
|
switch t {
|
|
|
|
case asan:
|
|
|
|
return "asan"
|
2018-08-03 01:19:13 +02:00
|
|
|
case hwasan:
|
|
|
|
return "hwasan"
|
2016-01-06 23:41:07 +01:00
|
|
|
case tsan:
|
|
|
|
return "tsan"
|
2017-06-28 18:10:48 +02:00
|
|
|
case intOverflow:
|
|
|
|
return "intOverflow"
|
2017-11-01 10:20:21 +01:00
|
|
|
case cfi:
|
|
|
|
return "cfi"
|
2018-11-20 01:03:58 +01:00
|
|
|
case scs:
|
|
|
|
return "scs"
|
2016-01-06 23:41:07 +01:00
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unknown sanitizerType %d", t))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type SanitizeProperties struct {
|
|
|
|
// enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
|
|
|
|
Sanitize struct {
|
2017-11-07 19:57:05 +01:00
|
|
|
Never *bool `android:"arch_variant"`
|
2016-01-06 23:41:07 +01:00
|
|
|
|
|
|
|
// main sanitizers
|
2018-08-03 01:19:13 +02:00
|
|
|
Address *bool `android:"arch_variant"`
|
|
|
|
Thread *bool `android:"arch_variant"`
|
|
|
|
Hwaddress *bool `android:"arch_variant"`
|
2016-01-06 23:41:07 +01:00
|
|
|
|
|
|
|
// local sanitizers
|
2017-06-28 18:10:48 +02:00
|
|
|
Undefined *bool `android:"arch_variant"`
|
|
|
|
All_undefined *bool `android:"arch_variant"`
|
|
|
|
Misc_undefined []string `android:"arch_variant"`
|
|
|
|
Coverage *bool `android:"arch_variant"`
|
|
|
|
Safestack *bool `android:"arch_variant"`
|
|
|
|
Cfi *bool `android:"arch_variant"`
|
|
|
|
Integer_overflow *bool `android:"arch_variant"`
|
2018-06-12 23:46:54 +02:00
|
|
|
Scudo *bool `android:"arch_variant"`
|
2018-11-20 01:03:58 +01:00
|
|
|
Scs *bool `android:"arch_variant"`
|
2016-08-17 00:39:54 +02:00
|
|
|
|
|
|
|
// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
|
|
|
|
// Replaces abort() on error with a human-readable error message.
|
|
|
|
// Address and Thread sanitizers always run in diagnostic mode.
|
|
|
|
Diag struct {
|
2017-06-28 18:10:48 +02:00
|
|
|
Undefined *bool `android:"arch_variant"`
|
|
|
|
Cfi *bool `android:"arch_variant"`
|
|
|
|
Integer_overflow *bool `android:"arch_variant"`
|
|
|
|
Misc_undefined []string `android:"arch_variant"`
|
2016-08-17 00:39:54 +02:00
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
|
2016-08-17 00:39:54 +02:00
|
|
|
// value to pass to -fsanitize-recover=
|
2016-01-06 23:41:07 +01:00
|
|
|
Recover []string
|
|
|
|
|
|
|
|
// value to pass to -fsanitize-blacklist
|
|
|
|
Blacklist *string
|
|
|
|
} `android:"arch_variant"`
|
|
|
|
|
2018-02-22 00:49:20 +01:00
|
|
|
SanitizerEnabled bool `blueprint:"mutated"`
|
|
|
|
SanitizeDep bool `blueprint:"mutated"`
|
|
|
|
MinimalRuntimeDep bool `blueprint:"mutated"`
|
2018-03-13 18:41:07 +01:00
|
|
|
UbsanRuntimeDep bool `blueprint:"mutated"`
|
2018-02-22 00:49:20 +01:00
|
|
|
InSanitizerDir bool `blueprint:"mutated"`
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type sanitize struct {
|
|
|
|
Properties SanitizeProperties
|
2017-05-08 22:44:11 +02:00
|
|
|
|
2017-07-18 06:23:39 +02:00
|
|
|
runtimeLibrary string
|
|
|
|
androidMkRuntimeLibrary string
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
2017-11-17 20:08:10 +01:00
|
|
|
func init() {
|
|
|
|
android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
|
2018-08-03 01:19:13 +02:00
|
|
|
android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
|
2017-11-17 20:08:10 +01:00
|
|
|
}
|
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
func (sanitize *sanitize) props() []interface{} {
|
|
|
|
return []interface{}{&sanitize.Properties}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sanitize *sanitize) begin(ctx BaseModuleContext) {
|
2016-07-07 19:54:07 +02:00
|
|
|
s := &sanitize.Properties.Sanitize
|
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
// Don't apply sanitizers to NDK code.
|
2017-09-28 02:01:44 +02:00
|
|
|
if ctx.useSdk() {
|
2017-11-07 19:57:05 +01:00
|
|
|
s.Never = BoolPtr(true)
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Never always wins.
|
2017-11-07 19:57:05 +01:00
|
|
|
if Bool(s.Never) {
|
2016-01-06 23:41:07 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var globalSanitizers []string
|
2017-06-28 18:10:48 +02:00
|
|
|
var globalSanitizersDiag []string
|
|
|
|
|
2018-10-08 05:54:34 +02:00
|
|
|
if ctx.Host() {
|
|
|
|
if !ctx.Windows() {
|
|
|
|
globalSanitizers = ctx.Config().SanitizeHost()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
arches := ctx.Config().SanitizeDeviceArch()
|
|
|
|
if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
|
|
|
|
globalSanitizers = ctx.Config().SanitizeDevice()
|
|
|
|
globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-07 19:38:41 +02:00
|
|
|
if len(globalSanitizers) > 0 {
|
|
|
|
var found bool
|
2016-07-07 19:54:07 +02:00
|
|
|
if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil {
|
|
|
|
s.All_undefined = boolPtr(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil {
|
|
|
|
s.Undefined = boolPtr(true)
|
2016-07-07 19:38:41 +02:00
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
|
2016-12-29 00:52:54 +01:00
|
|
|
if found, globalSanitizers = removeFromList("address", globalSanitizers); found {
|
|
|
|
if s.Address == nil {
|
|
|
|
s.Address = boolPtr(true)
|
|
|
|
} else if *s.Address == false {
|
|
|
|
// Coverage w/o address is an error. If globalSanitizers includes both, and the module
|
|
|
|
// disables address, then disable coverage as well.
|
|
|
|
_, globalSanitizers = removeFromList("coverage", globalSanitizers)
|
|
|
|
}
|
2016-07-07 19:38:41 +02:00
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
|
|
|
|
s.Thread = boolPtr(true)
|
2016-07-07 19:38:41 +02:00
|
|
|
}
|
2016-05-12 22:54:53 +02:00
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found && s.Coverage == nil {
|
|
|
|
s.Coverage = boolPtr(true)
|
2016-07-07 19:38:41 +02:00
|
|
|
}
|
2016-05-19 01:39:54 +02:00
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
|
|
|
|
s.Safestack = boolPtr(true)
|
2016-07-07 19:38:41 +02:00
|
|
|
}
|
2016-05-19 01:39:54 +02:00
|
|
|
|
2016-08-17 00:39:54 +02:00
|
|
|
if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil {
|
2017-11-29 09:27:14 +01:00
|
|
|
if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) {
|
2017-10-31 10:26:14 +01:00
|
|
|
s.Cfi = boolPtr(true)
|
|
|
|
}
|
2016-08-17 00:39:54 +02:00
|
|
|
}
|
|
|
|
|
2018-03-13 18:41:07 +01:00
|
|
|
// Global integer_overflow builds do not support static libraries.
|
2017-06-28 18:10:48 +02:00
|
|
|
if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil {
|
2018-03-13 18:41:07 +01:00
|
|
|
if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && !ctx.static() {
|
2017-07-13 23:46:05 +02:00
|
|
|
s.Integer_overflow = boolPtr(true)
|
|
|
|
}
|
2017-06-28 18:10:48 +02:00
|
|
|
}
|
|
|
|
|
2018-06-12 23:46:54 +02:00
|
|
|
if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil {
|
|
|
|
s.Scudo = boolPtr(true)
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
|
|
|
|
s.Hwaddress = boolPtr(true)
|
|
|
|
}
|
|
|
|
|
2016-07-07 19:38:41 +02:00
|
|
|
if len(globalSanitizers) > 0 {
|
|
|
|
ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
|
|
|
|
}
|
2017-06-28 18:10:48 +02:00
|
|
|
|
2018-03-13 18:41:07 +01:00
|
|
|
// Global integer_overflow builds do not support static library diagnostics.
|
2017-06-28 18:10:48 +02:00
|
|
|
if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found &&
|
2018-03-13 18:41:07 +01:00
|
|
|
s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) && !ctx.static() {
|
2017-06-28 18:10:48 +02:00
|
|
|
s.Diag.Integer_overflow = boolPtr(true)
|
|
|
|
}
|
|
|
|
|
2017-10-31 10:26:14 +01:00
|
|
|
if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found &&
|
|
|
|
s.Diag.Cfi == nil && Bool(s.Cfi) {
|
|
|
|
s.Diag.Cfi = boolPtr(true)
|
|
|
|
}
|
|
|
|
|
2017-06-28 18:10:48 +02:00
|
|
|
if len(globalSanitizersDiag) > 0 {
|
|
|
|
ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0])
|
|
|
|
}
|
2016-07-07 19:54:07 +02:00
|
|
|
}
|
2016-07-19 00:44:56 +02:00
|
|
|
|
2018-05-25 03:36:18 +02:00
|
|
|
// Enable CFI for all components in the include paths (for Aarch64 only)
|
|
|
|
if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
|
2018-03-30 04:55:23 +02:00
|
|
|
s.Cfi = boolPtr(true)
|
|
|
|
if inList("cfi", ctx.Config().SanitizeDeviceDiag()) {
|
|
|
|
s.Diag.Cfi = boolPtr(true)
|
2017-10-31 10:26:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-01 03:37:30 +01:00
|
|
|
// CFI needs gold linker, and mips toolchain does not have one.
|
2017-11-29 09:27:14 +01:00
|
|
|
if !ctx.Config().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 {
|
2017-01-19 22:54:55 +01:00
|
|
|
s.Cfi = nil
|
|
|
|
s.Diag.Cfi = nil
|
|
|
|
}
|
|
|
|
|
2017-02-08 05:31:41 +01:00
|
|
|
// Also disable CFI for arm32 until b/35157333 is fixed.
|
|
|
|
if ctx.Arch().ArchType == android.Arm {
|
|
|
|
s.Cfi = nil
|
|
|
|
s.Diag.Cfi = nil
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
// HWASan requires AArch64 hardware feature (top-byte-ignore).
|
|
|
|
if ctx.Arch().ArchType != android.Arm64 {
|
|
|
|
s.Hwaddress = nil
|
|
|
|
}
|
|
|
|
|
2018-11-20 01:03:58 +01:00
|
|
|
// SCS is only implemented on AArch64.
|
|
|
|
// We also disable SCS if ASAN, TSAN or HWASAN are enabled because Clang considers
|
|
|
|
// them to be incompatible, although they are in fact compatible.
|
|
|
|
// TODO(pcc): Remove these checks once r347282 is rolled into the compiler.
|
|
|
|
if ctx.Arch().ArchType != android.Arm64 || Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) {
|
|
|
|
s.Scs = nil
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:42:52 +02:00
|
|
|
// Also disable CFI if ASAN is enabled.
|
2018-08-03 01:19:13 +02:00
|
|
|
if Bool(s.Address) || Bool(s.Hwaddress) {
|
2017-04-20 16:42:52 +02:00
|
|
|
s.Cfi = nil
|
|
|
|
s.Diag.Cfi = nil
|
|
|
|
}
|
|
|
|
|
2018-03-13 18:41:07 +01:00
|
|
|
// Disable sanitizers that depend on the UBSan runtime for host builds.
|
2017-11-17 20:08:10 +01:00
|
|
|
if ctx.Host() {
|
|
|
|
s.Cfi = nil
|
|
|
|
s.Diag.Cfi = nil
|
2018-03-13 18:41:07 +01:00
|
|
|
s.Misc_undefined = nil
|
|
|
|
s.Undefined = nil
|
|
|
|
s.All_undefined = nil
|
|
|
|
s.Integer_overflow = nil
|
2017-11-17 20:08:10 +01:00
|
|
|
}
|
|
|
|
|
2018-05-28 22:54:48 +02:00
|
|
|
// Also disable CFI for VNDK variants of components
|
|
|
|
if ctx.isVndk() && ctx.useVndk() {
|
2018-05-24 04:29:55 +02:00
|
|
|
s.Cfi = nil
|
|
|
|
s.Diag.Cfi = nil
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
|
2018-11-16 02:34:18 +01:00
|
|
|
// Keep libc instrumented so that recovery can run hwasan-instrumented code if necessary.
|
|
|
|
if ctx.inRecovery() && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
|
2018-08-03 01:19:13 +02:00
|
|
|
s.Hwaddress = nil
|
|
|
|
}
|
|
|
|
|
2016-07-19 00:44:56 +02:00
|
|
|
if ctx.staticBinary() {
|
|
|
|
s.Address = nil
|
2016-08-12 00:54:20 +02:00
|
|
|
s.Coverage = nil
|
2016-07-19 00:44:56 +02:00
|
|
|
s.Thread = nil
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(s.All_undefined) {
|
|
|
|
s.Undefined = nil
|
|
|
|
}
|
|
|
|
|
2016-05-12 22:54:53 +02:00
|
|
|
if !ctx.toolchain().Is64Bit() {
|
|
|
|
// TSAN and SafeStack are not supported on 32-bit architectures
|
2016-07-07 19:54:07 +02:00
|
|
|
s.Thread = nil
|
|
|
|
s.Safestack = nil
|
2016-01-06 23:41:07 +01:00
|
|
|
// TODO(ccross): error for compile_multilib = "32"?
|
|
|
|
}
|
|
|
|
|
2017-01-28 00:44:44 +01:00
|
|
|
if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
|
2018-06-12 23:46:54 +02:00
|
|
|
Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
|
2018-11-20 01:03:58 +01:00
|
|
|
Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) {
|
2016-07-19 00:44:56 +02:00
|
|
|
sanitize.Properties.SanitizerEnabled = true
|
|
|
|
}
|
|
|
|
|
2018-06-12 23:46:54 +02:00
|
|
|
// Disable Scudo if ASan or TSan is enabled.
|
2018-08-03 01:19:13 +02:00
|
|
|
if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) {
|
2018-06-12 23:46:54 +02:00
|
|
|
s.Scudo = nil
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
if Bool(s.Hwaddress) {
|
|
|
|
s.Address = nil
|
|
|
|
s.Thread = nil
|
|
|
|
}
|
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(s.Coverage) {
|
|
|
|
if !Bool(s.Address) {
|
2016-01-06 23:41:07 +01:00
|
|
|
ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps {
|
|
|
|
if !sanitize.Properties.SanitizerEnabled { // || c.static() {
|
|
|
|
return deps
|
|
|
|
}
|
|
|
|
|
|
|
|
if ctx.Device() {
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Address) {
|
2017-06-15 23:45:18 +02:00
|
|
|
deps.StaticLibs = append(deps.StaticLibs, asanLibs...)
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return deps
|
|
|
|
}
|
|
|
|
|
2018-11-15 23:01:36 +01:00
|
|
|
func toDisableImplicitIntegerChange(flags []string) bool {
|
|
|
|
// Returns true if any flag is fsanitize*integer, and there is
|
|
|
|
// no explicit flag about sanitize=implicit-integer-sign-change.
|
|
|
|
for _, f := range flags {
|
|
|
|
if strings.Contains(f, "sanitize=implicit-integer-sign-change") {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, f := range flags {
|
|
|
|
if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
|
2018-05-10 23:17:22 +02:00
|
|
|
minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
|
|
|
|
minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib
|
2018-02-22 00:49:20 +01:00
|
|
|
|
|
|
|
if ctx.Device() && sanitize.Properties.MinimalRuntimeDep {
|
|
|
|
flags.LdFlags = append(flags.LdFlags, minimalRuntimePath)
|
2018-05-10 23:17:22 +02:00
|
|
|
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
|
2018-02-22 00:49:20 +01:00
|
|
|
}
|
2018-03-13 18:41:07 +01:00
|
|
|
if !sanitize.Properties.SanitizerEnabled && !sanitize.Properties.UbsanRuntimeDep {
|
2016-01-06 23:41:07 +01:00
|
|
|
return flags
|
|
|
|
}
|
|
|
|
|
|
|
|
var sanitizers []string
|
2016-08-17 00:39:54 +02:00
|
|
|
var diagSanitizers []string
|
2016-01-06 23:41:07 +01:00
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.All_undefined) {
|
2016-01-06 23:41:07 +01:00
|
|
|
sanitizers = append(sanitizers, "undefined")
|
|
|
|
} else {
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Undefined) {
|
2016-01-06 23:41:07 +01:00
|
|
|
sanitizers = append(sanitizers,
|
|
|
|
"bool",
|
|
|
|
"integer-divide-by-zero",
|
|
|
|
"return",
|
|
|
|
"returns-nonnull-attribute",
|
|
|
|
"shift-exponent",
|
|
|
|
"unreachable",
|
|
|
|
"vla-bound",
|
|
|
|
// TODO(danalbert): The following checks currently have compiler performance issues.
|
|
|
|
//"alignment",
|
|
|
|
//"bounds",
|
|
|
|
//"enum",
|
|
|
|
//"float-cast-overflow",
|
|
|
|
//"float-divide-by-zero",
|
|
|
|
//"nonnull-attribute",
|
|
|
|
//"null",
|
|
|
|
//"shift-base",
|
|
|
|
//"signed-integer-overflow",
|
|
|
|
// TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
|
|
|
|
// https://llvm.org/PR19302
|
|
|
|
// http://reviews.llvm.org/D6974
|
|
|
|
// "object-size",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
sanitizers = append(sanitizers, sanitize.Properties.Sanitize.Misc_undefined...)
|
|
|
|
}
|
|
|
|
|
2017-06-13 19:24:34 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Diag.Undefined) {
|
2016-08-17 00:39:54 +02:00
|
|
|
diagSanitizers = append(diagSanitizers, "undefined")
|
|
|
|
}
|
|
|
|
|
2017-06-13 19:24:34 +02:00
|
|
|
diagSanitizers = append(diagSanitizers, sanitize.Properties.Sanitize.Diag.Misc_undefined...)
|
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Address) {
|
2016-05-19 00:37:25 +02:00
|
|
|
if ctx.Arch().ArchType == android.Arm {
|
2016-01-06 23:41:07 +01:00
|
|
|
// Frame pointer based unwinder in ASan requires ARM frame setup.
|
|
|
|
// TODO: put in flags?
|
|
|
|
flags.RequiredInstructionSet = "arm"
|
|
|
|
}
|
2017-06-15 23:45:18 +02:00
|
|
|
flags.CFlags = append(flags.CFlags, asanCflags...)
|
|
|
|
flags.LdFlags = append(flags.LdFlags, asanLdflags...)
|
2016-01-06 23:41:07 +01:00
|
|
|
|
|
|
|
if ctx.Host() {
|
|
|
|
// -nodefaultlibs (provided with libc++) prevents the driver from linking
|
|
|
|
// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
|
|
|
|
flags.LdFlags = append(flags.LdFlags, "-Wl,--no-as-needed")
|
|
|
|
} else {
|
|
|
|
flags.CFlags = append(flags.CFlags, "-mllvm", "-asan-globals=0")
|
|
|
|
flags.DynamicLinker = "/system/bin/linker_asan"
|
|
|
|
if flags.Toolchain.Is64Bit() {
|
|
|
|
flags.DynamicLinker += "64"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sanitizers = append(sanitizers, "address")
|
2016-08-17 00:39:54 +02:00
|
|
|
diagSanitizers = append(diagSanitizers, "address")
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Hwaddress) {
|
|
|
|
flags.CFlags = append(flags.CFlags, hwasanCflags...)
|
|
|
|
sanitizers = append(sanitizers, "hwaddress")
|
|
|
|
}
|
|
|
|
|
2017-10-20 00:52:11 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Thread) {
|
|
|
|
sanitizers = append(sanitizers, "thread")
|
|
|
|
}
|
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Coverage) {
|
2017-08-21 23:12:32 +02:00
|
|
|
flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp")
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
2016-07-07 19:54:07 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Safestack) {
|
2016-05-12 22:54:53 +02:00
|
|
|
sanitizers = append(sanitizers, "safe-stack")
|
|
|
|
}
|
|
|
|
|
2016-08-17 00:39:54 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Cfi) {
|
2017-01-20 23:13:06 +01:00
|
|
|
if ctx.Arch().ArchType == android.Arm {
|
|
|
|
// __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
|
|
|
|
// to do this on a function basis, so force Thumb on the entire module.
|
|
|
|
flags.RequiredInstructionSet = "thumb"
|
|
|
|
}
|
2016-08-17 00:39:54 +02:00
|
|
|
sanitizers = append(sanitizers, "cfi")
|
2017-11-01 10:20:21 +01:00
|
|
|
|
2017-06-15 23:45:18 +02:00
|
|
|
flags.CFlags = append(flags.CFlags, cfiCflags...)
|
2018-08-31 21:54:33 +02:00
|
|
|
flags.AsFlags = append(flags.AsFlags, cfiAsflags...)
|
2017-11-01 10:20:21 +01:00
|
|
|
// Only append the default visibility flag if -fvisibility has not already been set
|
|
|
|
// to hidden.
|
|
|
|
if !inList("-fvisibility=hidden", flags.CFlags) {
|
|
|
|
flags.CFlags = append(flags.CFlags, "-fvisibility=default")
|
|
|
|
}
|
2017-06-15 23:45:18 +02:00
|
|
|
flags.LdFlags = append(flags.LdFlags, cfiLdflags...)
|
2016-08-17 00:39:54 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Diag.Cfi) {
|
|
|
|
diagSanitizers = append(diagSanitizers, "cfi")
|
|
|
|
}
|
2017-11-01 10:20:21 +01:00
|
|
|
|
|
|
|
if ctx.staticBinary() {
|
|
|
|
_, flags.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.CFlags)
|
|
|
|
_, flags.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.LdFlags)
|
|
|
|
}
|
2016-08-17 00:39:54 +02:00
|
|
|
}
|
|
|
|
|
2017-06-28 18:10:48 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Integer_overflow) {
|
2018-03-13 18:41:07 +01:00
|
|
|
sanitizers = append(sanitizers, "unsigned-integer-overflow")
|
|
|
|
sanitizers = append(sanitizers, "signed-integer-overflow")
|
|
|
|
flags.CFlags = append(flags.CFlags, intOverflowCflags...)
|
|
|
|
if Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) {
|
|
|
|
diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
|
|
|
|
diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
|
2017-06-28 18:10:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-12 23:46:54 +02:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Scudo) {
|
|
|
|
sanitizers = append(sanitizers, "scudo")
|
|
|
|
}
|
|
|
|
|
2018-11-20 01:03:58 +01:00
|
|
|
if Bool(sanitize.Properties.Sanitize.Scs) {
|
|
|
|
sanitizers = append(sanitizers, "shadow-call-stack")
|
|
|
|
}
|
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
if len(sanitizers) > 0 {
|
|
|
|
sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
|
2018-02-22 00:49:20 +01:00
|
|
|
|
2016-01-06 23:41:07 +01:00
|
|
|
flags.CFlags = append(flags.CFlags, sanitizeArg)
|
2018-08-31 21:54:33 +02:00
|
|
|
flags.AsFlags = append(flags.AsFlags, sanitizeArg)
|
2016-01-06 23:41:07 +01:00
|
|
|
if ctx.Host() {
|
|
|
|
flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
|
|
|
|
flags.LdFlags = append(flags.LdFlags, sanitizeArg)
|
2017-01-28 00:44:44 +01:00
|
|
|
// Host sanitizers only link symbols in the final executable, so
|
|
|
|
// there will always be undefined symbols in intermediate libraries.
|
|
|
|
_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
|
2016-01-06 23:41:07 +01:00
|
|
|
} else {
|
2016-07-15 22:10:48 +02:00
|
|
|
flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
|
2018-02-22 00:49:20 +01:00
|
|
|
|
|
|
|
if enableMinimalRuntime(sanitize) {
|
|
|
|
flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " "))
|
|
|
|
flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
|
2018-05-10 23:17:22 +02:00
|
|
|
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
|
2018-02-22 00:49:20 +01:00
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
2018-11-15 23:01:36 +01:00
|
|
|
// http://b/119329758, Android core does not boot up with this sanitizer yet.
|
|
|
|
if toDisableImplicitIntegerChange(flags.CFlags) {
|
|
|
|
flags.CFlags = append(flags.CFlags, "-fno-sanitize=implicit-integer-sign-change")
|
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
|
2016-08-17 00:39:54 +02:00
|
|
|
if len(diagSanitizers) > 0 {
|
2018-01-20 02:44:38 +01:00
|
|
|
flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap="+strings.Join(diagSanitizers, ","))
|
2016-08-17 00:39:54 +02:00
|
|
|
}
|
|
|
|
// FIXME: enable RTTI if diag + (cfi or vptr)
|
|
|
|
|
2017-05-08 22:15:23 +02:00
|
|
|
if sanitize.Properties.Sanitize.Recover != nil {
|
|
|
|
flags.CFlags = append(flags.CFlags, "-fsanitize-recover="+
|
|
|
|
strings.Join(sanitize.Properties.Sanitize.Recover, ","))
|
|
|
|
}
|
|
|
|
|
2016-08-17 00:39:54 +02:00
|
|
|
// Link a runtime library if needed.
|
|
|
|
runtimeLibrary := ""
|
|
|
|
if Bool(sanitize.Properties.Sanitize.Address) {
|
|
|
|
runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain())
|
2018-08-03 01:19:13 +02:00
|
|
|
} else if Bool(sanitize.Properties.Sanitize.Hwaddress) {
|
|
|
|
runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(ctx.toolchain())
|
2017-10-20 00:52:11 +02:00
|
|
|
} else if Bool(sanitize.Properties.Sanitize.Thread) {
|
|
|
|
runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
|
2018-06-12 23:46:54 +02:00
|
|
|
} else if Bool(sanitize.Properties.Sanitize.Scudo) {
|
2018-10-11 17:38:39 +02:00
|
|
|
if len(diagSanitizers) == 0 && !sanitize.Properties.UbsanRuntimeDep {
|
|
|
|
runtimeLibrary = config.ScudoMinimalRuntimeLibrary(ctx.toolchain())
|
|
|
|
} else {
|
|
|
|
runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
|
|
|
|
}
|
2018-03-13 18:41:07 +01:00
|
|
|
} else if len(diagSanitizers) > 0 || sanitize.Properties.UbsanRuntimeDep {
|
2016-08-17 00:39:54 +02:00
|
|
|
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
|
|
|
|
}
|
|
|
|
|
|
|
|
if runtimeLibrary != "" {
|
2018-03-13 18:41:07 +01:00
|
|
|
runtimeLibraryPath := "${config.ClangAsanLibDir}/" + runtimeLibrary
|
|
|
|
if !ctx.static() {
|
|
|
|
runtimeLibraryPath = runtimeLibraryPath + ctx.toolchain().ShlibSuffix()
|
|
|
|
} else {
|
|
|
|
runtimeLibraryPath = runtimeLibraryPath + ".a"
|
|
|
|
}
|
|
|
|
|
2017-07-18 06:23:39 +02:00
|
|
|
// ASan runtime library must be the first in the link order.
|
2018-03-13 18:41:07 +01:00
|
|
|
flags.libFlags = append([]string{runtimeLibraryPath}, flags.libFlags...)
|
2017-05-08 22:44:11 +02:00
|
|
|
sanitize.runtimeLibrary = runtimeLibrary
|
2017-07-18 06:23:39 +02:00
|
|
|
|
|
|
|
// When linking against VNDK, use the vendor variant of the runtime lib
|
2017-09-28 02:01:44 +02:00
|
|
|
if ctx.useVndk() {
|
2017-07-18 06:23:39 +02:00
|
|
|
sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix
|
2018-11-30 00:12:51 +01:00
|
|
|
} else if ctx.inRecovery() {
|
|
|
|
sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + recoverySuffix
|
|
|
|
} else {
|
|
|
|
sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
|
2017-07-18 06:23:39 +02:00
|
|
|
}
|
2016-08-17 00:39:54 +02:00
|
|
|
}
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
blacklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist)
|
2016-01-06 23:41:07 +01:00
|
|
|
if blacklist.Valid() {
|
|
|
|
flags.CFlags = append(flags.CFlags, "-fsanitize-blacklist="+blacklist.String())
|
|
|
|
flags.CFlagsDeps = append(flags.CFlagsDeps, blacklist.Path())
|
|
|
|
}
|
|
|
|
|
|
|
|
return flags
|
|
|
|
}
|
|
|
|
|
2017-05-08 22:44:11 +02:00
|
|
|
func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
|
2017-08-11 01:32:23 +02:00
|
|
|
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
|
2017-07-18 06:23:39 +02:00
|
|
|
if sanitize.androidMkRuntimeLibrary != "" {
|
|
|
|
fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES += "+sanitize.androidMkRuntimeLibrary)
|
2017-05-08 22:44:11 +02:00
|
|
|
}
|
|
|
|
})
|
2017-11-17 20:08:10 +01:00
|
|
|
|
|
|
|
// Add a suffix for CFI-enabled static libraries to allow surfacing both to make without a
|
|
|
|
// name conflict.
|
|
|
|
if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Cfi) {
|
|
|
|
ret.SubName += ".cfi"
|
2017-11-01 10:20:21 +01:00
|
|
|
}
|
2018-08-03 01:19:13 +02:00
|
|
|
if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Hwaddress) {
|
|
|
|
ret.SubName += ".hwasan"
|
|
|
|
}
|
2018-11-20 01:03:58 +01:00
|
|
|
if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Scs) {
|
|
|
|
ret.SubName += ".scs"
|
|
|
|
}
|
2017-05-08 22:44:11 +02:00
|
|
|
}
|
|
|
|
|
2017-03-30 07:00:18 +02:00
|
|
|
func (sanitize *sanitize) inSanitizerDir() bool {
|
|
|
|
return sanitize.Properties.InSanitizerDir
|
2016-05-04 03:02:42 +02:00
|
|
|
}
|
|
|
|
|
2017-11-01 10:20:21 +01:00
|
|
|
func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool {
|
2016-01-06 23:41:07 +01:00
|
|
|
switch t {
|
|
|
|
case asan:
|
2017-11-01 10:20:21 +01:00
|
|
|
return sanitize.Properties.Sanitize.Address
|
2018-08-03 01:19:13 +02:00
|
|
|
case hwasan:
|
|
|
|
return sanitize.Properties.Sanitize.Hwaddress
|
2016-01-06 23:41:07 +01:00
|
|
|
case tsan:
|
2017-11-01 10:20:21 +01:00
|
|
|
return sanitize.Properties.Sanitize.Thread
|
2017-06-28 18:10:48 +02:00
|
|
|
case intOverflow:
|
2017-11-01 10:20:21 +01:00
|
|
|
return sanitize.Properties.Sanitize.Integer_overflow
|
|
|
|
case cfi:
|
|
|
|
return sanitize.Properties.Sanitize.Cfi
|
2018-11-20 01:03:58 +01:00
|
|
|
case scs:
|
|
|
|
return sanitize.Properties.Sanitize.Scs
|
2016-01-06 23:41:07 +01:00
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unknown sanitizerType %d", t))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-19 21:30:45 +01:00
|
|
|
func (sanitize *sanitize) isUnsanitizedVariant() bool {
|
|
|
|
return !sanitize.isSanitizerEnabled(asan) &&
|
2018-08-03 01:19:13 +02:00
|
|
|
!sanitize.isSanitizerEnabled(hwasan) &&
|
2018-01-19 21:30:45 +01:00
|
|
|
!sanitize.isSanitizerEnabled(tsan) &&
|
2018-11-20 01:03:58 +01:00
|
|
|
!sanitize.isSanitizerEnabled(cfi) &&
|
|
|
|
!sanitize.isSanitizerEnabled(scs)
|
2018-01-19 21:30:45 +01:00
|
|
|
}
|
|
|
|
|
2018-05-11 00:29:24 +02:00
|
|
|
func (sanitize *sanitize) isVariantOnProductionDevice() bool {
|
|
|
|
return !sanitize.isSanitizerEnabled(asan) &&
|
2018-08-03 01:19:13 +02:00
|
|
|
!sanitize.isSanitizerEnabled(hwasan) &&
|
2018-05-11 00:29:24 +02:00
|
|
|
!sanitize.isSanitizerEnabled(tsan)
|
|
|
|
}
|
|
|
|
|
2017-08-11 02:53:16 +02:00
|
|
|
func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
|
2017-08-02 23:18:08 +02:00
|
|
|
switch t {
|
|
|
|
case asan:
|
2017-08-11 02:53:16 +02:00
|
|
|
sanitize.Properties.Sanitize.Address = boolPtr(b)
|
|
|
|
if !b {
|
|
|
|
sanitize.Properties.Sanitize.Coverage = nil
|
|
|
|
}
|
2018-08-03 01:19:13 +02:00
|
|
|
case hwasan:
|
|
|
|
sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
|
2017-08-02 23:18:08 +02:00
|
|
|
case tsan:
|
2017-08-11 02:53:16 +02:00
|
|
|
sanitize.Properties.Sanitize.Thread = boolPtr(b)
|
2017-08-02 23:18:08 +02:00
|
|
|
case intOverflow:
|
2017-08-11 02:53:16 +02:00
|
|
|
sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b)
|
2017-11-01 10:20:21 +01:00
|
|
|
case cfi:
|
|
|
|
sanitize.Properties.Sanitize.Cfi = boolPtr(b)
|
2018-11-20 01:03:58 +01:00
|
|
|
case scs:
|
|
|
|
sanitize.Properties.Sanitize.Scs = boolPtr(b)
|
2017-08-02 23:18:08 +02:00
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unknown sanitizerType %d", t))
|
|
|
|
}
|
2017-08-11 02:53:16 +02:00
|
|
|
if b {
|
|
|
|
sanitize.Properties.SanitizerEnabled = true
|
2017-08-02 23:18:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-01 10:20:21 +01:00
|
|
|
// Check if the sanitizer is explicitly disabled (as opposed to nil by
|
|
|
|
// virtue of not being set).
|
|
|
|
func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool {
|
|
|
|
if sanitize == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
sanitizerVal := sanitize.getSanitizerBoolPtr(t)
|
|
|
|
return sanitizerVal != nil && *sanitizerVal == false
|
|
|
|
}
|
|
|
|
|
|
|
|
// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled)
|
|
|
|
// because enabling a sanitizer either directly (via the blueprint) or
|
|
|
|
// indirectly (via a mutator) sets the bool ptr to true, and you can't
|
|
|
|
// distinguish between the cases. It isn't needed though - both cases can be
|
|
|
|
// treated identically.
|
|
|
|
func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool {
|
|
|
|
if sanitize == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
sanitizerVal := sanitize.getSanitizerBoolPtr(t)
|
|
|
|
return sanitizerVal != nil && *sanitizerVal == true
|
|
|
|
}
|
|
|
|
|
2018-06-21 22:03:07 +02:00
|
|
|
func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
|
|
|
|
t, ok := tag.(dependencyTag)
|
|
|
|
return ok && t.library || t == reuseObjTag
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
// Propagate sanitizer requirements down from binaries
|
2016-05-19 00:37:25 +02:00
|
|
|
func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
|
|
|
|
return func(mctx android.TopDownMutatorContext) {
|
2017-11-01 10:20:21 +01:00
|
|
|
if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
|
2018-06-21 22:03:07 +02:00
|
|
|
mctx.WalkDeps(func(child, parent android.Module) bool {
|
|
|
|
if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if d, ok := child.(*Module); ok && d.sanitize != nil &&
|
2017-11-07 19:57:05 +01:00
|
|
|
!Bool(d.sanitize.Properties.Sanitize.Never) &&
|
2017-11-01 10:20:21 +01:00
|
|
|
!d.sanitize.isSanitizerExplicitlyDisabled(t) {
|
2018-11-20 01:03:58 +01:00
|
|
|
if t == cfi || t == hwasan || t == scs {
|
2018-08-03 01:19:13 +02:00
|
|
|
if d.static() {
|
|
|
|
d.sanitize.Properties.SanitizeDep = true
|
|
|
|
}
|
|
|
|
} else {
|
2017-11-01 10:20:21 +01:00
|
|
|
d.sanitize.Properties.SanitizeDep = true
|
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
2018-06-21 22:03:07 +02:00
|
|
|
return true
|
2016-01-06 23:41:07 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-22 00:49:20 +01:00
|
|
|
// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
|
2018-06-21 22:03:07 +02:00
|
|
|
func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
|
|
|
|
if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
|
|
|
|
mctx.WalkDeps(func(child, parent android.Module) bool {
|
|
|
|
if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if d, ok := child.(*Module); ok && d.static() && d.sanitize != nil {
|
|
|
|
|
|
|
|
if enableMinimalRuntime(d.sanitize) {
|
|
|
|
// If a static dependency is built with the minimal runtime,
|
|
|
|
// make sure we include the ubsan minimal runtime.
|
|
|
|
c.sanitize.Properties.MinimalRuntimeDep = true
|
|
|
|
} else if Bool(d.sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
|
|
|
|
len(d.sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0 {
|
|
|
|
// If a static dependency runs with full ubsan diagnostics,
|
|
|
|
// make sure we include the ubsan runtime.
|
|
|
|
c.sanitize.Properties.UbsanRuntimeDep = true
|
2018-02-22 00:49:20 +01:00
|
|
|
}
|
2018-06-21 22:03:07 +02:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
2018-02-22 00:49:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-01 10:20:21 +01:00
|
|
|
// Create sanitized variants for modules that need them
|
2016-05-19 00:37:25 +02:00
|
|
|
func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
|
|
|
|
return func(mctx android.BottomUpMutatorContext) {
|
2017-08-11 02:52:44 +02:00
|
|
|
if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
|
2017-11-01 10:20:21 +01:00
|
|
|
if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) {
|
2016-05-04 03:02:42 +02:00
|
|
|
modules := mctx.CreateVariations(t.String())
|
|
|
|
modules[0].(*Module).sanitize.SetSanitizer(t, true)
|
2017-11-01 10:20:21 +01:00
|
|
|
} else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep {
|
|
|
|
// Save original sanitizer status before we assign values to variant
|
|
|
|
// 0 as that overwrites the original.
|
|
|
|
isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t)
|
|
|
|
|
2016-09-20 01:46:53 +02:00
|
|
|
modules := mctx.CreateVariations("", t.String())
|
|
|
|
modules[0].(*Module).sanitize.SetSanitizer(t, false)
|
|
|
|
modules[1].(*Module).sanitize.SetSanitizer(t, true)
|
2017-11-01 10:20:21 +01:00
|
|
|
|
2016-09-20 01:46:53 +02:00
|
|
|
modules[0].(*Module).sanitize.Properties.SanitizeDep = false
|
|
|
|
modules[1].(*Module).sanitize.Properties.SanitizeDep = false
|
2017-11-17 20:08:10 +01:00
|
|
|
|
|
|
|
// We don't need both variants active for anything but CFI-enabled
|
|
|
|
// target static libraries, so suppress the appropriate variant in
|
|
|
|
// all other cases.
|
|
|
|
if t == cfi {
|
|
|
|
if c.static() {
|
|
|
|
if !mctx.Device() {
|
|
|
|
if isSanitizerEnabled {
|
|
|
|
modules[0].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[0].(*Module).Properties.HideFromMake = true
|
|
|
|
} else {
|
|
|
|
modules[1].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[1].(*Module).Properties.HideFromMake = true
|
|
|
|
}
|
2017-11-01 10:20:21 +01:00
|
|
|
} else {
|
2017-11-29 09:27:14 +01:00
|
|
|
cfiStaticLibs := cfiStaticLibs(mctx.Config())
|
2017-11-17 20:08:10 +01:00
|
|
|
|
|
|
|
cfiStaticLibsMutex.Lock()
|
|
|
|
*cfiStaticLibs = append(*cfiStaticLibs, c.Name())
|
|
|
|
cfiStaticLibsMutex.Unlock()
|
2017-11-01 10:20:21 +01:00
|
|
|
}
|
2017-11-17 20:08:10 +01:00
|
|
|
} else {
|
|
|
|
modules[0].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[0].(*Module).Properties.HideFromMake = true
|
|
|
|
}
|
|
|
|
} else if t == asan {
|
|
|
|
if mctx.Device() {
|
|
|
|
// CFI and ASAN are currently mutually exclusive so disable
|
|
|
|
// CFI if this is an ASAN variant.
|
|
|
|
modules[1].(*Module).sanitize.Properties.InSanitizerDir = true
|
|
|
|
modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
|
2017-11-01 10:20:21 +01:00
|
|
|
}
|
2017-11-02 03:42:45 +01:00
|
|
|
if isSanitizerEnabled {
|
|
|
|
modules[0].(*Module).Properties.PreventInstall = true
|
2017-11-17 20:08:10 +01:00
|
|
|
modules[0].(*Module).Properties.HideFromMake = true
|
2017-11-02 03:42:45 +01:00
|
|
|
} else {
|
|
|
|
modules[1].(*Module).Properties.PreventInstall = true
|
2017-11-17 20:08:10 +01:00
|
|
|
modules[1].(*Module).Properties.HideFromMake = true
|
2017-11-02 03:42:45 +01:00
|
|
|
}
|
2018-11-20 01:03:58 +01:00
|
|
|
} else if t == scs {
|
|
|
|
// We don't currently link any static libraries built with make into
|
|
|
|
// libraries built with SCS, so we don't need logic for propagating
|
|
|
|
// SCSness of dependencies into make.
|
|
|
|
if !c.static() {
|
|
|
|
if isSanitizerEnabled {
|
|
|
|
modules[0].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[0].(*Module).Properties.HideFromMake = true
|
|
|
|
} else {
|
|
|
|
modules[1].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[1].(*Module).Properties.HideFromMake = true
|
|
|
|
}
|
|
|
|
}
|
2018-08-03 01:19:13 +02:00
|
|
|
} else if t == hwasan {
|
|
|
|
if mctx.Device() {
|
|
|
|
// CFI and HWASAN are currently mutually exclusive so disable
|
|
|
|
// CFI if this is an HWASAN variant.
|
|
|
|
modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.static() {
|
|
|
|
if c.useVndk() {
|
|
|
|
hwasanVendorStaticLibs := hwasanVendorStaticLibs(mctx.Config())
|
|
|
|
hwasanStaticLibsMutex.Lock()
|
|
|
|
*hwasanVendorStaticLibs = append(*hwasanVendorStaticLibs, c.Name())
|
|
|
|
hwasanStaticLibsMutex.Unlock()
|
|
|
|
} else {
|
|
|
|
hwasanStaticLibs := hwasanStaticLibs(mctx.Config())
|
|
|
|
hwasanStaticLibsMutex.Lock()
|
|
|
|
*hwasanStaticLibs = append(*hwasanStaticLibs, c.Name())
|
|
|
|
hwasanStaticLibsMutex.Unlock()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if isSanitizerEnabled {
|
|
|
|
modules[0].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[0].(*Module).Properties.HideFromMake = true
|
|
|
|
} else {
|
|
|
|
modules[1].(*Module).Properties.PreventInstall = true
|
|
|
|
modules[1].(*Module).Properties.HideFromMake = true
|
|
|
|
}
|
|
|
|
}
|
2017-11-02 03:42:45 +01:00
|
|
|
}
|
2016-01-06 23:41:07 +01:00
|
|
|
}
|
|
|
|
c.sanitize.Properties.SanitizeDep = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-17 20:08:10 +01:00
|
|
|
|
|
|
|
func cfiStaticLibs(config android.Config) *[]string {
|
|
|
|
return config.Once("cfiStaticLibs", func() interface{} {
|
|
|
|
return &[]string{}
|
|
|
|
}).(*[]string)
|
|
|
|
}
|
|
|
|
|
2018-08-03 01:19:13 +02:00
|
|
|
func hwasanStaticLibs(config android.Config) *[]string {
|
|
|
|
return config.Once("hwasanStaticLibs", func() interface{} {
|
|
|
|
return &[]string{}
|
|
|
|
}).(*[]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
func hwasanVendorStaticLibs(config android.Config) *[]string {
|
|
|
|
return config.Once("hwasanVendorStaticLibs", func() interface{} {
|
|
|
|
return &[]string{}
|
|
|
|
}).(*[]string)
|
|
|
|
}
|
|
|
|
|
2018-02-22 00:49:20 +01:00
|
|
|
func enableMinimalRuntime(sanitize *sanitize) bool {
|
|
|
|
if !Bool(sanitize.Properties.Sanitize.Address) &&
|
2018-08-03 01:19:13 +02:00
|
|
|
!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
|
2018-02-22 00:49:20 +01:00
|
|
|
(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
|
|
|
|
len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
|
|
|
|
!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
|
|
|
|
Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
|
|
|
|
len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-11-17 20:08:10 +01:00
|
|
|
func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
|
|
|
|
cfiStaticLibs := cfiStaticLibs(ctx.Config())
|
2017-11-29 01:37:53 +01:00
|
|
|
sort.Strings(*cfiStaticLibs)
|
2017-11-17 20:08:10 +01:00
|
|
|
ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " "))
|
|
|
|
}
|
2018-08-03 01:19:13 +02:00
|
|
|
|
|
|
|
func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
|
|
|
|
hwasanStaticLibs := hwasanStaticLibs(ctx.Config())
|
|
|
|
sort.Strings(*hwasanStaticLibs)
|
|
|
|
ctx.Strict("SOONG_HWASAN_STATIC_LIBRARIES", strings.Join(*hwasanStaticLibs, " "))
|
|
|
|
|
|
|
|
hwasanVendorStaticLibs := hwasanVendorStaticLibs(ctx.Config())
|
|
|
|
sort.Strings(*hwasanVendorStaticLibs)
|
|
|
|
ctx.Strict("SOONG_HWASAN_VENDOR_STATIC_LIBRARIES", strings.Join(*hwasanVendorStaticLibs, " "))
|
|
|
|
}
|