1// Copyright 2020 The Android Open Source Project 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 rust 16 17import ( 18 "android/soong/android" 19 "android/soong/cc" 20 "android/soong/fuzz" 21 "android/soong/rust/config" 22 "path/filepath" 23) 24 25func init() { 26 android.RegisterModuleType("rust_fuzz", RustFuzzFactory) 27 android.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory) 28} 29 30type fuzzDecorator struct { 31 *binaryDecorator 32 33 fuzzPackagedModule fuzz.FuzzPackagedModule 34 sharedLibraries android.RuleBuilderInstalls 35 installedSharedDeps []string 36} 37 38var _ compiler = (*fuzzDecorator)(nil) 39 40// rust_binary produces a binary that is runnable on a device. 41func RustFuzzFactory() android.Module { 42 module, _ := NewRustFuzz(android.HostAndDeviceSupported) 43 return module.Init() 44} 45 46func RustFuzzHostFactory() android.Module { 47 module, _ := NewRustFuzz(android.HostSupported) 48 return module.Init() 49} 50 51func NewRustFuzz(hod android.HostOrDeviceSupported) (*Module, *fuzzDecorator) { 52 module, binary := NewRustBinary(hod) 53 fuzz := &fuzzDecorator{ 54 binaryDecorator: binary, 55 } 56 57 // Change the defaults for the binaryDecorator's baseCompiler 58 fuzz.binaryDecorator.baseCompiler.dir = "fuzz" 59 fuzz.binaryDecorator.baseCompiler.dir64 = "fuzz" 60 fuzz.binaryDecorator.baseCompiler.location = InstallInData 61 module.sanitize.SetSanitizer(cc.Fuzzer, true) 62 63 // The fuzzer runtime is not present for darwin or bionic host modules, so disable rust_fuzz modules for these. 64 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 65 66 extraProps := struct { 67 Target struct { 68 Darwin struct { 69 Enabled *bool 70 } 71 Linux_bionic struct { 72 Enabled *bool 73 } 74 } 75 }{} 76 extraProps.Target.Darwin.Enabled = cc.BoolPtr(false) 77 extraProps.Target.Linux_bionic.Enabled = cc.BoolPtr(false) 78 ctx.AppendProperties(&extraProps) 79 }) 80 81 module.compiler = fuzz 82 return module, fuzz 83} 84 85func (fuzzer *fuzzDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { 86 flags = fuzzer.binaryDecorator.compilerFlags(ctx, flags) 87 88 // `../lib` for installed fuzz targets (both host and device), and `./lib` for fuzz target packages. 89 flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`) 90 91 if ctx.InstallInVendor() { 92 flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`) 93 } else { 94 flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../lib`) 95 96 } 97 return flags 98} 99 100func (fuzzer *fuzzDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { 101 if libFuzzerRuntimeLibrary := config.LibFuzzerRuntimeLibrary(ctx.toolchain()); libFuzzerRuntimeLibrary != "" { 102 deps.StaticLibs = append(deps.StaticLibs, libFuzzerRuntimeLibrary) 103 } 104 deps.SharedLibs = append(deps.SharedLibs, "libc++") 105 deps.Rlibs = append(deps.Rlibs, "liblibfuzzer_sys") 106 107 deps = fuzzer.binaryDecorator.compilerDeps(ctx, deps) 108 109 return deps 110} 111 112func (fuzzer *fuzzDecorator) compilerProps() []interface{} { 113 return append(fuzzer.binaryDecorator.compilerProps(), 114 &fuzzer.fuzzPackagedModule.FuzzProperties) 115} 116 117func (fuzzer *fuzzDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { 118 119 out := fuzzer.binaryDecorator.compile(ctx, flags, deps) 120 121 return out 122} 123 124func (fuzzer *fuzzDecorator) stdLinkage(ctx *depsContext) RustLinkage { 125 return RlibLinkage 126} 127 128func (fuzzer *fuzzDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { 129 return rlibAutoDep 130} 131 132func (fuzz *fuzzDecorator) install(ctx ModuleContext) { 133 fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule, pctx) 134 135 installBase := "fuzz" 136 137 // Grab the list of required shared libraries. 138 fuzz.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx) 139 140 for _, ruleBuilderInstall := range fuzz.sharedLibraries { 141 install := ruleBuilderInstall.To 142 143 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps, 144 cc.SharedLibraryInstallLocation( 145 install, ctx.Host(), ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String())) 146 147 // Also add the dependency on the shared library symbols dir. 148 if !ctx.Host() { 149 fuzz.installedSharedDeps = append(fuzz.installedSharedDeps, 150 cc.SharedLibrarySymbolsInstallLocation(install, ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String())) 151 } 152 } 153 154 var fuzzData []android.DataPath 155 for _, d := range fuzz.fuzzPackagedModule.Corpus { 156 fuzzData = append(fuzzData, android.DataPath{SrcPath: d, RelativeInstallPath: "corpus", WithoutRel: true}) 157 } 158 159 for _, d := range fuzz.fuzzPackagedModule.Data { 160 fuzzData = append(fuzzData, android.DataPath{SrcPath: d, RelativeInstallPath: "data"}) 161 } 162 163 if d := fuzz.fuzzPackagedModule.Dictionary; d != nil { 164 fuzzData = append(fuzzData, android.DataPath{SrcPath: d, WithoutRel: true}) 165 } 166 167 if d := fuzz.fuzzPackagedModule.Config; d != nil { 168 fuzzData = append(fuzzData, android.DataPath{SrcPath: d, WithoutRel: true}) 169 } 170 171 fuzz.binaryDecorator.baseCompiler.dir = filepath.Join( 172 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName()) 173 fuzz.binaryDecorator.baseCompiler.dir64 = filepath.Join( 174 "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName()) 175 fuzz.binaryDecorator.baseCompiler.installTestData(ctx, fuzzData) 176 177 fuzz.binaryDecorator.baseCompiler.install(ctx) 178 179} 180