blob: 8b0f93e0e78543c8fbed783dcaee22c6a547b440 [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
Victor Chang00c144f2021-02-09 12:30:33 +000023 "github.com/google/blueprint/proptools"
24
Mitch Phillipsda9a4632019-07-15 09:34:09 -070025 "android/soong/android"
26 "android/soong/cc/config"
27)
28
Kris Alderf979ee32019-10-22 10:52:01 -070029type FuzzConfig struct {
30 // Email address of people to CC on bugs or contact about this fuzz target.
31 Cc []string `json:"cc,omitempty"`
hamzeh3478a0d2019-12-16 16:25:50 -080032 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
33 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
34 // Specify whether to enable continuous fuzzing on host. Defaults to true.
35 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
Kris Alderf979ee32019-10-22 10:52:01 -070036 // Component in Google's bug tracking system that bugs should be filed to.
37 Componentid *int64 `json:"componentid,omitempty"`
38 // Hotlists in Google's bug tracking system that bugs should be marked with.
39 Hotlists []string `json:"hotlists,omitempty"`
Kris Aldere051d0d2020-04-28 18:32:23 +000040 // Specify whether this fuzz target was submitted by a researcher. Defaults
41 // to false.
42 Researcher_submitted *bool `json:"researcher_submitted,omitempty"`
Kris Alder2598c9b2020-09-29 22:09:36 +000043 // Specify who should be acknowledged for CVEs in the Android Security
44 // Bulletin.
45 Acknowledgement []string `json:"acknowledgement,omitempty"`
Kris Alderc81f59f2021-01-07 20:57:23 +000046 // Additional options to be passed to libfuzzer when run in Haiku.
47 Libfuzzer_options []string `json:"libfuzzer_options,omitempty"`
48 // Additional options to be passed to HWASAN when running on-device in Haiku.
49 Hwasan_options []string `json:"hwasan_options,omitempty"`
50 // Additional options to be passed to HWASAN when running on host in Haiku.
51 Asan_options []string `json:"asan_options,omitempty"`
Kris Alderf979ee32019-10-22 10:52:01 -070052}
53
54func (f *FuzzConfig) String() string {
55 b, err := json.Marshal(f)
56 if err != nil {
57 panic(err)
58 }
59
60 return string(b)
61}
62
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070063type FuzzProperties struct {
64 // Optional list of seed files to be installed to the fuzz target's output
65 // directory.
66 Corpus []string `android:"path"`
Tri Voad172d82019-11-27 13:45:45 -080067 // Optional list of data files to be installed to the fuzz target's output
68 // directory. Directory structure relative to the module is preserved.
69 Data []string `android:"path"`
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070070 // Optional dictionary to be installed to the fuzz target's output directory.
71 Dictionary *string `android:"path"`
Kris Alderf979ee32019-10-22 10:52:01 -070072 // Config for running the target on fuzzing infrastructure.
73 Fuzz_config *FuzzConfig
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070074}
75
Mitch Phillipsda9a4632019-07-15 09:34:09 -070076func init() {
77 android.RegisterModuleType("cc_fuzz", FuzzFactory)
Mitch Phillipsd3254b42019-09-24 13:03:28 -070078 android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
Mitch Phillipsda9a4632019-07-15 09:34:09 -070079}
80
81// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
82// $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
83// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
84func FuzzFactory() android.Module {
85 module := NewFuzz(android.HostAndDeviceSupported)
86 return module.Init()
87}
88
89func NewFuzzInstaller() *baseInstaller {
90 return NewBaseInstaller("fuzz", "fuzz", InstallInData)
91}
92
93type fuzzBinary struct {
94 *binaryDecorator
95 *baseCompiler
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -070096
hamzeh41ad8812021-07-07 14:00:07 -070097 fuzzPackagedModule FuzzPackagedModule
98
99 installedSharedDeps []string
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700100}
101
102func (fuzz *fuzzBinary) linkerProps() []interface{} {
103 props := fuzz.binaryDecorator.linkerProps()
hamzeh41ad8812021-07-07 14:00:07 -0700104 props = append(props, &fuzz.fuzzPackagedModule.FuzzProperties)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700105 return props
106}
107
108func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) {
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700109 fuzz.binaryDecorator.linkerInit(ctx)
110}
111
112func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
113 deps.StaticLibs = append(deps.StaticLibs,
114 config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
115 deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
116 return deps
117}
118
119func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
120 flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800121 // RunPaths on devices isn't instantiated by the base linker. `../lib` for
122 // installed fuzz targets (both host and device), and `./lib` for fuzz
123 // target packages.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700124 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
Mitch Phillips1f7f54f2019-11-14 14:50:47 -0800125 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700126 return flags
127}
128
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700129// This function performs a breadth-first search over the provided module's
130// dependencies using `visitDirectDeps` to enumerate all shared library
131// dependencies. We require breadth-first expansion, as otherwise we may
132// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
133// from a dependency. This may cause issues when dependencies have explicit
134// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
Colin Crossdc809f92019-11-20 15:58:32 -0800135func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700136 var fringe []android.Module
137
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700138 seen := make(map[string]bool)
Colin Crossdc809f92019-11-20 15:58:32 -0800139
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700140 // Enumerate the first level of dependencies, as we discard all non-library
141 // modules in the BFS loop below.
142 ctx.VisitDirectDeps(module, func(dep android.Module) {
Colin Crossdc809f92019-11-20 15:58:32 -0800143 if isValidSharedDependency(dep) {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800144 fringe = append(fringe, dep)
145 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700146 })
147
Colin Crossdc809f92019-11-20 15:58:32 -0800148 var sharedLibraries android.Paths
149
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700150 for i := 0; i < len(fringe); i++ {
151 module := fringe[i]
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700152 if seen[module.Name()] {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700153 continue
154 }
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700155 seen[module.Name()] = true
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700156
157 ccModule := module.(*Module)
Colin Crossdc809f92019-11-20 15:58:32 -0800158 sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700159 ctx.VisitDirectDeps(module, func(dep android.Module) {
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700160 if isValidSharedDependency(dep) && !seen[dep.Name()] {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800161 fringe = append(fringe, dep)
162 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700163 })
164 }
Colin Crossdc809f92019-11-20 15:58:32 -0800165
166 return sharedLibraries
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700167}
168
169// This function takes a module and determines if it is a unique shared library
170// that should be installed in the fuzz target output directories. This function
171// returns true, unless:
Victor Chang00c144f2021-02-09 12:30:33 +0000172// - The module is not an installable shared library, or
Martin Stjernholm02460ab2020-10-06 02:36:43 +0100173// - The module is a header, stub, or vendor-linked library, or
174// - The module is a prebuilt and its source is available, or
175// - The module is a versioned member of an SDK snapshot.
Colin Crossdc809f92019-11-20 15:58:32 -0800176func isValidSharedDependency(dependency android.Module) bool {
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700177 // TODO(b/144090547): We should be parsing these modules using
178 // ModuleDependencyTag instead of the current brute-force checking.
179
Colin Cross31076b32020-10-23 17:22:06 -0700180 linkable, ok := dependency.(LinkableInterface)
181 if !ok || !linkable.CcLibraryInterface() {
182 // Discard non-linkables.
183 return false
184 }
185
186 if !linkable.Shared() {
187 // Discard static libs.
188 return false
189 }
190
191 if linkable.UseVndk() {
192 // Discard vendor linked libraries.
193 return false
194 }
195
196 if lib := moduleLibraryInterface(dependency); lib != nil && lib.buildStubs() && linkable.CcLibrary() {
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800197 // Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
198 // be excluded on the basis of they're not CCLibrary()'s.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700199 return false
200 }
201
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800202 // We discarded module stubs libraries above, but the LLNDK prebuilts stubs
203 // libraries must be handled differently - by looking for the stubDecorator.
204 // Discard LLNDK prebuilts stubs as well.
205 if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
206 if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
207 return false
208 }
Victor Chang00c144f2021-02-09 12:30:33 +0000209 // Discard installable:false libraries because they are expected to be absent
210 // in runtime.
211 if !proptools.BoolDefault(ccLibrary.Properties.Installable, true) {
212 return false
213 }
Mitch Phillipsf50bddb2019-11-12 14:03:31 -0800214 }
215
Martin Stjernholm02460ab2020-10-06 02:36:43 +0100216 // If the same library is present both as source and a prebuilt we must pick
217 // only one to avoid a conflict. Always prefer the source since the prebuilt
218 // probably won't be built with sanitizers enabled.
Paul Duffinf7c99f52021-04-28 10:41:21 +0100219 if prebuilt := android.GetEmbeddedPrebuilt(dependency); prebuilt != nil && prebuilt.SourceExists() {
Martin Stjernholm02460ab2020-10-06 02:36:43 +0100220 return false
221 }
222
223 // Discard versioned members of SDK snapshots, because they will conflict with
224 // unversioned ones.
225 if sdkMember, ok := dependency.(android.SdkAware); ok && !sdkMember.ContainingSdk().Unversioned() {
226 return false
227 }
228
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700229 return true
230}
231
232func sharedLibraryInstallLocation(
233 libraryPath android.Path, isHost bool, archString string) string {
234 installLocation := "$(PRODUCT_OUT)/data"
235 if isHost {
236 installLocation = "$(HOST_OUT)"
237 }
238 installLocation = filepath.Join(
239 installLocation, "fuzz", archString, "lib", libraryPath.Base())
240 return installLocation
241}
242
Mitch Phillips0bf97132020-03-06 09:38:12 -0800243// Get the device-only shared library symbols install directory.
244func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, archString string) string {
245 return filepath.Join("$(PRODUCT_OUT)/symbols/data/fuzz/", archString, "/lib/", libraryPath.Base())
246}
247
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700248func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700249 fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
250 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
251 fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
252 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700253 fuzz.binaryDecorator.baseInstaller.install(ctx, file)
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700254
hamzeh41ad8812021-07-07 14:00:07 -0700255 fuzz.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Corpus)
Colin Crossf1a035e2020-11-16 17:32:30 -0800256 builder := android.NewRuleBuilder(pctx, ctx)
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700257 intermediateDir := android.PathForModuleOut(ctx, "corpus")
hamzeh41ad8812021-07-07 14:00:07 -0700258 for _, entry := range fuzz.fuzzPackagedModule.Corpus {
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700259 builder.Command().Text("cp").
260 Input(entry).
261 Output(intermediateDir.Join(ctx, entry.Base()))
262 }
Colin Crossf1a035e2020-11-16 17:32:30 -0800263 builder.Build("copy_corpus", "copy corpus")
hamzeh41ad8812021-07-07 14:00:07 -0700264 fuzz.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
Mitch Phillips8a2bc0b2019-10-17 15:04:01 -0700265
hamzeh41ad8812021-07-07 14:00:07 -0700266 fuzz.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Data)
Colin Crossf1a035e2020-11-16 17:32:30 -0800267 builder = android.NewRuleBuilder(pctx, ctx)
Tri Voad172d82019-11-27 13:45:45 -0800268 intermediateDir = android.PathForModuleOut(ctx, "data")
hamzeh41ad8812021-07-07 14:00:07 -0700269 for _, entry := range fuzz.fuzzPackagedModule.Data {
Tri Voad172d82019-11-27 13:45:45 -0800270 builder.Command().Text("cp").
271 Input(entry).
272 Output(intermediateDir.Join(ctx, entry.Rel()))
273 }
Colin Crossf1a035e2020-11-16 17:32:30 -0800274 builder.Build("copy_data", "copy data")
hamzeh41ad8812021-07-07 14:00:07 -0700275 fuzz.fuzzPackagedModule.DataIntermediateDir = intermediateDir
Tri Voad172d82019-11-27 13:45:45 -0800276
hamzeh41ad8812021-07-07 14:00:07 -0700277 if fuzz.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
278 fuzz.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzz.fuzzPackagedModule.FuzzProperties.Dictionary)
279 if fuzz.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700280 ctx.PropertyErrorf("dictionary",
281 "Fuzzer dictionary %q does not have '.dict' extension",
hamzeh41ad8812021-07-07 14:00:07 -0700282 fuzz.fuzzPackagedModule.Dictionary.String())
Mitch Phillips4e4ab8a2019-09-13 17:32:50 -0700283 }
284 }
Kris Alderf979ee32019-10-22 10:52:01 -0700285
hamzeh41ad8812021-07-07 14:00:07 -0700286 if fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
Kris Alderdb97af42019-10-30 10:17:04 -0700287 configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
hamzeh41ad8812021-07-07 14:00:07 -0700288 android.WriteFileRule(ctx, configPath, fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
289 fuzz.fuzzPackagedModule.Config = configPath
Kris Alderf979ee32019-10-22 10:52:01 -0700290 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700291
292 // Grab the list of required shared libraries.
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700293 seen := make(map[string]bool)
Colin Crossdc809f92019-11-20 15:58:32 -0800294 var sharedLibraries android.Paths
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700295 ctx.WalkDeps(func(child, parent android.Module) bool {
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700296 if seen[child.Name()] {
Colin Crossdc809f92019-11-20 15:58:32 -0800297 return false
298 }
Mitch Phillipsc0b442f2020-04-27 16:44:58 -0700299 seen[child.Name()] = true
Colin Crossdc809f92019-11-20 15:58:32 -0800300
301 if isValidSharedDependency(child) {
302 sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700303 return true
304 }
305 return false
306 })
307
308 for _, lib := range sharedLibraries {
309 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
310 sharedLibraryInstallLocation(
311 lib, ctx.Host(), ctx.Arch().ArchType.String()))
Mitch Phillips0bf97132020-03-06 09:38:12 -0800312
313 // Also add the dependency on the shared library symbols dir.
314 if !ctx.Host() {
315 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
316 sharedLibrarySymbolsInstallLocation(lib, ctx.Arch().ArchType.String()))
317 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700318 }
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700319}
320
321func NewFuzz(hod android.HostOrDeviceSupported) *Module {
322 module, binary := NewBinary(hod)
323
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700324 binary.baseInstaller = NewFuzzInstaller()
Ivan Lozano3968d8f2020-12-14 11:27:52 -0500325 module.sanitize.SetSanitizer(Fuzzer, true)
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700326
327 fuzz := &fuzzBinary{
328 binaryDecorator: binary,
329 baseCompiler: NewBaseCompiler(),
330 }
331 module.compiler = fuzz
332 module.linker = fuzz
333 module.installer = fuzz
Colin Crosseec9b282019-07-18 16:20:52 -0700334
335 // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
336 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Alex Light71123ec2019-07-24 13:34:19 -0700337 disableDarwinAndLinuxBionic := struct {
Colin Crosseec9b282019-07-18 16:20:52 -0700338 Target struct {
339 Darwin struct {
340 Enabled *bool
341 }
Alex Light71123ec2019-07-24 13:34:19 -0700342 Linux_bionic struct {
343 Enabled *bool
344 }
Colin Crosseec9b282019-07-18 16:20:52 -0700345 }
346 }{}
Alex Light71123ec2019-07-24 13:34:19 -0700347 disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false)
348 disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false)
349 ctx.AppendProperties(&disableDarwinAndLinuxBionic)
Colin Crosseec9b282019-07-18 16:20:52 -0700350 })
351
Mitch Phillipsda9a4632019-07-15 09:34:09 -0700352 return module
353}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700354
355// Responsible for generating GNU Make rules that package fuzz targets into
356// their architecture & target/host specific zip file.
hamzeh41ad8812021-07-07 14:00:07 -0700357type ccFuzzPackager struct {
358 FuzzPackager
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700359 sharedLibInstallStrings []string
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700360}
361
362func fuzzPackagingFactory() android.Singleton {
hamzeh41ad8812021-07-07 14:00:07 -0700363 return &ccFuzzPackager{}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700364}
365
hamzeh41ad8812021-07-07 14:00:07 -0700366func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700367 // Map between each architecture + host/device combination, and the files that
368 // need to be packaged (in the tuple of {source file, destination folder in
369 // archive}).
hamzeh41ad8812021-07-07 14:00:07 -0700370 archDirs := make(map[ArchOs][]FileToZip)
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700371
Colin Crossdc809f92019-11-20 15:58:32 -0800372 // Map tracking whether each shared library has an install rule to avoid duplicate install rules from
373 // multiple fuzzers that depend on the same shared library.
374 sharedLibraryInstalled := make(map[string]bool)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700375
376 // List of individual fuzz targets, so that 'make fuzz' also installs the targets
377 // to the correct output directories as well.
hamzeh41ad8812021-07-07 14:00:07 -0700378 s.FuzzTargets = make(map[string]bool)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700379
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700380 ctx.VisitAllModules(func(module android.Module) {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700381 ccModule, ok := module.(*Module)
hamzeh41ad8812021-07-07 14:00:07 -0700382 if !ok || ccModule.Properties.PreventInstall {
383 return
384 }
385
386 // Discard non-fuzz targets.
387 if ok := IsValid(ccModule.FuzzModule); !ok {
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700388 return
389 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700390
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700391 fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
392 if !ok {
393 return
394 }
395
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700396 hostOrTargetString := "target"
397 if ccModule.Host() {
398 hostOrTargetString = "host"
399 }
400
401 archString := ccModule.Arch().ArchType.String()
402 archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
hamzeh41ad8812021-07-07 14:00:07 -0700403 archOs := ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700404
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700405 // Grab the list of required shared libraries.
Colin Crossdc809f92019-11-20 15:58:32 -0800406 sharedLibraries := collectAllSharedDependencies(ctx, module)
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700407
hamzeh41ad8812021-07-07 14:00:07 -0700408 var files []FileToZip
Colin Crossf1a035e2020-11-16 17:32:30 -0800409 builder := android.NewRuleBuilder(pctx, ctx)
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800410
hamzeh41ad8812021-07-07 14:00:07 -0700411 // Package the corpus, data, dict and config into a zipfile.
412 files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder)
Tri Voad172d82019-11-27 13:45:45 -0800413
Mitch Phillips2edbe8e2019-11-13 08:36:07 -0800414 // Find and mark all the transiently-dependent shared libraries for
415 // packaging.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700416 for _, library := range sharedLibraries {
hamzeh41ad8812021-07-07 14:00:07 -0700417 files = append(files, FileToZip{library, "lib"})
Mitch Phillips13ed3f52019-11-12 11:12:10 -0800418
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700419 // For each architecture-specific shared library dependency, we need to
420 // install it to the output directory. Setup the install destination here,
421 // which will be used by $(copy-many-files) in the Make backend.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700422 installDestination := sharedLibraryInstallLocation(
423 library, ccModule.Host(), archString)
Colin Crossdc809f92019-11-20 15:58:32 -0800424 if sharedLibraryInstalled[installDestination] {
425 continue
426 }
427 sharedLibraryInstalled[installDestination] = true
Mitch Phillips0bf97132020-03-06 09:38:12 -0800428
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700429 // Escape all the variables, as the install destination here will be called
430 // via. $(eval) in Make.
431 installDestination = strings.ReplaceAll(
432 installDestination, "$", "$$")
433 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
434 library.String()+":"+installDestination)
Mitch Phillips0bf97132020-03-06 09:38:12 -0800435
436 // Ensure that on device, the library is also reinstalled to the /symbols/
437 // dir. Symbolized DSO's are always installed to the device when fuzzing, but
438 // we want symbolization tools (like `stack`) to be able to find the symbols
439 // in $ANDROID_PRODUCT_OUT/symbols automagically.
440 if !ccModule.Host() {
441 symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
442 symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
443 s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
444 library.String()+":"+symbolsInstallDestination)
445 }
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700446 }
447
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700448 // The executable.
hamzeh41ad8812021-07-07 14:00:07 -0700449 files = append(files, FileToZip{ccModule.UnstrippedOutputFile(), ""})
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700450
hamzeh41ad8812021-07-07 14:00:07 -0700451 archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
452 if !ok {
453 return
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700454 }
455 })
456
hamzeh41ad8812021-07-07 14:00:07 -0700457 s.CreateFuzzPackage(ctx, archDirs, Cc)
Colin Crossdc809f92019-11-20 15:58:32 -0800458
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700459}
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700460
hamzeh41ad8812021-07-07 14:00:07 -0700461func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
462 packages := s.Packages.Strings()
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700463 sort.Strings(packages)
464 sort.Strings(s.sharedLibInstallStrings)
Mitch Phillipsa0a5e192019-09-27 14:00:06 -0700465 // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
466 // ready to handle phony targets created in Soong. In the meantime, this
467 // exports the phony 'fuzz' target and dependencies on packages to
468 // core/main.mk so that we can use dist-for-goals.
Mitch Phillipse1ee1a12019-10-17 19:20:41 -0700469 ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
470 ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
471 strings.Join(s.sharedLibInstallStrings, " "))
472
473 // Preallocate the slice of fuzz targets to minimise memory allocations.
hamzeh41ad8812021-07-07 14:00:07 -0700474 s.PreallocateSlice(ctx, "ALL_FUZZ_TARGETS")
Mitch Phillipsd3254b42019-09-24 13:03:28 -0700475}