blob: cf2c981d5b023ce02d58790ae8513129cbb20899 [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 Ahmade3803102022-01-10 21:37:07 +000018 "sort"
19 "strings"
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000020
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000021 "github.com/google/blueprint"
22 "github.com/google/blueprint/proptools"
23
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000024 "android/soong/android"
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000025 "android/soong/cc"
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000026 "android/soong/fuzz"
27)
28
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000029type jniProperties struct {
30 // list of jni libs
31 Jni_libs []string
32
33 // sanitization
34 Sanitizers []string
35}
36
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000037func init() {
38 RegisterJavaFuzzBuildComponents(android.InitRegistrationContext)
39}
40
41func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
42 ctx.RegisterModuleType("java_fuzz_host", FuzzFactory)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +000043 ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000044}
45
46type JavaFuzzLibrary struct {
47 Library
48 fuzzPackagedModule fuzz.FuzzPackagedModule
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000049 jniProperties jniProperties
50 jniFilePaths android.Paths
51}
52
Lukacs T. Berki8c77ae32022-05-12 16:30:16 +020053// IsSanitizerEnabledForJni implemented to make JavaFuzzLibrary implement
54// cc.JniSanitizeable. It returns a bool for whether a cc dependency should be
55// sanitized for the given sanitizer or not.
56func (j *JavaFuzzLibrary) IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool {
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000057 for _, s := range j.jniProperties.Sanitizers {
58 if sanitizerName == s {
59 return true
60 }
61 }
62 return false
63}
64
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000065func (j *JavaFuzzLibrary) DepsMutator(mctx android.BottomUpMutatorContext) {
66 if len(j.jniProperties.Jni_libs) > 0 {
67 if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
68 config := &fuzz.FuzzConfig{}
69 j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
70 }
71 // this will be used by the ingestion pipeline to determine the version
72 // of jazzer to add to the fuzzer package
73 j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
74
75 for _, target := range mctx.MultiTargets() {
76 sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
77 mctx.AddFarVariationDependencies(sharedLibVariations, cc.JniFuzzLibTag, j.jniProperties.Jni_libs...)
78 }
79 }
80 j.Library.DepsMutator(mctx)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000081}
82
83func (j *JavaFuzzLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +000084 if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
85 j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
86 }
87 if j.fuzzPackagedModule.FuzzProperties.Data != nil {
88 j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data)
89 }
90 if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
91 j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
92 }
93
94 if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
95 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
96 android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
97 j.fuzzPackagedModule.Config = configPath
98 }
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +000099
100 ctx.VisitDirectDepsWithTag(cc.JniFuzzLibTag, func(dep android.Module) {
101 sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
102 if sharedLibInfo.SharedLibrary != nil {
103 libPath := android.PathForModuleOut(ctx, sharedLibInfo.SharedLibrary.Base())
104 ctx.Build(pctx, android.BuildParams{
105 Rule: android.Cp,
106 Input: sharedLibInfo.SharedLibrary,
107 Output: libPath,
108 })
109 j.jniFilePaths = append(j.jniFilePaths, libPath)
110 } else {
111 ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
112 }
113 })
114
115 j.Library.GenerateAndroidBuildActions(ctx)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000116}
117
118// java_fuzz builds and links sources into a `.jar` file for the host.
119//
120// By default, a java_fuzz produces a `.jar` file containing `.class` files.
121// This jar is not suitable for installing on a device.
122func FuzzFactory() android.Module {
123 module := &JavaFuzzLibrary{}
124
125 module.addHostProperties()
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000126 module.AddProperties(&module.jniProperties)
127 module.Module.properties.Installable = proptools.BoolPtr(true)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000128 module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
129
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000130 // java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants.
131 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
132 disableLinuxBionic := struct {
133 Target struct {
134 Linux_bionic struct {
135 Enabled *bool
136 }
137 }
138 }{}
139 disableLinuxBionic.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
140 ctx.AppendProperties(&disableLinuxBionic)
141 })
142
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000143 module.initModuleAndImport(module)
144 android.InitSdkAwareModule(module)
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000145 InitJavaModuleMultiTargets(module, android.HostSupported)
Muhammad Haseeb Ahmadaa1d0cf2022-01-01 05:14:32 +0000146 return module
147}
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000148
149// Responsible for generating rules that package fuzz targets into
150// their architecture & target/host specific zip file.
151type javaFuzzPackager struct {
152 fuzz.FuzzPackager
153}
154
155func javaFuzzPackagingFactory() android.Singleton {
156 return &javaFuzzPackager{}
157}
158
159func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
160 // Map between each architecture + host/device combination.
161 archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
162
163 // List of individual fuzz targets.
164 s.FuzzTargets = make(map[string]bool)
165
166 ctx.VisitAllModules(func(module android.Module) {
167 // Discard non-fuzz targets.
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000168 javaFuzzModule, ok := module.(*JavaFuzzLibrary)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000169 if !ok {
170 return
171 }
172
173 fuzzModuleValidator := fuzz.FuzzModule{
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000174 javaFuzzModule.ModuleBase,
175 javaFuzzModule.DefaultableModuleBase,
176 javaFuzzModule.ApexModuleBase,
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000177 }
178
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000179 if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000180 return
181 }
182
183 hostOrTargetString := "target"
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000184 if javaFuzzModule.Host() {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000185 hostOrTargetString = "host"
186 }
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000187 archString := javaFuzzModule.Arch().ArchType.String()
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000188
189 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
190 archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
191
192 var files []fuzz.FileToZip
193 builder := android.NewRuleBuilder(pctx, ctx)
194
195 // Package the artifacts (data, corpus, config and dictionary into a zipfile.
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000196 files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000197
198 // Add .jar
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000199 files = append(files, fuzz.FileToZip{javaFuzzModule.outputFile, ""})
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000200
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000201 // Add jni .so files
202 for _, fPath := range javaFuzzModule.jniFilePaths {
203 files = append(files, fuzz.FileToZip{fPath, ""})
204 }
205
206 archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000207 if !ok {
208 return
209 }
210
211 })
212 s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
213}
214
215func (s *javaFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
216 packages := s.Packages.Strings()
217 sort.Strings(packages)
218
219 ctx.Strict("SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
220
221 // Preallocate the slice of fuzz targets to minimize memory allocations.
222 s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_TARGETS")
223}