Copy Rust fuzzer dependencies to /data.

Fix an issue where rust_fuzz modules were
not correctly packaging and copying their
dependencies.

This is done by extending the CC fuzz packager
to simply handle both Rust and CC modules,
ensuring this doesn't get out of sync again.
Fuzzer related functions are added to the
Linkable interface to facilitate this.

There was a bug where the Make definitions for
Rust fuzzers were not being created as well,
and that is addressed here.

Bug: 249551848
Test: m android_log_fuzzer #check $OUT/data/fuzz/arm64/libs
Change-Id: I9b41153e0cf08ab510476b75003c3a3baccc3858
diff --git a/cc/cc.go b/cc/cc.go
index 753975e..2dd59b4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1065,6 +1065,31 @@
 	return false
 }
 
+func (c *Module) IsFuzzModule() bool {
+	if _, ok := c.compiler.(*fuzzBinary); ok {
+		return true
+	}
+	return false
+}
+
+func (c *Module) FuzzModuleStruct() fuzz.FuzzModule {
+	return c.FuzzModule
+}
+
+func (c *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
+	if fuzzer, ok := c.compiler.(*fuzzBinary); ok {
+		return fuzzer.fuzzPackagedModule
+	}
+	panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", c.BaseModuleName()))
+}
+
+func (c *Module) FuzzSharedLibraries() android.Paths {
+	if fuzzer, ok := c.compiler.(*fuzzBinary); ok {
+		return fuzzer.sharedLibraries
+	}
+	panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", c.BaseModuleName()))
+}
+
 func (c *Module) NonCcVariants() bool {
 	return false
 }
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 7113d87..7aa8b91 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -212,7 +212,7 @@
 	return true
 }
 
-func sharedLibraryInstallLocation(
+func SharedLibraryInstallLocation(
 	libraryPath android.Path, isHost bool, fuzzDir string, archString string) string {
 	installLocation := "$(PRODUCT_OUT)/data"
 	if isHost {
@@ -224,7 +224,7 @@
 }
 
 // Get the device-only shared library symbols install directory.
-func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string {
+func SharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string {
 	return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryPath.Base())
 }
 
@@ -237,59 +237,64 @@
 		installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
 	fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
 
-	fuzzBin.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Corpus)
-	builder := android.NewRuleBuilder(pctx, ctx)
-	intermediateDir := android.PathForModuleOut(ctx, "corpus")
-	for _, entry := range fuzzBin.fuzzPackagedModule.Corpus {
-		builder.Command().Text("cp").
-			Input(entry).
-			Output(intermediateDir.Join(ctx, entry.Base()))
-	}
-	builder.Build("copy_corpus", "copy corpus")
-	fuzzBin.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
-
-	fuzzBin.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Data)
-	builder = android.NewRuleBuilder(pctx, ctx)
-	intermediateDir = android.PathForModuleOut(ctx, "data")
-	for _, entry := range fuzzBin.fuzzPackagedModule.Data {
-		builder.Command().Text("cp").
-			Input(entry).
-			Output(intermediateDir.Join(ctx, entry.Rel()))
-	}
-	builder.Build("copy_data", "copy data")
-	fuzzBin.fuzzPackagedModule.DataIntermediateDir = intermediateDir
-
-	if fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
-		fuzzBin.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary)
-		if fuzzBin.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
-			ctx.PropertyErrorf("dictionary",
-				"Fuzzer dictionary %q does not have '.dict' extension",
-				fuzzBin.fuzzPackagedModule.Dictionary.String())
-		}
-	}
-
-	if fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
-		configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
-		android.WriteFileRule(ctx, configPath, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
-		fuzzBin.fuzzPackagedModule.Config = configPath
-	}
+	fuzzBin.fuzzPackagedModule = PackageFuzzModule(ctx, fuzzBin.fuzzPackagedModule, pctx)
 
 	// Grab the list of required shared libraries.
 	fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
 
 	for _, lib := range fuzzBin.sharedLibraries {
 		fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
-			sharedLibraryInstallLocation(
+			SharedLibraryInstallLocation(
 				lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
 
 		// Also add the dependency on the shared library symbols dir.
 		if !ctx.Host() {
 			fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
-				sharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
+				SharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
 		}
 	}
 }
 
+func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule, pctx android.PackageContext) fuzz.FuzzPackagedModule {
+	fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Corpus)
+	builder := android.NewRuleBuilder(pctx, ctx)
+	intermediateDir := android.PathForModuleOut(ctx, "corpus")
+	for _, entry := range fuzzPackagedModule.Corpus {
+		builder.Command().Text("cp").
+			Input(entry).
+			Output(intermediateDir.Join(ctx, entry.Base()))
+	}
+	builder.Build("copy_corpus", "copy corpus")
+	fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
+
+	fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
+	builder = android.NewRuleBuilder(pctx, ctx)
+	intermediateDir = android.PathForModuleOut(ctx, "data")
+	for _, entry := range fuzzPackagedModule.Data {
+		builder.Command().Text("cp").
+			Input(entry).
+			Output(intermediateDir.Join(ctx, entry.Rel()))
+	}
+	builder.Build("copy_data", "copy data")
+	fuzzPackagedModule.DataIntermediateDir = intermediateDir
+
+	if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
+		fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
+		if fuzzPackagedModule.Dictionary.Ext() != ".dict" {
+			ctx.PropertyErrorf("dictionary",
+				"Fuzzer dictionary %q does not have '.dict' extension",
+				fuzzPackagedModule.Dictionary.String())
+		}
+	}
+
+	if fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
+		configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
+		android.WriteFileRule(ctx, configPath, fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
+		fuzzPackagedModule.Config = configPath
+	}
+	return fuzzPackagedModule
+}
+
 func NewFuzzer(hod android.HostOrDeviceSupported) *Module {
 	module, binary := newBinary(hod, false)
 	baseInstallerPath := "fuzz"
@@ -344,7 +349,7 @@
 
 // Responsible for generating GNU Make rules that package fuzz targets into
 // their architecture & target/host specific zip file.
-type ccFuzzPackager struct {
+type ccRustFuzzPackager struct {
 	fuzz.FuzzPackager
 	fuzzPackagingArchModules         string
 	fuzzTargetSharedDepsInstallPairs string
@@ -353,7 +358,7 @@
 
 func fuzzPackagingFactory() android.Singleton {
 
-	fuzzPackager := &ccFuzzPackager{
+	fuzzPackager := &ccRustFuzzPackager{
 		fuzzPackagingArchModules:         "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
 		fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
 		allFuzzTargetsName:               "ALL_FUZZ_TARGETS",
@@ -361,7 +366,7 @@
 	return fuzzPackager
 }
 
-func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
 	// Map between each architecture + host/device combination, and the files that
 	// need to be packaged (in the tuple of {source file, destination folder in
 	// archive}).
@@ -376,19 +381,18 @@
 	sharedLibraryInstalled := make(map[string]bool)
 
 	ctx.VisitAllModules(func(module android.Module) {
-		ccModule, ok := module.(*Module)
-		if !ok || ccModule.Properties.PreventInstall {
+		ccModule, ok := module.(LinkableInterface)
+		if !ok || ccModule.PreventInstall() {
 			return
 		}
 
 		// Discard non-fuzz targets.
-		if ok := fuzz.IsValid(ccModule.FuzzModule); !ok {
+		if ok := fuzz.IsValid(ccModule.FuzzModuleStruct()); !ok {
 			return
 		}
 
 		sharedLibsInstallDirPrefix := "lib"
-		fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
-		if !ok {
+		if !ccModule.IsFuzzModule() {
 			return
 		}
 
@@ -399,12 +403,12 @@
 
 		fpm := fuzz.FuzzPackagedModule{}
 		if ok {
-			fpm = fuzzModule.fuzzPackagedModule
+			fpm = ccModule.FuzzPackagedModule()
 		}
 
 		intermediatePath := "fuzz"
 
-		archString := ccModule.Arch().ArchType.String()
+		archString := ccModule.Target().Arch.ArchType.String()
 		archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString)
 		archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
 
@@ -415,7 +419,7 @@
 		files = s.PackageArtifacts(ctx, module, fpm, archDir, builder)
 
 		// Package shared libraries
-		files = append(files, GetSharedLibsToZip(fuzzModule.sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
+		files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries(), ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
 
 		// The executable.
 		files = append(files, fuzz.FileToZip{android.OutputFileForModule(ctx, ccModule, "unstripped"), ""})
@@ -429,7 +433,7 @@
 	s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
 }
 
-func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+func (s *ccRustFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
 	packages := s.Packages.Strings()
 	sort.Strings(packages)
 	sort.Strings(s.FuzzPackager.SharedLibInstallStrings)
@@ -460,7 +464,7 @@
 		// For each architecture-specific shared library dependency, we need to
 		// install it to the output directory. Setup the install destination here,
 		// which will be used by $(copy-many-files) in the Make backend.
-		installDestination := sharedLibraryInstallLocation(
+		installDestination := SharedLibraryInstallLocation(
 			library, module.Host(), fuzzDir, archString)
 		if (*sharedLibraryInstalled)[installDestination] {
 			continue
@@ -479,7 +483,7 @@
 		// we want symbolization tools (like `stack`) to be able to find the symbols
 		// in $ANDROID_PRODUCT_OUT/symbols automagically.
 		if !module.Host() {
-			symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, fuzzDir, archString)
+			symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(library, fuzzDir, archString)
 			symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
 			s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
 				library.String()+":"+symbolsInstallDestination)
diff --git a/cc/linkable.go b/cc/linkable.go
index 0522fc6..9578807 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -3,6 +3,7 @@
 import (
 	"android/soong/android"
 	"android/soong/bazel/cquery"
+	"android/soong/fuzz"
 	"android/soong/snapshot"
 
 	"github.com/google/blueprint"
@@ -120,6 +121,17 @@
 	IsPrebuilt() bool
 	Toc() android.OptionalPath
 
+	// IsFuzzModule returns true if this a *_fuzz module.
+	IsFuzzModule() bool
+
+	// FuzzPackagedModule returns the fuzz.FuzzPackagedModule for this module.
+	// Expects that IsFuzzModule returns true.
+	FuzzPackagedModule() fuzz.FuzzPackagedModule
+
+	// FuzzSharedLibraries returns the shared library dependencies for this module.
+	// Expects that IsFuzzModule returns true.
+	FuzzSharedLibraries() android.Paths
+
 	Device() bool
 	Host() bool
 
@@ -256,6 +268,9 @@
 
 	// Partition returns the partition string for this module.
 	Partition() string
+
+	// FuzzModule returns the fuzz.FuzzModule associated with the module.
+	FuzzModuleStruct() fuzz.FuzzModule
 }
 
 var (
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 32c746e..20e9919 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -205,8 +205,8 @@
 		})
 }
 
-func (fuzz *fuzzDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
-	ctx.SubAndroidMk(entries, fuzz.binaryDecorator)
+func (fuzz *fuzzDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
+	ctx.SubAndroidMk(ret, fuzz.binaryDecorator)
 
 	var fuzzFiles []string
 	for _, d := range fuzz.fuzzPackagedModule.Corpus {
@@ -229,11 +229,14 @@
 			filepath.Dir(fuzz.fuzzPackagedModule.Config.String())+":config.json")
 	}
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
+	ret.ExtraEntries = append(ret.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
 		entries *android.AndroidMkEntries) {
 		entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
 		if len(fuzzFiles) > 0 {
 			entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
 		}
+		if fuzz.installedSharedDeps != nil {
+			entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
+		}
 	})
 }
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 6faf55c..d7e7ddf 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -16,8 +16,6 @@
 
 import (
 	"path/filepath"
-	"sort"
-	"strings"
 
 	"android/soong/android"
 	"android/soong/cc"
@@ -27,14 +25,14 @@
 
 func init() {
 	android.RegisterModuleType("rust_fuzz", RustFuzzFactory)
-	android.RegisterSingletonType("rust_fuzz_packaging", rustFuzzPackagingFactory)
 }
 
 type fuzzDecorator struct {
 	*binaryDecorator
 
-	fuzzPackagedModule fuzz.FuzzPackagedModule
-	sharedLibraries    android.Paths
+	fuzzPackagedModule  fuzz.FuzzPackagedModule
+	sharedLibraries     android.Paths
+	installedSharedDeps []string
 }
 
 var _ compiler = (*fuzzDecorator)(nil)
@@ -64,9 +62,14 @@
 	flags = fuzzer.binaryDecorator.compilerFlags(ctx, flags)
 
 	// `../lib` for installed fuzz targets (both host and device), and `./lib` for fuzz target packages.
-	flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
 	flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
 
+	if ctx.InstallInVendor() {
+		flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+	} else {
+		flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+
+	}
 	return flags
 }
 
@@ -88,10 +91,8 @@
 }
 
 func (fuzzer *fuzzDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
-	out := fuzzer.binaryDecorator.compile(ctx, flags, deps)
 
-	// Grab the list of required shared libraries.
-	fuzzer.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
+	out := fuzzer.binaryDecorator.compile(ctx, flags, deps)
 
 	return out
 }
@@ -104,83 +105,6 @@
 	return rlibAutoDep
 }
 
-// Responsible for generating GNU Make rules that package fuzz targets into
-// their architecture & target/host specific zip file.
-type rustFuzzPackager struct {
-	fuzz.FuzzPackager
-}
-
-func rustFuzzPackagingFactory() android.Singleton {
-	return &rustFuzzPackager{}
-}
-
-func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
-	// Map between each architecture + host/device combination.
-	archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
-
-	// List of individual fuzz targets.
-	s.FuzzTargets = make(map[string]bool)
-
-	// Map tracking whether each shared library has an install rule to avoid duplicate install rules from
-	// multiple fuzzers that depend on the same shared library.
-	sharedLibraryInstalled := make(map[string]bool)
-
-	ctx.VisitAllModules(func(module android.Module) {
-		// Discard non-fuzz targets.
-		rustModule, ok := module.(*Module)
-		if !ok {
-			return
-		}
-
-		if ok := fuzz.IsValid(rustModule.FuzzModule); !ok || rustModule.Properties.PreventInstall {
-			return
-		}
-
-		fuzzModule, ok := rustModule.compiler.(*fuzzDecorator)
-		if !ok {
-			return
-		}
-
-		hostOrTargetString := "target"
-		if rustModule.Host() {
-			hostOrTargetString = "host"
-		}
-
-		archString := rustModule.Arch().ArchType.String()
-		archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
-		archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
-
-		var files []fuzz.FileToZip
-		builder := android.NewRuleBuilder(pctx, ctx)
-
-		// Package the artifacts (data, corpus, config and dictionary into a zipfile.
-		files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder)
-
-		// The executable.
-		files = append(files, fuzz.FileToZip{rustModule.UnstrippedOutputFile(), ""})
-
-		// Package shared libraries
-		files = append(files, cc.GetSharedLibsToZip(fuzzModule.sharedLibraries, rustModule, &s.FuzzPackager, archString, "lib", &sharedLibraryInstalled)...)
-
-		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
-		if !ok {
-			return
-		}
-
-	})
-	s.CreateFuzzPackage(ctx, archDirs, fuzz.Rust, pctx)
-}
-
-func (s *rustFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
-	packages := s.Packages.Strings()
-	sort.Strings(packages)
-
-	ctx.Strict("SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
-
-	// Preallocate the slice of fuzz targets to minimize memory allocations.
-	s.PreallocateSlice(ctx, "ALL_RUST_FUZZ_TARGETS")
-}
-
 func (fuzz *fuzzDecorator) install(ctx ModuleContext) {
 	fuzz.binaryDecorator.baseCompiler.dir = filepath.Join(
 		"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
@@ -188,13 +112,22 @@
 		"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
 	fuzz.binaryDecorator.baseCompiler.install(ctx)
 
-	if fuzz.fuzzPackagedModule.FuzzProperties.Corpus != nil {
-		fuzz.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Corpus)
-	}
-	if fuzz.fuzzPackagedModule.FuzzProperties.Data != nil {
-		fuzz.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Data)
-	}
-	if fuzz.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
-		fuzz.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzz.fuzzPackagedModule.FuzzProperties.Dictionary)
+	fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule, pctx)
+
+	installBase := "fuzz"
+
+	// Grab the list of required shared libraries.
+	fuzz.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
+
+	for _, lib := range fuzz.sharedLibraries {
+		fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+			cc.SharedLibraryInstallLocation(
+				lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
+
+		// Also add the dependency on the shared library symbols dir.
+		if !ctx.Host() {
+			fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+				cc.SharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
+		}
 	}
 }
diff --git a/rust/rust.go b/rust/rust.go
index 28a300b..67e0d7c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -208,6 +208,11 @@
 			}
 			return android.Paths{}, nil
 		}
+	case "unstripped":
+		if mod.compiler != nil {
+			return android.PathsIfNonNil(mod.compiler.unstrippedOutputFilePath()), nil
+		}
+		return nil, nil
 	default:
 		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
 	}
@@ -619,6 +624,31 @@
 	return false
 }
 
+func (mod *Module) IsFuzzModule() bool {
+	if _, ok := mod.compiler.(*fuzzDecorator); ok {
+		return true
+	}
+	return false
+}
+
+func (mod *Module) FuzzModuleStruct() fuzz.FuzzModule {
+	return mod.FuzzModule
+}
+
+func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
+	if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
+		return fuzzer.fuzzPackagedModule
+	}
+	panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) FuzzSharedLibraries() android.Paths {
+	if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
+		return fuzzer.sharedLibraries
+	}
+	panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", mod.BaseModuleName()))
+}
+
 func (mod *Module) UnstrippedOutputFile() android.Path {
 	if mod.compiler != nil {
 		return mod.compiler.unstrippedOutputFilePath()