aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2016-01-06 14:41:07 -0800
committerColin Cross <ccross@android.com>2016-04-21 16:42:08 -0700
commit16b234919080732f438598adc3a3ca5fe2456b88 (patch)
tree1e55a1a80cac5d1657dd4585cf37bd87751dbed5
parent4a97cb432823899dfc70cd5a874409b353e08115 (diff)
downloadbuild_soong-16b234919080732f438598adc3a3ca5fe2456b88.tar.gz
build_soong-16b234919080732f438598adc3a3ca5fe2456b88.tar.bz2
build_soong-16b234919080732f438598adc3a3ca5fe2456b88.zip
Add support for sanitizer property
Add a new feature to cc modules that adds the cflags and libraries necessary to implement AddressSanitizer, ThreadSanitizer, and UndefinedBehaviorSanitizer. Change-Id: Ibe5ffadc7ece56080a2521f2c7c00da9ef712584
-rw-r--r--Android.bp1
-rw-r--r--cc/arm64_device.go4
-rw-r--r--cc/arm_device.go4
-rw-r--r--cc/builder.go11
-rw-r--r--cc/cc.go94
-rw-r--r--cc/sanitize.go329
-rw-r--r--cc/toolchain.go6
-rw-r--r--cc/util.go22
-rw-r--r--cc/x86_device.go4
-rw-r--r--common/config.go14
-rw-r--r--common/variable.go3
11 files changed, 467 insertions, 25 deletions
diff --git a/Android.bp b/Android.bp
index b4928f8b..831b703f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -124,6 +124,7 @@ bootstrap_go_package {
"cc/cc.go",
"cc/clang.go",
"cc/gen.go",
+ "cc/sanitize.go",
"cc/stl.go",
"cc/toolchain.go",
"cc/util.go",
diff --git a/cc/arm64_device.go b/cc/arm64_device.go
index 1a0408c6..9194c6d1 100644
--- a/cc/arm64_device.go
+++ b/cc/arm64_device.go
@@ -190,6 +190,10 @@ func (t *toolchainArm64) ToolchainClangCflags() string {
return t.toolchainClangCflags
}
+func (toolchainArm64) AddressSanitizerRuntimeLibrary() string {
+ return "libclang_rt.asan-aarch64-android.so"
+}
+
func arm64ToolchainFactory(arch common.Arch) Toolchain {
if arch.ArchVariant != "armv8-a" {
panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant))
diff --git a/cc/arm_device.go b/cc/arm_device.go
index ea7db431..764aaa9a 100644
--- a/cc/arm_device.go
+++ b/cc/arm_device.go
@@ -337,6 +337,10 @@ func (t *toolchainArm) ClangInstructionSetFlags(isa string) (string, error) {
}
}
+func (toolchainArm) AddressSanitizerRuntimeLibrary() string {
+ return "libclang_rt.asan-arm-android.so"
+}
+
func armToolchainFactory(arch common.Arch) Toolchain {
var fixCortexA8 string
toolchainCflags := make([]string, 2, 3)
diff --git a/cc/builder.go b/cc/builder.go
index 38bb141c..f67f9bd3 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -133,6 +133,7 @@ type builderFlags struct {
conlyFlags string
cppFlags string
ldFlags string
+ libFlags string
yaccFlags string
nocrt bool
toolchain Toolchain
@@ -190,7 +191,7 @@ func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFil
panic("unrecoginzied ccCmd")
}
- ccCmd = "${clangPath}/" + ccCmd
+ ccCmd = "${clangBin}/" + ccCmd
} else {
ccCmd = gccCmd(flags.toolchain, ccCmd)
}
@@ -288,7 +289,7 @@ func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
var ldCmd string
if flags.clang {
- ldCmd = "${clangPath}/clang++"
+ ldCmd = "${clangBin}/clang++"
} else {
ldCmd = gccCmd(flags.toolchain, "g++")
}
@@ -296,6 +297,10 @@ func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
var ldDirs []string
var libFlagsList []string
+ if len(flags.libFlags) > 0 {
+ libFlagsList = append(libFlagsList, flags.libFlags)
+ }
+
if len(wholeStaticLibs) > 0 {
if ctx.Host() && ctx.Darwin() {
libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
@@ -359,7 +364,7 @@ func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles common.Paths,
var ldCmd string
if flags.clang {
- ldCmd = "${clangPath}clang++"
+ ldCmd = "${clangBin}clang++"
} else {
ldCmd = gccCmd(flags.toolchain, "g++")
}
diff --git a/cc/cc.go b/cc/cc.go
index 18dd09c7..851e4c3e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -59,6 +59,12 @@ func init() {
common.RegisterBottomUpMutator("link", linkageMutator)
common.RegisterBottomUpMutator("test_per_src", testPerSrcMutator)
common.RegisterBottomUpMutator("deps", depsMutator)
+
+ common.RegisterTopDownMutator("asan_deps", sanitizerDepsMutator(asan))
+ common.RegisterBottomUpMutator("asan", sanitizerMutator(asan))
+
+ common.RegisterTopDownMutator("tsan_deps", sanitizerDepsMutator(tsan))
+ common.RegisterBottomUpMutator("tsan", sanitizerMutator(tsan))
}
var (
@@ -168,7 +174,8 @@ func init() {
}
return "clang-2690385", nil
})
- pctx.StaticVariable("clangPath", "${clangBase}/${HostPrebuiltTag}/${clangVersion}/bin")
+ pctx.StaticVariable("clangPath", "${clangBase}/${HostPrebuiltTag}/${clangVersion}")
+ pctx.StaticVariable("clangBin", "${clangPath}/bin")
}
type Deps struct {
@@ -208,12 +215,16 @@ type Flags struct {
CppFlags []string // Flags that apply to C++ source files
YaccFlags []string // Flags that apply to Yacc source files
LdFlags []string // Flags that apply to linker command lines
+ libFlags []string // Flags to add libraries early to the link order
Nocrt bool
Toolchain Toolchain
Clang bool
RequiredInstructionSet string
+ DynamicLinker string
+
+ CFlagsDeps common.Paths // Files depended on by compiler flags
}
type BaseCompilerProperties struct {
@@ -371,6 +382,8 @@ type LibraryLinkerProperties struct {
// don't link in crt_begin and crt_end. This flag should only be necessary for
// compiling crt or libc.
Nocrt *bool `android:"arch_variant"`
+
+ VariantName string `blueprint:"mutated"`
}
type BinaryLinkerProperties struct {
@@ -426,16 +439,6 @@ type UnusedProperties struct {
Required []string
Strip string
Tags []string
- Sanitize struct {
- Never bool `android:"arch_variant"`
- Address bool `android:"arch_variant"`
- Thread bool `android:"arch_variant"`
- Undefined bool `android:"arch_variant"`
- All_undefined bool `android:"arch_variant"`
- Misc_undefined []string `android:"arch_variant"`
- Coverage bool `android:"arch_variant"`
- Recover []string
- } `android:"arch_variant"`
}
type ModuleContextIntf interface {
@@ -529,6 +532,9 @@ type Module struct {
linker linker
installer installer
stl *stl
+ sanitize *sanitize
+
+ androidMkSharedLibDeps []string
outputFile common.OptionalPath
@@ -552,6 +558,9 @@ func (c *Module) Init() (blueprint.Module, []interface{}) {
if c.stl != nil {
props = append(props, c.stl.props()...)
}
+ if c.sanitize != nil {
+ props = append(props, c.sanitize.props()...)
+ }
for _, feature := range c.features {
props = append(props, feature.props()...)
}
@@ -632,6 +641,7 @@ func newBaseModule(hod common.HostOrDeviceSupported, multilib common.Multilib) *
func newModule(hod common.HostOrDeviceSupported, multilib common.Multilib) *Module {
module := newBaseModule(hod, multilib)
module.stl = &stl{}
+ module.sanitize = &sanitize{}
return module
}
@@ -648,7 +658,6 @@ func (c *Module) GenerateAndroidBuildActions(actx common.AndroidModuleContext) {
Toolchain: c.toolchain(ctx),
Clang: c.clang(ctx),
}
-
if c.compiler != nil {
flags = c.compiler.flags(ctx, flags)
}
@@ -658,6 +667,9 @@ func (c *Module) GenerateAndroidBuildActions(actx common.AndroidModuleContext) {
if c.stl != nil {
flags = c.stl.flags(ctx, flags)
}
+ if c.sanitize != nil {
+ flags = c.sanitize.flags(ctx, flags)
+ }
for _, feature := range c.features {
flags = feature.flags(ctx, flags)
}
@@ -734,6 +746,9 @@ func (c *Module) begin(ctx BaseModuleContext) {
if c.stl != nil {
c.stl.begin(ctx)
}
+ if c.sanitize != nil {
+ c.sanitize.begin(ctx)
+ }
for _, feature := range c.features {
feature.begin(ctx)
}
@@ -751,6 +766,9 @@ func (c *Module) deps(ctx BaseModuleContext) Deps {
if c.stl != nil {
deps = c.stl.deps(ctx, deps)
}
+ if c.sanitize != nil {
+ deps = c.sanitize.deps(ctx, deps)
+ }
for _, feature := range c.features {
deps = feature.deps(ctx, deps)
}
@@ -960,6 +978,20 @@ func (c *Module) InstallInData() bool {
return c.installer.inData()
}
+type appendVariantName interface {
+ appendVariantName(string)
+}
+
+func (c *Module) appendVariantName(name string) {
+ if c.linker == nil {
+ return
+ }
+
+ if l, ok := c.linker.(appendVariantName); ok {
+ l.appendVariantName(name)
+ }
+}
+
// Compiler
type baseCompiler struct {
@@ -1152,6 +1184,7 @@ func (compiler *baseCompiler) compileObjs(ctx common.AndroidModuleContext, flags
srcPaths, gendeps := genSources(ctx, inputFiles, buildFlags)
deps = append(deps, gendeps...)
+ deps = append(deps, flags.CFlagsDeps...)
return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
}
@@ -1269,6 +1302,10 @@ func (linker *baseLinker) setStatic(static bool) {
linker.dynamicProperties.VariantIsStatic = static
}
+func (linker *baseLinker) isDependencyRoot() bool {
+ return false
+}
+
type baseLinkerInterface interface {
// Returns true if the build options for the module have selected a static or shared build
buildStatic() bool
@@ -1282,6 +1319,10 @@ type baseLinkerInterface interface {
// Returns whether a module is a static binary
staticBinary() bool
+
+ // Returns true for dependency roots (binaries)
+ // TODO(ccross): also handle dlopenable libraries
+ isDependencyRoot() bool
}
type baseInstaller struct {
@@ -1417,6 +1458,7 @@ type libraryLinker struct {
}
var _ linker = (*libraryLinker)(nil)
+var _ appendVariantName = (*libraryLinker)(nil)
func (library *libraryLinker) props() []interface{} {
props := library.baseLinker.props()
@@ -1493,7 +1535,8 @@ func (library *libraryLinker) linkStatic(ctx ModuleContext,
objFiles = append(objFiles, deps.WholeStaticLibObjFiles...)
library.objFiles = objFiles
- outputFile := common.PathForModuleOut(ctx, ctx.ModuleName()+staticLibraryExtension)
+ outputFile := common.PathForModuleOut(ctx,
+ ctx.ModuleName()+library.Properties.VariantName+staticLibraryExtension)
if ctx.Darwin() {
TransformDarwinObjToStaticLib(ctx, objFiles, flagsToBuilderFlags(flags), outputFile)
@@ -1511,7 +1554,8 @@ func (library *libraryLinker) linkStatic(ctx ModuleContext,
func (library *libraryLinker) linkShared(ctx ModuleContext,
flags Flags, deps PathDeps, objFiles common.Paths) common.Path {
- outputFile := common.PathForModuleOut(ctx, ctx.ModuleName()+flags.Toolchain.ShlibSuffix())
+ outputFile := common.PathForModuleOut(ctx,
+ ctx.ModuleName()+library.Properties.VariantName+flags.Toolchain.ShlibSuffix())
var linkerDeps common.Paths
@@ -1595,6 +1639,10 @@ func (library *libraryLinker) installable() bool {
return !library.static()
}
+func (library *libraryLinker) appendVariantName(variant string) {
+ library.Properties.VariantName += variant
+}
+
type libraryInstaller struct {
baseInstaller
@@ -1771,6 +1819,10 @@ func (*binaryLinker) installable() bool {
return true
}
+func (binary *binaryLinker) isDependencyRoot() bool {
+ return true
+}
+
func NewBinary(hod common.HostOrDeviceSupported) *Module {
module := newModule(hod, common.MultilibFirst)
module.compiler = &baseCompiler{}
@@ -1829,16 +1881,17 @@ func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
)
} else {
- linker := "/system/bin/linker"
- if flags.Toolchain.Is64Bit() {
- linker += "64"
+ if flags.DynamicLinker == "" {
+ flags.DynamicLinker = "/system/bin/linker"
+ if flags.Toolchain.Is64Bit() {
+ flags.DynamicLinker += "64"
+ }
}
flags.LdFlags = append(flags.LdFlags,
"-pie",
"-nostdlib",
"-Bdynamic",
- fmt.Sprintf("-Wl,-dynamic-linker,%s", linker),
"-Wl,--gc-sections",
"-Wl,-z,nocopyreloc",
)
@@ -1871,6 +1924,10 @@ func (binary *binaryLinker) link(ctx ModuleContext,
sharedLibs := deps.SharedLibs
sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
+ if flags.DynamicLinker != "" {
+ flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
+ }
+
TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
flagsToBuilderFlags(flags), outputFile)
@@ -2101,6 +2158,7 @@ func defaultsFactory() (blueprint.Module, []interface{}) {
&TestLinkerProperties{},
&UnusedProperties{},
&StlProperties{},
+ &SanitizeProperties{},
}
_, propertyStructs = common.InitAndroidArchModule(module, common.HostAndDeviceDefault,
diff --git a/cc/sanitize.go b/cc/sanitize.go
new file mode 100644
index 00000000..676d5b37
--- /dev/null
+++ b/cc/sanitize.go
@@ -0,0 +1,329 @@
+// 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"
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong/common"
+)
+
+type sanitizerType int
+
+func init() {
+ pctx.StaticVariable("clangAsanLibDir", "${clangPath}/lib64/clang/3.8/lib/linux")
+}
+
+const (
+ asan sanitizerType = iota + 1
+ tsan
+)
+
+func (t sanitizerType) String() string {
+ switch t {
+ case asan:
+ return "asan"
+ case tsan:
+ return "tsan"
+ default:
+ panic(fmt.Errorf("unknown sanitizerType %d", t))
+ }
+}
+
+type SanitizeProperties struct {
+ // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
+ Sanitize struct {
+ Never bool `android:"arch_variant"`
+
+ // main sanitizers
+ Address bool `android:"arch_variant"`
+ Thread bool `android:"arch_variant"`
+
+ // local sanitizers
+ Undefined bool `android:"arch_variant"`
+ All_undefined bool `android:"arch_variant"`
+ Misc_undefined []string `android:"arch_variant"`
+ Coverage bool `android:"arch_variant"`
+
+ // value to pass to -fsantitize-recover=
+ Recover []string
+
+ // value to pass to -fsanitize-blacklist
+ Blacklist *string
+ } `android:"arch_variant"`
+
+ SanitizerEnabled bool `blueprint:"mutated"`
+ SanitizeDep bool `blueprint:"mutated"`
+}
+
+type sanitize struct {
+ Properties SanitizeProperties
+}
+
+func (sanitize *sanitize) props() []interface{} {
+ return []interface{}{&sanitize.Properties}
+}
+
+func (sanitize *sanitize) begin(ctx BaseModuleContext) {
+ // Don't apply sanitizers to NDK code.
+ if ctx.sdk() {
+ sanitize.Properties.Sanitize.Never = true
+ }
+
+ // Never always wins.
+ if sanitize.Properties.Sanitize.Never {
+ return
+ }
+
+ if ctx.ContainsProperty("sanitize") {
+ sanitize.Properties.SanitizerEnabled = true
+ }
+
+ var globalSanitizers []string
+ if ctx.clang() {
+ if ctx.Host() {
+ globalSanitizers = ctx.AConfig().SanitizeHost()
+ } else {
+ globalSanitizers = ctx.AConfig().SanitizeDevice()
+ }
+ }
+
+ // The sanitizer specified by the environment wins over the module.
+ if len(globalSanitizers) > 0 {
+ // wipe the enabled sanitizers
+ sanitize.Properties = SanitizeProperties{}
+ var found bool
+ if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found {
+ sanitize.Properties.Sanitize.All_undefined = true
+ } else if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found {
+ sanitize.Properties.Sanitize.Undefined = true
+ }
+
+ if found, globalSanitizers = removeFromList("address", globalSanitizers); found {
+ sanitize.Properties.Sanitize.Address = true
+ }
+
+ if found, globalSanitizers = removeFromList("thread", globalSanitizers); found {
+ sanitize.Properties.Sanitize.Thread = true
+ }
+
+ if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found {
+ sanitize.Properties.Sanitize.Coverage = true
+ }
+
+ if len(globalSanitizers) > 0 {
+ ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
+ }
+ sanitize.Properties.SanitizerEnabled = true
+ }
+
+ if !ctx.toolchain().Is64Bit() && sanitize.Properties.Sanitize.Thread {
+ // TSAN is not supported on 32-bit architectures
+ sanitize.Properties.Sanitize.Thread = false
+ // TODO(ccross): error for compile_multilib = "32"?
+ }
+
+ if sanitize.Properties.Sanitize.Coverage {
+ if !sanitize.Properties.Sanitize.Address {
+ 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() {
+ deps.SharedLibs = append(deps.SharedLibs, "libdl")
+ if sanitize.Properties.Sanitize.Address {
+ deps.StaticLibs = append(deps.StaticLibs, "libasan")
+ }
+ }
+
+ return deps
+}
+
+func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
+ if !sanitize.Properties.SanitizerEnabled {
+ return flags
+ }
+
+ if !ctx.clang() {
+ ctx.ModuleErrorf("Use of sanitizers requires clang")
+ }
+
+ var sanitizers []string
+
+ if sanitize.Properties.Sanitize.All_undefined {
+ sanitizers = append(sanitizers, "undefined")
+ if ctx.Device() {
+ ctx.ModuleErrorf("ubsan is not yet supported on the device")
+ }
+ } else {
+ if sanitize.Properties.Sanitize.Undefined {
+ 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...)
+ }
+
+ if sanitize.Properties.Sanitize.Address {
+ if ctx.Arch().ArchType == common.Arm {
+ // Frame pointer based unwinder in ASan requires ARM frame setup.
+ // TODO: put in flags?
+ flags.RequiredInstructionSet = "arm"
+ }
+ flags.CFlags = append(flags.CFlags, "-fno-omit-frame-pointer")
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-u,__asan_preinit")
+
+ // ASan runtime library must be the first in the link order.
+ runtimeLibrary := ctx.toolchain().AddressSanitizerRuntimeLibrary()
+ if runtimeLibrary != "" {
+ flags.libFlags = append([]string{"${clangAsanLibDir}/" + runtimeLibrary}, flags.libFlags...)
+ }
+ 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, "-lm", "-lpthread")
+ 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")
+ }
+
+ if sanitize.Properties.Sanitize.Coverage {
+ flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp")
+ }
+
+ if sanitize.Properties.Sanitize.Recover != nil {
+ flags.CFlags = append(flags.CFlags, "-fsanitize-recover="+
+ strings.Join(sanitize.Properties.Sanitize.Recover, ","))
+ }
+
+ if len(sanitizers) > 0 {
+ sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
+ flags.CFlags = append(flags.CFlags, sanitizeArg)
+ if ctx.Host() {
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
+ flags.LdFlags = append(flags.LdFlags, sanitizeArg)
+ flags.LdFlags = append(flags.LdFlags, "-lrt", "-ldl")
+ } else {
+ if !sanitize.Properties.Sanitize.Address {
+ flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
+ }
+ }
+ }
+
+ blacklist := common.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist)
+ if blacklist.Valid() {
+ flags.CFlags = append(flags.CFlags, "-fsanitize-blacklist="+blacklist.String())
+ flags.CFlagsDeps = append(flags.CFlagsDeps, blacklist.Path())
+ }
+
+ return flags
+}
+
+func (sanitize *sanitize) Sanitizer(t sanitizerType) bool {
+ if sanitize == nil {
+ return false
+ }
+
+ switch t {
+ case asan:
+ return sanitize.Properties.Sanitize.Address
+ case tsan:
+ return sanitize.Properties.Sanitize.Thread
+ default:
+ panic(fmt.Errorf("unknown sanitizerType %d", t))
+ }
+}
+
+func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
+ switch t {
+ case asan:
+ sanitize.Properties.Sanitize.Address = b
+ case tsan:
+ sanitize.Properties.Sanitize.Thread = b
+ default:
+ panic(fmt.Errorf("unknown sanitizerType %d", t))
+ }
+ if b {
+ sanitize.Properties.SanitizerEnabled = true
+ }
+}
+
+// Propagate asan requirements down from binaries
+func sanitizerDepsMutator(t sanitizerType) func(common.AndroidTopDownMutatorContext) {
+ return func(mctx common.AndroidTopDownMutatorContext) {
+ if c, ok := mctx.Module().(*Module); ok && c.sanitize.Sanitizer(t) {
+ mctx.VisitDepsDepthFirst(func(module blueprint.Module) {
+ if d, ok := mctx.Module().(*Module); ok && c.sanitize != nil &&
+ !c.sanitize.Properties.Sanitize.Never {
+ d.sanitize.Properties.SanitizeDep = true
+ }
+ })
+ }
+ }
+}
+
+// Create asan variants for modules that need them
+func sanitizerMutator(t sanitizerType) func(common.AndroidBottomUpMutatorContext) {
+ return func(mctx common.AndroidBottomUpMutatorContext) {
+ if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
+ if d, ok := c.linker.(baseLinkerInterface); ok && d.isDependencyRoot() && c.sanitize.Sanitizer(t) {
+ mctx.CreateVariations(t.String())
+ } else if c.sanitize.Properties.SanitizeDep {
+ modules := mctx.CreateVariations("", t.String())
+ modules[0].(*Module).sanitize.SetSanitizer(t, false)
+ modules[1].(*Module).sanitize.SetSanitizer(t, true)
+ modules[1].(*Module).appendVariantName("_" + t.String())
+ modules[0].(*Module).sanitize.Properties.SanitizeDep = false
+ modules[1].(*Module).sanitize.Properties.SanitizeDep = false
+ }
+ c.sanitize.Properties.SanitizeDep = false
+ }
+ }
+}
diff --git a/cc/toolchain.go b/cc/toolchain.go
index 397ec090..09dcff27 100644
--- a/cc/toolchain.go
+++ b/cc/toolchain.go
@@ -74,6 +74,8 @@ type Toolchain interface {
SystemCppCppflags() string
SystemCppLdflags() string
+
+ AddressSanitizerRuntimeLibrary() string
}
type toolchainBase struct {
@@ -133,6 +135,10 @@ func (toolchainBase) SystemCppLdflags() string {
return ""
}
+func (toolchainBase) AddressSanitizerRuntimeLibrary() string {
+ return ""
+}
+
type toolchain64Bit struct {
toolchainBase
}
diff --git a/cc/util.go b/cc/util.go
index 1d27f735..70433b1d 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -40,14 +40,18 @@ func libNamesToFlags(names []string) string {
return common.JoinWithPrefix(names, "-l")
}
-func inList(s string, list []string) bool {
- for _, l := range list {
+func indexList(s string, list []string) int {
+ for i, l := range list {
if l == s {
- return true
+ return i
}
}
- return false
+ return -1
+}
+
+func inList(s string, list []string) bool {
+ return indexList(s, list) != -1
}
func filterList(list []string, filter []string) (remainder []string, filtered []string) {
@@ -62,6 +66,15 @@ func filterList(list []string, filter []string) (remainder []string, filtered []
return
}
+func removeFromList(s string, list []string) (bool, []string) {
+ i := indexList(s, list)
+ if i != -1 {
+ return true, append(list[:i], list[i+1:]...)
+ } else {
+ return false, list
+ }
+}
+
var libNameRegexp = regexp.MustCompile(`^lib(.*)$`)
func moduleToLibName(module string) (string, error) {
@@ -81,6 +94,7 @@ func flagsToBuilderFlags(in Flags) builderFlags {
cppFlags: strings.Join(in.CppFlags, " "),
yaccFlags: strings.Join(in.YaccFlags, " "),
ldFlags: strings.Join(in.LdFlags, " "),
+ libFlags: strings.Join(in.libFlags, " "),
nocrt: in.Nocrt,
toolchain: in.Toolchain,
clang: in.Clang,
diff --git a/cc/x86_device.go b/cc/x86_device.go
index 92cae927..6b90f17b 100644
--- a/cc/x86_device.go
+++ b/cc/x86_device.go
@@ -236,6 +236,10 @@ func (t *toolchainX86) ClangLdflags() string {
return "${x86Ldflags}"
}
+func (toolchainX86) AddressSanitizerRuntimeLibrary() string {
+ return "libclang_rt.asan-i686-android.so"
+}
+
func x86ToolchainFactory(arch common.Arch) Toolchain {
toolchainCflags := []string{
"${x86ToolchainCflags}",
diff --git a/common/config.go b/common/config.go
index 08129034..5e2f7153 100644
--- a/common/config.go
+++ b/common/config.go
@@ -307,3 +307,17 @@ func (c *config) AllowMissingDependencies() bool {
func (c *config) SkipDeviceInstall() bool {
return c.EmbeddedInMake() || Bool(c.Mega_device)
}
+
+func (c *config) SanitizeHost() []string {
+ if c.ProductVariables.SanitizeHost == nil {
+ return nil
+ }
+ return *c.ProductVariables.SanitizeHost
+}
+
+func (c *config) SanitizeDevice() []string {
+ if c.ProductVariables.SanitizeDevice == nil {
+ return nil
+ }
+ return *c.ProductVariables.SanitizeDevice
+}
diff --git a/common/variable.go b/common/variable.go
index de313245..ae727617 100644
--- a/common/variable.go
+++ b/common/variable.go
@@ -77,6 +77,9 @@ type productVariables struct {
Unbundled_build *bool `json:",omitempty"`
Brillo *bool `json:",omitempty"`
Malloc_not_svelte *bool `json:",omitempty"`
+
+ SanitizeHost *[]string `json:",omitempty"`
+ SanitizeDevice *[]string `json:",omitempty"`
}
func boolPtr(v bool) *bool {