Refactor CC to prep for Rust sanitizable modules.

Adds a PlatformSanitizable interface which both CC and Rust can
implement so that the sanitizer mutators in CC can sanitize Rust
shared/static libraries appropriately.

Bug: 147140513
Test: m nothing
Change-Id: Ib31103b6c4902a4d5df2565c0d7c981298d100a3
diff --git a/cc/sanitize.go b/cc/sanitize.go
index bb92a88..5992611 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -71,7 +71,7 @@
 		"export_memory_stats=0", "max_malloc_fill_size=0"}
 )
 
-type sanitizerType int
+type SanitizerType int
 
 func boolPtr(v bool) *bool {
 	if v {
@@ -82,19 +82,19 @@
 }
 
 const (
-	asan sanitizerType = iota + 1
+	Asan SanitizerType = iota + 1
 	hwasan
 	tsan
 	intOverflow
 	cfi
 	scs
-	fuzzer
+	Fuzzer
 )
 
 // Name of the sanitizer variation for this sanitizer type
-func (t sanitizerType) variationName() string {
+func (t SanitizerType) variationName() string {
 	switch t {
-	case asan:
+	case Asan:
 		return "asan"
 	case hwasan:
 		return "hwasan"
@@ -106,17 +106,17 @@
 		return "cfi"
 	case scs:
 		return "scs"
-	case fuzzer:
+	case Fuzzer:
 		return "fuzzer"
 	default:
-		panic(fmt.Errorf("unknown sanitizerType %d", t))
+		panic(fmt.Errorf("unknown SanitizerType %d", t))
 	}
 }
 
 // This is the sanitizer names in SANITIZE_[TARGET|HOST]
-func (t sanitizerType) name() string {
+func (t SanitizerType) name() string {
 	switch t {
-	case asan:
+	case Asan:
 		return "address"
 	case hwasan:
 		return "hwaddress"
@@ -128,15 +128,37 @@
 		return "cfi"
 	case scs:
 		return "shadow-call-stack"
-	case fuzzer:
+	case Fuzzer:
 		return "fuzzer"
 	default:
-		panic(fmt.Errorf("unknown sanitizerType %d", t))
+		panic(fmt.Errorf("unknown SanitizerType %d", t))
 	}
 }
 
-func (t sanitizerType) incompatibleWithCfi() bool {
-	return t == asan || t == fuzzer || t == hwasan
+func (*Module) SanitizerSupported(t SanitizerType) bool {
+	switch t {
+	case Asan:
+		return true
+	case hwasan:
+		return true
+	case tsan:
+		return true
+	case intOverflow:
+		return true
+	case cfi:
+		return true
+	case scs:
+		return true
+	case Fuzzer:
+		return true
+	default:
+		return false
+	}
+}
+
+// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
+func (t SanitizerType) incompatibleWithCfi() bool {
+	return t == Asan || t == Fuzzer || t == hwasan
 }
 
 type SanitizeUserProps struct {
@@ -680,9 +702,10 @@
 	return sanitize.Properties.InSanitizerDir
 }
 
-func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool {
+// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties.
+func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
 	switch t {
-	case asan:
+	case Asan:
 		return sanitize.Properties.Sanitize.Address
 	case hwasan:
 		return sanitize.Properties.Sanitize.Hwaddress
@@ -694,32 +717,34 @@
 		return sanitize.Properties.Sanitize.Cfi
 	case scs:
 		return sanitize.Properties.Sanitize.Scs
-	case fuzzer:
+	case Fuzzer:
 		return sanitize.Properties.Sanitize.Fuzzer
 	default:
-		panic(fmt.Errorf("unknown sanitizerType %d", t))
+		panic(fmt.Errorf("unknown SanitizerType %d", t))
 	}
 }
 
+// isUnsanitizedVariant returns true if no sanitizers are enabled.
 func (sanitize *sanitize) isUnsanitizedVariant() bool {
-	return !sanitize.isSanitizerEnabled(asan) &&
+	return !sanitize.isSanitizerEnabled(Asan) &&
 		!sanitize.isSanitizerEnabled(hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
 		!sanitize.isSanitizerEnabled(cfi) &&
 		!sanitize.isSanitizerEnabled(scs) &&
-		!sanitize.isSanitizerEnabled(fuzzer)
+		!sanitize.isSanitizerEnabled(Fuzzer)
 }
 
+// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
 func (sanitize *sanitize) isVariantOnProductionDevice() bool {
-	return !sanitize.isSanitizerEnabled(asan) &&
+	return !sanitize.isSanitizerEnabled(Asan) &&
 		!sanitize.isSanitizerEnabled(hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
-		!sanitize.isSanitizerEnabled(fuzzer)
+		!sanitize.isSanitizerEnabled(Fuzzer)
 }
 
-func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
+func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) {
 	switch t {
-	case asan:
+	case Asan:
 		sanitize.Properties.Sanitize.Address = boolPtr(b)
 	case hwasan:
 		sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
@@ -731,10 +756,10 @@
 		sanitize.Properties.Sanitize.Cfi = boolPtr(b)
 	case scs:
 		sanitize.Properties.Sanitize.Scs = boolPtr(b)
-	case fuzzer:
+	case Fuzzer:
 		sanitize.Properties.Sanitize.Fuzzer = boolPtr(b)
 	default:
-		panic(fmt.Errorf("unknown sanitizerType %d", t))
+		panic(fmt.Errorf("unknown SanitizerType %d", t))
 	}
 	if b {
 		sanitize.Properties.SanitizerEnabled = true
@@ -743,7 +768,7 @@
 
 // Check if the sanitizer is explicitly disabled (as opposed to nil by
 // virtue of not being set).
-func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool {
+func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool {
 	if sanitize == nil {
 		return false
 	}
@@ -757,7 +782,7 @@
 // indirectly (via a mutator) sets the bool ptr to true, and you can't
 // distinguish between the cases. It isn't needed though - both cases can be
 // treated identically.
-func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool {
+func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool {
 	if sanitize == nil {
 		return false
 	}
@@ -766,7 +791,8 @@
 	return sanitizerVal != nil && *sanitizerVal == true
 }
 
-func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
+// IsSanitizableDependencyTag returns true if the dependency tag is sanitizable.
+func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
 	switch t := tag.(type) {
 	case dependencyTag:
 		return t == reuseObjTag || t == objDepTag
@@ -777,6 +803,10 @@
 	}
 }
 
+func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
+	return IsSanitizableDependencyTag
+}
+
 // Determines if the current module is a static library going to be captured
 // as vendor snapshot. Such modules must create both cfi and non-cfi variants,
 // except for ones which explicitly disable cfi.
@@ -785,51 +815,58 @@
 		return false
 	}
 
-	c := mctx.Module().(*Module)
+	c := mctx.Module().(PlatformSanitizeable)
 
-	if !c.inVendor() {
+	if !c.InVendor() {
 		return false
 	}
 
-	if !c.static() {
+	if !c.StaticallyLinked() {
 		return false
 	}
 
-	if c.Prebuilt() != nil {
+	if c.IsPrebuilt() {
 		return false
 	}
 
-	return c.sanitize != nil &&
-		!Bool(c.sanitize.Properties.Sanitize.Never) &&
-		!c.sanitize.isSanitizerExplicitlyDisabled(cfi)
+	if !c.SanitizerSupported(cfi) {
+		return false
+	}
+
+	return c.SanitizePropDefined() &&
+		!c.SanitizeNever() &&
+		!c.IsSanitizerExplicitlyDisabled(cfi)
 }
 
 // Propagate sanitizer requirements down from binaries
-func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
+func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
 	return func(mctx android.TopDownMutatorContext) {
-		if c, ok := mctx.Module().(*Module); ok {
-			enabled := c.sanitize.isSanitizerEnabled(t)
+		if c, ok := mctx.Module().(PlatformSanitizeable); ok {
+			enabled := c.IsSanitizerEnabled(t)
 			if t == cfi && needsCfiForVendorSnapshot(mctx) {
 				// We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
 				// determine defaultVariation in sanitizerMutator below.
 				// Instead, just mark SanitizeDep to forcefully create cfi variant.
 				enabled = true
-				c.sanitize.Properties.SanitizeDep = true
+				c.SetSanitizeDep(true)
 			}
 			if enabled {
+				isSanitizableDependencyTag := c.SanitizableDepTagChecker()
 				mctx.WalkDeps(func(child, parent android.Module) bool {
 					if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
 						return false
 					}
-					if d, ok := child.(*Module); ok && d.sanitize != nil &&
-						!Bool(d.sanitize.Properties.Sanitize.Never) &&
-						!d.sanitize.isSanitizerExplicitlyDisabled(t) {
+					if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
+						!d.SanitizeNever() &&
+						!d.IsSanitizerExplicitlyDisabled(t) {
 						if t == cfi || t == hwasan || t == scs {
-							if d.static() {
-								d.sanitize.Properties.SanitizeDep = true
+							if d.StaticallyLinked() && d.SanitizerSupported(t) {
+								// Rust does not support some of these sanitizers, so we need to check if it's
+								// supported before setting this true.
+								d.SetSanitizeDep(true)
 							}
 						} else {
-							d.sanitize.Properties.SanitizeDep = true
+							d.SetSanitizeDep(true)
 						}
 					}
 					return true
@@ -847,9 +884,19 @@
 	}
 }
 
+func (c *Module) SanitizeNever() bool {
+	return Bool(c.sanitize.Properties.Sanitize.Never)
+}
+
+func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool {
+	return c.sanitize.isSanitizerExplicitlyDisabled(t)
+}
+
 // Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
 func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
+	// Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers.
 	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
+		isSanitizableDependencyTag := c.SanitizableDepTagChecker()
 		mctx.WalkDeps(func(child, parent android.Module) bool {
 			if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
 				return false
@@ -1057,7 +1104,7 @@
 					variations = append(variations, c.ImageVariation())
 				}
 				mctx.AddFarVariationDependencies(variations, depTag, deps...)
-			} else if !c.static() && !c.header() {
+			} else if !c.static() && !c.Header() {
 				// If we're using snapshots and in vendor, redirect to snapshot whenever possible
 				if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() {
 					snapshots := vendorSnapshotSharedLibs(mctx.Config())
@@ -1098,16 +1145,52 @@
 	AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
 }
 
+func (c *Module) SanitizePropDefined() bool {
+	return c.sanitize != nil
+}
+
+func (c *Module) IsSanitizerEnabled(t SanitizerType) bool {
+	return c.sanitize.isSanitizerEnabled(t)
+}
+
+func (c *Module) SanitizeDep() bool {
+	return c.sanitize.Properties.SanitizeDep
+}
+
+func (c *Module) StaticallyLinked() bool {
+	return c.static()
+}
+
+func (c *Module) SetInSanitizerDir() {
+	if c.sanitize != nil {
+		c.sanitize.Properties.InSanitizerDir = true
+	}
+}
+
+func (c *Module) SetSanitizer(t SanitizerType, b bool) {
+	if c.sanitize != nil {
+		c.sanitize.SetSanitizer(t, b)
+	}
+}
+
+func (c *Module) SetSanitizeDep(b bool) {
+	if c.sanitize != nil {
+		c.sanitize.Properties.SanitizeDep = b
+	}
+}
+
+var _ PlatformSanitizeable = (*Module)(nil)
+
 // Create sanitized variants for modules that need them
-func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
+func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
 	return func(mctx android.BottomUpMutatorContext) {
-		if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
-			if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) {
+		if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
+			if c.IsDependencyRoot() && c.IsSanitizerEnabled(t) {
 				modules := mctx.CreateVariations(t.variationName())
-				modules[0].(*Module).sanitize.SetSanitizer(t, true)
-			} else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep {
-				isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t)
-				if c.static() || c.header() || t == asan || t == fuzzer {
+				modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
+			} else if c.IsSanitizerEnabled(t) || c.SanitizeDep() {
+				isSanitizerEnabled := c.IsSanitizerEnabled(t)
+				if c.StaticallyLinked() || c.Header() || t == Asan || t == Fuzzer {
 					// Static and header libs are split into non-sanitized and sanitized variants.
 					// Shared libs are not split. However, for asan and fuzzer, we split even for shared
 					// libs because a library sanitized for asan/fuzzer can't be linked from a library
@@ -1121,17 +1204,20 @@
 					// module. By setting it to the name of the sanitized variation, the dangling dependency
 					// is redirected to the sanitized variant of the dependent module.
 					defaultVariation := t.variationName()
+					// Not all PlatformSanitizeable modules support the CFI sanitizer
+					cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
 					mctx.SetDefaultDependencyVariation(&defaultVariation)
-					modules := mctx.CreateVariations("", t.variationName())
-					modules[0].(*Module).sanitize.SetSanitizer(t, false)
-					modules[1].(*Module).sanitize.SetSanitizer(t, true)
-					modules[0].(*Module).sanitize.Properties.SanitizeDep = false
-					modules[1].(*Module).sanitize.Properties.SanitizeDep = false
 
-					if mctx.Device() && t.incompatibleWithCfi() {
+					modules := mctx.CreateVariations("", t.variationName())
+					modules[0].(PlatformSanitizeable).SetSanitizer(t, false)
+					modules[1].(PlatformSanitizeable).SetSanitizer(t, true)
+					modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
+					modules[1].(PlatformSanitizeable).SetSanitizeDep(false)
+
+					if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
 						// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
 						// are incompatible with cfi
-						modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+						modules[1].(PlatformSanitizeable).SetSanitizer(cfi, false)
 					}
 
 					// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
@@ -1139,46 +1225,48 @@
 					// For other types of sanitizers, suppress the variation that is disabled.
 					if t != cfi && t != scs && t != hwasan {
 						if isSanitizerEnabled {
-							modules[0].(*Module).Properties.PreventInstall = true
-							modules[0].(*Module).Properties.HideFromMake = true
+							modules[0].(PlatformSanitizeable).SetPreventInstall()
+							modules[0].(PlatformSanitizeable).SetHideFromMake()
 						} else {
-							modules[1].(*Module).Properties.PreventInstall = true
-							modules[1].(*Module).Properties.HideFromMake = true
+							modules[1].(PlatformSanitizeable).SetPreventInstall()
+							modules[1].(PlatformSanitizeable).SetHideFromMake()
 						}
 					}
 
 					// Export the static lib name to make
-					if c.static() && c.ExportedToMake() {
+					if c.StaticallyLinked() && c.ExportedToMake() {
 						if t == cfi {
-							cfiStaticLibs(mctx.Config()).add(c, c.Name())
+							cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
 						} else if t == hwasan {
-							hwasanStaticLibs(mctx.Config()).add(c, c.Name())
+							hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
 						}
 					}
 				} else {
 					// Shared libs are not split. Only the sanitized variant is created.
 					modules := mctx.CreateVariations(t.variationName())
-					modules[0].(*Module).sanitize.SetSanitizer(t, true)
-					modules[0].(*Module).sanitize.Properties.SanitizeDep = false
+					modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
+					modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
 
 					// locate the asan libraries under /data/asan
-					if mctx.Device() && t == asan && isSanitizerEnabled {
-						modules[0].(*Module).sanitize.Properties.InSanitizerDir = true
+					if mctx.Device() && t == Asan && isSanitizerEnabled {
+						modules[0].(PlatformSanitizeable).SetInSanitizerDir()
 					}
 
 					if mctx.Device() && t.incompatibleWithCfi() {
 						// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
 						// are incompatible with cfi
-						modules[0].(*Module).sanitize.SetSanitizer(cfi, false)
+						modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false)
 					}
 				}
 			}
-			c.sanitize.Properties.SanitizeDep = false
+			c.SetSanitizeDep(false)
 		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
 			// APEX modules fall here
 			sanitizeable.AddSanitizerDependencies(mctx, t.name())
 			mctx.CreateVariations(t.variationName())
 		} else if c, ok := mctx.Module().(*Module); ok {
+			//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
+
 			// Check if it's a snapshot module supporting sanitizer
 			if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
 				// Set default variation as above.
@@ -1203,23 +1291,23 @@
 type sanitizerStaticLibsMap struct {
 	// libsMap contains one list of modules per each image and each arch.
 	// e.g. libs[vendor]["arm"] contains arm modules installed to vendor
-	libsMap       map[imageVariantType]map[string][]string
+	libsMap       map[ImageVariantType]map[string][]string
 	libsMapLock   sync.Mutex
-	sanitizerType sanitizerType
+	sanitizerType SanitizerType
 }
 
-func newSanitizerStaticLibsMap(t sanitizerType) *sanitizerStaticLibsMap {
+func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap {
 	return &sanitizerStaticLibsMap{
 		sanitizerType: t,
-		libsMap:       make(map[imageVariantType]map[string][]string),
+		libsMap:       make(map[ImageVariantType]map[string][]string),
 	}
 }
 
 // Add the current module to sanitizer static libs maps
 // Each module should pass its exported name as names of Make and Soong can differ.
-func (s *sanitizerStaticLibsMap) add(c *Module, name string) {
-	image := c.getImageVariantType()
-	arch := c.Arch().ArchType.String()
+func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) {
+	image := GetImageVariantType(c)
+	arch := c.Module().Target().Arch.ArchType.String()
 
 	s.libsMapLock.Lock()
 	defer s.libsMapLock.Unlock()
@@ -1238,7 +1326,7 @@
 // See build/make/core/binary.mk for more details.
 func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
 	for _, image := range android.SortedStringKeys(s.libsMap) {
-		archMap := s.libsMap[imageVariantType(image)]
+		archMap := s.libsMap[ImageVariantType(image)]
 		for _, arch := range android.SortedStringKeys(archMap) {
 			libs := archMap[arch]
 			sort.Strings(libs)