xref: /aosp_15_r20/build/soong/rust/sanitize.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 The Android Open Source Project
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage rust
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"strings"
20*333d2b36SAndroid Build Coastguard Worker
21*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/cc"
26*333d2b36SAndroid Build Coastguard Worker	"android/soong/rust/config"
27*333d2b36SAndroid Build Coastguard Worker)
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Worker// TODO: When Rust has sanitizer-parity with CC, deduplicate this struct
30*333d2b36SAndroid Build Coastguard Workertype SanitizeProperties struct {
31*333d2b36SAndroid Build Coastguard Worker	// enable AddressSanitizer, HWAddressSanitizer, and others.
32*333d2b36SAndroid Build Coastguard Worker	Sanitize struct {
33*333d2b36SAndroid Build Coastguard Worker		Address   *bool `android:"arch_variant"`
34*333d2b36SAndroid Build Coastguard Worker		Hwaddress *bool `android:"arch_variant"`
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Worker		// Memory-tagging, only available on arm64
37*333d2b36SAndroid Build Coastguard Worker		// if diag.memtag unset or false, enables async memory tagging
38*333d2b36SAndroid Build Coastguard Worker		Memtag_heap *bool `android:"arch_variant"`
39*333d2b36SAndroid Build Coastguard Worker		Fuzzer      *bool `android:"arch_variant"`
40*333d2b36SAndroid Build Coastguard Worker		Never       *bool `android:"arch_variant"`
41*333d2b36SAndroid Build Coastguard Worker
42*333d2b36SAndroid Build Coastguard Worker		// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
43*333d2b36SAndroid Build Coastguard Worker		// Replaces abort() on error with a human-readable error message.
44*333d2b36SAndroid Build Coastguard Worker		// Address and Thread sanitizers always run in diagnostic mode.
45*333d2b36SAndroid Build Coastguard Worker		Diag struct {
46*333d2b36SAndroid Build Coastguard Worker			// Memory-tagging, only available on arm64
47*333d2b36SAndroid Build Coastguard Worker			// requires sanitizer.memtag: true
48*333d2b36SAndroid Build Coastguard Worker			// if set, enables sync memory tagging
49*333d2b36SAndroid Build Coastguard Worker			Memtag_heap *bool `android:"arch_variant"`
50*333d2b36SAndroid Build Coastguard Worker		}
51*333d2b36SAndroid Build Coastguard Worker	}
52*333d2b36SAndroid Build Coastguard Worker	SanitizerEnabled bool `blueprint:"mutated"`
53*333d2b36SAndroid Build Coastguard Worker
54*333d2b36SAndroid Build Coastguard Worker	// Used when we need to place libraries in their own directory, such as ASAN.
55*333d2b36SAndroid Build Coastguard Worker	InSanitizerDir bool `blueprint:"mutated"`
56*333d2b36SAndroid Build Coastguard Worker}
57*333d2b36SAndroid Build Coastguard Worker
58*333d2b36SAndroid Build Coastguard Workervar fuzzerFlags = []string{
59*333d2b36SAndroid Build Coastguard Worker	"-Z external-clangrt=true",
60*333d2b36SAndroid Build Coastguard Worker
61*333d2b36SAndroid Build Coastguard Worker	"-C passes='sancov-module'",
62*333d2b36SAndroid Build Coastguard Worker
63*333d2b36SAndroid Build Coastguard Worker	"--cfg fuzzing",
64*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=-sanitizer-coverage-level=3",
65*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=-sanitizer-coverage-trace-compares",
66*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=-sanitizer-coverage-inline-8bit-counters",
67*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=-sanitizer-coverage-pc-table",
68*333d2b36SAndroid Build Coastguard Worker
69*333d2b36SAndroid Build Coastguard Worker	// See https://github.com/rust-fuzz/cargo-fuzz/pull/193
70*333d2b36SAndroid Build Coastguard Worker	"-C link-dead-code",
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Worker	// Sancov breaks with lto
73*333d2b36SAndroid Build Coastguard Worker	// TODO: Remove when https://bugs.llvm.org/show_bug.cgi?id=41734 is resolved and sancov-module works with LTO
74*333d2b36SAndroid Build Coastguard Worker	"-C lto=no",
75*333d2b36SAndroid Build Coastguard Worker}
76*333d2b36SAndroid Build Coastguard Worker
77*333d2b36SAndroid Build Coastguard Workervar asanFlags = []string{
78*333d2b36SAndroid Build Coastguard Worker	"-Z external-clangrt=true",
79*333d2b36SAndroid Build Coastguard Worker	"-Z sanitizer=address",
80*333d2b36SAndroid Build Coastguard Worker}
81*333d2b36SAndroid Build Coastguard Worker
82*333d2b36SAndroid Build Coastguard Worker// See cc/sanitize.go's hwasanGlobalOptions for global hwasan options.
83*333d2b36SAndroid Build Coastguard Workervar hwasanFlags = []string{
84*333d2b36SAndroid Build Coastguard Worker	"-Z external-clangrt=true",
85*333d2b36SAndroid Build Coastguard Worker	"-Z sanitizer=hwaddress",
86*333d2b36SAndroid Build Coastguard Worker	"-C target-feature=+tagged-globals",
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Worker	// Flags from cc/sanitize.go hwasanFlags
89*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=--aarch64-enable-global-isel-at-O=-1",
90*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=-fast-isel=false",
91*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=-instcombine-lower-dbg-declare=0",
92*333d2b36SAndroid Build Coastguard Worker
93*333d2b36SAndroid Build Coastguard Worker	// Additional flags for HWASAN-ified Rust/C interop
94*333d2b36SAndroid Build Coastguard Worker	"-C llvm-args=--hwasan-with-ifunc",
95*333d2b36SAndroid Build Coastguard Worker}
96*333d2b36SAndroid Build Coastguard Worker
97*333d2b36SAndroid Build Coastguard Workerfunc init() {
98*333d2b36SAndroid Build Coastguard Worker}
99*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) props() []interface{} {
100*333d2b36SAndroid Build Coastguard Worker	return []interface{}{&sanitize.Properties}
101*333d2b36SAndroid Build Coastguard Worker}
102*333d2b36SAndroid Build Coastguard Worker
103*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) begin(ctx BaseModuleContext) {
104*333d2b36SAndroid Build Coastguard Worker	s := &sanitize.Properties.Sanitize
105*333d2b36SAndroid Build Coastguard Worker
106*333d2b36SAndroid Build Coastguard Worker	// Disable sanitizers for musl x86 modules, rustc does not support any sanitizers.
107*333d2b36SAndroid Build Coastguard Worker	if ctx.Os() == android.LinuxMusl && ctx.Arch().ArchType == android.X86 {
108*333d2b36SAndroid Build Coastguard Worker		s.Never = proptools.BoolPtr(true)
109*333d2b36SAndroid Build Coastguard Worker	}
110*333d2b36SAndroid Build Coastguard Worker
111*333d2b36SAndroid Build Coastguard Worker	// Never always wins.
112*333d2b36SAndroid Build Coastguard Worker	if Bool(s.Never) {
113*333d2b36SAndroid Build Coastguard Worker		return
114*333d2b36SAndroid Build Coastguard Worker	}
115*333d2b36SAndroid Build Coastguard Worker
116*333d2b36SAndroid Build Coastguard Worker	// rust_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {Memtag_heap}).
117*333d2b36SAndroid Build Coastguard Worker	if binary, ok := ctx.RustModule().compiler.(binaryInterface); ok && binary.testBinary() {
118*333d2b36SAndroid Build Coastguard Worker		if s.Memtag_heap == nil {
119*333d2b36SAndroid Build Coastguard Worker			s.Memtag_heap = proptools.BoolPtr(true)
120*333d2b36SAndroid Build Coastguard Worker		}
121*333d2b36SAndroid Build Coastguard Worker		if s.Diag.Memtag_heap == nil {
122*333d2b36SAndroid Build Coastguard Worker			s.Diag.Memtag_heap = proptools.BoolPtr(true)
123*333d2b36SAndroid Build Coastguard Worker		}
124*333d2b36SAndroid Build Coastguard Worker	}
125*333d2b36SAndroid Build Coastguard Worker
126*333d2b36SAndroid Build Coastguard Worker	var globalSanitizers []string
127*333d2b36SAndroid Build Coastguard Worker	var globalSanitizersDiag []string
128*333d2b36SAndroid Build Coastguard Worker
129*333d2b36SAndroid Build Coastguard Worker	if ctx.Host() {
130*333d2b36SAndroid Build Coastguard Worker		if !ctx.Windows() {
131*333d2b36SAndroid Build Coastguard Worker			globalSanitizers = ctx.Config().SanitizeHost()
132*333d2b36SAndroid Build Coastguard Worker		}
133*333d2b36SAndroid Build Coastguard Worker	} else {
134*333d2b36SAndroid Build Coastguard Worker		arches := ctx.Config().SanitizeDeviceArch()
135*333d2b36SAndroid Build Coastguard Worker		if len(arches) == 0 || android.InList(ctx.Arch().ArchType.Name, arches) {
136*333d2b36SAndroid Build Coastguard Worker			globalSanitizers = ctx.Config().SanitizeDevice()
137*333d2b36SAndroid Build Coastguard Worker			globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
138*333d2b36SAndroid Build Coastguard Worker		}
139*333d2b36SAndroid Build Coastguard Worker	}
140*333d2b36SAndroid Build Coastguard Worker
141*333d2b36SAndroid Build Coastguard Worker	if len(globalSanitizers) > 0 {
142*333d2b36SAndroid Build Coastguard Worker		var found bool
143*333d2b36SAndroid Build Coastguard Worker
144*333d2b36SAndroid Build Coastguard Worker		// Global Sanitizers
145*333d2b36SAndroid Build Coastguard Worker		if found, globalSanitizers = android.RemoveFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
146*333d2b36SAndroid Build Coastguard Worker			// TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
147*333d2b36SAndroid Build Coastguard Worker			if !ctx.RustModule().StaticExecutable() {
148*333d2b36SAndroid Build Coastguard Worker				s.Hwaddress = proptools.BoolPtr(true)
149*333d2b36SAndroid Build Coastguard Worker			}
150*333d2b36SAndroid Build Coastguard Worker		}
151*333d2b36SAndroid Build Coastguard Worker
152*333d2b36SAndroid Build Coastguard Worker		if found, globalSanitizers = android.RemoveFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil {
153*333d2b36SAndroid Build Coastguard Worker			if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) {
154*333d2b36SAndroid Build Coastguard Worker				s.Memtag_heap = proptools.BoolPtr(true)
155*333d2b36SAndroid Build Coastguard Worker			}
156*333d2b36SAndroid Build Coastguard Worker		}
157*333d2b36SAndroid Build Coastguard Worker
158*333d2b36SAndroid Build Coastguard Worker		if found, globalSanitizers = android.RemoveFromList("address", globalSanitizers); found && s.Address == nil {
159*333d2b36SAndroid Build Coastguard Worker			s.Address = proptools.BoolPtr(true)
160*333d2b36SAndroid Build Coastguard Worker		}
161*333d2b36SAndroid Build Coastguard Worker
162*333d2b36SAndroid Build Coastguard Worker		if found, globalSanitizers = android.RemoveFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
163*333d2b36SAndroid Build Coastguard Worker			// TODO(b/204776996): HWASan for static Rust binaries isn't supported yet, and fuzzer enables HWAsan
164*333d2b36SAndroid Build Coastguard Worker			if !ctx.RustModule().StaticExecutable() {
165*333d2b36SAndroid Build Coastguard Worker				s.Fuzzer = proptools.BoolPtr(true)
166*333d2b36SAndroid Build Coastguard Worker			}
167*333d2b36SAndroid Build Coastguard Worker		}
168*333d2b36SAndroid Build Coastguard Worker
169*333d2b36SAndroid Build Coastguard Worker		// Global Diag Sanitizers
170*333d2b36SAndroid Build Coastguard Worker		if found, globalSanitizersDiag = android.RemoveFromList("memtag_heap", globalSanitizersDiag); found &&
171*333d2b36SAndroid Build Coastguard Worker			s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) {
172*333d2b36SAndroid Build Coastguard Worker			s.Diag.Memtag_heap = proptools.BoolPtr(true)
173*333d2b36SAndroid Build Coastguard Worker		}
174*333d2b36SAndroid Build Coastguard Worker	}
175*333d2b36SAndroid Build Coastguard Worker
176*333d2b36SAndroid Build Coastguard Worker	// Enable Memtag for all components in the include paths (for Aarch64 only)
177*333d2b36SAndroid Build Coastguard Worker	if ctx.Arch().ArchType == android.Arm64 && ctx.Os().Bionic() {
178*333d2b36SAndroid Build Coastguard Worker		if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
179*333d2b36SAndroid Build Coastguard Worker			if s.Memtag_heap == nil {
180*333d2b36SAndroid Build Coastguard Worker				s.Memtag_heap = proptools.BoolPtr(true)
181*333d2b36SAndroid Build Coastguard Worker			}
182*333d2b36SAndroid Build Coastguard Worker			if s.Diag.Memtag_heap == nil {
183*333d2b36SAndroid Build Coastguard Worker				s.Diag.Memtag_heap = proptools.BoolPtr(true)
184*333d2b36SAndroid Build Coastguard Worker			}
185*333d2b36SAndroid Build Coastguard Worker		} else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) {
186*333d2b36SAndroid Build Coastguard Worker			if s.Memtag_heap == nil {
187*333d2b36SAndroid Build Coastguard Worker				s.Memtag_heap = proptools.BoolPtr(true)
188*333d2b36SAndroid Build Coastguard Worker			}
189*333d2b36SAndroid Build Coastguard Worker		}
190*333d2b36SAndroid Build Coastguard Worker	}
191*333d2b36SAndroid Build Coastguard Worker
192*333d2b36SAndroid Build Coastguard Worker	// HWASan requires AArch64 hardware feature (top-byte-ignore).
193*333d2b36SAndroid Build Coastguard Worker	if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
194*333d2b36SAndroid Build Coastguard Worker		s.Hwaddress = nil
195*333d2b36SAndroid Build Coastguard Worker	}
196*333d2b36SAndroid Build Coastguard Worker
197*333d2b36SAndroid Build Coastguard Worker	// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
198*333d2b36SAndroid Build Coastguard Worker	// Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
199*333d2b36SAndroid Build Coastguard Worker	if (ctx.RustModule().InRamdisk() || ctx.RustModule().InVendorRamdisk() || ctx.RustModule().InRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
200*333d2b36SAndroid Build Coastguard Worker		s.Hwaddress = nil
201*333d2b36SAndroid Build Coastguard Worker	}
202*333d2b36SAndroid Build Coastguard Worker
203*333d2b36SAndroid Build Coastguard Worker	if Bool(s.Hwaddress) {
204*333d2b36SAndroid Build Coastguard Worker		s.Address = nil
205*333d2b36SAndroid Build Coastguard Worker	}
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Worker	// Memtag_heap is only implemented on AArch64.
208*333d2b36SAndroid Build Coastguard Worker	if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
209*333d2b36SAndroid Build Coastguard Worker		s.Memtag_heap = nil
210*333d2b36SAndroid Build Coastguard Worker	}
211*333d2b36SAndroid Build Coastguard Worker
212*333d2b36SAndroid Build Coastguard Worker	// TODO:(b/178369775)
213*333d2b36SAndroid Build Coastguard Worker	// For now sanitizing is only supported on non-windows targets
214*333d2b36SAndroid Build Coastguard Worker	if ctx.Os() != android.Windows && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
215*333d2b36SAndroid Build Coastguard Worker		sanitize.Properties.SanitizerEnabled = true
216*333d2b36SAndroid Build Coastguard Worker	}
217*333d2b36SAndroid Build Coastguard Worker}
218*333d2b36SAndroid Build Coastguard Worker
219*333d2b36SAndroid Build Coastguard Workertype sanitize struct {
220*333d2b36SAndroid Build Coastguard Worker	Properties SanitizeProperties
221*333d2b36SAndroid Build Coastguard Worker}
222*333d2b36SAndroid Build Coastguard Worker
223*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
224*333d2b36SAndroid Build Coastguard Worker	if !sanitize.Properties.SanitizerEnabled {
225*333d2b36SAndroid Build Coastguard Worker		return flags, deps
226*333d2b36SAndroid Build Coastguard Worker	}
227*333d2b36SAndroid Build Coastguard Worker
228*333d2b36SAndroid Build Coastguard Worker	if Bool(sanitize.Properties.Sanitize.Fuzzer) {
229*333d2b36SAndroid Build Coastguard Worker		flags.RustFlags = append(flags.RustFlags, fuzzerFlags...)
230*333d2b36SAndroid Build Coastguard Worker	}
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Worker	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
233*333d2b36SAndroid Build Coastguard Worker		flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
234*333d2b36SAndroid Build Coastguard Worker	}
235*333d2b36SAndroid Build Coastguard Worker
236*333d2b36SAndroid Build Coastguard Worker	if Bool(sanitize.Properties.Sanitize.Address) {
237*333d2b36SAndroid Build Coastguard Worker		flags.RustFlags = append(flags.RustFlags, asanFlags...)
238*333d2b36SAndroid Build Coastguard Worker		if ctx.Host() {
239*333d2b36SAndroid Build Coastguard Worker			// -nodefaultlibs (provided with libc++) prevents the driver from linking
240*333d2b36SAndroid Build Coastguard Worker			// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
241*333d2b36SAndroid Build Coastguard Worker			flags.LinkFlags = append(flags.LinkFlags, []string{"-Wl,--no-as-needed"}...)
242*333d2b36SAndroid Build Coastguard Worker		}
243*333d2b36SAndroid Build Coastguard Worker	}
244*333d2b36SAndroid Build Coastguard Worker	return flags, deps
245*333d2b36SAndroid Build Coastguard Worker}
246*333d2b36SAndroid Build Coastguard Worker
247*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps {
248*333d2b36SAndroid Build Coastguard Worker	return deps
249*333d2b36SAndroid Build Coastguard Worker}
250*333d2b36SAndroid Build Coastguard Worker
251*333d2b36SAndroid Build Coastguard Workerfunc rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
252*333d2b36SAndroid Build Coastguard Worker	if mod, ok := mctx.Module().(*Module); ok && mod.sanitize != nil {
253*333d2b36SAndroid Build Coastguard Worker		if !mod.Enabled(mctx) {
254*333d2b36SAndroid Build Coastguard Worker			return
255*333d2b36SAndroid Build Coastguard Worker		}
256*333d2b36SAndroid Build Coastguard Worker
257*333d2b36SAndroid Build Coastguard Worker		if Bool(mod.sanitize.Properties.Sanitize.Memtag_heap) && mod.Binary() {
258*333d2b36SAndroid Build Coastguard Worker			noteDep := "note_memtag_heap_async"
259*333d2b36SAndroid Build Coastguard Worker			if Bool(mod.sanitize.Properties.Sanitize.Diag.Memtag_heap) {
260*333d2b36SAndroid Build Coastguard Worker				noteDep = "note_memtag_heap_sync"
261*333d2b36SAndroid Build Coastguard Worker			}
262*333d2b36SAndroid Build Coastguard Worker			depTag := cc.StaticDepTag(true)
263*333d2b36SAndroid Build Coastguard Worker			variations := append(mctx.Target().Variations(),
264*333d2b36SAndroid Build Coastguard Worker				blueprint.Variation{Mutator: "link", Variation: "static"})
265*333d2b36SAndroid Build Coastguard Worker			if mod.Device() {
266*333d2b36SAndroid Build Coastguard Worker				variations = append(variations, mod.ImageVariation())
267*333d2b36SAndroid Build Coastguard Worker			}
268*333d2b36SAndroid Build Coastguard Worker			mctx.AddFarVariationDependencies(variations, depTag, noteDep)
269*333d2b36SAndroid Build Coastguard Worker		}
270*333d2b36SAndroid Build Coastguard Worker
271*333d2b36SAndroid Build Coastguard Worker		variations := mctx.Target().Variations()
272*333d2b36SAndroid Build Coastguard Worker		var depTag blueprint.DependencyTag
273*333d2b36SAndroid Build Coastguard Worker		var deps []string
274*333d2b36SAndroid Build Coastguard Worker
275*333d2b36SAndroid Build Coastguard Worker		if mod.IsSanitizerEnabled(cc.Asan) {
276*333d2b36SAndroid Build Coastguard Worker			if mod.Host() {
277*333d2b36SAndroid Build Coastguard Worker				variations = append(variations,
278*333d2b36SAndroid Build Coastguard Worker					blueprint.Variation{Mutator: "link", Variation: "static"})
279*333d2b36SAndroid Build Coastguard Worker				depTag = cc.StaticDepTag(false)
280*333d2b36SAndroid Build Coastguard Worker				deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan.static")}
281*333d2b36SAndroid Build Coastguard Worker			} else {
282*333d2b36SAndroid Build Coastguard Worker				variations = append(variations,
283*333d2b36SAndroid Build Coastguard Worker					blueprint.Variation{Mutator: "link", Variation: "shared"})
284*333d2b36SAndroid Build Coastguard Worker				depTag = cc.SharedDepTag()
285*333d2b36SAndroid Build Coastguard Worker				deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
286*333d2b36SAndroid Build Coastguard Worker			}
287*333d2b36SAndroid Build Coastguard Worker		} else if mod.IsSanitizerEnabled(cc.Hwasan) {
288*333d2b36SAndroid Build Coastguard Worker			// TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
289*333d2b36SAndroid Build Coastguard Worker			if binary, ok := mod.compiler.(binaryInterface); ok {
290*333d2b36SAndroid Build Coastguard Worker				if binary.staticallyLinked() {
291*333d2b36SAndroid Build Coastguard Worker					mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.")
292*333d2b36SAndroid Build Coastguard Worker				}
293*333d2b36SAndroid Build Coastguard Worker			}
294*333d2b36SAndroid Build Coastguard Worker
295*333d2b36SAndroid Build Coastguard Worker			// Always link against the shared library -- static binaries will pull in the static
296*333d2b36SAndroid Build Coastguard Worker			// library during final link if necessary
297*333d2b36SAndroid Build Coastguard Worker			variations = append(variations,
298*333d2b36SAndroid Build Coastguard Worker				blueprint.Variation{Mutator: "link", Variation: "shared"})
299*333d2b36SAndroid Build Coastguard Worker			depTag = cc.SharedDepTag()
300*333d2b36SAndroid Build Coastguard Worker			deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
301*333d2b36SAndroid Build Coastguard Worker		}
302*333d2b36SAndroid Build Coastguard Worker
303*333d2b36SAndroid Build Coastguard Worker		if len(deps) > 0 {
304*333d2b36SAndroid Build Coastguard Worker			mctx.AddFarVariationDependencies(variations, depTag, deps...)
305*333d2b36SAndroid Build Coastguard Worker		}
306*333d2b36SAndroid Build Coastguard Worker	}
307*333d2b36SAndroid Build Coastguard Worker}
308*333d2b36SAndroid Build Coastguard Worker
309*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) SetSanitizer(t cc.SanitizerType, b bool) {
310*333d2b36SAndroid Build Coastguard Worker	sanitizerSet := false
311*333d2b36SAndroid Build Coastguard Worker	switch t {
312*333d2b36SAndroid Build Coastguard Worker	case cc.Fuzzer:
313*333d2b36SAndroid Build Coastguard Worker		sanitize.Properties.Sanitize.Fuzzer = proptools.BoolPtr(b)
314*333d2b36SAndroid Build Coastguard Worker		sanitizerSet = true
315*333d2b36SAndroid Build Coastguard Worker	case cc.Asan:
316*333d2b36SAndroid Build Coastguard Worker		sanitize.Properties.Sanitize.Address = proptools.BoolPtr(b)
317*333d2b36SAndroid Build Coastguard Worker		sanitizerSet = true
318*333d2b36SAndroid Build Coastguard Worker	case cc.Hwasan:
319*333d2b36SAndroid Build Coastguard Worker		sanitize.Properties.Sanitize.Hwaddress = proptools.BoolPtr(b)
320*333d2b36SAndroid Build Coastguard Worker		sanitizerSet = true
321*333d2b36SAndroid Build Coastguard Worker	case cc.Memtag_heap:
322*333d2b36SAndroid Build Coastguard Worker		sanitize.Properties.Sanitize.Memtag_heap = proptools.BoolPtr(b)
323*333d2b36SAndroid Build Coastguard Worker		sanitizerSet = true
324*333d2b36SAndroid Build Coastguard Worker	default:
325*333d2b36SAndroid Build Coastguard Worker		panic(fmt.Errorf("setting unsupported sanitizerType %d", t))
326*333d2b36SAndroid Build Coastguard Worker	}
327*333d2b36SAndroid Build Coastguard Worker	if b && sanitizerSet {
328*333d2b36SAndroid Build Coastguard Worker		sanitize.Properties.SanitizerEnabled = true
329*333d2b36SAndroid Build Coastguard Worker	}
330*333d2b36SAndroid Build Coastguard Worker}
331*333d2b36SAndroid Build Coastguard Worker
332*333d2b36SAndroid Build Coastguard Workerfunc (m *Module) UbsanRuntimeNeeded() bool {
333*333d2b36SAndroid Build Coastguard Worker	return false
334*333d2b36SAndroid Build Coastguard Worker}
335*333d2b36SAndroid Build Coastguard Worker
336*333d2b36SAndroid Build Coastguard Workerfunc (m *Module) MinimalRuntimeNeeded() bool {
337*333d2b36SAndroid Build Coastguard Worker	return false
338*333d2b36SAndroid Build Coastguard Worker}
339*333d2b36SAndroid Build Coastguard Worker
340*333d2b36SAndroid Build Coastguard Workerfunc (m *Module) UbsanRuntimeDep() bool {
341*333d2b36SAndroid Build Coastguard Worker	return false
342*333d2b36SAndroid Build Coastguard Worker}
343*333d2b36SAndroid Build Coastguard Worker
344*333d2b36SAndroid Build Coastguard Workerfunc (m *Module) MinimalRuntimeDep() bool {
345*333d2b36SAndroid Build Coastguard Worker	return false
346*333d2b36SAndroid Build Coastguard Worker}
347*333d2b36SAndroid Build Coastguard Worker
348*333d2b36SAndroid Build Coastguard Worker// Check if the sanitizer is explicitly disabled (as opposed to nil by
349*333d2b36SAndroid Build Coastguard Worker// virtue of not being set).
350*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) isSanitizerExplicitlyDisabled(t cc.SanitizerType) bool {
351*333d2b36SAndroid Build Coastguard Worker	if sanitize == nil {
352*333d2b36SAndroid Build Coastguard Worker		return false
353*333d2b36SAndroid Build Coastguard Worker	}
354*333d2b36SAndroid Build Coastguard Worker	if Bool(sanitize.Properties.Sanitize.Never) {
355*333d2b36SAndroid Build Coastguard Worker		return true
356*333d2b36SAndroid Build Coastguard Worker	}
357*333d2b36SAndroid Build Coastguard Worker	sanitizerVal := sanitize.getSanitizerBoolPtr(t)
358*333d2b36SAndroid Build Coastguard Worker	return sanitizerVal != nil && *sanitizerVal == false
359*333d2b36SAndroid Build Coastguard Worker}
360*333d2b36SAndroid Build Coastguard Worker
361*333d2b36SAndroid Build Coastguard Worker// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled)
362*333d2b36SAndroid Build Coastguard Worker// because enabling a sanitizer either directly (via the blueprint) or
363*333d2b36SAndroid Build Coastguard Worker// indirectly (via a mutator) sets the bool ptr to true, and you can't
364*333d2b36SAndroid Build Coastguard Worker// distinguish between the cases. It isn't needed though - both cases can be
365*333d2b36SAndroid Build Coastguard Worker// treated identically.
366*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) isSanitizerEnabled(t cc.SanitizerType) bool {
367*333d2b36SAndroid Build Coastguard Worker	if sanitize == nil || !sanitize.Properties.SanitizerEnabled {
368*333d2b36SAndroid Build Coastguard Worker		return false
369*333d2b36SAndroid Build Coastguard Worker	}
370*333d2b36SAndroid Build Coastguard Worker
371*333d2b36SAndroid Build Coastguard Worker	sanitizerVal := sanitize.getSanitizerBoolPtr(t)
372*333d2b36SAndroid Build Coastguard Worker	return sanitizerVal != nil && *sanitizerVal == true
373*333d2b36SAndroid Build Coastguard Worker}
374*333d2b36SAndroid Build Coastguard Worker
375*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) getSanitizerBoolPtr(t cc.SanitizerType) *bool {
376*333d2b36SAndroid Build Coastguard Worker	switch t {
377*333d2b36SAndroid Build Coastguard Worker	case cc.Fuzzer:
378*333d2b36SAndroid Build Coastguard Worker		return sanitize.Properties.Sanitize.Fuzzer
379*333d2b36SAndroid Build Coastguard Worker	case cc.Asan:
380*333d2b36SAndroid Build Coastguard Worker		return sanitize.Properties.Sanitize.Address
381*333d2b36SAndroid Build Coastguard Worker	case cc.Hwasan:
382*333d2b36SAndroid Build Coastguard Worker		return sanitize.Properties.Sanitize.Hwaddress
383*333d2b36SAndroid Build Coastguard Worker	case cc.Memtag_heap:
384*333d2b36SAndroid Build Coastguard Worker		return sanitize.Properties.Sanitize.Memtag_heap
385*333d2b36SAndroid Build Coastguard Worker	default:
386*333d2b36SAndroid Build Coastguard Worker		return nil
387*333d2b36SAndroid Build Coastguard Worker	}
388*333d2b36SAndroid Build Coastguard Worker}
389*333d2b36SAndroid Build Coastguard Worker
390*333d2b36SAndroid Build Coastguard Workerfunc (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
391*333d2b36SAndroid Build Coastguard Worker	// Add a suffix for hwasan rlib libraries to allow surfacing both the sanitized and
392*333d2b36SAndroid Build Coastguard Worker	// non-sanitized variants to make without a name conflict.
393*333d2b36SAndroid Build Coastguard Worker	if entries.Class == "RLIB_LIBRARIES" || entries.Class == "STATIC_LIBRARIES" {
394*333d2b36SAndroid Build Coastguard Worker		if sanitize.isSanitizerEnabled(cc.Hwasan) {
395*333d2b36SAndroid Build Coastguard Worker			entries.SubName += ".hwasan"
396*333d2b36SAndroid Build Coastguard Worker		}
397*333d2b36SAndroid Build Coastguard Worker	}
398*333d2b36SAndroid Build Coastguard Worker}
399*333d2b36SAndroid Build Coastguard Worker
400*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) SanitizerSupported(t cc.SanitizerType) bool {
401*333d2b36SAndroid Build Coastguard Worker	// Sanitizers are not supported on Windows targets.
402*333d2b36SAndroid Build Coastguard Worker	if mod.Os() == android.Windows {
403*333d2b36SAndroid Build Coastguard Worker		return false
404*333d2b36SAndroid Build Coastguard Worker	}
405*333d2b36SAndroid Build Coastguard Worker	switch t {
406*333d2b36SAndroid Build Coastguard Worker	case cc.Fuzzer:
407*333d2b36SAndroid Build Coastguard Worker		return true
408*333d2b36SAndroid Build Coastguard Worker	case cc.Asan:
409*333d2b36SAndroid Build Coastguard Worker		return true
410*333d2b36SAndroid Build Coastguard Worker	case cc.Hwasan:
411*333d2b36SAndroid Build Coastguard Worker		// TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
412*333d2b36SAndroid Build Coastguard Worker		if mod.StaticExecutable() {
413*333d2b36SAndroid Build Coastguard Worker			return false
414*333d2b36SAndroid Build Coastguard Worker		}
415*333d2b36SAndroid Build Coastguard Worker		return true
416*333d2b36SAndroid Build Coastguard Worker	case cc.Memtag_heap:
417*333d2b36SAndroid Build Coastguard Worker		return true
418*333d2b36SAndroid Build Coastguard Worker	default:
419*333d2b36SAndroid Build Coastguard Worker		return false
420*333d2b36SAndroid Build Coastguard Worker	}
421*333d2b36SAndroid Build Coastguard Worker}
422*333d2b36SAndroid Build Coastguard Worker
423*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) IsSanitizerEnabled(t cc.SanitizerType) bool {
424*333d2b36SAndroid Build Coastguard Worker	return mod.sanitize.isSanitizerEnabled(t)
425*333d2b36SAndroid Build Coastguard Worker}
426*333d2b36SAndroid Build Coastguard Worker
427*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) IsSanitizerExplicitlyDisabled(t cc.SanitizerType) bool {
428*333d2b36SAndroid Build Coastguard Worker	// Sanitizers are not supported on Windows targets.
429*333d2b36SAndroid Build Coastguard Worker	if mod.Os() == android.Windows {
430*333d2b36SAndroid Build Coastguard Worker		return true
431*333d2b36SAndroid Build Coastguard Worker	}
432*333d2b36SAndroid Build Coastguard Worker
433*333d2b36SAndroid Build Coastguard Worker	return mod.sanitize.isSanitizerExplicitlyDisabled(t)
434*333d2b36SAndroid Build Coastguard Worker}
435*333d2b36SAndroid Build Coastguard Worker
436*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) SetSanitizer(t cc.SanitizerType, b bool) {
437*333d2b36SAndroid Build Coastguard Worker	if !Bool(mod.sanitize.Properties.Sanitize.Never) {
438*333d2b36SAndroid Build Coastguard Worker		mod.sanitize.SetSanitizer(t, b)
439*333d2b36SAndroid Build Coastguard Worker	}
440*333d2b36SAndroid Build Coastguard Worker}
441*333d2b36SAndroid Build Coastguard Worker
442*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) StaticallyLinked() bool {
443*333d2b36SAndroid Build Coastguard Worker	if lib, ok := mod.compiler.(libraryInterface); ok {
444*333d2b36SAndroid Build Coastguard Worker		return lib.rlib() || lib.static()
445*333d2b36SAndroid Build Coastguard Worker	} else if binary, ok := mod.compiler.(binaryInterface); ok {
446*333d2b36SAndroid Build Coastguard Worker		return binary.staticallyLinked()
447*333d2b36SAndroid Build Coastguard Worker	}
448*333d2b36SAndroid Build Coastguard Worker	return false
449*333d2b36SAndroid Build Coastguard Worker}
450*333d2b36SAndroid Build Coastguard Worker
451*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) SetInSanitizerDir() {
452*333d2b36SAndroid Build Coastguard Worker	mod.sanitize.Properties.InSanitizerDir = true
453*333d2b36SAndroid Build Coastguard Worker}
454*333d2b36SAndroid Build Coastguard Worker
455*333d2b36SAndroid Build Coastguard Workerfunc (mod *Module) SanitizeNever() bool {
456*333d2b36SAndroid Build Coastguard Worker	return Bool(mod.sanitize.Properties.Sanitize.Never)
457*333d2b36SAndroid Build Coastguard Worker}
458*333d2b36SAndroid Build Coastguard Worker
459*333d2b36SAndroid Build Coastguard Workervar _ cc.PlatformSanitizeable = (*Module)(nil)
460*333d2b36SAndroid Build Coastguard Worker
461*333d2b36SAndroid Build Coastguard Workerfunc IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
462*333d2b36SAndroid Build Coastguard Worker	switch t := tag.(type) {
463*333d2b36SAndroid Build Coastguard Worker	case dependencyTag:
464*333d2b36SAndroid Build Coastguard Worker		return t.library
465*333d2b36SAndroid Build Coastguard Worker	default:
466*333d2b36SAndroid Build Coastguard Worker		return cc.IsSanitizableDependencyTag(tag)
467*333d2b36SAndroid Build Coastguard Worker	}
468*333d2b36SAndroid Build Coastguard Worker}
469*333d2b36SAndroid Build Coastguard Worker
470*333d2b36SAndroid Build Coastguard Workerfunc (m *Module) SanitizableDepTagChecker() cc.SantizableDependencyTagChecker {
471*333d2b36SAndroid Build Coastguard Worker	return IsSanitizableDependencyTag
472*333d2b36SAndroid Build Coastguard Worker}
473