Merge "Add jni support to java_fuzz_host" am: 4e70b7586a
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2045705 Change-Id: Ia5971f11a607df9d214469a133db41d0c7c0d83d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
5b63f52025
6 changed files with 173 additions and 20 deletions
1
cc/cc.go
1
cc/cc.go
|
@ -746,6 +746,7 @@ var (
|
|||
runtimeDepTag = installDependencyTag{name: "runtime lib"}
|
||||
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
|
||||
stubImplDepTag = dependencyTag{name: "stub_impl"}
|
||||
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
|
||||
)
|
||||
|
||||
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
|
||||
|
|
|
@ -969,6 +969,22 @@ func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
|
|||
})
|
||||
}
|
||||
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
|
||||
// If it's a Java module with native dependencies through jni,
|
||||
// set the sanitizer for them
|
||||
if jniSanitizeable, ok := mctx.Module().(JniSanitizeable); ok {
|
||||
if jniSanitizeable.IsSanitizerEnabledForJni(mctx, t.name()) {
|
||||
mctx.VisitDirectDeps(func(child android.Module) {
|
||||
if c, ok := child.(PlatformSanitizeable); ok &&
|
||||
mctx.OtherModuleDependencyTag(child) == JniFuzzLibTag &&
|
||||
c.SanitizePropDefined() &&
|
||||
!c.SanitizeNever() &&
|
||||
!c.IsSanitizerExplicitlyDisabled(t) {
|
||||
c.SetSanitizeDep(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// If an APEX module includes a lib which is enabled for a sanitizer T, then
|
||||
// the APEX module is also enabled for the same sanitizer type.
|
||||
mctx.VisitDirectDeps(func(child android.Module) {
|
||||
|
@ -1280,6 +1296,11 @@ type Sanitizeable interface {
|
|||
AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
|
||||
}
|
||||
|
||||
type JniSanitizeable interface {
|
||||
android.Module
|
||||
IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool
|
||||
}
|
||||
|
||||
func (c *Module) MinimalRuntimeDep() bool {
|
||||
return c.sanitize.Properties.MinimalRuntimeDep
|
||||
}
|
||||
|
@ -1407,7 +1428,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
|
|||
}
|
||||
c.SetSanitizeDep(false)
|
||||
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
|
||||
// APEX modules fall here
|
||||
// APEX and Java fuzz modules fall here
|
||||
sanitizeable.AddSanitizerDependencies(mctx, t.name())
|
||||
mctx.CreateVariations(t.variationName())
|
||||
} else if c, ok := mctx.Module().(*Module); ok {
|
||||
|
|
|
@ -82,6 +82,9 @@ type FuzzConfig struct {
|
|||
Hwasan_options []string `json:"hwasan_options,omitempty"`
|
||||
// Additional options to be passed to HWASAN when running on host in Haiku.
|
||||
Asan_options []string `json:"asan_options,omitempty"`
|
||||
// If there's a Java fuzzer with JNI, a different version of Jazzer would
|
||||
// need to be added to the fuzzer package than one without JNI
|
||||
IsJni *bool `json:"is_jni,omitempty"`
|
||||
}
|
||||
|
||||
type FuzzProperties struct {
|
||||
|
|
|
@ -132,6 +132,16 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
return entriesList
|
||||
}
|
||||
|
||||
func (j *JavaFuzzLibrary) AndroidMkEntries() []android.AndroidMkEntries {
|
||||
entriesList := j.Library.AndroidMkEntries()
|
||||
entries := &entriesList[0]
|
||||
entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
||||
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", "null-suite")
|
||||
androidMkWriteTestData(j.jniFilePaths, entries)
|
||||
})
|
||||
return entriesList
|
||||
}
|
||||
|
||||
// Called for modules that are a component of a test suite.
|
||||
func testSuiteComponent(entries *android.AndroidMkEntries, test_suites []string, perTestcaseDirectory bool) {
|
||||
entries.SetString("LOCAL_MODULE_TAGS", "tests")
|
||||
|
|
113
java/fuzz.go
113
java/fuzz.go
|
@ -15,14 +15,25 @@
|
|||
package java
|
||||
|
||||
import (
|
||||
"github.com/google/blueprint/proptools"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
"android/soong/fuzz"
|
||||
)
|
||||
|
||||
type jniProperties struct {
|
||||
// list of jni libs
|
||||
Jni_libs []string
|
||||
|
||||
// sanitization
|
||||
Sanitizers []string
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterJavaFuzzBuildComponents(android.InitRegistrationContext)
|
||||
}
|
||||
|
@ -35,11 +46,60 @@ func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
|
|||
type JavaFuzzLibrary struct {
|
||||
Library
|
||||
fuzzPackagedModule fuzz.FuzzPackagedModule
|
||||
jniProperties jniProperties
|
||||
jniFilePaths android.Paths
|
||||
}
|
||||
|
||||
// IsSanitizerEnabled implemented to make JavaFuzzLibrary implement
|
||||
// cc.Sanitizeable
|
||||
func (j *JavaFuzzLibrary) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool {
|
||||
for _, s := range j.jniProperties.Sanitizers {
|
||||
if sanitizerName == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsSanitizerEnabledForJni implemented to make JavaFuzzLibrary implement
|
||||
// cc.JniSanitizeable. It returns a bool for whether a cc dependency should be
|
||||
// sanitized for the given sanitizer or not.
|
||||
func (j *JavaFuzzLibrary) IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool {
|
||||
return j.IsSanitizerEnabled(ctx, sanitizerName)
|
||||
}
|
||||
|
||||
// EnableSanitizer implemented to make JavaFuzzLibrary implement
|
||||
// cc.Sanitizeable
|
||||
func (j *JavaFuzzLibrary) EnableSanitizer(sanitizerName string) {
|
||||
}
|
||||
|
||||
// AddSanitizerDependencies implemented to make JavaFuzzLibrary implement
|
||||
// cc.Sanitizeable
|
||||
func (j *JavaFuzzLibrary) AddSanitizerDependencies(mctx android.BottomUpMutatorContext, sanitizerName string) {
|
||||
}
|
||||
|
||||
// To verify that JavaFuzzLibrary implements cc.Sanitizeable
|
||||
var _ cc.Sanitizeable = (*JavaFuzzLibrary)(nil)
|
||||
|
||||
func (j *JavaFuzzLibrary) DepsMutator(mctx android.BottomUpMutatorContext) {
|
||||
if len(j.jniProperties.Jni_libs) > 0 {
|
||||
if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
|
||||
config := &fuzz.FuzzConfig{}
|
||||
j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
|
||||
}
|
||||
// this will be used by the ingestion pipeline to determine the version
|
||||
// of jazzer to add to the fuzzer package
|
||||
j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
|
||||
|
||||
for _, target := range mctx.MultiTargets() {
|
||||
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
|
||||
mctx.AddFarVariationDependencies(sharedLibVariations, cc.JniFuzzLibTag, j.jniProperties.Jni_libs...)
|
||||
}
|
||||
}
|
||||
j.Library.DepsMutator(mctx)
|
||||
}
|
||||
|
||||
func (j *JavaFuzzLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
j.Library.GenerateAndroidBuildActions(ctx)
|
||||
|
||||
if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
|
||||
j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
|
||||
}
|
||||
|
@ -55,6 +115,23 @@ func (j *JavaFuzzLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
|
|||
android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
|
||||
j.fuzzPackagedModule.Config = configPath
|
||||
}
|
||||
|
||||
ctx.VisitDirectDepsWithTag(cc.JniFuzzLibTag, func(dep android.Module) {
|
||||
sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
|
||||
if sharedLibInfo.SharedLibrary != nil {
|
||||
libPath := android.PathForModuleOut(ctx, sharedLibInfo.SharedLibrary.Base())
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.Cp,
|
||||
Input: sharedLibInfo.SharedLibrary,
|
||||
Output: libPath,
|
||||
})
|
||||
j.jniFilePaths = append(j.jniFilePaths, libPath)
|
||||
} else {
|
||||
ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
|
||||
}
|
||||
})
|
||||
|
||||
j.Library.GenerateAndroidBuildActions(ctx)
|
||||
}
|
||||
|
||||
// java_fuzz builds and links sources into a `.jar` file for the host.
|
||||
|
@ -65,7 +142,8 @@ func FuzzFactory() android.Module {
|
|||
module := &JavaFuzzLibrary{}
|
||||
|
||||
module.addHostProperties()
|
||||
module.Module.properties.Installable = proptools.BoolPtr(false)
|
||||
module.AddProperties(&module.jniProperties)
|
||||
module.Module.properties.Installable = proptools.BoolPtr(true)
|
||||
module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
|
||||
|
||||
// java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants.
|
||||
|
@ -83,7 +161,7 @@ func FuzzFactory() android.Module {
|
|||
|
||||
module.initModuleAndImport(module)
|
||||
android.InitSdkAwareModule(module)
|
||||
InitJavaModule(module, android.HostSupported)
|
||||
InitJavaModuleMultiTargets(module, android.HostSupported)
|
||||
return module
|
||||
}
|
||||
|
||||
|
@ -106,26 +184,26 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
|
||||
ctx.VisitAllModules(func(module android.Module) {
|
||||
// Discard non-fuzz targets.
|
||||
javaModule, ok := module.(*JavaFuzzLibrary)
|
||||
javaFuzzModule, ok := module.(*JavaFuzzLibrary)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
fuzzModuleValidator := fuzz.FuzzModule{
|
||||
javaModule.ModuleBase,
|
||||
javaModule.DefaultableModuleBase,
|
||||
javaModule.ApexModuleBase,
|
||||
javaFuzzModule.ModuleBase,
|
||||
javaFuzzModule.DefaultableModuleBase,
|
||||
javaFuzzModule.ApexModuleBase,
|
||||
}
|
||||
|
||||
if ok := fuzz.IsValid(fuzzModuleValidator); !ok || *javaModule.Module.properties.Installable {
|
||||
if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
hostOrTargetString := "target"
|
||||
if javaModule.Host() {
|
||||
if javaFuzzModule.Host() {
|
||||
hostOrTargetString = "host"
|
||||
}
|
||||
archString := javaModule.Arch().ArchType.String()
|
||||
archString := javaFuzzModule.Arch().ArchType.String()
|
||||
|
||||
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
|
||||
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
|
||||
|
@ -134,12 +212,17 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
builder := android.NewRuleBuilder(pctx, ctx)
|
||||
|
||||
// Package the artifacts (data, corpus, config and dictionary into a zipfile.
|
||||
files = s.PackageArtifacts(ctx, module, javaModule.fuzzPackagedModule, archDir, builder)
|
||||
files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
|
||||
|
||||
// Add .jar
|
||||
files = append(files, fuzz.FileToZip{javaModule.outputFile, ""})
|
||||
files = append(files, fuzz.FileToZip{javaFuzzModule.outputFile, ""})
|
||||
|
||||
archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaModule.fuzzPackagedModule, files, builder, archDir, archString, "host", archOs, archDirs)
|
||||
// Add jni .so files
|
||||
for _, fPath := range javaFuzzModule.jniFilePaths {
|
||||
files = append(files, fuzz.FileToZip{fPath, ""})
|
||||
}
|
||||
|
||||
archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -15,13 +15,17 @@
|
|||
package java
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
)
|
||||
|
||||
var prepForJavaFuzzTest = android.GroupFixturePreparers(
|
||||
PrepareForTestWithJavaDefaultModules,
|
||||
cc.PrepareForTestWithCcBuildComponents,
|
||||
android.FixtureRegisterWithContext(RegisterJavaFuzzBuildComponents),
|
||||
)
|
||||
|
||||
|
@ -32,6 +36,13 @@ func TestJavaFuzz(t *testing.T) {
|
|||
srcs: ["a.java"],
|
||||
libs: ["bar"],
|
||||
static_libs: ["baz"],
|
||||
jni_libs: [
|
||||
"libjni",
|
||||
],
|
||||
sanitizers: [
|
||||
"address",
|
||||
"fuzzer",
|
||||
],
|
||||
}
|
||||
|
||||
java_library_host {
|
||||
|
@ -42,11 +53,21 @@ func TestJavaFuzz(t *testing.T) {
|
|||
java_library_host {
|
||||
name: "baz",
|
||||
srcs: ["c.java"],
|
||||
}`)
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libjni",
|
||||
host_supported: true,
|
||||
device_supported: false,
|
||||
stl: "none",
|
||||
}
|
||||
`)
|
||||
|
||||
osCommonTarget := result.Config.BuildOSCommonTarget.String()
|
||||
javac := result.ModuleForTests("foo", osCommonTarget).Rule("javac")
|
||||
combineJar := result.ModuleForTests("foo", osCommonTarget).Description("for javac")
|
||||
|
||||
osCommonTargetWithSan := osCommonTarget + "_asan" + "_fuzzer"
|
||||
javac := result.ModuleForTests("foo", osCommonTargetWithSan).Rule("javac")
|
||||
combineJar := result.ModuleForTests("foo", osCommonTargetWithSan).Description("for javac")
|
||||
|
||||
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
|
||||
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
|
||||
|
@ -62,4 +83,18 @@ func TestJavaFuzz(t *testing.T) {
|
|||
if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
|
||||
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
|
||||
}
|
||||
|
||||
ctx := result.TestContext
|
||||
foo := ctx.ModuleForTests("foo", osCommonTargetWithSan).Module().(*JavaFuzzLibrary)
|
||||
|
||||
expected := "libjni.so"
|
||||
if runtime.GOOS == "darwin" {
|
||||
expected = "libjni.dylib"
|
||||
}
|
||||
|
||||
fooJniFilePaths := foo.jniFilePaths
|
||||
if len(fooJniFilePaths) != 1 || fooJniFilePaths[0].Rel() != expected {
|
||||
t.Errorf(`expected foo test data relative path [%q], got %q`,
|
||||
expected, fooJniFilePaths.Strings())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue