From 16b234919080732f438598adc3a3ca5fe2456b88 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 6 Jan 2016 14:41:07 -0800 Subject: [PATCH] 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 --- Android.bp | 1 + cc/arm64_device.go | 4 + cc/arm_device.go | 4 + cc/builder.go | 11 +- cc/cc.go | 94 ++++++++++--- cc/sanitize.go | 329 +++++++++++++++++++++++++++++++++++++++++++++ cc/toolchain.go | 6 + cc/util.go | 22 ++- cc/x86_device.go | 4 + common/config.go | 14 ++ common/variable.go | 3 + 11 files changed, 467 insertions(+), 25 deletions(-) create mode 100644 cc/sanitize.go diff --git a/Android.bp b/Android.bp index b4928f8b8..831b703f1 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 1a0408c61..9194c6d12 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 ea7db4315..764aaa9ae 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 38bb141ca..f67f9bd31 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 18dd09c74..851e4c3e7 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 000000000..676d5b370 --- /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 397ec090d..09dcff27f 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 1d27f7354..70433b1d7 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 92cae9271..6b90f17bb 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 081290347..5e2f71532 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 de3132452..ae7276179 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 {