diff --git a/cc/cc.go b/cc/cc.go index f04b6f054..bc958134f 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -61,6 +61,9 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator).Parallel() ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel() + ctx.TopDown("fuzz_deps", fuzzMutatorDeps) + ctx.BottomUp("fuzz", fuzzMutator) + ctx.BottomUp("coverage", coverageMutator).Parallel() ctx.TopDown("afdo_deps", afdoDepsMutator) @@ -838,6 +841,7 @@ type Module struct { stl *stl sanitize *sanitize coverage *coverage + fuzzer *fuzzer sabi *sabi vndkdep *vndkdep lto *lto @@ -1163,6 +1167,9 @@ func (c *Module) Init() android.Module { if c.coverage != nil { c.AddProperties(c.coverage.props()...) } + if c.fuzzer != nil { + c.AddProperties(c.fuzzer.props()...) + } if c.sabi != nil { c.AddProperties(c.sabi.props()...) } @@ -1680,6 +1687,7 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo module.stl = &stl{} module.sanitize = &sanitize{} module.coverage = &coverage{} + module.fuzzer = &fuzzer{} module.sabi = &sabi{} module.vndkdep = &vndkdep{} module.lto = <o{} @@ -1901,6 +1909,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if c.coverage != nil { flags, deps = c.coverage.flags(ctx, flags, deps) } + if c.fuzzer != nil { + flags = c.fuzzer.flags(ctx, flags) + } if c.lto != nil { flags = c.lto.flags(ctx, flags) } diff --git a/cc/cc_test.go b/cc/cc_test.go index b6d196cc2..24732bf7d 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -3342,6 +3342,125 @@ func TestErrorsIfAModuleDependsOnDisabled(t *testing.T) { `) } +func TestAFLFuzzTarget(t *testing.T) { + ctx := testCc(t, ` + cc_afl_fuzz { + name: "test_afl_fuzz_target", + srcs: ["foo.c"], + host_supported: true, + static_libs: [ + "afl_fuzz_static_lib", + ], + shared_libs: [ + "afl_fuzz_shared_lib", + ], + } + cc_fuzz { + name: "test_fuzz_target", + srcs: ["foo.c"], + static_libs: [ + "afl_fuzz_static_lib", + "libfuzzer_only_static_lib", + ], + shared_libs: [ + "afl_fuzz_shared_lib", + ], + } + cc_library { + name: "afl_fuzz_static_lib", + host_supported: true, + srcs: ["static_file.c"], + } + cc_library { + name: "libfuzzer_only_static_lib", + host_supported: true, + srcs: ["static_file.c"], + } + cc_library { + name: "afl_fuzz_shared_lib", + host_supported: true, + srcs: ["shared_file.c"], + static_libs: [ + "second_static_lib", + ], + } + cc_library_headers { + name: "libafl_headers", + vendor_available: true, + host_supported: true, + export_include_dirs: [ + "include", + "instrumentation", + ], + } + cc_object { + name: "afl-compiler-rt", + vendor_available: true, + host_supported: true, + cflags: [ + "-fPIC", + ], + srcs: [ + "instrumentation/afl-compiler-rt.o.c", + ], + } + cc_library { + name: "second_static_lib", + host_supported: true, + srcs: ["second_file.c"], + } + filegroup { + name: "aflpp_driver", + srcs: [ + "aflpp_driver.c", + ], + }`) + + checkPcGuardFlag := func( + modName string, variantName string, shouldHave bool) { + cc := ctx.ModuleForTests(modName, variantName).Rule("cc") + + cFlags, ok := cc.Args["cFlags"] + if !ok { + t.Errorf("Could not find cFlags for module %s and variant %s", + modName, variantName) + } + + if strings.Contains( + cFlags, "-fsanitize-coverage=trace-pc-guard") != shouldHave { + t.Errorf("Flag was found: %t. Expected to find flag: %t. "+ + "Test failed for module %s and variant %s", + !shouldHave, shouldHave, modName, variantName) + } + } + + for _, vnt := range ctx.ModuleVariantsForTests("libfuzzer_only_static_lib") { + if strings.Contains(vnt, "fuzzer_afl") { + t.Errorf("libfuzzer_only_static_lib has afl variant and should not") + } + } + + moduleName := "test_afl_fuzz_target" + variantName := "android_arm64_armv8-a_fuzzer_afl" + checkPcGuardFlag(moduleName, variantName, true) + + moduleName = "afl_fuzz_static_lib" + variantName = "android_arm64_armv8-a_static" + checkPcGuardFlag(moduleName, variantName, false) + checkPcGuardFlag(moduleName, variantName+"_fuzzer", false) + checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true) + + moduleName = "second_static_lib" + checkPcGuardFlag(moduleName, variantName, false) + checkPcGuardFlag(moduleName, variantName+"_fuzzer", false) + checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true) + + ctx.ModuleForTests("afl_fuzz_shared_lib", + "android_arm64_armv8-a_shared").Rule("cc") + ctx.ModuleForTests("afl_fuzz_shared_lib", + "android_arm64_armv8-a_shared_fuzzer_afl").Rule("cc") +} + // Simple smoke test for the cc_fuzz target that ensures the rule compiles // correctly. func TestFuzzTarget(t *testing.T) { diff --git a/cc/fuzz.go b/cc/fuzz.go index 23d81d600..d6af97f6d 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -27,29 +27,113 @@ import ( ) func init() { - android.RegisterModuleType("cc_fuzz", FuzzFactory) + android.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory) + android.RegisterModuleType("cc_fuzz", LibFuzzFactory) android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory) + android.RegisterSingletonType("cc_afl_fuzz_packaging", fuzzAFLPackagingFactory) +} + +type FuzzProperties struct { + AFLEnabled bool `blueprint:"mutated"` + AFLAddFlags bool `blueprint:"mutated"` +} + +type fuzzer struct { + Properties FuzzProperties +} + +func (fuzzer *fuzzer) flags(ctx ModuleContext, flags Flags) Flags { + if fuzzer.Properties.AFLAddFlags { + flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-coverage=trace-pc-guard") + } + + return flags +} + +func (fuzzer *fuzzer) props() []interface{} { + return []interface{}{&fuzzer.Properties} +} + +func fuzzMutatorDeps(mctx android.TopDownMutatorContext) { + currentModule, ok := mctx.Module().(*Module) + if !ok { + return + } + + if currentModule.fuzzer == nil || !currentModule.fuzzer.Properties.AFLEnabled { + return + } + + mctx.WalkDeps(func(child android.Module, parent android.Module) bool { + c, ok := child.(*Module) + if !ok { + return false + } + + if c.sanitize == nil { + return false + } + + isFuzzerPointer := c.sanitize.getSanitizerBoolPtr(Fuzzer) + if isFuzzerPointer == nil || !*isFuzzerPointer { + return false + } + + if c.fuzzer == nil { + return false + } + + c.fuzzer.Properties.AFLEnabled = true + c.fuzzer.Properties.AFLAddFlags = true + return true + }) +} + +func fuzzMutator(mctx android.BottomUpMutatorContext) { + if c, ok := mctx.Module().(*Module); ok && c.fuzzer != nil { + if !c.fuzzer.Properties.AFLEnabled { + return + } + + if c.Binary() { + m := mctx.CreateVariations("afl") + m[0].(*Module).fuzzer.Properties.AFLEnabled = true + m[0].(*Module).fuzzer.Properties.AFLAddFlags = true + } else { + m := mctx.CreateVariations("", "afl") + m[0].(*Module).fuzzer.Properties.AFLEnabled = false + m[0].(*Module).fuzzer.Properties.AFLAddFlags = false + + m[1].(*Module).fuzzer.Properties.AFLEnabled = true + m[1].(*Module).fuzzer.Properties.AFLAddFlags = true + } + } } // cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at // $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on // your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree. -func FuzzFactory() android.Module { - module := NewFuzz(android.HostAndDeviceSupported) +func LibFuzzFactory() android.Module { + module := NewFuzzer(android.HostAndDeviceSupported, fuzz.Cc) return module.Init() } -func NewFuzzInstaller() *baseInstaller { - return NewBaseInstaller("fuzz", "fuzz", InstallInData) +// cc_afl_fuzz creates a host/device AFL++ fuzzer binary. +// AFL++ is an open source framework used to fuzz libraries +// Host binaries can be found at $ANDROID_HOST_OUT/afl_fuzz/ and device +// binaries can be found at $ANDROID_PRODUCT_OUT/data/afl_fuzz in your +// build tree +func AFLFuzzFactory() android.Module { + module := NewFuzzer(android.HostAndDeviceSupported, fuzz.AFL) + return module.Init() } type fuzzBinary struct { *binaryDecorator *baseCompiler - - fuzzPackagedModule fuzz.FuzzPackagedModule - + fuzzPackagedModule fuzz.FuzzPackagedModule installedSharedDeps []string + fuzzType fuzz.FuzzType } func (fuzz *fuzzBinary) fuzzBinary() bool { @@ -66,11 +150,17 @@ func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) { fuzz.binaryDecorator.linkerInit(ctx) } -func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { - deps.StaticLibs = append(deps.StaticLibs, - config.LibFuzzerRuntimeLibrary(ctx.toolchain())) - deps = fuzz.binaryDecorator.linkerDeps(ctx, deps) - return deps +func (fuzzBin *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { + if fuzzBin.fuzzType == fuzz.AFL { + deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers") + deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps) + return deps + + } else { + deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain())) + deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps) + return deps + } } func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { @@ -80,6 +170,7 @@ func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { // target packages. flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`) flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`) + return flags } @@ -149,63 +240,68 @@ func IsValidSharedDependency(dependency android.Module) bool { } func sharedLibraryInstallLocation( - libraryPath android.Path, isHost bool, archString string) string { + libraryPath android.Path, isHost bool, fuzzDir string, archString string) string { installLocation := "$(PRODUCT_OUT)/data" if isHost { installLocation = "$(HOST_OUT)" } installLocation = filepath.Join( - installLocation, "fuzz", archString, "lib", libraryPath.Base()) + installLocation, fuzzDir, archString, "lib", libraryPath.Base()) return installLocation } // Get the device-only shared library symbols install directory. -func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, archString string) string { - return filepath.Join("$(PRODUCT_OUT)/symbols/data/fuzz/", archString, "/lib/", libraryPath.Base()) +func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string { + return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryPath.Base()) } -func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) { - fuzz.binaryDecorator.baseInstaller.dir = filepath.Join( - "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName()) - fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join( - "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName()) - fuzz.binaryDecorator.baseInstaller.install(ctx, file) +func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) { + installBase := "fuzz" + if fuzzBin.fuzzType == fuzz.AFL { + installBase = "afl_fuzz" + } - fuzz.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Corpus) + fuzzBin.binaryDecorator.baseInstaller.dir = filepath.Join( + installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName()) + fuzzBin.binaryDecorator.baseInstaller.dir64 = filepath.Join( + 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 fuzz.fuzzPackagedModule.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") - fuzz.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir + fuzzBin.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir - fuzz.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Data) + fuzzBin.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Data) builder = android.NewRuleBuilder(pctx, ctx) intermediateDir = android.PathForModuleOut(ctx, "data") - for _, entry := range fuzz.fuzzPackagedModule.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") - fuzz.fuzzPackagedModule.DataIntermediateDir = intermediateDir + fuzzBin.fuzzPackagedModule.DataIntermediateDir = intermediateDir - if fuzz.fuzzPackagedModule.FuzzProperties.Dictionary != nil { - fuzz.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzz.fuzzPackagedModule.FuzzProperties.Dictionary) - if fuzz.fuzzPackagedModule.Dictionary.Ext() != ".dict" { + 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", - fuzz.fuzzPackagedModule.Dictionary.String()) + fuzzBin.fuzzPackagedModule.Dictionary.String()) } } - if fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil { + if fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil { configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json") - android.WriteFileRule(ctx, configPath, fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config.String()) - fuzz.fuzzPackagedModule.Config = configPath + android.WriteFileRule(ctx, configPath, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config.String()) + fuzzBin.fuzzPackagedModule.Config = configPath } // Grab the list of required shared libraries. @@ -225,31 +321,36 @@ func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) { }) for _, lib := range sharedLibraries { - fuzz.installedSharedDeps = append(fuzz.installedSharedDeps, + fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps, sharedLibraryInstallLocation( - lib, ctx.Host(), ctx.Arch().ArchType.String())) + 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, - sharedLibrarySymbolsInstallLocation(lib, ctx.Arch().ArchType.String())) + fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps, + sharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String())) } } } -func NewFuzz(hod android.HostOrDeviceSupported) *Module { +func NewFuzzer(hod android.HostOrDeviceSupported, fuzzType fuzz.FuzzType) *Module { module, binary := newBinary(hod, false) + baseInstallerPath := "fuzz" + if fuzzType == fuzz.AFL { + baseInstallerPath = "afl_fuzz" + } - binary.baseInstaller = NewFuzzInstaller() + binary.baseInstaller = NewBaseInstaller(baseInstallerPath, baseInstallerPath, InstallInData) module.sanitize.SetSanitizer(Fuzzer, true) - fuzz := &fuzzBinary{ + fuzzBin := &fuzzBinary{ binaryDecorator: binary, baseCompiler: NewBaseCompiler(), + fuzzType: fuzzType, } - module.compiler = fuzz - module.linker = fuzz - module.installer = fuzz + module.compiler = fuzzBin + module.linker = fuzzBin + module.installer = fuzzBin // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin. android.AddLoadHook(module, func(ctx android.LoadHookContext) { @@ -268,6 +369,17 @@ func NewFuzz(hod android.HostOrDeviceSupported) *Module { ctx.AppendProperties(&disableDarwinAndLinuxBionic) }) + if fuzzType == fuzz.AFL { + // Add cc_objects to Srcs + fuzzBin.baseCompiler.Properties.Srcs = append(fuzzBin.baseCompiler.Properties.Srcs, ":aflpp_driver", ":afl-compiler-rt") + module.fuzzer.Properties.AFLEnabled = true + module.compiler.appendCflags([]string{ + "-Wno-unused-result", + "-Wno-unused-parameter", + "-Wno-unused-function", + }) + } + return module } @@ -275,10 +387,30 @@ func NewFuzz(hod android.HostOrDeviceSupported) *Module { // their architecture & target/host specific zip file. type ccFuzzPackager struct { fuzz.FuzzPackager + fuzzPackagingArchModules string + fuzzTargetSharedDepsInstallPairs string + allFuzzTargetsName string } func fuzzPackagingFactory() android.Singleton { - return &ccFuzzPackager{} + + fuzzPackager := &ccFuzzPackager{ + fuzzPackagingArchModules: "SOONG_FUZZ_PACKAGING_ARCH_MODULES", + fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS", + allFuzzTargetsName: "ALL_FUZZ_TARGETS", + } + fuzzPackager.FuzzType = fuzz.Cc + return fuzzPackager +} + +func fuzzAFLPackagingFactory() android.Singleton { + fuzzPackager := &ccFuzzPackager{ + fuzzPackagingArchModules: "SOONG_AFL_FUZZ_PACKAGING_ARCH_MODULES", + fuzzTargetSharedDepsInstallPairs: "AFL_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS", + allFuzzTargetsName: "ALL_AFL_FUZZ_TARGETS", + } + fuzzPackager.FuzzType = fuzz.AFL + return fuzzPackager } func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { @@ -306,8 +438,9 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { return } + sharedLibsInstallDirPrefix := "lib" fuzzModule, ok := ccModule.compiler.(*fuzzBinary) - if !ok { + if !ok || fuzzModule.fuzzType != s.FuzzType { return } @@ -316,8 +449,18 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { hostOrTargetString = "host" } + fpm := fuzz.FuzzPackagedModule{} + if ok { + fpm = fuzzModule.fuzzPackagedModule + } + + intermediatePath := "fuzz" + if s.FuzzType == fuzz.AFL { + intermediatePath = "afl_fuzz" + } + archString := ccModule.Arch().ArchType.String() - archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString) + archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString) archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()} // Grab the list of required shared libraries. @@ -327,22 +470,21 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { builder := android.NewRuleBuilder(pctx, ctx) // Package the corpus, data, dict and config into a zipfile. - files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder) + files = s.PackageArtifacts(ctx, module, fpm, archDir, builder) // Package shared libraries - files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...) + files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...) // The executable. files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""}) - archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) + archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) if !ok { return } }) - s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx) - + s.CreateFuzzPackage(ctx, archDirs, s.FuzzType, pctx) } func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) { @@ -353,27 +495,34 @@ func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) { // ready to handle phony targets created in Soong. In the meantime, this // exports the phony 'fuzz' target and dependencies on packages to // core/main.mk so that we can use dist-for-goals. - ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " ")) - ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS", + + ctx.Strict(s.fuzzPackagingArchModules, strings.Join(packages, " ")) + + ctx.Strict(s.fuzzTargetSharedDepsInstallPairs, strings.Join(s.FuzzPackager.SharedLibInstallStrings, " ")) // Preallocate the slice of fuzz targets to minimise memory allocations. - s.PreallocateSlice(ctx, "ALL_FUZZ_TARGETS") + s.PreallocateSlice(ctx, s.allFuzzTargetsName) } // GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for // packaging. -func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip { +func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip { var files []fuzz.FileToZip + fuzzDir := "fuzz" + if s.FuzzType == fuzz.AFL { + fuzzDir = "afl_fuzz" + } + for _, library := range sharedLibraries { - files = append(files, fuzz.FileToZip{library, "lib"}) + files = append(files, fuzz.FileToZip{library, destinationPathPrefix}) // 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( - library, module.Host(), archString) + library, module.Host(), fuzzDir, archString) if (*sharedLibraryInstalled)[installDestination] { continue } @@ -391,7 +540,7 @@ func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, // 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, archString) + symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, fuzzDir, archString) symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$") s.SharedLibInstallStrings = append(s.SharedLibInstallStrings, library.String()+":"+symbolsInstallDestination) diff --git a/cc/testing.go b/cc/testing.go index 077fcda3c..6b858d593 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -534,7 +534,8 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( android.PrepareForTestWithAndroidBuildComponents, android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest), android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { - ctx.RegisterModuleType("cc_fuzz", FuzzFactory) + ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory) + ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory) ctx.RegisterModuleType("cc_test", TestFactory) ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) @@ -648,7 +649,8 @@ func TestConfig(buildDir string, os android.OsType, env map[string]string, func CreateTestContext(config android.Config) *android.TestContext { ctx := android.NewTestArchContext(config) genrule.RegisterGenruleBuildComponents(ctx) - ctx.RegisterModuleType("cc_fuzz", FuzzFactory) + ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory) + ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory) ctx.RegisterModuleType("cc_test", TestFactory) ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) ctx.RegisterModuleType("filegroup", android.FileGroupFactory) diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index 46b254f0b..1a87b30d4 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -27,12 +27,13 @@ import ( "android/soong/android" ) -type Lang string +type FuzzType string const ( - Cc Lang = "" - Rust Lang = "rust" - Java Lang = "java" + Cc FuzzType = "" + Rust FuzzType = "rust" + Java FuzzType = "java" + AFL FuzzType = "AFL" ) var BoolDefault = proptools.BoolDefault @@ -47,6 +48,7 @@ type FuzzPackager struct { Packages android.Paths FuzzTargets map[string]bool SharedLibInstallStrings []string + FuzzType FuzzType } type FileToZip struct { @@ -265,7 +267,7 @@ func (f *FuzzConfig) String() string { return string(b) } -func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, lang Lang, pctx android.PackageContext) { +func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType FuzzType, pctx android.PackageContext) { var archOsList []ArchOs for archOs := range archDirs { archOsList = append(archOsList, archOs) @@ -278,12 +280,15 @@ func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs hostOrTarget := archOs.HostOrTarget builder := android.NewRuleBuilder(pctx, ctx) zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip" - if lang == Rust { + if fuzzType == Rust { zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip" } - if lang == Java { + if fuzzType == Java { zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip" } + if fuzzType == AFL { + zipFileName = "fuzz-afl-" + hostOrTarget + "-" + arch + ".zip" + } outputFile := android.PathForOutput(ctx, zipFileName) s.Packages = append(s.Packages, outputFile) @@ -294,7 +299,6 @@ func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs Flag("-L 0") // No need to try and re-compress the zipfiles. for _, fileToZip := range filesToZip { - if fileToZip.DestinationPathPrefix != "" { command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix) } else { @@ -313,6 +317,7 @@ func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets str for target, _ := range s.FuzzTargets { fuzzTargets = append(fuzzTargets, target) } + sort.Strings(fuzzTargets) ctx.Strict(targets, strings.Join(fuzzTargets, " ")) } diff --git a/rust/fuzz.go b/rust/fuzz.go index 55921ba4b..586095c49 100644 --- a/rust/fuzz.go +++ b/rust/fuzz.go @@ -153,7 +153,7 @@ func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency) // Package shared libraries - files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...) + files = append(files, cc.GetSharedLibsToZip(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 {