Add minimal-runtime support for integer overflows.

Adds Soong support for -fsanitze-minimal-runtime when using
the integer overflow sanitizers. This makes the crashes due to these
sanitizers less mysterious.

Bug: 64091660
Test: Compiled and checked the generated compiler commands
Test: Checked program that overflows for the abort reason

Change-Id: Ieeceaf6c35c8371592952d3b8b977aefc11601c5
Merged-In: Ieeceaf6c35c8371592952d3b8b977aefc11601c5
(cherry picked from commit 30c5db2f47e0305cd50f0cc90047e9ac9c5f676e)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index c47c319..535d28f 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -42,7 +42,8 @@
 	cfiExportsMap      android.Path
 	cfiStaticLibsMutex sync.Mutex
 
-	intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
+	intOverflowCflags   = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
+	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer", "-fno-sanitize-recover=integer"}
 )
 
 type sanitizerType int
@@ -112,9 +113,10 @@
 		Blacklist *string
 	} `android:"arch_variant"`
 
-	SanitizerEnabled bool `blueprint:"mutated"`
-	SanitizeDep      bool `blueprint:"mutated"`
-	InSanitizerDir   bool `blueprint:"mutated"`
+	SanitizerEnabled  bool `blueprint:"mutated"`
+	SanitizeDep       bool `blueprint:"mutated"`
+	MinimalRuntimeDep bool `blueprint:"mutated"`
+	InSanitizerDir    bool `blueprint:"mutated"`
 }
 
 type sanitize struct {
@@ -301,6 +303,11 @@
 }
 
 func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
+	minimalRuntimePath := "${config.ClangAsanLibDir}/" + config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
+
+	if ctx.Device() && sanitize.Properties.MinimalRuntimeDep {
+		flags.LdFlags = append(flags.LdFlags, minimalRuntimePath)
+	}
 	if !sanitize.Properties.SanitizerEnabled {
 		return flags
 	}
@@ -431,6 +438,7 @@
 
 	if len(sanitizers) > 0 {
 		sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
+
 		flags.CFlags = append(flags.CFlags, sanitizeArg)
 		if ctx.Host() {
 			flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
@@ -440,6 +448,11 @@
 			_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
 		} else {
 			flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
+
+			if enableMinimalRuntime(sanitize) {
+				flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " "))
+				flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
+			}
 		}
 	}
 
@@ -589,6 +602,24 @@
 	}
 }
 
+// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
+func minimalRuntimeDepsMutator() func(android.TopDownMutatorContext) {
+	return func(mctx android.TopDownMutatorContext) {
+		if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
+			mctx.VisitDepsDepthFirst(func(module android.Module) {
+				if d, ok := module.(*Module); ok && d.static() && d.sanitize != nil {
+
+					// If a static dependency will be built with the minimal runtime,
+					// make sure we include the ubsan minimal runtime.
+					if enableMinimalRuntime(d.sanitize) {
+						c.sanitize.Properties.MinimalRuntimeDep = true
+					}
+				}
+			})
+		}
+	}
+}
+
 // Create sanitized variants for modules that need them
 func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
 	return func(mctx android.BottomUpMutatorContext) {
@@ -659,6 +690,18 @@
 	}).(*[]string)
 }
 
+func enableMinimalRuntime(sanitize *sanitize) bool {
+	if !Bool(sanitize.Properties.Sanitize.Address) &&
+		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
+			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
+		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
+			Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
+			len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
+		return true
+	}
+	return false
+}
+
 func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
 	cfiStaticLibs := cfiStaticLibs(ctx.Config())
 	sort.Strings(*cfiStaticLibs)