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
This commit is contained in:
Colin Cross 2016-01-06 14:41:07 -08:00
parent 4a97cb4328
commit 16b2349190
11 changed files with 467 additions and 25 deletions

View file

@ -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",

View file

@ -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))

View file

@ -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)

View file

@ -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++")
}

View file

@ -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,

329
cc/sanitize.go Normal file
View file

@ -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
}
}
}

View file

@ -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
}

View file

@ -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,

View file

@ -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}",

View file

@ -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
}

View file

@ -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 {