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:
Muhammad Haseeb Ahmad 2022-04-27 17:29:03 +00:00 committed by Automerger Merge Worker
commit 5b63f52025
6 changed files with 173 additions and 20 deletions

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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")

View file

@ -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
}

View file

@ -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())
}
}