Fix -Wl,--exclude-libs for clang runtime libraries

THe sanitize code was assuming that the names of the clang runtime
library modules were the same as their static library output files,
but that's not true after I39e2cf8ae14edf8510276dab38011afaef85822c.
Use the dependency to get the name of the library to pass to
-Wl,--exclude-libs.

Bug: 235624976
Test: TestUbsan
Change-Id: If6ca7838800c76f90105fb02d39e8a68cec96314
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index c1ca034..0e5552f 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -201,6 +201,121 @@
 	t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
 }
 
+func TestUbsan(t *testing.T) {
+	bp := `
+		cc_binary {
+			name: "bin_with_ubsan",
+			host_supported: true,
+			shared_libs: [
+				"libshared",
+			],
+			static_libs: [
+				"libstatic",
+				"libnoubsan",
+			],
+			sanitize: {
+				undefined: true,
+			}
+		}
+
+		cc_binary {
+			name: "bin_depends_ubsan",
+			host_supported: true,
+			shared_libs: [
+				"libshared",
+			],
+			static_libs: [
+				"libstatic",
+				"libubsan",
+				"libnoubsan",
+			],
+		}
+
+		cc_binary {
+			name: "bin_no_ubsan",
+			host_supported: true,
+			shared_libs: [
+				"libshared",
+			],
+			static_libs: [
+				"libstatic",
+				"libnoubsan",
+			],
+		}
+
+		cc_library_shared {
+			name: "libshared",
+			host_supported: true,
+			shared_libs: ["libtransitive"],
+		}
+
+		cc_library_shared {
+			name: "libtransitive",
+			host_supported: true,
+		}
+
+		cc_library_static {
+			name: "libubsan",
+			host_supported: true,
+			sanitize: {
+				undefined: true,
+			}
+		}
+
+		cc_library_static {
+			name: "libstatic",
+			host_supported: true,
+		}
+
+		cc_library_static {
+			name: "libnoubsan",
+			host_supported: true,
+		}
+	`
+
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+	).RunTestWithBp(t, bp)
+
+	check := func(t *testing.T, result *android.TestResult, variant string) {
+		staticVariant := variant + "_static"
+
+		minimalRuntime := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant)
+
+		// The binaries, one with ubsan and one without
+		binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant)
+		binDependsUbsan := result.ModuleForTests("bin_depends_ubsan", variant)
+		binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant)
+
+		android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_with_ubsan static libs",
+			strings.Split(binWithUbsan.Rule("ld").Args["libFlags"], " "),
+			minimalRuntime.OutputFiles(t, "")[0].String())
+
+		android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_depends_ubsan static libs",
+			strings.Split(binDependsUbsan.Rule("ld").Args["libFlags"], " "),
+			minimalRuntime.OutputFiles(t, "")[0].String())
+
+		android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_no_ubsan static libs",
+			strings.Split(binNoUbsan.Rule("ld").Args["libFlags"], " "),
+			minimalRuntime.OutputFiles(t, "")[0].String())
+
+		android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_with_ubsan",
+			strings.Split(binWithUbsan.Rule("ld").Args["ldFlags"], " "),
+			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+
+		android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan static libs",
+			strings.Split(binDependsUbsan.Rule("ld").Args["ldFlags"], " "),
+			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+
+		android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_no_ubsan static libs",
+			strings.Split(binNoUbsan.Rule("ld").Args["ldFlags"], " "),
+			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+	}
+
+	t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
+	t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+}
+
 type MemtagNoteType int
 
 const (