blob: ebe42524ab357066e8feb819ef2127c3b429fb2a [file] [log] [blame]
Mitch Phillipsda9a4632019-07-15 09:34:09 -07001// Copyright 2016 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 cc
16
17import (
Kris Alderf979ee32019-10-22 10:52:01 -070018 "encoding/json"
Mitch Phillips4de896e2019-08-28 16:04:36 -070019 "path/filepath"
Mitch Phillipse1ee1a12019-10-17 19:20:41 -070020 "sort"
Mitch Phillipsa0a5e192019-09-27 14:00:06 -070021 "strings"
Mitch Phillips4de896e2019-08-28 16:04:36 -070022
Mitch Phillipsda9a4632019-07-15 09:34:09 -070023 "android/soong/android"
24 "android/soong/cc/config"
25)
26
Kris Alderf979ee32019-10-22 10:52:01 -070027type FuzzConfig struct {
28 // Email address of people to CC on bugs or contact about this fuzz target.
29 Cc []string `json:"cc,omitempty"`
hamzeh3478a0d2019-12-16 16:25:50 -080030 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
31 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
32 // Specify whether to enable continuous fuzzing on host. Defaults to true.
33 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
Kris Alderf979ee32019-10-22 10:52:01 -070034 // Component in Google's bug tracking system that bugs should be filed to.
35 Componentid *int64 `json:"componentid,omitempty"`
36 // Hotlists in Google's bug tracking system that bugs should be marked with.
37 Hotlists []string `json:"hotlists,omitempty"`
38}
39
40func (f *FuzzConfig) String() string {
41 b, err := json.Marshal(f)
42 if err != nil {
43 panic(err)
44 }
45
46 return string(b)
47}
48
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070049type FuzzProperties struct {
50 // Optional list of seed files to be installed to the fuzz target's output
51 // directory.
52 Corpus []string `android:"path"`
Tri Voad172d82019-11-27 13:45:45 -080053 // Optional list of data files to be installed to the fuzz target's output
54 // directory. Directory structure relative to the module is preserved.
55 Data []string `android:"path"`
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070056 // Optional dictionary to be installed to the fuzz target's output directory.
57 Dictionary *string `android:"path"`
Kris Alderf979ee32019-10-22 10:52:01 -070058 // Config for running the target on fuzzing infrastructure.
59 Fuzz_config *FuzzConfig
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070060}
61
Mitch Phillipsda9a4632019-07-15 09:34:09 -070062func init() {
63 android.RegisterModuleType("cc_fuzz", FuzzFactory)
Mitch Phillipsd3254b42019-09-24 13:03:28 -070064 android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070065}
66
67// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
68// $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
69// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
70func FuzzFactory() android.Module {
71 module := NewFuzz(android.HostAndDeviceSupported)
72 return module.Init()
73}
74
75func NewFuzzInstaller() *baseInstaller {
76 return NewBaseInstaller("fuzz", "fuzz", InstallInData)
77}
78
79type fuzzBinary struct {
80 *binaryDecorator
81 *baseCompiler
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070082
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -070083 Properties FuzzProperties
84 dictionary android.Path
85 corpus android.Paths
86 corpusIntermediateDir android.Path
Kris Alderf979ee32019-10-22 10:52:01 -070087 config android.Path
Tri Voad172d82019-11-27 13:45:45 -080088 data android.Paths
89 dataIntermediateDir android.Path
Mitch Phillipse1ee1a12019-10-17 19:20:41 -070090 installedSharedDeps []string
Mitch Phillipsda9a4632019-07-15 09:34:09 -070091}
92
93func (fuzz *fuzzBinary) linkerProps() []interface{} {
94 props := fuzz.binaryDecorator.linkerProps()
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070095 props = append(props, &fuzz.Properties)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070096 return props
97}
98
99func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) {
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700100 fuzz.binaryDecorator.linkerInit(ctx)
101}
102
103func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
104 deps.StaticLibs = append(deps.StaticLibs,
105 config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
106 deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
107 return deps
108}
109
110func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
111 flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800112 // RunPaths on devices isn't instantiated by the base linker. `../lib` for
113 // installed fuzz targets (both host and device), and `./lib` for fuzz
114 // target packages.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700115 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800116 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700117 return flags
118}
119
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700120// This function performs a breadth-first search over the provided module's
121// dependencies using `visitDirectDeps` to enumerate all shared library
122// dependencies. We require breadth-first expansion, as otherwise we may
123// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
124// from a dependency. This may cause issues when dependencies have explicit
125// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
Colin Crossdc809f92019-11-20 15:58:32 -0800126func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700127 var fringe []android.Module
128
Colin Crossdc809f92019-11-20 15:58:32 -0800129 seen := make(map[android.Module]bool)
130
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700131 // Enumerate the first level of dependencies, as we discard all non-library
132 // modules in the BFS loop below.
133 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800134 if isValidSharedDependency(dep) {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800135 fringe = append(fringe, dep)
136 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700137 })
138
Colin Crossdc809f92019-11-20 15:58:32 -0800139 var sharedLibraries android.Paths
140
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700141 for i := 0; i < len(fringe); i++ {
142 module := fringe[i]
Colin Crossdc809f92019-11-20 15:58:32 -0800143 if seen[module] {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700144 continue
145 }
Colin Crossdc809f92019-11-20 15:58:32 -0800146 seen[module] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700147
148 ccModule := module.(*Module)
Colin Crossdc809f92019-11-20 15:58:32 -0800149 sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700150 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800151 if isValidSharedDependency(dep) && !seen[dep] {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800152 fringe = append(fringe, dep)
153 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700154 })
155 }
Colin Crossdc809f92019-11-20 15:58:32 -0800156
157 return sharedLibraries
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700158}
159
160// This function takes a module and determines if it is a unique shared library
161// that should be installed in the fuzz target output directories. This function
162// returns true, unless:
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700163// - The module is not a shared library, or
164// - The module is a header, stub, or vendor-linked library.
Colin Crossdc809f92019-11-20 15:58:32 -0800165func isValidSharedDependency(dependency android.Module) bool {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700166 // TODO(b/144090547): We should be parsing these modules using
167 // ModuleDependencyTag instead of the current brute-force checking.
168
169 if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
170 !linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
171 linkable.UseVndk() || // Discard vendor linked libraries.
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800172 // Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
173 // be excluded on the basis of they're not CCLibrary()'s.
174 (linkable.CcLibrary() && linkable.BuildStubs()) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700175 return false
176 }
177
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800178 // We discarded module stubs libraries above, but the LLNDK prebuilts stubs
179 // libraries must be handled differently - by looking for the stubDecorator.
180 // Discard LLNDK prebuilts stubs as well.
181 if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
182 if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
183 return false
184 }
185 }
186
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700187 return true
188}
189
190func sharedLibraryInstallLocation(
191 libraryPath android.Path, isHost bool, archString string) string {
192 installLocation := "$(PRODUCT_OUT)/data"
193 if isHost {
194 installLocation = "$(HOST_OUT)"
195 }
196 installLocation = filepath.Join(
197 installLocation, "fuzz", archString, "lib", libraryPath.Base())
198 return installLocation
199}
200
Mitch Phillips0bf97132020-03-06 09:38:12 -0800201// Get the device-only shared library symbols install directory.
202func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, archString string) string {
203 return filepath.Join("$(PRODUCT_OUT)/symbols/data/fuzz/", archString, "/lib/", libraryPath.Base())
204}
205
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700206func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700207 fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
208 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
209 fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
210 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700211 fuzz.binaryDecorator.baseInstaller.install(ctx, file)
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700212
213 fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700214 builder := android.NewRuleBuilder()
215 intermediateDir := android.PathForModuleOut(ctx, "corpus")
216 for _, entry := range fuzz.corpus {
217 builder.Command().Text("cp").
218 Input(entry).
219 Output(intermediateDir.Join(ctx, entry.Base()))
220 }
221 builder.Build(pctx, ctx, "copy_corpus", "copy corpus")
222 fuzz.corpusIntermediateDir = intermediateDir
223
Tri Voad172d82019-11-27 13:45:45 -0800224 fuzz.data = android.PathsForModuleSrc(ctx, fuzz.Properties.Data)
225 builder = android.NewRuleBuilder()
226 intermediateDir = android.PathForModuleOut(ctx, "data")
227 for _, entry := range fuzz.data {
228 builder.Command().Text("cp").
229 Input(entry).
230 Output(intermediateDir.Join(ctx, entry.Rel()))
231 }
232 builder.Build(pctx, ctx, "copy_data", "copy data")
233 fuzz.dataIntermediateDir = intermediateDir
234
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700235 if fuzz.Properties.Dictionary != nil {
236 fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
237 if fuzz.dictionary.Ext() != ".dict" {
238 ctx.PropertyErrorf("dictionary",
239 "Fuzzer dictionary %q does not have '.dict' extension",
240 fuzz.dictionary.String())
241 }
242 }
Kris Alderf979ee32019-10-22 10:52:01 -0700243
244 if fuzz.Properties.Fuzz_config != nil {
Kris Alderdb97af42019-10-30 10:17:04 -0700245 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
Kris Alderf979ee32019-10-22 10:52:01 -0700246 ctx.Build(pctx, android.BuildParams{
247 Rule: android.WriteFile,
248 Description: "fuzzer infrastructure configuration",
249 Output: configPath,
250 Args: map[string]string{
251 "content": fuzz.Properties.Fuzz_config.String(),
252 },
253 })
254 fuzz.config = configPath
255 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700256
257 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800258 seen := make(map[android.Module]bool)
259 var sharedLibraries android.Paths
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700260 ctx.WalkDeps(func(child, parent android.Module) bool {
Colin Crossdc809f92019-11-20 15:58:32 -0800261 if seen[child] {
262 return false
263 }
264 seen[child] = true
265
266 if isValidSharedDependency(child) {
267 sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700268 return true
269 }
270 return false
271 })
272
273 for _, lib := range sharedLibraries {
274 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
275 sharedLibraryInstallLocation(
276 lib, ctx.Host(), ctx.Arch().ArchType.String()))
Mitch Phillips0bf97132020-03-06 09:38:12 -0800277
278 // Also add the dependency on the shared library symbols dir.
279 if !ctx.Host() {
280 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
281 sharedLibrarySymbolsInstallLocation(lib, ctx.Arch().ArchType.String()))
282 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700283 }
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700284}
285
286func NewFuzz(hod android.HostOrDeviceSupported) *Module {
287 module, binary := NewBinary(hod)
288
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700289 binary.baseInstaller = NewFuzzInstaller()
290 module.sanitize.SetSanitizer(fuzzer, true)
291
292 fuzz := &fuzzBinary{
293 binaryDecorator: binary,
294 baseCompiler: NewBaseCompiler(),
295 }
296 module.compiler = fuzz
297 module.linker = fuzz
298 module.installer = fuzz
Colin Crosseec9b282019-07-18 16:20:52 -0700299
300 // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
301 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Alex Light71123ec2019-07-24 13:34:19 -0700302 disableDarwinAndLinuxBionic := struct {
Colin Crosseec9b282019-07-18 16:20:52 -0700303 Target struct {
304 Darwin struct {
305 Enabled *bool
306 }
Alex Light71123ec2019-07-24 13:34:19 -0700307 Linux_bionic struct {
308 Enabled *bool
309 }
Colin Crosseec9b282019-07-18 16:20:52 -0700310 }
311 }{}
Alex Light71123ec2019-07-24 13:34:19 -0700312 disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false)
313 disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false)
314 ctx.AppendProperties(&disableDarwinAndLinuxBionic)
Colin Crosseec9b282019-07-18 16:20:52 -0700315 })
316
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700317 return module
318}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700319
320// Responsible for generating GNU Make rules that package fuzz targets into
321// their architecture & target/host specific zip file.
322type fuzzPackager struct {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700323 packages android.Paths
324 sharedLibInstallStrings []string
325 fuzzTargets map[string]bool
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700326}
327
328func fuzzPackagingFactory() android.Singleton {
329 return &fuzzPackager{}
330}
331
332type fileToZip struct {
333 SourceFilePath android.Path
334 DestinationPathPrefix string
335}
336
Colin Crossdc809f92019-11-20 15:58:32 -0800337type archOs struct {
338 hostOrTarget string
339 arch string
340 dir string
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700341}
342
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700343func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
344 // Map between each architecture + host/device combination, and the files that
345 // need to be packaged (in the tuple of {source file, destination folder in
346 // archive}).
Colin Crossdc809f92019-11-20 15:58:32 -0800347 archDirs := make(map[archOs][]fileToZip)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700348
Colin Crossdc809f92019-11-20 15:58:32 -0800349 // Map tracking whether each shared library has an install rule to avoid duplicate install rules from
350 // multiple fuzzers that depend on the same shared library.
351 sharedLibraryInstalled := make(map[string]bool)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700352
353 // List of individual fuzz targets, so that 'make fuzz' also installs the targets
354 // to the correct output directories as well.
355 s.fuzzTargets = make(map[string]bool)
356
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700357 ctx.VisitAllModules(func(module android.Module) {
358 // Discard non-fuzz targets.
359 ccModule, ok := module.(*Module)
360 if !ok {
361 return
362 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700363
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700364 fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
365 if !ok {
366 return
367 }
368
Hamzeh Zawawy0540ae72020-04-25 16:14:52 +0000369 // Discard ramdisk + recovery modules, they're duplicates of
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800370 // fuzz targets we're going to package anyway.
371 if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
Hamzeh Zawawy0540ae72020-04-25 16:14:52 +0000372 ccModule.InRamdisk() || ccModule.InRecovery() {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700373 return
374 }
375
Mitch Phillips6a9bf212019-12-05 07:36:11 -0800376 // Discard modules that are in an unavailable namespace.
377 if !ccModule.ExportedToMake() {
378 return
379 }
380
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700381 hostOrTargetString := "target"
382 if ccModule.Host() {
383 hostOrTargetString = "host"
384 }
385
386 archString := ccModule.Arch().ArchType.String()
387 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800388 archOs := archOs{hostOrTarget: hostOrTargetString, arch: archString, dir: archDir.String()}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700389
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700390 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800391 sharedLibraries := collectAllSharedDependencies(ctx, module)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700392
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800393 var files []fileToZip
394 builder := android.NewRuleBuilder()
395
396 // Package the corpora into a zipfile.
397 if fuzzModule.corpus != nil {
398 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
399 command := builder.Command().BuiltTool(ctx, "soong_zip").
400 Flag("-j").
401 FlagWithOutput("-o ", corpusZip)
402 command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
403 files = append(files, fileToZip{corpusZip, ""})
404 }
405
Tri Voad172d82019-11-27 13:45:45 -0800406 // Package the data into a zipfile.
407 if fuzzModule.data != nil {
408 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
409 command := builder.Command().BuiltTool(ctx, "soong_zip").
410 FlagWithOutput("-o ", dataZip)
411 for _, f := range fuzzModule.data {
412 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
413 command.FlagWithArg("-C ", intermediateDir)
414 command.FlagWithInput("-f ", f)
415 }
416 files = append(files, fileToZip{dataZip, ""})
417 }
418
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800419 // Find and mark all the transiently-dependent shared libraries for
420 // packaging.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700421 for _, library := range sharedLibraries {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800422 files = append(files, fileToZip{library, "lib"})
Mitch Phillips13ed3f52019-11-12 11:12:10 -0800423
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700424 // For each architecture-specific shared library dependency, we need to
425 // install it to the output directory. Setup the install destination here,
426 // which will be used by $(copy-many-files) in the Make backend.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700427 installDestination := sharedLibraryInstallLocation(
428 library, ccModule.Host(), archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800429 if sharedLibraryInstalled[installDestination] {
430 continue
431 }
432 sharedLibraryInstalled[installDestination] = true
Mitch Phillips0bf97132020-03-06 09:38:12 -0800433
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700434 // Escape all the variables, as the install destination here will be called
435 // via. $(eval) in Make.
436 installDestination = strings.ReplaceAll(
437 installDestination, "$", "$$")
438 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
439 library.String()+":"+installDestination)
Mitch Phillips0bf97132020-03-06 09:38:12 -0800440
441 // Ensure that on device, the library is also reinstalled to the /symbols/
442 // dir. Symbolized DSO's are always installed to the device when fuzzing, but
443 // we want symbolization tools (like `stack`) to be able to find the symbols
444 // in $ANDROID_PRODUCT_OUT/symbols automagically.
445 if !ccModule.Host() {
446 symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
447 symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
448 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
449 library.String()+":"+symbolsInstallDestination)
450 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700451 }
452
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700453 // The executable.
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800454 files = append(files, fileToZip{ccModule.UnstrippedOutputFile(), ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700455
456 // The dictionary.
457 if fuzzModule.dictionary != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800458 files = append(files, fileToZip{fuzzModule.dictionary, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700459 }
Kris Alderf979ee32019-10-22 10:52:01 -0700460
461 // Additional fuzz config.
462 if fuzzModule.config != nil {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800463 files = append(files, fileToZip{fuzzModule.config, ""})
Kris Alderf979ee32019-10-22 10:52:01 -0700464 }
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800465
466 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
467 command := builder.Command().BuiltTool(ctx, "soong_zip").
468 Flag("-j").
469 FlagWithOutput("-o ", fuzzZip)
470 for _, file := range files {
471 if file.DestinationPathPrefix != "" {
472 command.FlagWithArg("-P ", file.DestinationPathPrefix)
473 } else {
474 command.Flag("-P ''")
475 }
476 command.FlagWithInput("-f ", file.SourceFilePath)
477 }
478
479 builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
480 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
481
Mitch Phillips18e67192020-02-24 08:26:20 -0800482 // Don't add modules to 'make haiku' that are set to not be exported to the
483 // fuzzing infrastructure.
484 if config := fuzzModule.Properties.Fuzz_config; config != nil {
485 if ccModule.Host() && !BoolDefault(config.Fuzz_on_haiku_host, true) {
486 return
487 } else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
488 return
489 }
490 }
491
492 s.fuzzTargets[module.Name()] = true
Colin Crossdc809f92019-11-20 15:58:32 -0800493 archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700494 })
495
Colin Crossdc809f92019-11-20 15:58:32 -0800496 var archOsList []archOs
497 for archOs := range archDirs {
498 archOsList = append(archOsList, archOs)
499 }
500 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].dir < archOsList[j].dir })
501
502 for _, archOs := range archOsList {
503 filesToZip := archDirs[archOs]
504 arch := archOs.arch
505 hostOrTarget := archOs.hostOrTarget
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700506 builder := android.NewRuleBuilder()
507 outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700508 s.packages = append(s.packages, outputFile)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700509
510 command := builder.Command().BuiltTool(ctx, "soong_zip").
511 Flag("-j").
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800512 FlagWithOutput("-o ", outputFile).
513 Flag("-L 0") // No need to try and re-compress the zipfiles.
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700514
515 for _, fileToZip := range filesToZip {
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800516 if fileToZip.DestinationPathPrefix != "" {
517 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
518 } else {
519 command.Flag("-P ''")
520 }
521 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700522 }
523
524 builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
525 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
526 }
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700527}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700528
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700529func (s *fuzzPackager) MakeVars(ctx android.MakeVarsContext) {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700530 packages := s.packages.Strings()
531 sort.Strings(packages)
532 sort.Strings(s.sharedLibInstallStrings)
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700533 // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
534 // ready to handle phony targets created in Soong. In the meantime, this
535 // exports the phony 'fuzz' target and dependencies on packages to
536 // core/main.mk so that we can use dist-for-goals.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700537 ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
538 ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
539 strings.Join(s.sharedLibInstallStrings, " "))
540
541 // Preallocate the slice of fuzz targets to minimise memory allocations.
542 fuzzTargets := make([]string, 0, len(s.fuzzTargets))
543 for target, _ := range s.fuzzTargets {
544 fuzzTargets = append(fuzzTargets, target)
545 }
546 sort.Strings(fuzzTargets)
547 ctx.Strict("ALL_FUZZ_TARGETS", strings.Join(fuzzTargets, " "))
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700548}