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:
parent
4a97cb4328
commit
16b2349190
11 changed files with 467 additions and 25 deletions
|
@ -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",
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++")
|
||||
}
|
||||
|
|
94
cc/cc.go
94
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,
|
||||
|
|
329
cc/sanitize.go
Normal file
329
cc/sanitize.go
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
22
cc/util.go
22
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,
|
||||
|
|
|
@ -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}",
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue