blob: 98ed7f4bc1e95c7c7b592ffce08cc362e1105449 [file] [log] [blame]
hamzeh41ad8812021-07-07 14:00:07 -07001// 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 cc
16
17// This file contains the common code for compiling C/C++ and Rust fuzzers for Android.
18
19import (
20 "sort"
21 "strings"
22
23 "android/soong/android"
24)
25
26type Lang string
27
28const (
29 Cc Lang = ""
30 Rust Lang = "rust"
31)
32
33type FuzzModule struct {
34 android.ModuleBase
35 android.DefaultableModuleBase
36 android.ApexModuleBase
37}
38
39type FuzzPackager struct {
40 Packages android.Paths
41 FuzzTargets map[string]bool
42}
43
44type FileToZip struct {
45 SourceFilePath android.Path
46 DestinationPathPrefix string
47}
48
49type ArchOs struct {
50 HostOrTarget string
51 Arch string
52 Dir string
53}
54
55type FuzzPackagedModule struct {
56 FuzzProperties FuzzProperties
57 Dictionary android.Path
58 Corpus android.Paths
59 CorpusIntermediateDir android.Path
60 Config android.Path
61 Data android.Paths
62 DataIntermediateDir android.Path
63}
64
65func IsValid(fuzzModule FuzzModule) bool {
66 // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
67 // fuzz targets we're going to package anyway.
68 if !fuzzModule.Enabled() || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
69 return false
70 }
71
72 // Discard modules that are in an unavailable namespace.
73 if !fuzzModule.ExportedToMake() {
74 return false
75 }
76
77 return true
78}
79
80func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
81 // Package the corpora into a zipfile.
82 var files []FileToZip
83 if fuzzModule.Corpus != nil {
84 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
85 command := builder.Command().BuiltTool("soong_zip").
86 Flag("-j").
87 FlagWithOutput("-o ", corpusZip)
88 rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
89 command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus)
90 files = append(files, FileToZip{corpusZip, ""})
91 }
92
93 // Package the data into a zipfile.
94 if fuzzModule.Data != nil {
95 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
96 command := builder.Command().BuiltTool("soong_zip").
97 FlagWithOutput("-o ", dataZip)
98 for _, f := range fuzzModule.Data {
99 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
100 command.FlagWithArg("-C ", intermediateDir)
101 command.FlagWithInput("-f ", f)
102 }
103 files = append(files, FileToZip{dataZip, ""})
104 }
105
106 // The dictionary.
107 if fuzzModule.Dictionary != nil {
108 files = append(files, FileToZip{fuzzModule.Dictionary, ""})
109 }
110
111 // Additional fuzz config.
112 if fuzzModule.Config != nil {
113 files = append(files, FileToZip{fuzzModule.Config, ""})
114 }
115
116 return files
117}
118
119func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
120 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
121
122 command := builder.Command().BuiltTool("soong_zip").
123 Flag("-j").
124 FlagWithOutput("-o ", fuzzZip)
125
126 for _, file := range files {
127 if file.DestinationPathPrefix != "" {
128 command.FlagWithArg("-P ", file.DestinationPathPrefix)
129 } else {
130 command.Flag("-P ''")
131 }
132 command.FlagWithInput("-f ", file.SourceFilePath)
133 }
134
135 builder.Build("create-"+fuzzZip.String(),
136 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
137
138 // Don't add modules to 'make haiku-rust' that are set to not be
139 // exported to the fuzzing infrastructure.
140 if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
141 if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
142 return archDirs[archOs], false
143 } else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
144 return archDirs[archOs], false
145 }
146 }
147
148 s.FuzzTargets[module.Name()] = true
149 archDirs[archOs] = append(archDirs[archOs], FileToZip{fuzzZip, ""})
150
151 return archDirs[archOs], true
152}
153
154func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, lang Lang) {
155 var archOsList []ArchOs
156 for archOs := range archDirs {
157 archOsList = append(archOsList, archOs)
158 }
159 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir })
160
161 for _, archOs := range archOsList {
162 filesToZip := archDirs[archOs]
163 arch := archOs.Arch
164 hostOrTarget := archOs.HostOrTarget
165 builder := android.NewRuleBuilder(pctx, ctx)
166 zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
167 if lang == Rust {
168 zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
169 }
170 outputFile := android.PathForOutput(ctx, zipFileName)
171
172 s.Packages = append(s.Packages, outputFile)
173
174 command := builder.Command().BuiltTool("soong_zip").
175 Flag("-j").
176 FlagWithOutput("-o ", outputFile).
177 Flag("-L 0") // No need to try and re-compress the zipfiles.
178
179 for _, fileToZip := range filesToZip {
180
181 if fileToZip.DestinationPathPrefix != "" {
182 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
183 } else {
184 command.Flag("-P ''")
185 }
186 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
187
188 }
189 builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
190 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
191 }
192}
193
194func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) {
195 fuzzTargets := make([]string, 0, len(s.FuzzTargets))
196 for target, _ := range s.FuzzTargets {
197 fuzzTargets = append(fuzzTargets, target)
198 }
199 sort.Strings(fuzzTargets)
200 ctx.Strict(targets, strings.Join(fuzzTargets, " "))
201}