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
diff --git a/cc/cc.go b/cc/cc.go
index 18dd09c..851e4c3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -59,6 +59,12 @@
 	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 @@
 		}
 		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 @@
 	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 @@
 	// 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 @@
 	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 @@
 	linker     linker
 	installer  installer
 	stl        *stl
+	sanitize   *sanitize
+
+	androidMkSharedLibDeps []string
 
 	outputFile common.OptionalPath
 
@@ -552,6 +558,9 @@
 	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 newModule(hod common.HostOrDeviceSupported, multilib common.Multilib) *Module {
 	module := newBaseModule(hod, multilib)
 	module.stl = &stl{}
+	module.sanitize = &sanitize{}
 	return module
 }
 
@@ -648,7 +658,6 @@
 		Toolchain: c.toolchain(ctx),
 		Clang:     c.clang(ctx),
 	}
-
 	if c.compiler != nil {
 		flags = c.compiler.flags(ctx, flags)
 	}
@@ -658,6 +667,9 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	// 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 @@
 }
 
 var _ linker = (*libraryLinker)(nil)
+var _ appendVariantName = (*libraryLinker)(nil)
 
 func (library *libraryLinker) props() []interface{} {
 	props := library.baseLinker.props()
@@ -1493,7 +1535,8 @@
 	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) 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 @@
 	return !library.static()
 }
 
+func (library *libraryLinker) appendVariantName(variant string) {
+	library.Properties.VariantName += variant
+}
+
 type libraryInstaller struct {
 	baseInstaller
 
@@ -1771,6 +1819,10 @@
 	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 @@
 			)
 
 		} 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 @@
 	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 @@
 		&TestLinkerProperties{},
 		&UnusedProperties{},
 		&StlProperties{},
+		&SanitizeProperties{},
 	}
 
 	_, propertyStructs = common.InitAndroidArchModule(module, common.HostAndDeviceDefault,