Soong support for Scudo

Scudo is a hardened usermode allocator that is part of LLVM's compiler-rt
project (home of the Sanitizers). clang allows for -fsanitize=scudo as a
possible command line option to link the shared Scudo library to a binary.

This patch add Scudo as a potential sanitize option. Scudo is not compatible
with ASan and TSan and will be disabled if either is enabled.

Bug: 72112048
Test: aosp compiled with m -j
Test: local experiment with scudo: true to ensure that a test target
(tombstoned) could be linked with scudo.

Change-Id: I76bb6c60891d4782f6665a112c4c2bf7c31645da
diff --git a/cc/sanitize.go b/cc/sanitize.go
index e59edf5..38f4fc2 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -94,6 +94,7 @@
 		Safestack        *bool    `android:"arch_variant"`
 		Cfi              *bool    `android:"arch_variant"`
 		Integer_overflow *bool    `android:"arch_variant"`
+		Scudo            *bool    `android:"arch_variant"`
 
 		// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
 		// Replaces abort() on error with a human-readable error message.
@@ -207,6 +208,10 @@
 			}
 		}
 
+		if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil {
+			s.Scudo = boolPtr(true)
+		}
+
 		if len(globalSanitizers) > 0 {
 			ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
 		}
@@ -281,10 +286,16 @@
 	}
 
 	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
-		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0) {
+		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
+		Bool(s.Scudo)) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
 
+	// Disable Scudo if ASan or TSan is enabled.
+	if Bool(s.Address) || Bool(s.Thread) {
+		s.Scudo = nil
+	}
+
 	if Bool(s.Coverage) {
 		if !Bool(s.Address) {
 			ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
@@ -434,6 +445,10 @@
 		}
 	}
 
+	if Bool(sanitize.Properties.Sanitize.Scudo) {
+		sanitizers = append(sanitizers, "scudo")
+	}
+
 	if len(sanitizers) > 0 {
 		sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
 
@@ -471,6 +486,8 @@
 		runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain())
 	} else if Bool(sanitize.Properties.Sanitize.Thread) {
 		runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
+	} else if Bool(sanitize.Properties.Sanitize.Scudo) {
+		runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
 	} else if len(diagSanitizers) > 0 || sanitize.Properties.UbsanRuntimeDep {
 		runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
 	}
@@ -705,6 +722,7 @@
 
 func enableMinimalRuntime(sanitize *sanitize) bool {
 	if !Bool(sanitize.Properties.Sanitize.Address) &&
+		!Bool(sanitize.Properties.Sanitize.Scudo) &&
 		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
 			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
 		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||