Merge changes I46e851c8,I2c9eb248 am: eed4716def am: 77bf9bd71a

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1662661

Change-Id: Ib8ef6d35d6280c2e293f4c4f2fadac679a49e0ed
diff --git a/cc/cc.go b/cc/cc.go
index 1ce83a9..9176bc3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -56,8 +56,8 @@
 		ctx.TopDown("asan_deps", sanitizerDepsMutator(Asan))
 		ctx.BottomUp("asan", sanitizerMutator(Asan)).Parallel()
 
-		ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan))
-		ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel()
+		ctx.TopDown("hwasan_deps", sanitizerDepsMutator(Hwasan))
+		ctx.BottomUp("hwasan", sanitizerMutator(Hwasan)).Parallel()
 
 		ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(Fuzzer))
 		ctx.BottomUp("fuzzer", sanitizerMutator(Fuzzer)).Parallel()
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 8f17e4e..397121e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -83,7 +83,7 @@
 
 const (
 	Asan SanitizerType = iota + 1
-	hwasan
+	Hwasan
 	tsan
 	intOverflow
 	cfi
@@ -97,7 +97,7 @@
 	switch t {
 	case Asan:
 		return "asan"
-	case hwasan:
+	case Hwasan:
 		return "hwasan"
 	case tsan:
 		return "tsan"
@@ -121,7 +121,7 @@
 	switch t {
 	case Asan:
 		return "address"
-	case hwasan:
+	case Hwasan:
 		return "hwaddress"
 	case memtag_heap:
 		return "memtag_heap"
@@ -144,7 +144,7 @@
 	switch t {
 	case Asan:
 		return true
-	case hwasan:
+	case Hwasan:
 		return true
 	case tsan:
 		return true
@@ -163,7 +163,7 @@
 
 // incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
 func (t SanitizerType) incompatibleWithCfi() bool {
-	return t == Asan || t == Fuzzer || t == hwasan
+	return t == Asan || t == Fuzzer || t == Hwasan
 }
 
 type SanitizeUserProps struct {
@@ -745,7 +745,7 @@
 	switch t {
 	case Asan:
 		return sanitize.Properties.Sanitize.Address
-	case hwasan:
+	case Hwasan:
 		return sanitize.Properties.Sanitize.Hwaddress
 	case tsan:
 		return sanitize.Properties.Sanitize.Thread
@@ -767,7 +767,7 @@
 // isUnsanitizedVariant returns true if no sanitizers are enabled.
 func (sanitize *sanitize) isUnsanitizedVariant() bool {
 	return !sanitize.isSanitizerEnabled(Asan) &&
-		!sanitize.isSanitizerEnabled(hwasan) &&
+		!sanitize.isSanitizerEnabled(Hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
 		!sanitize.isSanitizerEnabled(cfi) &&
 		!sanitize.isSanitizerEnabled(scs) &&
@@ -778,7 +778,7 @@
 // isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
 func (sanitize *sanitize) isVariantOnProductionDevice() bool {
 	return !sanitize.isSanitizerEnabled(Asan) &&
-		!sanitize.isSanitizerEnabled(hwasan) &&
+		!sanitize.isSanitizerEnabled(Hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
 		!sanitize.isSanitizerEnabled(Fuzzer)
 }
@@ -787,7 +787,7 @@
 	switch t {
 	case Asan:
 		sanitize.Properties.Sanitize.Address = boolPtr(b)
-	case hwasan:
+	case Hwasan:
 		sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
 	case tsan:
 		sanitize.Properties.Sanitize.Thread = boolPtr(b)
@@ -902,7 +902,7 @@
 					if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
 						!d.SanitizeNever() &&
 						!d.IsSanitizerExplicitlyDisabled(t) {
-						if t == cfi || t == hwasan || t == scs {
+						if t == cfi || t == Hwasan || t == scs {
 							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.
@@ -1286,7 +1286,7 @@
 					// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
 					// to Make, because the sanitized version has a different suffix in name.
 					// For other types of sanitizers, suppress the variation that is disabled.
-					if t != cfi && t != scs && t != hwasan {
+					if t != cfi && t != scs && t != Hwasan {
 						if isSanitizerEnabled {
 							modules[0].(PlatformSanitizeable).SetPreventInstall()
 							modules[0].(PlatformSanitizeable).SetHideFromMake()
@@ -1300,7 +1300,7 @@
 					if c.StaticallyLinked() && c.ExportedToMake() {
 						if t == cfi {
 							cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
-						} else if t == hwasan {
+						} else if t == Hwasan {
 							hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
 						}
 					}
@@ -1417,7 +1417,7 @@
 
 func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
 	return config.Once(hwasanStaticLibsKey, func() interface{} {
-		return newSanitizerStaticLibsMap(hwasan)
+		return newSanitizerStaticLibsMap(Hwasan)
 	}).(*sanitizerStaticLibsMap)
 }
 
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 3d31be4..3437d77 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -196,7 +196,7 @@
 		if m.sanitize != nil {
 			// scs and hwasan export both sanitized and unsanitized variants for static and header
 			// Always use unsanitized variants of them.
-			for _, t := range []SanitizerType{scs, hwasan} {
+			for _, t := range []SanitizerType{scs, Hwasan} {
 				if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
 					return false
 				}
diff --git a/rust/androidmk.go b/rust/androidmk.go
index b0e6967..dea32a3 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -70,6 +70,11 @@
 		// If the compiler is disabled, this is a SourceProvider.
 		mod.SubAndroidMk(&ret, mod.sourceProvider)
 	}
+
+	if mod.sanitize != nil {
+		mod.SubAndroidMk(&ret, mod.sanitize)
+	}
+
 	ret.SubName += mod.Properties.SubName
 
 	return []android.AndroidMkEntries{ret}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index a02a72b..ae3eff0 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -23,11 +23,12 @@
 )
 
 type SanitizeProperties struct {
-	// enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
+	// enable AddressSanitizer, HWAddressSanitizer, and others.
 	Sanitize struct {
-		Address *bool `android:"arch_variant"`
-		Fuzzer  *bool `android:"arch_variant"`
-		Never   *bool `android:"arch_variant"`
+		Address   *bool `android:"arch_variant"`
+		Hwaddress *bool `android:"arch_variant"`
+		Fuzzer    *bool `android:"arch_variant"`
+		Never     *bool `android:"arch_variant"`
 	}
 	SanitizerEnabled bool `blueprint:"mutated"`
 	SanitizeDep      bool `blueprint:"mutated"`
@@ -56,6 +57,11 @@
 	"-Z sanitizer=address",
 }
 
+var hwasanFlags = []string{
+	"-Z sanitizer=hwaddress",
+	"-C target-feature=+tagged-globals",
+}
+
 func boolPtr(v bool) *bool {
 	if v {
 		return &v
@@ -82,6 +88,15 @@
 	if ctx.Os() == android.Android && Bool(s.Address) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
+
+	// HWASan requires AArch64 hardware feature (top-byte-ignore).
+	if ctx.Arch().ArchType != android.Arm64 {
+		s.Hwaddress = nil
+	}
+
+	if ctx.Os() == android.Android && Bool(s.Hwaddress) {
+		sanitize.Properties.SanitizerEnabled = true
+	}
 }
 
 type sanitize struct {
@@ -98,6 +113,9 @@
 	if Bool(sanitize.Properties.Sanitize.Address) {
 		flags.RustFlags = append(flags.RustFlags, asanFlags...)
 	}
+	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+		flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
+	}
 	return flags, deps
 }
 
@@ -110,11 +128,38 @@
 		if !mod.Enabled() {
 			return
 		}
+
+		variations := mctx.Target().Variations()
+		var depTag blueprint.DependencyTag
+		var deps []string
+
 		if Bool(mod.sanitize.Properties.Sanitize.Fuzzer) || Bool(mod.sanitize.Properties.Sanitize.Address) {
-			mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
-				{Mutator: "link", Variation: "shared"},
-			}...), cc.SharedDepTag(), config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan"))
+			variations = append(variations,
+				blueprint.Variation{Mutator: "link", Variation: "shared"})
+			depTag = cc.SharedDepTag()
+			deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
+		} else if mod.IsSanitizerEnabled(cc.Hwasan) {
+			// TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
+			if binary, ok := mod.compiler.(*binaryDecorator); ok {
+				if Bool(binary.Properties.Static_executable) {
+					mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.")
+				}
+			}
+
+			if mod.StaticallyLinked() {
+				variations = append(variations,
+					blueprint.Variation{Mutator: "link", Variation: "static"})
+				depTag = cc.StaticDepTag(false)
+				deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan_static")}
+			} else {
+				variations = append(variations,
+					blueprint.Variation{Mutator: "link", Variation: "shared"})
+				depTag = cc.SharedDepTag()
+				deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
+			}
 		}
+
+		mctx.AddFarVariationDependencies(variations, depTag, deps...)
 	}
 }
 
@@ -127,6 +172,9 @@
 	case cc.Asan:
 		sanitize.Properties.Sanitize.Address = boolPtr(b)
 		sanitizerSet = true
+	case cc.Hwasan:
+		sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
+		sanitizerSet = true
 	default:
 		panic(fmt.Errorf("setting unsupported sanitizerType %d", t))
 	}
@@ -168,11 +216,23 @@
 		return sanitize.Properties.Sanitize.Fuzzer
 	case cc.Asan:
 		return sanitize.Properties.Sanitize.Address
+	case cc.Hwasan:
+		return sanitize.Properties.Sanitize.Hwaddress
 	default:
 		return nil
 	}
 }
 
+func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+	// Add a suffix for hwasan rlib libraries to allow surfacing both the sanitized and
+	// non-sanitized variants to make without a name conflict.
+	if entries.Class == "RLIB_LIBRARIES" || entries.Class == "STATIC_LIBRARIES" {
+		if sanitize.isSanitizerEnabled(cc.Hwasan) {
+			entries.SubName += ".hwasan"
+		}
+	}
+}
+
 func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool {
 	if mod.Host() {
 		return false
@@ -182,6 +242,8 @@
 		return true
 	case cc.Asan:
 		return true
+	case cc.Hwasan:
+		return true
 	default:
 		return false
 	}