1// Copyright 2021 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "github.com/google/blueprint/proptools" 19 "sort" 20 "strings" 21 22 "android/soong/android" 23 "android/soong/fuzz" 24) 25 26func init() { 27 RegisterJavaFuzzBuildComponents(android.InitRegistrationContext) 28} 29 30func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) { 31 ctx.RegisterModuleType("java_fuzz_host", FuzzFactory) 32 ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory) 33} 34 35type JavaFuzzLibrary struct { 36 Library 37 fuzzPackagedModule fuzz.FuzzPackagedModule 38} 39 40func (j *JavaFuzzLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 41 j.Library.GenerateAndroidBuildActions(ctx) 42 43 if j.fuzzPackagedModule.FuzzProperties.Corpus != nil { 44 j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus) 45 } 46 if j.fuzzPackagedModule.FuzzProperties.Data != nil { 47 j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data) 48 } 49 if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil { 50 j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary) 51 } 52 53 if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil { 54 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json") 55 android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String()) 56 j.fuzzPackagedModule.Config = configPath 57 } 58} 59 60// java_fuzz builds and links sources into a `.jar` file for the host. 61// 62// By default, a java_fuzz produces a `.jar` file containing `.class` files. 63// This jar is not suitable for installing on a device. 64func FuzzFactory() android.Module { 65 module := &JavaFuzzLibrary{} 66 67 module.addHostProperties() 68 module.Module.properties.Installable = proptools.BoolPtr(false) 69 module.AddProperties(&module.fuzzPackagedModule.FuzzProperties) 70 71 // java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants. 72 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 73 disableLinuxBionic := struct { 74 Target struct { 75 Linux_bionic struct { 76 Enabled *bool 77 } 78 } 79 }{} 80 disableLinuxBionic.Target.Linux_bionic.Enabled = proptools.BoolPtr(false) 81 ctx.AppendProperties(&disableLinuxBionic) 82 }) 83 84 module.initModuleAndImport(module) 85 android.InitSdkAwareModule(module) 86 InitJavaModule(module, android.HostSupported) 87 return module 88} 89 90// Responsible for generating rules that package fuzz targets into 91// their architecture & target/host specific zip file. 92type javaFuzzPackager struct { 93 fuzz.FuzzPackager 94} 95 96func javaFuzzPackagingFactory() android.Singleton { 97 return &javaFuzzPackager{} 98} 99 100func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { 101 // Map between each architecture + host/device combination. 102 archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip) 103 104 // List of individual fuzz targets. 105 s.FuzzTargets = make(map[string]bool) 106 107 ctx.VisitAllModules(func(module android.Module) { 108 // Discard non-fuzz targets. 109 javaModule, ok := module.(*JavaFuzzLibrary) 110 if !ok { 111 return 112 } 113 114 fuzzModuleValidator := fuzz.FuzzModule{ 115 javaModule.ModuleBase, 116 javaModule.DefaultableModuleBase, 117 javaModule.ApexModuleBase, 118 } 119 120 if ok := fuzz.IsValid(fuzzModuleValidator); !ok || *javaModule.Module.properties.Installable { 121 return 122 } 123 124 hostOrTargetString := "target" 125 if javaModule.Host() { 126 hostOrTargetString = "host" 127 } 128 archString := javaModule.Arch().ArchType.String() 129 130 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString) 131 archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()} 132 133 var files []fuzz.FileToZip 134 builder := android.NewRuleBuilder(pctx, ctx) 135 136 // Package the artifacts (data, corpus, config and dictionary into a zipfile. 137 files = s.PackageArtifacts(ctx, module, javaModule.fuzzPackagedModule, archDir, builder) 138 139 // Add .jar 140 files = append(files, fuzz.FileToZip{javaModule.outputFile, ""}) 141 142 archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaModule.fuzzPackagedModule, files, builder, archDir, archString, "host", archOs, archDirs) 143 if !ok { 144 return 145 } 146 147 }) 148 s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx) 149} 150 151func (s *javaFuzzPackager) MakeVars(ctx android.MakeVarsContext) { 152 packages := s.Packages.Strings() 153 sort.Strings(packages) 154 155 ctx.Strict("SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " ")) 156 157 // Preallocate the slice of fuzz targets to minimize memory allocations. 158 s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_TARGETS") 159} 160