blob: 848d364f11613ba9c3c467b0e747350d1f3a9110 [file] [log] [blame]
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +00001// 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 (
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +000018 "path/filepath"
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +000019 "sort"
20 "strings"
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000021
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000022 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000025 "android/soong/android"
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000026 "android/soong/cc"
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000027 "android/soong/fuzz"
28)
29
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +000030const (
31 hostString = "host"
32 targetString = "target"
33)
34
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000035type jniProperties struct {
36 // list of jni libs
37 Jni_libs []string
38
39 // sanitization
40 Sanitizers []string
41}
42
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000043func init() {
44 RegisterJavaFuzzBuildComponents(android.InitRegistrationContext)
45}
46
47func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +000048 ctx.RegisterModuleType("java_fuzz", JavaFuzzFactory)
49 ctx.RegisterModuleType("java_fuzz_host", JavaFuzzHostFactory)
50 ctx.RegisterSingletonType("java_fuzz_host_packaging", javaFuzzHostPackagingFactory)
51 ctx.RegisterSingletonType("java_fuzz_device_packaging", javaFuzzDevicePackagingFactory)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000052}
53
54type JavaFuzzLibrary struct {
55 Library
56 fuzzPackagedModule fuzz.FuzzPackagedModule
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000057 jniProperties jniProperties
58 jniFilePaths android.Paths
59}
60
Lukacs T. Berki8c77ae32022-05-12 16:30:16 +020061// IsSanitizerEnabledForJni implemented to make JavaFuzzLibrary implement
62// cc.JniSanitizeable. It returns a bool for whether a cc dependency should be
63// sanitized for the given sanitizer or not.
64func (j *JavaFuzzLibrary) IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool {
Muhammad Haseeb Ahmade6567fe2022-05-24 21:09:46 +000065 // TODO: once b/231370928 is resolved, please uncomment the loop
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +000066 // for _, s := range j.jniProperties.Sanitizers {
67 // if sanitizerName == s {
68 // return true
69 // }
70 // }
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000071 return false
72}
73
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000074func (j *JavaFuzzLibrary) DepsMutator(mctx android.BottomUpMutatorContext) {
75 if len(j.jniProperties.Jni_libs) > 0 {
76 if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
77 config := &fuzz.FuzzConfig{}
78 j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
79 }
80 // this will be used by the ingestion pipeline to determine the version
81 // of jazzer to add to the fuzzer package
82 j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000083 for _, target := range mctx.MultiTargets() {
84 sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
85 mctx.AddFarVariationDependencies(sharedLibVariations, cc.JniFuzzLibTag, j.jniProperties.Jni_libs...)
86 }
87 }
88 j.Library.DepsMutator(mctx)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000089}
90
91func (j *JavaFuzzLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000092 if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
93 j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
94 }
95 if j.fuzzPackagedModule.FuzzProperties.Data != nil {
96 j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data)
97 }
98 if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
99 j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
100 }
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000101 if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
102 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
103 android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
104 j.fuzzPackagedModule.Config = configPath
105 }
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000106
107 ctx.VisitDirectDepsWithTag(cc.JniFuzzLibTag, func(dep android.Module) {
108 sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
109 if sharedLibInfo.SharedLibrary != nil {
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000110 // The .class jars are output in slightly different locations
111 // relative to the jni libs. Therefore, for consistency across
112 // host and device fuzzers of jni lib location, we save it in a
113 // native_libs directory.
114 var relPath string
115 if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
116 relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
117 } else {
118 relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
119 }
120 libPath := android.PathForModuleOut(ctx, relPath)
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000121 ctx.Build(pctx, android.BuildParams{
122 Rule: android.Cp,
123 Input: sharedLibInfo.SharedLibrary,
124 Output: libPath,
125 })
126 j.jniFilePaths = append(j.jniFilePaths, libPath)
127 } else {
128 ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
129 }
130 })
131
132 j.Library.GenerateAndroidBuildActions(ctx)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000133}
134
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000135// java_fuzz_host builds and links sources into a `.jar` file for the host.
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000136//
137// By default, a java_fuzz produces a `.jar` file containing `.class` files.
138// This jar is not suitable for installing on a device.
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000139func JavaFuzzHostFactory() android.Module {
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000140 module := &JavaFuzzLibrary{}
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000141 module.addHostProperties()
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000142 module.AddProperties(&module.jniProperties)
143 module.Module.properties.Installable = proptools.BoolPtr(true)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000144 module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
145
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000146 // java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants.
147 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
148 disableLinuxBionic := struct {
149 Target struct {
150 Linux_bionic struct {
151 Enabled *bool
152 }
153 }
154 }{}
155 disableLinuxBionic.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
156 ctx.AppendProperties(&disableLinuxBionic)
157 })
158
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000159 InitJavaModuleMultiTargets(module, android.HostSupportedNoCross)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000160 return module
161}
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000162
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000163// java_fuzz builds and links sources into a `.jar` file for the device.
164// This generates .class files in a jar which can then be instrumented before
165// fuzzing in Android Runtime (ART: Android OS on emulator or device)
166func JavaFuzzFactory() android.Module {
167 module := &JavaFuzzLibrary{}
168 module.addHostAndDeviceProperties()
169 module.AddProperties(&module.jniProperties)
170 module.Module.properties.Installable = proptools.BoolPtr(true)
171 module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
172 module.Module.dexpreopter.isTest = true
173 module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
174 InitJavaModuleMultiTargets(module, android.DeviceSupported)
175 return module
176}
177
178// Responsible for generating rules that package host fuzz targets into
179// a zip file.
180type javaFuzzHostPackager struct {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000181 fuzz.FuzzPackager
182}
183
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000184// Responsible for generating rules that package device fuzz targets into
185// a zip file.
186type javaFuzzDevicePackager struct {
187 fuzz.FuzzPackager
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000188}
189
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000190func javaFuzzHostPackagingFactory() android.Singleton {
191 return &javaFuzzHostPackager{}
192}
193
194func javaFuzzDevicePackagingFactory() android.Singleton {
195 return &javaFuzzDevicePackager{}
196}
197
198func (s *javaFuzzHostPackager) GenerateBuildActions(ctx android.SingletonContext) {
199 generateBuildActions(&s.FuzzPackager, hostString, ctx)
200}
201
202func (s *javaFuzzDevicePackager) GenerateBuildActions(ctx android.SingletonContext) {
203 generateBuildActions(&s.FuzzPackager, targetString, ctx)
204}
205
206func generateBuildActions(s *fuzz.FuzzPackager, hostOrTargetString string, ctx android.SingletonContext) {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000207 // Map between each architecture + host/device combination.
208 archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
209
210 // List of individual fuzz targets.
211 s.FuzzTargets = make(map[string]bool)
212
213 ctx.VisitAllModules(func(module android.Module) {
214 // Discard non-fuzz targets.
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000215 javaFuzzModule, ok := module.(*JavaFuzzLibrary)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000216 if !ok {
217 return
218 }
219
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000220 if hostOrTargetString == hostString {
221 if !javaFuzzModule.Host() {
222 return
223 }
224 } else if hostOrTargetString == targetString {
225 if javaFuzzModule.Host() || javaFuzzModule.Target().HostCross {
226 return
227 }
Colin Cross39a18142022-06-24 18:43:40 -0700228 }
229
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000230 fuzzModuleValidator := fuzz.FuzzModule{
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000231 javaFuzzModule.ModuleBase,
232 javaFuzzModule.DefaultableModuleBase,
233 javaFuzzModule.ApexModuleBase,
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000234 }
235
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000236 if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000237 return
238 }
239
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000240 archString := javaFuzzModule.Arch().ArchType.String()
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000241 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
242 archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
243
244 var files []fuzz.FileToZip
245 builder := android.NewRuleBuilder(pctx, ctx)
246
247 // Package the artifacts (data, corpus, config and dictionary into a zipfile.
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000248 files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000249
250 // Add .jar
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000251 files = append(files, fuzz.FileToZip{javaFuzzModule.implementationJarFile, ""})
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000252
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000253 // Add jni .so files
254 for _, fPath := range javaFuzzModule.jniFilePaths {
255 files = append(files, fuzz.FileToZip{fPath, ""})
256 }
257
258 archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000259 if !ok {
260 return
261 }
262
263 })
264 s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
265}
266
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000267func (s *javaFuzzHostPackager) MakeVars(ctx android.MakeVarsContext) {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000268 packages := s.Packages.Strings()
269 sort.Strings(packages)
270
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000271 ctx.Strict("SOONG_JAVA_FUZZ_HOST_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000272
273 // Preallocate the slice of fuzz targets to minimize memory allocations.
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000274 s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_HOST_TARGETS")
275}
276
277func (s *javaFuzzDevicePackager) MakeVars(ctx android.MakeVarsContext) {
278 packages := s.Packages.Strings()
279 sort.Strings(packages)
280
281 ctx.Strict("SOONG_JAVA_FUZZ_DEVICE_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
282
283 // Preallocate the slice of fuzz targets to minimize memory allocations.
284 s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_DEVICE_TARGETS")
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000285}