Add 'make fuzz' build rule.

Adds the `make fuzz` build rule. This offers a few features on top of
`make haiku`:
 1. Identifies all fuzz targets through the build system, rather than
 having to maintain a golden file.
 2. Packages now exist in out/soong/ and are packaged on a per-architecture
 basis. Packages also now contain fuzzer seed corpus && dictionary.
 3. This gives us further extension options:
  - Packaging shared libraries for shared library fuzzing.
  - Presubmit tests for fuzzing. Each fuzz target could be made into a
  regression test by adding the crash testcase to the corpus. We can
  also ensure that example_fuzzer finds a bug with an ASan report as a
  presubmit smoke test.

Bug: 141026328
Test: m fuzz && unzip -l out/soong/fuzz-$ARCH.zip

Change-Id: I7aaad616d6b194a3beaf908241a9817df9dfdce1
This commit is contained in:
Mitch Phillips 2019-09-24 13:03:28 -07:00
parent de8b140bf6
commit d3254b4899

View file

@ -17,6 +17,7 @@ package cc
import (
"path/filepath"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@ -33,6 +34,7 @@ type FuzzProperties struct {
func init() {
android.RegisterModuleType("cc_fuzz", FuzzFactory)
android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
}
// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
@ -155,3 +157,96 @@ func NewFuzz(hod android.HostOrDeviceSupported) *Module {
return module
}
// Responsible for generating GNU Make rules that package fuzz targets into
// their architecture & target/host specific zip file.
type fuzzPackager struct {
}
func fuzzPackagingFactory() android.Singleton {
return &fuzzPackager{}
}
type fileToZip struct {
SourceFilePath android.Path
DestinationPathPrefix string
}
func (s *fuzzPackager) 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}).
archDirs := make(map[android.OutputPath][]fileToZip)
ctx.VisitAllModules(func(module android.Module) {
// Discard non-fuzz targets.
ccModule, ok := module.(*Module)
if !ok {
return
}
fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
if !ok {
return
}
// Discard vendor-NDK-linked modules, they're duplicates of fuzz targets
// we're going to package anyway.
if ccModule.useVndk() || !ccModule.Enabled() {
return
}
hostOrTargetString := "target"
if ccModule.Host() {
hostOrTargetString = "host"
}
archString := ccModule.Arch().ArchType.String()
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
// The executable.
archDirs[archDir] = append(archDirs[archDir],
fileToZip{ccModule.outputFile.Path(), ccModule.Name()})
// The corpora.
for _, corpusEntry := range fuzzModule.corpus {
archDirs[archDir] = append(archDirs[archDir],
fileToZip{corpusEntry, ccModule.Name() + "/corpus/" + corpusEntry.Base()})
}
// The dictionary.
if fuzzModule.dictionary != nil {
archDirs[archDir] = append(archDirs[archDir],
fileToZip{fuzzModule.dictionary, ccModule.Name()})
}
})
// List of architecture + host/device specific packages to build via. 'make fuzz'.
var archDirTargets android.Paths
for archDir, filesToZip := range archDirs {
arch := archDir.Base()
hostOrTarget := filepath.Base(filepath.Dir(archDir.String()))
builder := android.NewRuleBuilder()
outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
archDirTargets = append(archDirTargets, outputFile)
command := builder.Command().BuiltTool(ctx, "soong_zip").
Flag("-j").
FlagWithOutput("-o ", outputFile)
for _, fileToZip := range filesToZip {
command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix).
FlagWithInput("-f ", fileToZip.SourceFilePath)
}
builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
"Create fuzz target packages for "+arch+"-"+hostOrTarget)
}
ctx.Build(pctx, android.BuildParams{
Rule: blueprint.Phony,
Output: android.PathForPhony(ctx, "fuzz"),
Implicits: archDirTargets,
Description: "Build all Android fuzz targets, and create packages.",
})
}