• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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