rust: Add SCS sanitizer option for AArch64

SCS has been supported in Rust since 1.64.0.

This adds SCS as a sanitizer option in Rust.

Bug: 168914033
Test: Built module with sanitize: { scs: true }
Change-Id: Ie54ac4693286878b98704cf052649a267777d764
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 5c68a96..a23e2db 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -96,7 +96,7 @@
 	Hwasan
 	tsan
 	intOverflow
-	scs
+	Scs
 	Fuzzer
 	Memtag_heap
 	Memtag_stack
@@ -109,7 +109,7 @@
 	Hwasan,
 	tsan,
 	intOverflow,
-	scs,
+	Scs,
 	Fuzzer,
 	Memtag_heap,
 	Memtag_stack,
@@ -130,7 +130,7 @@
 		return "intOverflow"
 	case cfi:
 		return "cfi"
-	case scs:
+	case Scs:
 		return "scs"
 	case Memtag_heap:
 		return "memtag_heap"
@@ -164,7 +164,7 @@
 		return "integer_overflow"
 	case cfi:
 		return "cfi"
-	case scs:
+	case Scs:
 		return "shadow-call-stack"
 	case Fuzzer:
 		return "fuzzer"
@@ -175,7 +175,7 @@
 
 func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) {
 	switch t {
-	case cfi, Hwasan, Asan, tsan, Fuzzer, scs:
+	case cfi, Hwasan, Asan, tsan, Fuzzer, Scs:
 		sanitizer := &sanitizerSplitMutator{t}
 		ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
 		ctx.Transition(t.variationName(), sanitizer)
@@ -212,7 +212,7 @@
 		return true
 	case cfi:
 		return true
-	case scs:
+	case Scs:
 		return true
 	case Fuzzer:
 		return true
@@ -1012,7 +1012,7 @@
 		return s.Properties.SanitizeMutated.Integer_overflow
 	case cfi:
 		return s.Properties.SanitizeMutated.Cfi
-	case scs:
+	case Scs:
 		return s.Properties.SanitizeMutated.Scs
 	case Memtag_heap:
 		return s.Properties.SanitizeMutated.Memtag_heap
@@ -1033,7 +1033,7 @@
 		!sanitize.isSanitizerEnabled(Hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
 		!sanitize.isSanitizerEnabled(cfi) &&
-		!sanitize.isSanitizerEnabled(scs) &&
+		!sanitize.isSanitizerEnabled(Scs) &&
 		!sanitize.isSanitizerEnabled(Memtag_heap) &&
 		!sanitize.isSanitizerEnabled(Memtag_stack) &&
 		!sanitize.isSanitizerEnabled(Memtag_globals) &&
@@ -1070,7 +1070,7 @@
 		sanitize.Properties.SanitizeMutated.Integer_overflow = bPtr
 	case cfi:
 		sanitize.Properties.SanitizeMutated.Cfi = bPtr
-	case scs:
+	case Scs:
 		sanitize.Properties.SanitizeMutated.Scs = bPtr
 	case Memtag_heap:
 		sanitize.Properties.SanitizeMutated.Memtag_heap = bPtr
@@ -1330,7 +1330,7 @@
 
 		oneMakeVariation := false
 		if c.StaticallyLinked() || c.Header() {
-			if s.sanitizer != cfi && s.sanitizer != scs && s.sanitizer != Hwasan {
+			if s.sanitizer != cfi && s.sanitizer != Scs && s.sanitizer != Hwasan {
 				// These sanitizers export only one variation to Make. For the rest,
 				// Make targets can depend on both the sanitized and non-sanitized
 				// versions.
@@ -1340,7 +1340,7 @@
 			// Shared library. These are the sanitizers that do propagate through shared
 			// library dependencies and therefore can cause multiple variations of a
 			// shared library to be built.
-			if s.sanitizer != cfi && s.sanitizer != Hwasan && s.sanitizer != scs && s.sanitizer != Asan {
+			if s.sanitizer != cfi && s.sanitizer != Hwasan && s.sanitizer != Scs && s.sanitizer != Asan {
 				oneMakeVariation = true
 			}
 		}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 9ea337b..2421e24 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -95,7 +95,7 @@
 		if sanitizable.SanitizePropDefined() {
 			// scs exports both sanitized and unsanitized variants for static and header
 			// Always use unsanitized variant of it.
-			if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(scs) {
+			if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(Scs) {
 				return false
 			}
 			// cfi and hwasan also export both variants. But for static, we capture both.
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 0f7cf6e..e232b53 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -32,6 +32,7 @@
 	Sanitize struct {
 		Address   *bool `android:"arch_variant"`
 		Hwaddress *bool `android:"arch_variant"`
+		Scs       *bool `android:"arch_variant"`
 
 		// Memory-tagging, only available on arm64
 		// if diag.memtag unset or false, enables async memory tagging
@@ -75,6 +76,9 @@
 var asanFlags = []string{
 	"-Z sanitizer=address",
 }
+var scsFlags = []string{
+	"-Z sanitizer=shadow-call-stack",
+}
 
 // See cc/sanitize.go's hwasanGlobalOptions for global hwasan options.
 var hwasanFlags = []string{
@@ -208,9 +212,15 @@
 		s.Memtag_heap = nil
 	}
 
+	// SCS is only supported on AArch64 in Rust.
+	// TODO: Add riscv when riscv supported.
+	if (ctx.Arch().ArchType != android.Arm64) || !ctx.toolchain().Bionic() {
+		s.Scs = nil
+	}
+
 	// TODO:(b/178369775)
 	// For now sanitizing is only supported on devices
-	if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
+	if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer) || Bool(s.Scs)) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
 }
@@ -229,7 +239,10 @@
 		flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
 	} else if Bool(sanitize.Properties.Sanitize.Address) {
 		flags.RustFlags = append(flags.RustFlags, asanFlags...)
+	} else if Bool(sanitize.Properties.Sanitize.Scs) {
+		flags.RustFlags = append(flags.RustFlags, scsFlags...)
 	}
+
 	return flags, deps
 }
 
@@ -311,6 +324,9 @@
 	case cc.Memtag_heap:
 		sanitize.Properties.Sanitize.Memtag_heap = boolPtr(b)
 		sanitizerSet = true
+	case cc.Scs:
+		sanitize.Properties.Sanitize.Scs = boolPtr(b)
+		sanitizerSet = true
 	default:
 		panic(fmt.Errorf("setting unsupported sanitizerType %d", t))
 	}
@@ -372,6 +388,8 @@
 		return sanitize.Properties.Sanitize.Hwaddress
 	case cc.Memtag_heap:
 		return sanitize.Properties.Sanitize.Memtag_heap
+	case cc.Scs:
+		return sanitize.Properties.Sanitize.Scs
 	default:
 		return nil
 	}
@@ -384,6 +402,10 @@
 		if sanitize.isSanitizerEnabled(cc.Hwasan) {
 			entries.SubName += ".hwasan"
 		}
+		if sanitize.isSanitizerEnabled(cc.Scs) {
+			entries.SubName += ".scs"
+		}
+
 	}
 }
 
@@ -404,6 +426,13 @@
 		return true
 	case cc.Memtag_heap:
 		return true
+	case cc.Scs:
+		// SCS is only supported on AArch64 in Rust.
+		// TODO: Add riscv when riscv supported.
+		if mod.Target().Arch.ArchType == android.Arm64 {
+			return true
+		}
+		return false
 	default:
 		return false
 	}