diff --git a/cc/cc.go b/cc/cc.go index 1c845f622..486295b7d 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -3330,6 +3330,11 @@ func (c *Module) OutputFiles(tag string) (android.Paths, error) { return android.Paths{c.outputFile.Path()}, nil } return android.Paths{}, nil + case "unstripped": + if c.linker != nil { + return android.PathsIfNonNil(c.linker.unstrippedOutputFilePath()), nil + } + return nil, nil default: return nil, fmt.Errorf("unsupported module reference tag %q", tag) } diff --git a/cc/fuzz.go b/cc/fuzz.go index 8a8c10723..13c94adb3 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -103,6 +103,7 @@ type fuzzBinary struct { *baseCompiler fuzzPackagedModule fuzz.FuzzPackagedModule installedSharedDeps []string + sharedLibraries android.Paths } func (fuzz *fuzzBinary) fuzzBinary() bool { @@ -142,13 +143,6 @@ func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { return flags } -func UnstrippedOutputFile(module android.Module) android.Path { - if mod, ok := module.(LinkableInterface); ok { - return mod.UnstrippedOutputFile() - } - panic("UnstrippedOutputFile called on non-LinkableInterface module: " + module.Name()) -} - // IsValidSharedDependency takes a module and determines if it is a unique shared library // that should be installed in the fuzz target output directories. This function // returns true, unless: @@ -270,22 +264,9 @@ func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) { } // Grab the list of required shared libraries. - seen := make(map[string]bool) - var sharedLibraries android.Paths - ctx.WalkDeps(func(child, parent android.Module) bool { - if seen[child.Name()] { - return false - } - seen[child.Name()] = true + fuzzBin.sharedLibraries = CollectAllSharedDependencies(ctx) - if IsValidSharedDependency(child) { - sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile()) - return true - } - return false - }) - - for _, lib := range sharedLibraries { + for _, lib := range fuzzBin.sharedLibraries { fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps, sharedLibraryInstallLocation( lib, ctx.Host(), installBase, ctx.Arch().ArchType.String())) @@ -412,9 +393,6 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString) archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()} - // Grab the list of required shared libraries. - sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, UnstrippedOutputFile, IsValidSharedDependency) - var files []fuzz.FileToZip builder := android.NewRuleBuilder(pctx, ctx) @@ -422,10 +400,10 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { files = s.PackageArtifacts(ctx, module, fpm, archDir, builder) // Package shared libraries - files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...) + files = append(files, GetSharedLibsToZip(fuzzModule.sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...) // The executable. - files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""}) + files = append(files, fuzz.FileToZip{android.OutputFileForModule(ctx, ccModule, "unstripped"), ""}) archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) if !ok { @@ -494,3 +472,46 @@ func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, } return files } + +// CollectAllSharedDependencies search over the provided module's dependencies using +// VisitDirectDeps and WalkDeps to enumerate all shared library dependencies. +// VisitDirectDeps is used first to avoid incorrectly using the core libraries (sanitizer +// runtimes, libc, libdl, etc.) from a dependency. This may cause issues when dependencies +// have explicit sanitizer tags, as we may get a dependency on an unsanitized libc, etc. +func CollectAllSharedDependencies(ctx android.ModuleContext) android.Paths { + seen := make(map[string]bool) + recursed := make(map[string]bool) + + var sharedLibraries android.Paths + + // Enumerate the first level of dependencies, as we discard all non-library + // modules in the BFS loop below. + ctx.VisitDirectDeps(func(dep android.Module) { + if !IsValidSharedDependency(dep) { + return + } + if seen[ctx.OtherModuleName(dep)] { + return + } + seen[ctx.OtherModuleName(dep)] = true + sharedLibraries = append(sharedLibraries, android.OutputFileForModule(ctx, dep, "unstripped")) + }) + + ctx.WalkDeps(func(child, parent android.Module) bool { + if !IsValidSharedDependency(child) { + return false + } + if !seen[ctx.OtherModuleName(child)] { + seen[ctx.OtherModuleName(child)] = true + sharedLibraries = append(sharedLibraries, android.OutputFileForModule(ctx, child, "unstripped")) + } + + if recursed[ctx.OtherModuleName(child)] { + return false + } + recursed[ctx.OtherModuleName(child)] = true + return true + }) + + return sharedLibraries +} diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index c8cd21b7e..eb248bb40 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -379,42 +379,3 @@ func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets str sort.Strings(fuzzTargets) ctx.Strict(targets, strings.Join(fuzzTargets, " ")) } - -// CollectAllSharedDependencies performs a breadth-first search over the provided module's -// dependencies using `visitDirectDeps` to enumerate all shared library -// dependencies. We require breadth-first expansion, as otherwise we may -// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.) -// from a dependency. This may cause issues when dependencies have explicit -// sanitizer tags, as we may get a dependency on an unsanitized libc, etc. -func CollectAllSharedDependencies(ctx android.SingletonContext, module android.Module, unstrippedOutputFile func(module android.Module) android.Path, isValidSharedDependency func(dependency android.Module) bool) android.Paths { - var fringe []android.Module - - seen := make(map[string]bool) - - // Enumerate the first level of dependencies, as we discard all non-library - // modules in the BFS loop below. - ctx.VisitDirectDeps(module, func(dep android.Module) { - if isValidSharedDependency(dep) { - fringe = append(fringe, dep) - } - }) - - var sharedLibraries android.Paths - - for i := 0; i < len(fringe); i++ { - module := fringe[i] - if seen[module.Name()] { - continue - } - seen[module.Name()] = true - - sharedLibraries = append(sharedLibraries, unstrippedOutputFile(module)) - ctx.VisitDirectDeps(module, func(dep android.Module) { - if isValidSharedDependency(dep) && !seen[dep.Name()] { - fringe = append(fringe, dep) - } - }) - } - - return sharedLibraries -} diff --git a/rust/fuzz.go b/rust/fuzz.go index 586095c49..76cf21aa0 100644 --- a/rust/fuzz.go +++ b/rust/fuzz.go @@ -34,6 +34,7 @@ type fuzzDecorator struct { *binaryDecorator fuzzPackagedModule fuzz.FuzzPackagedModule + sharedLibraries android.Paths } var _ compiler = (*fuzzDecorator)(nil) @@ -86,6 +87,15 @@ func (fuzzer *fuzzDecorator) compilerProps() []interface{} { &fuzzer.fuzzPackagedModule.FuzzProperties) } +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) + + return out +} + func (fuzzer *fuzzDecorator) stdLinkage(ctx *depsContext) RustLinkage { return RlibLinkage } @@ -149,11 +159,8 @@ func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { // The executable. files = append(files, fuzz.FileToZip{rustModule.UnstrippedOutputFile(), ""}) - // Grab the list of required shared libraries. - sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency) - // Package shared libraries - files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, "lib", &sharedLibraryInstalled)...) + 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 {