blob: 1d6b91346099ed19508dc9f73002b75389c72f32 [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
Muhammad Haseeb Ahmad431ddf92022-10-20 00:55:58 +0000107 _, sharedDeps := cc.CollectAllSharedDependencies(ctx)
108
109 for _, dep := range sharedDeps {
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000110 sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
111 if sharedLibInfo.SharedLibrary != nil {
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000112 // The .class jars are output in slightly different locations
113 // relative to the jni libs. Therefore, for consistency across
114 // host and device fuzzers of jni lib location, we save it in a
115 // native_libs directory.
116 var relPath string
117 if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
118 relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
119 } else {
120 relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
121 }
122 libPath := android.PathForModuleOut(ctx, relPath)
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000123 ctx.Build(pctx, android.BuildParams{
124 Rule: android.Cp,
125 Input: sharedLibInfo.SharedLibrary,
126 Output: libPath,
127 })
128 j.jniFilePaths = append(j.jniFilePaths, libPath)
129 } else {
130 ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
131 }
Muhammad Haseeb Ahmad431ddf92022-10-20 00:55:58 +0000132 }
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000133
134 j.Library.GenerateAndroidBuildActions(ctx)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000135}
136
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000137// java_fuzz_host builds and links sources into a `.jar` file for the host.
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000138//
139// By default, a java_fuzz produces a `.jar` file containing `.class` files.
140// This jar is not suitable for installing on a device.
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000141func JavaFuzzHostFactory() android.Module {
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000142 module := &JavaFuzzLibrary{}
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000143 module.addHostProperties()
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000144 module.AddProperties(&module.jniProperties)
145 module.Module.properties.Installable = proptools.BoolPtr(true)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000146 module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
147
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000148 // java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants.
149 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
150 disableLinuxBionic := struct {
151 Target struct {
152 Linux_bionic struct {
153 Enabled *bool
154 }
155 }
156 }{}
157 disableLinuxBionic.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
158 ctx.AppendProperties(&disableLinuxBionic)
159 })
160
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000161 InitJavaModuleMultiTargets(module, android.HostSupportedNoCross)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000162 return module
163}
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000164
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000165// java_fuzz builds and links sources into a `.jar` file for the device.
166// This generates .class files in a jar which can then be instrumented before
167// fuzzing in Android Runtime (ART: Android OS on emulator or device)
168func JavaFuzzFactory() android.Module {
169 module := &JavaFuzzLibrary{}
170 module.addHostAndDeviceProperties()
171 module.AddProperties(&module.jniProperties)
172 module.Module.properties.Installable = proptools.BoolPtr(true)
173 module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
174 module.Module.dexpreopter.isTest = true
175 module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
176 InitJavaModuleMultiTargets(module, android.DeviceSupported)
177 return module
178}
179
180// Responsible for generating rules that package host fuzz targets into
181// a zip file.
182type javaFuzzHostPackager struct {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000183 fuzz.FuzzPackager
184}
185
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000186// Responsible for generating rules that package device fuzz targets into
187// a zip file.
188type javaFuzzDevicePackager struct {
189 fuzz.FuzzPackager
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000190}
191
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000192func javaFuzzHostPackagingFactory() android.Singleton {
193 return &javaFuzzHostPackager{}
194}
195
196func javaFuzzDevicePackagingFactory() android.Singleton {
197 return &javaFuzzDevicePackager{}
198}
199
200func (s *javaFuzzHostPackager) GenerateBuildActions(ctx android.SingletonContext) {
201 generateBuildActions(&s.FuzzPackager, hostString, ctx)
202}
203
204func (s *javaFuzzDevicePackager) GenerateBuildActions(ctx android.SingletonContext) {
205 generateBuildActions(&s.FuzzPackager, targetString, ctx)
206}
207
208func generateBuildActions(s *fuzz.FuzzPackager, hostOrTargetString string, ctx android.SingletonContext) {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000209 // Map between each architecture + host/device combination.
210 archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
211
212 // List of individual fuzz targets.
213 s.FuzzTargets = make(map[string]bool)
214
215 ctx.VisitAllModules(func(module android.Module) {
216 // Discard non-fuzz targets.
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000217 javaFuzzModule, ok := module.(*JavaFuzzLibrary)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000218 if !ok {
219 return
220 }
221
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000222 if hostOrTargetString == hostString {
223 if !javaFuzzModule.Host() {
224 return
225 }
226 } else if hostOrTargetString == targetString {
227 if javaFuzzModule.Host() || javaFuzzModule.Target().HostCross {
228 return
229 }
Colin Cross39a18142022-06-24 18:43:40 -0700230 }
231
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000232 fuzzModuleValidator := fuzz.FuzzModule{
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000233 javaFuzzModule.ModuleBase,
234 javaFuzzModule.DefaultableModuleBase,
235 javaFuzzModule.ApexModuleBase,
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000236 }
237
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000238 if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000239 return
240 }
241
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000242 archString := javaFuzzModule.Arch().ArchType.String()
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000243 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
244 archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
245
246 var files []fuzz.FileToZip
247 builder := android.NewRuleBuilder(pctx, ctx)
248
249 // Package the artifacts (data, corpus, config and dictionary into a zipfile.
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000250 files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000251
252 // Add .jar
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000253 files = append(files, fuzz.FileToZip{javaFuzzModule.implementationJarFile, ""})
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000254
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000255 // Add jni .so files
256 for _, fPath := range javaFuzzModule.jniFilePaths {
257 files = append(files, fuzz.FileToZip{fPath, ""})
258 }
259
260 archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000261 if !ok {
262 return
263 }
264
265 })
266 s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
267}
268
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000269func (s *javaFuzzHostPackager) MakeVars(ctx android.MakeVarsContext) {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000270 packages := s.Packages.Strings()
271 sort.Strings(packages)
272
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000273 ctx.Strict("SOONG_JAVA_FUZZ_HOST_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000274
275 // Preallocate the slice of fuzz targets to minimize memory allocations.
Muhammad Haseeb Ahmadeb14ff22022-09-28 17:53:11 +0000276 s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_HOST_TARGETS")
277}
278
279func (s *javaFuzzDevicePackager) MakeVars(ctx android.MakeVarsContext) {
280 packages := s.Packages.Strings()
281 sort.Strings(packages)
282
283 ctx.Strict("SOONG_JAVA_FUZZ_DEVICE_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
284
285 // Preallocate the slice of fuzz targets to minimize memory allocations.
286 s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_DEVICE_TARGETS")
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000287}