Merge "Move sanitizer.libraries.txt logic into Soong" into main
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 7dc990b..5d8c351 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -209,58 +209,58 @@
 	return list
 }
 
-func LibclangRuntimeLibrary(t Toolchain, library string) string {
+func LibclangRuntimeLibrary(library string) string {
 	return "libclang_rt." + library
 }
 
-func BuiltinsRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "builtins")
+func BuiltinsRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("builtins")
 }
 
-func AddressSanitizerRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "asan")
+func AddressSanitizerRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("asan")
 }
 
-func AddressSanitizerStaticRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "asan.static")
+func AddressSanitizerStaticRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("asan.static")
 }
 
-func AddressSanitizerCXXStaticRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "asan_cxx.static")
+func AddressSanitizerCXXStaticRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("asan_cxx.static")
 }
 
-func HWAddressSanitizerRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "hwasan")
+func HWAddressSanitizerRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("hwasan")
 }
 
-func HWAddressSanitizerStaticLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "hwasan_static")
+func HWAddressSanitizerStaticLibrary() string {
+	return LibclangRuntimeLibrary("hwasan_static")
 }
 
-func UndefinedBehaviorSanitizerRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "ubsan_standalone")
+func UndefinedBehaviorSanitizerRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("ubsan_standalone")
 }
 
-func UndefinedBehaviorSanitizerMinimalRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "ubsan_minimal")
+func UndefinedBehaviorSanitizerMinimalRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("ubsan_minimal")
 }
 
-func ThreadSanitizerRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "tsan")
+func ThreadSanitizerRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("tsan")
 }
 
-func ScudoRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "scudo")
+func ScudoRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("scudo")
 }
 
-func ScudoMinimalRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "scudo_minimal")
+func ScudoMinimalRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("scudo_minimal")
 }
 
-func LibFuzzerRuntimeLibrary(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "fuzzer")
+func LibFuzzerRuntimeLibrary() string {
+	return LibclangRuntimeLibrary("fuzzer")
 }
 
-func LibFuzzerRuntimeInterceptors(t Toolchain) string {
-	return LibclangRuntimeLibrary(t, "fuzzer_interceptors")
+func LibFuzzerRuntimeInterceptors() string {
+	return LibclangRuntimeLibrary("fuzzer_interceptors")
 }
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 164ec99..92f2c5e 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -128,13 +128,13 @@
 	if ctx.Config().Getenv("FUZZ_FRAMEWORK") == "AFL" {
 		deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers")
 	} else {
-		deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
+		deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary())
 		// Fuzzers built with HWASAN should use the interceptors for better
 		// mutation based on signals in strcmp, memcpy, etc. This is only needed for
 		// fuzz targets, not generic HWASAN-ified binaries or libraries.
 		if module, ok := ctx.Module().(*Module); ok {
 			if module.IsSanitizerEnabled(Hwasan) {
-				deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeInterceptors(ctx.toolchain()))
+				deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeInterceptors())
 			}
 		}
 	}
diff --git a/cc/linker.go b/cc/linker.go
index f325c12..1b5a33a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -431,7 +431,7 @@
 	if ctx.toolchain().Bionic() {
 		// libclang_rt.builtins has to be last on the command line
 		if linker.Properties.libCrt() && !ctx.header() {
-			deps.UnexportedStaticLibs = append(deps.UnexportedStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
+			deps.UnexportedStaticLibs = append(deps.UnexportedStaticLibs, config.BuiltinsRuntimeLibrary())
 		}
 
 		if inList("libdl", deps.SharedLibs) {
@@ -454,7 +454,7 @@
 		}
 	} else if ctx.toolchain().Musl() {
 		if linker.Properties.libCrt() && !ctx.header() {
-			deps.UnexportedStaticLibs = append(deps.UnexportedStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
+			deps.UnexportedStaticLibs = append(deps.UnexportedStaticLibs, config.BuiltinsRuntimeLibrary())
 		}
 	}
 
diff --git a/cc/makevars.go b/cc/makevars.go
index 51bcbf0..9d29aff 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -28,6 +28,16 @@
 	modulesWarningsAllowedKey    = android.NewOnceKey("ModulesWarningsAllowed")
 	modulesUsingWnoErrorKey      = android.NewOnceKey("ModulesUsingWnoError")
 	modulesMissingProfileFileKey = android.NewOnceKey("ModulesMissingProfileFile")
+	sanitizerVariables           = map[string]string{
+		"ADDRESS_SANITIZER_RUNTIME_LIBRARY":   config.AddressSanitizerRuntimeLibrary(),
+		"HWADDRESS_SANITIZER_RUNTIME_LIBRARY": config.HWAddressSanitizerRuntimeLibrary(),
+		"HWADDRESS_SANITIZER_STATIC_LIBRARY":  config.HWAddressSanitizerStaticLibrary(),
+		"UBSAN_RUNTIME_LIBRARY":               config.UndefinedBehaviorSanitizerRuntimeLibrary(),
+		"UBSAN_MINIMAL_RUNTIME_LIBRARY":       config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(),
+		"TSAN_RUNTIME_LIBRARY":                config.ThreadSanitizerRuntimeLibrary(),
+		"SCUDO_RUNTIME_LIBRARY":               config.ScudoRuntimeLibrary(),
+		"SCUDO_MINIMAL_RUNTIME_LIBRARY":       config.ScudoMinimalRuntimeLibrary(),
+	}
 )
 
 func init() {
@@ -261,43 +271,9 @@
 	}, " "))
 
 	if target.Os.Class == android.Device {
-		sanitizerVariables := map[string]string{
-			"ADDRESS_SANITIZER_RUNTIME_LIBRARY":   config.AddressSanitizerRuntimeLibrary(toolchain),
-			"HWADDRESS_SANITIZER_RUNTIME_LIBRARY": config.HWAddressSanitizerRuntimeLibrary(toolchain),
-			"HWADDRESS_SANITIZER_STATIC_LIBRARY":  config.HWAddressSanitizerStaticLibrary(toolchain),
-			"UBSAN_RUNTIME_LIBRARY":               config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain),
-			"UBSAN_MINIMAL_RUNTIME_LIBRARY":       config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain),
-			"TSAN_RUNTIME_LIBRARY":                config.ThreadSanitizerRuntimeLibrary(toolchain),
-			"SCUDO_RUNTIME_LIBRARY":               config.ScudoRuntimeLibrary(toolchain),
-			"SCUDO_MINIMAL_RUNTIME_LIBRARY":       config.ScudoMinimalRuntimeLibrary(toolchain),
-		}
-
 		for variable, value := range sanitizerVariables {
 			ctx.Strict(secondPrefix+variable, value)
 		}
-
-		sanitizerLibs := android.SortedStringValues(sanitizerVariables)
-		var sanitizerLibStems []string
-		ctx.VisitAllModules(func(m android.Module) {
-			if !m.Enabled(ctx) {
-				return
-			}
-
-			ccModule, _ := m.(*Module)
-			if ccModule == nil || ccModule.library == nil || !ccModule.library.shared() {
-				return
-			}
-
-			if android.InList(strings.TrimPrefix(ctx.ModuleName(m), "prebuilt_"), sanitizerLibs) &&
-				m.Target().Os == target.Os && m.Target().Arch.ArchType == target.Arch.ArchType {
-				outputFile := ccModule.outputFile
-				if outputFile.Valid() {
-					sanitizerLibStems = append(sanitizerLibStems, outputFile.Path().Base())
-				}
-			}
-		})
-		sanitizerLibStems = android.SortedUniqueStrings(sanitizerLibStems)
-		ctx.Strict(secondPrefix+"SANITIZER_STEMS", strings.Join(sanitizerLibStems, " "))
 	}
 
 	// This is used by external/gentoo/...
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 1a94729..e6075ad 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -25,6 +25,7 @@
 
 	"android/soong/android"
 	"android/soong/cc/config"
+	"android/soong/etc"
 )
 
 var (
@@ -408,6 +409,8 @@
 	android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
 	android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
 	android.RegisterMakeVarsProvider(pctx, memtagStackMakeVarsProvider)
+
+	RegisterSanitizerLibrariesTxtType(android.InitRegistrationContext)
 }
 
 func (sanitize *sanitize) props() []interface{} {
@@ -1316,7 +1319,7 @@
 				} else if s.sanitizer == cfi {
 					cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
 				} else if s.sanitizer == Memtag_stack {
-					memtagStackStaticLibs(mctx.Config()).add(c, c.Module().Name());
+					memtagStackStaticLibs(mctx.Config()).add(c, c.Module().Name())
 				}
 			}
 		} else if c.IsSanitizerEnabled(s.sanitizer) {
@@ -1522,25 +1525,25 @@
 		if Bool(sanProps.Address) {
 			if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
 				// Use a static runtime for musl to match what clang does for glibc.
-				addStaticDeps(config.AddressSanitizerStaticRuntimeLibrary(toolchain), false)
-				addStaticDeps(config.AddressSanitizerCXXStaticRuntimeLibrary(toolchain), false)
+				addStaticDeps(config.AddressSanitizerStaticRuntimeLibrary(), false)
+				addStaticDeps(config.AddressSanitizerCXXStaticRuntimeLibrary(), false)
 			} else {
-				runtimeSharedLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
+				runtimeSharedLibrary = config.AddressSanitizerRuntimeLibrary()
 			}
 		} else if Bool(sanProps.Hwaddress) {
 			if c.staticBinary() {
-				addStaticDeps(config.HWAddressSanitizerStaticLibrary(toolchain), true)
+				addStaticDeps(config.HWAddressSanitizerStaticLibrary(), true)
 				addStaticDeps("libdl", false)
 			} else {
-				runtimeSharedLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
+				runtimeSharedLibrary = config.HWAddressSanitizerRuntimeLibrary()
 			}
 		} else if Bool(sanProps.Thread) {
-			runtimeSharedLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
+			runtimeSharedLibrary = config.ThreadSanitizerRuntimeLibrary()
 		} else if Bool(sanProps.Scudo) {
 			if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
-				runtimeSharedLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
+				runtimeSharedLibrary = config.ScudoMinimalRuntimeLibrary()
 			} else {
-				runtimeSharedLibrary = config.ScudoRuntimeLibrary(toolchain)
+				runtimeSharedLibrary = config.ScudoRuntimeLibrary()
 			}
 		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
 			Bool(sanProps.Fuzzer) ||
@@ -1553,17 +1556,17 @@
 				// Also manually add a static runtime for musl to match what clang does for glibc.
 				// Otherwise dlopening libraries that depend on libclang_rt.ubsan_standalone.so fails with:
 				// Error relocating ...: initial-exec TLS resolves to dynamic definition
-				addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)+".static", true)
+				addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary()+".static", true)
 			} else {
-				runtimeSharedLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
+				runtimeSharedLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary()
 			}
 		}
 
 		if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep {
-			addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), true)
+			addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(), true)
 		}
 		if c.sanitize.Properties.BuiltinsDep {
-			addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain), true)
+			addStaticDeps(config.BuiltinsRuntimeLibrary(), true)
 		}
 
 		if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl()) {
@@ -1787,3 +1790,126 @@
 func memtagStackMakeVarsProvider(ctx android.MakeVarsContext) {
 	memtagStackStaticLibs(ctx.Config()).exportToMake(ctx)
 }
+
+type sanitizerLibrariesTxtModule struct {
+	android.ModuleBase
+
+	outputFile android.OutputPath
+}
+
+var _ etc.PrebuiltEtcModule = (*sanitizerLibrariesTxtModule)(nil)
+var _ android.OutputFileProducer = (*sanitizerLibrariesTxtModule)(nil)
+
+func RegisterSanitizerLibrariesTxtType(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("sanitizer_libraries_txt", sanitizerLibrariesTxtFactory)
+}
+
+func sanitizerLibrariesTxtFactory() android.Module {
+	m := &sanitizerLibrariesTxtModule{}
+	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+	return m
+}
+
+type sanitizerLibraryDependencyTag struct {
+	blueprint.BaseDependencyTag
+}
+
+func (t sanitizerLibraryDependencyTag) AllowDisabledModuleDependency(target android.Module) bool {
+	return true
+}
+
+var _ android.AllowDisabledModuleDependency = (*sanitizerLibraryDependencyTag)(nil)
+
+func (txt *sanitizerLibrariesTxtModule) DepsMutator(actx android.BottomUpMutatorContext) {
+	targets := actx.Config().Targets[android.Android]
+	depTag := sanitizerLibraryDependencyTag{}
+
+	for _, target := range targets {
+		variation := append(target.Variations(),
+			blueprint.Variation{Mutator: "image", Variation: ""},
+			blueprint.Variation{Mutator: "sdk", Variation: ""},
+			blueprint.Variation{Mutator: "link", Variation: "shared"},
+		)
+		for _, lib := range android.SortedStringValues(sanitizerVariables) {
+			if actx.OtherModuleFarDependencyVariantExists(variation, lib) {
+				actx.AddFarVariationDependencies(variation, depTag, lib)
+			}
+
+			prebuiltLibName := "prebuilt_" + lib
+			if actx.OtherModuleFarDependencyVariantExists(variation, prebuiltLibName) {
+				actx.AddFarVariationDependencies(variation, depTag, prebuiltLibName)
+			}
+		}
+	}
+
+}
+
+func (txt *sanitizerLibrariesTxtModule) getSanitizerLibs(ctx android.ModuleContext) string {
+	var sanitizerLibStems []string
+
+	ctx.VisitDirectDepsIf(func(m android.Module) bool {
+		if !m.Enabled(ctx) {
+			return false
+		}
+
+		ccModule, _ := m.(*Module)
+		if ccModule == nil || ccModule.library == nil || !ccModule.library.shared() {
+			return false
+		}
+
+		targets := ctx.Config().Targets[android.Android]
+
+		for _, target := range targets {
+			if m.Target().Os == target.Os && m.Target().Arch.ArchType == target.Arch.ArchType {
+				return true
+			}
+		}
+
+		return false
+	}, func(m android.Module) {
+		ccModule, _ := m.(*Module)
+		outputFile := ccModule.outputFile
+		if outputFile.Valid() {
+			sanitizerLibStems = append(sanitizerLibStems, outputFile.Path().Base())
+		}
+	})
+
+	sanitizerLibStems = android.SortedUniqueStrings(sanitizerLibStems)
+	return strings.Join(sanitizerLibStems, "\n")
+}
+
+func (txt *sanitizerLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	filename := txt.Name()
+
+	txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
+	android.WriteFileRule(ctx, txt.outputFile, txt.getSanitizerLibs(ctx))
+
+	installPath := android.PathForModuleInstall(ctx, "etc")
+	ctx.InstallFile(installPath, filename, txt.outputFile)
+}
+
+func (txt *sanitizerLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(txt.outputFile),
+	}}
+}
+
+// PrebuiltEtcModule interface
+func (txt *sanitizerLibrariesTxtModule) OutputFile() android.OutputPath {
+	return txt.outputFile
+}
+
+// PrebuiltEtcModule interface
+func (txt *sanitizerLibrariesTxtModule) BaseDir() string {
+	return "etc"
+}
+
+// PrebuiltEtcModule interface
+func (txt *sanitizerLibrariesTxtModule) SubDir() string {
+	return ""
+}
+
+func (txt *sanitizerLibrariesTxtModule) OutputFiles(tag string) (android.Paths, error) {
+	return android.Paths{txt.outputFile}, nil
+}