• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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 (
18	"fmt"
19	"sort"
20	"strings"
21	"sync"
22
23	"github.com/google/blueprint"
24	"github.com/google/blueprint/proptools"
25
26	"android/soong/android"
27	"android/soong/cc/config"
28	"android/soong/snapshot"
29)
30
31var (
32	// Any C flags added by sanitizer which libTooling tools may not
33	// understand also need to be added to ClangLibToolingUnknownCflags in
34	// cc/config/clang.go
35
36	asanCflags = []string{
37		"-fno-omit-frame-pointer",
38	}
39	asanLdflags = []string{"-Wl,-u,__asan_preinit"}
40
41	hwasanCflags = []string{
42		"-fno-omit-frame-pointer",
43		"-Wno-frame-larger-than=",
44		"-fsanitize-hwaddress-abi=platform",
45		"-mllvm", "-hwasan-use-after-scope=1",
46	}
47
48	// ThinLTO performs codegen during link time, thus these flags need to
49	// passed to both CFLAGS and LDFLAGS.
50	hwasanCommonflags = []string{
51		// The following improves debug location information
52		// availability at the cost of its accuracy. It increases
53		// the likelihood of a stack variable's frame offset
54		// to be recorded in the debug info, which is important
55		// for the quality of hwasan reports. The downside is a
56		// higher number of "optimized out" stack variables.
57		// b/112437883.
58		"-instcombine-lower-dbg-declare=0",
59		// TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
60		// GlobalISel is the default at -O0 on aarch64.
61		"--aarch64-enable-global-isel-at-O=-1",
62		"-fast-isel=false",
63	}
64
65	cfiBlocklistPath     = "external/compiler-rt/lib/cfi"
66	cfiBlocklistFilename = "cfi_blocklist.txt"
67	cfiCrossDsoFlag      = "-fsanitize-cfi-cross-dso"
68	cfiCflags            = []string{"-flto", cfiCrossDsoFlag,
69		"-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
70	// -flto and -fvisibility are required by clang when -fsanitize=cfi is
71	// used, but have no effect on assembly files
72	cfiAsflags = []string{"-flto", "-fvisibility=default"}
73	cfiLdflags = []string{"-flto", cfiCrossDsoFlag, "-fsanitize=cfi",
74		"-Wl,-plugin-opt,O1"}
75	cfiExportsMapPath      = "build/soong/cc/config"
76	cfiExportsMapFilename  = "cfi_exports.map"
77	cfiAssemblySupportFlag = "-fno-sanitize-cfi-canonical-jump-tables"
78
79	intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
80
81	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
82		"-fno-sanitize-recover=integer,undefined"}
83	hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
84		"export_memory_stats=0", "max_malloc_fill_size=131072", "malloc_fill_byte=0"}
85	memtagStackCommonFlags = []string{"-march=armv8-a+memtag", "-mllvm", "-dom-tree-reachability-max-bbs-to-explore=128"}
86
87	hostOnlySanitizeFlags   = []string{"-fno-sanitize-recover=all"}
88	deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all", "-ftrap-function=abort"}
89)
90
91type SanitizerType int
92
93const (
94	Asan SanitizerType = iota + 1
95	Hwasan
96	tsan
97	intOverflow
98	scs
99	Fuzzer
100	Memtag_heap
101	Memtag_stack
102	cfi // cfi is last to prevent it running before incompatible mutators
103)
104
105var Sanitizers = []SanitizerType{
106	Asan,
107	Hwasan,
108	tsan,
109	intOverflow,
110	scs,
111	Fuzzer,
112	Memtag_heap,
113	Memtag_stack,
114	cfi, // cfi is last to prevent it running before incompatible mutators
115}
116
117// Name of the sanitizer variation for this sanitizer type
118func (t SanitizerType) variationName() string {
119	switch t {
120	case Asan:
121		return "asan"
122	case Hwasan:
123		return "hwasan"
124	case tsan:
125		return "tsan"
126	case intOverflow:
127		return "intOverflow"
128	case cfi:
129		return "cfi"
130	case scs:
131		return "scs"
132	case Memtag_heap:
133		return "memtag_heap"
134	case Memtag_stack:
135		return "memtag_stack"
136	case Fuzzer:
137		return "fuzzer"
138	default:
139		panic(fmt.Errorf("unknown SanitizerType %d", t))
140	}
141}
142
143// This is the sanitizer names in SANITIZE_[TARGET|HOST]
144func (t SanitizerType) name() string {
145	switch t {
146	case Asan:
147		return "address"
148	case Hwasan:
149		return "hwaddress"
150	case Memtag_heap:
151		return "memtag_heap"
152	case Memtag_stack:
153		return "memtag_stack"
154	case tsan:
155		return "thread"
156	case intOverflow:
157		return "integer_overflow"
158	case cfi:
159		return "cfi"
160	case scs:
161		return "shadow-call-stack"
162	case Fuzzer:
163		return "fuzzer"
164	default:
165		panic(fmt.Errorf("unknown SanitizerType %d", t))
166	}
167}
168
169func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) {
170	switch t {
171	case cfi, Hwasan, Asan, tsan, Fuzzer, scs:
172		sanitizer := &sanitizerSplitMutator{t}
173		ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
174		ctx.Transition(t.variationName(), sanitizer)
175	case Memtag_heap, Memtag_stack, intOverflow:
176		// do nothing
177	default:
178		panic(fmt.Errorf("unknown SanitizerType %d", t))
179	}
180}
181
182// shouldPropagateToSharedLibraryDeps returns whether a sanitizer type should propagate to share
183// dependencies. In most cases, sanitizers only propagate to static dependencies; however, some
184// sanitizers also must be enabled for shared libraries for linking.
185func (t SanitizerType) shouldPropagateToSharedLibraryDeps() bool {
186	switch t {
187	case Fuzzer:
188		// Typically, shared libs are not split. However, for fuzzer, we split even for shared libs
189		// because a library sanitized for fuzzer can't be linked from a library that isn't sanitized
190		// for fuzzer.
191		return true
192	default:
193		return false
194	}
195}
196func (*Module) SanitizerSupported(t SanitizerType) bool {
197	switch t {
198	case Asan:
199		return true
200	case Hwasan:
201		return true
202	case tsan:
203		return true
204	case intOverflow:
205		return true
206	case cfi:
207		return true
208	case scs:
209		return true
210	case Fuzzer:
211		return true
212	case Memtag_heap:
213		return true
214	case Memtag_stack:
215		return true
216	default:
217		return false
218	}
219}
220
221// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
222func (t SanitizerType) incompatibleWithCfi() bool {
223	return t == Asan || t == Fuzzer || t == Hwasan
224}
225
226type SanitizeUserProps struct {
227	// Prevent use of any sanitizers on this module
228	Never *bool `android:"arch_variant"`
229
230	// ASan (Address sanitizer), incompatible with static binaries.
231	// Always runs in a diagnostic mode.
232	// Use of address sanitizer disables cfi sanitizer.
233	// Hwaddress sanitizer takes precedence over this sanitizer.
234	Address *bool `android:"arch_variant"`
235	// TSan (Thread sanitizer), incompatible with static binaries and 32 bit architectures.
236	// Always runs in a diagnostic mode.
237	// Use of thread sanitizer disables cfi and scudo sanitizers.
238	// Hwaddress sanitizer takes precedence over this sanitizer.
239	Thread *bool `android:"arch_variant"`
240	// HWASan (Hardware Address sanitizer).
241	// Use of hwasan sanitizer disables cfi, address, thread, and scudo sanitizers.
242	Hwaddress *bool `android:"arch_variant"`
243
244	// Undefined behavior sanitizer
245	All_undefined *bool `android:"arch_variant"`
246	// Subset of undefined behavior sanitizer
247	Undefined *bool `android:"arch_variant"`
248	// List of specific undefined behavior sanitizers to enable
249	Misc_undefined []string `android:"arch_variant"`
250	// Fuzzer, incompatible with static binaries.
251	Fuzzer *bool `android:"arch_variant"`
252	// safe-stack sanitizer, incompatible with 32-bit architectures.
253	Safestack *bool `android:"arch_variant"`
254	// cfi sanitizer, incompatible with asan, hwasan, fuzzer, or Darwin
255	Cfi *bool `android:"arch_variant"`
256	// signed/unsigned integer overflow sanitizer, incompatible with Darwin.
257	Integer_overflow *bool `android:"arch_variant"`
258	// scudo sanitizer, incompatible with asan, hwasan, tsan
259	// This should not be used in Android 11+ : https://source.android.com/devices/tech/debug/scudo
260	// deprecated
261	Scudo *bool `android:"arch_variant"`
262	// shadow-call-stack sanitizer, only available on arm64/riscv64.
263	Scs *bool `android:"arch_variant"`
264	// Memory-tagging, only available on arm64
265	// if diag.memtag unset or false, enables async memory tagging
266	Memtag_heap *bool `android:"arch_variant"`
267	// Memory-tagging stack instrumentation, only available on arm64
268	// Adds instrumentation to detect stack buffer overflows and use-after-scope using MTE.
269	Memtag_stack *bool `android:"arch_variant"`
270
271	// A modifier for ASAN and HWASAN for write only instrumentation
272	Writeonly *bool `android:"arch_variant"`
273
274	// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
275	// Replaces abort() on error with a human-readable error message.
276	// Address and Thread sanitizers always run in diagnostic mode.
277	Diag struct {
278		// Undefined behavior sanitizer, diagnostic mode
279		Undefined *bool `android:"arch_variant"`
280		// cfi sanitizer, diagnostic mode, incompatible with asan, hwasan, fuzzer, or Darwin
281		Cfi *bool `android:"arch_variant"`
282		// signed/unsigned integer overflow sanitizer, diagnostic mode, incompatible with Darwin.
283		Integer_overflow *bool `android:"arch_variant"`
284		// Memory-tagging, only available on arm64
285		// requires sanitizer.memtag: true
286		// if set, enables sync memory tagging
287		Memtag_heap *bool `android:"arch_variant"`
288		// List of specific undefined behavior sanitizers to enable in diagnostic mode
289		Misc_undefined []string `android:"arch_variant"`
290		// List of sanitizers to pass to -fno-sanitize-recover
291		// results in only the first detected error for these sanitizers being reported and program then
292		// exits with a non-zero exit code.
293		No_recover []string `android:"arch_variant"`
294	} `android:"arch_variant"`
295
296	// Sanitizers to run with flag configuration specified
297	Config struct {
298		// Enables CFI support flags for assembly-heavy libraries
299		Cfi_assembly_support *bool `android:"arch_variant"`
300	} `android:"arch_variant"`
301
302	// List of sanitizers to pass to -fsanitize-recover
303	// allows execution to continue for these sanitizers to detect multiple errors rather than only
304	// the first one
305	Recover []string
306
307	// value to pass to -fsanitize-ignorelist
308	Blocklist *string
309}
310
311type sanitizeMutatedProperties struct {
312	// Whether sanitizers can be enabled on this module
313	Never *bool `blueprint:"mutated"`
314
315	// Whether ASan (Address sanitizer) is enabled for this module.
316	// Hwaddress sanitizer takes precedence over this sanitizer.
317	Address *bool `blueprint:"mutated"`
318	// Whether TSan (Thread sanitizer) is enabled for this module
319	Thread *bool `blueprint:"mutated"`
320	// Whether HWASan (Hardware Address sanitizer) is enabled for this module
321	Hwaddress *bool `blueprint:"mutated"`
322
323	// Whether Undefined behavior sanitizer is enabled for this module
324	All_undefined *bool `blueprint:"mutated"`
325	// Whether undefined behavior sanitizer subset is enabled for this module
326	Undefined *bool `blueprint:"mutated"`
327	// List of specific undefined behavior sanitizers enabled for this module
328	Misc_undefined []string `blueprint:"mutated"`
329	// Whether Fuzzeris enabled for this module
330	Fuzzer *bool `blueprint:"mutated"`
331	// whether safe-stack sanitizer is enabled for this module
332	Safestack *bool `blueprint:"mutated"`
333	// Whether cfi sanitizer is enabled for this module
334	Cfi *bool `blueprint:"mutated"`
335	// Whether signed/unsigned integer overflow sanitizer is enabled for this module
336	Integer_overflow *bool `blueprint:"mutated"`
337	// Whether scudo sanitizer is enabled for this module
338	Scudo *bool `blueprint:"mutated"`
339	// Whether shadow-call-stack sanitizer is enabled for this module.
340	Scs *bool `blueprint:"mutated"`
341	// Whether Memory-tagging is enabled for this module
342	Memtag_heap *bool `blueprint:"mutated"`
343	// Whether Memory-tagging stack instrumentation is enabled for this module
344	Memtag_stack *bool `blueprint:"mutated"`
345
346	// Whether a modifier for ASAN and HWASAN for write only instrumentation is enabled for this
347	// module
348	Writeonly *bool `blueprint:"mutated"`
349
350	// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
351	Diag struct {
352		// Whether Undefined behavior sanitizer, diagnostic mode is enabled for this module
353		Undefined *bool `blueprint:"mutated"`
354		// Whether cfi sanitizer, diagnostic mode is enabled for this module
355		Cfi *bool `blueprint:"mutated"`
356		// Whether signed/unsigned integer overflow sanitizer, diagnostic mode is enabled for this
357		// module
358		Integer_overflow *bool `blueprint:"mutated"`
359		// Whether Memory-tagging, diagnostic mode is enabled for this module
360		Memtag_heap *bool `blueprint:"mutated"`
361		// List of specific undefined behavior sanitizers enabled in diagnostic mode
362		Misc_undefined []string `blueprint:"mutated"`
363	} `blueprint:"mutated"`
364}
365
366type SanitizeProperties struct {
367	Sanitize        SanitizeUserProps         `android:"arch_variant"`
368	SanitizeMutated sanitizeMutatedProperties `blueprint:"mutated"`
369
370	SanitizerEnabled  bool     `blueprint:"mutated"`
371	MinimalRuntimeDep bool     `blueprint:"mutated"`
372	BuiltinsDep       bool     `blueprint:"mutated"`
373	UbsanRuntimeDep   bool     `blueprint:"mutated"`
374	InSanitizerDir    bool     `blueprint:"mutated"`
375	Sanitizers        []string `blueprint:"mutated"`
376	DiagSanitizers    []string `blueprint:"mutated"`
377}
378
379type sanitize struct {
380	Properties SanitizeProperties
381}
382
383// Mark this tag with a check to see if apex dependency check should be skipped
384func (t libraryDependencyTag) SkipApexAllowedDependenciesCheck() bool {
385	return t.skipApexAllowedDependenciesCheck
386}
387
388var _ android.SkipApexAllowedDependenciesCheck = (*libraryDependencyTag)(nil)
389
390var exportedVars = android.NewExportedVariables(pctx)
391
392func init() {
393	exportedVars.ExportStringListStaticVariable("HostOnlySanitizeFlags", hostOnlySanitizeFlags)
394	exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
395
396	// Leave out "-flto" from the slices exported to bazel, as we will use the
397	// dedicated LTO feature for this. For C Flags and Linker Flags, also leave
398	// out the cross DSO flag which will be added separately by transitions.
399	exportedVars.ExportStringList("CfiCFlags", cfiCflags[2:])
400	exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[2:])
401	exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
402
403	exportedVars.ExportString("CfiCrossDsoFlag", cfiCrossDsoFlag)
404	exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
405	exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
406	exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
407	exportedVars.ExportString("CfiExportsMapFilename", cfiExportsMapFilename)
408	exportedVars.ExportString("CfiAssemblySupportFlag", cfiAssemblySupportFlag)
409
410	android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
411	android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
412}
413
414func (sanitize *sanitize) props() []interface{} {
415	return []interface{}{&sanitize.Properties}
416}
417
418func (p *sanitizeMutatedProperties) copyUserPropertiesToMutated(userProps *SanitizeUserProps) {
419	p.Never = userProps.Never
420	p.Address = userProps.Address
421	p.All_undefined = userProps.All_undefined
422	p.Cfi = userProps.Cfi
423	p.Fuzzer = userProps.Fuzzer
424	p.Hwaddress = userProps.Hwaddress
425	p.Integer_overflow = userProps.Integer_overflow
426	p.Memtag_heap = userProps.Memtag_heap
427	p.Memtag_stack = userProps.Memtag_stack
428	p.Safestack = userProps.Safestack
429	p.Scs = userProps.Scs
430	p.Scudo = userProps.Scudo
431	p.Thread = userProps.Thread
432	p.Undefined = userProps.Undefined
433	p.Writeonly = userProps.Writeonly
434
435	p.Misc_undefined = make([]string, 0, len(userProps.Misc_undefined))
436	for _, v := range userProps.Misc_undefined {
437		p.Misc_undefined = append(p.Misc_undefined, v)
438	}
439
440	p.Diag.Cfi = userProps.Diag.Cfi
441	p.Diag.Integer_overflow = userProps.Diag.Integer_overflow
442	p.Diag.Memtag_heap = userProps.Diag.Memtag_heap
443	p.Diag.Undefined = userProps.Diag.Undefined
444
445	p.Diag.Misc_undefined = make([]string, 0, len(userProps.Diag.Misc_undefined))
446	for _, v := range userProps.Diag.Misc_undefined {
447		p.Diag.Misc_undefined = append(p.Diag.Misc_undefined, v)
448	}
449}
450
451func (sanitize *sanitize) begin(ctx BaseModuleContext) {
452	s := &sanitize.Properties.SanitizeMutated
453	s.copyUserPropertiesToMutated(&sanitize.Properties.Sanitize)
454
455	// Don't apply sanitizers to NDK code.
456	if ctx.useSdk() {
457		s.Never = BoolPtr(true)
458	}
459
460	// Never always wins.
461	if Bool(s.Never) {
462		return
463	}
464
465	// cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap: false}).
466	if ctx.testBinary() {
467		if s.Memtag_heap == nil {
468			s.Memtag_heap = proptools.BoolPtr(true)
469		}
470		if s.Diag.Memtag_heap == nil {
471			s.Diag.Memtag_heap = proptools.BoolPtr(true)
472		}
473	}
474
475	var globalSanitizers []string
476	var globalSanitizersDiag []string
477
478	if ctx.Host() {
479		if !ctx.Windows() {
480			globalSanitizers = ctx.Config().SanitizeHost()
481		}
482	} else {
483		arches := ctx.Config().SanitizeDeviceArch()
484		if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
485			globalSanitizers = ctx.Config().SanitizeDevice()
486			globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
487		}
488	}
489
490	if len(globalSanitizers) > 0 {
491		var found bool
492		if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil {
493			s.All_undefined = proptools.BoolPtr(true)
494		}
495
496		if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil {
497			s.Undefined = proptools.BoolPtr(true)
498		}
499
500		if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil {
501			s.Address = proptools.BoolPtr(true)
502		}
503
504		if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
505			s.Thread = proptools.BoolPtr(true)
506		}
507
508		if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
509			s.Fuzzer = proptools.BoolPtr(true)
510		}
511
512		if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
513			s.Safestack = proptools.BoolPtr(true)
514		}
515
516		if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil {
517			if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) {
518				s.Cfi = proptools.BoolPtr(true)
519			}
520		}
521
522		// Global integer_overflow builds do not support static libraries.
523		if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil {
524			if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && !ctx.static() {
525				s.Integer_overflow = proptools.BoolPtr(true)
526			}
527		}
528
529		if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil {
530			s.Scudo = proptools.BoolPtr(true)
531		}
532
533		if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
534			s.Hwaddress = proptools.BoolPtr(true)
535		}
536
537		if found, globalSanitizers = removeFromList("writeonly", globalSanitizers); found && s.Writeonly == nil {
538			// Hwaddress and Address are set before, so we can check them here
539			// If they aren't explicitly set in the blueprint/SANITIZE_(HOST|TARGET), they would be nil instead of false
540			if s.Address == nil && s.Hwaddress == nil {
541				ctx.ModuleErrorf("writeonly modifier cannot be used without 'address' or 'hwaddress'")
542			}
543			s.Writeonly = proptools.BoolPtr(true)
544		}
545		if found, globalSanitizers = removeFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil {
546			if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) {
547				s.Memtag_heap = proptools.BoolPtr(true)
548			}
549		}
550
551		if found, globalSanitizers = removeFromList("memtag_stack", globalSanitizers); found && s.Memtag_stack == nil {
552			s.Memtag_stack = proptools.BoolPtr(true)
553		}
554
555		if len(globalSanitizers) > 0 {
556			ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
557		}
558
559		// Global integer_overflow builds do not support static library diagnostics.
560		if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found &&
561			s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) && !ctx.static() {
562			s.Diag.Integer_overflow = proptools.BoolPtr(true)
563		}
564
565		if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found &&
566			s.Diag.Cfi == nil && Bool(s.Cfi) {
567			s.Diag.Cfi = proptools.BoolPtr(true)
568		}
569
570		if found, globalSanitizersDiag = removeFromList("memtag_heap", globalSanitizersDiag); found &&
571			s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) {
572			s.Diag.Memtag_heap = proptools.BoolPtr(true)
573		}
574
575		if len(globalSanitizersDiag) > 0 {
576			ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0])
577		}
578	}
579
580	// Enable Memtag for all components in the include paths (for Aarch64 only)
581	if ctx.Arch().ArchType == android.Arm64 && ctx.toolchain().Bionic() {
582		if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
583			if s.Memtag_heap == nil {
584				s.Memtag_heap = proptools.BoolPtr(true)
585			}
586			if s.Diag.Memtag_heap == nil {
587				s.Diag.Memtag_heap = proptools.BoolPtr(true)
588			}
589		} else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) {
590			if s.Memtag_heap == nil {
591				s.Memtag_heap = proptools.BoolPtr(true)
592			}
593		}
594	}
595
596	// Enable HWASan for all components in the include paths (for Aarch64 only)
597	if s.Hwaddress == nil && ctx.Config().HWASanEnabledForPath(ctx.ModuleDir()) &&
598		ctx.Arch().ArchType == android.Arm64 && ctx.toolchain().Bionic() {
599		s.Hwaddress = proptools.BoolPtr(true)
600	}
601
602	// Enable CFI for non-host components in the include paths
603	if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && !ctx.Host() {
604		s.Cfi = proptools.BoolPtr(true)
605		if inList("cfi", ctx.Config().SanitizeDeviceDiag()) {
606			s.Diag.Cfi = proptools.BoolPtr(true)
607		}
608	}
609
610	// Is CFI actually enabled?
611	if !ctx.Config().EnableCFI() {
612		s.Cfi = nil
613		s.Diag.Cfi = nil
614	}
615
616	// HWASan requires AArch64 hardware feature (top-byte-ignore).
617	if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() {
618		s.Hwaddress = nil
619	}
620
621	// SCS is only implemented on AArch64/riscv64.
622	if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() {
623		s.Scs = nil
624	}
625	// ...but temporarily globally disabled on riscv64 (http://b/277909695).
626	if ctx.Arch().ArchType == android.Riscv64 {
627		s.Scs = nil
628	}
629
630	// Memtag_heap is only implemented on AArch64.
631	// Memtag ABI is Android specific for now, so disable for host.
632	if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() || ctx.Host() {
633		s.Memtag_heap = nil
634		s.Memtag_stack = nil
635	}
636
637	// Also disable CFI if ASAN is enabled.
638	if Bool(s.Address) || Bool(s.Hwaddress) {
639		s.Cfi = nil
640		s.Diag.Cfi = nil
641		// HWASAN and ASAN win against MTE.
642		s.Memtag_heap = nil
643		s.Memtag_stack = nil
644	}
645
646	// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
647	if !ctx.Os().Linux() {
648		s.Cfi = nil
649		s.Diag.Cfi = nil
650		s.Misc_undefined = nil
651		s.Undefined = nil
652		s.All_undefined = nil
653		s.Integer_overflow = nil
654	}
655
656	// TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work.
657	if ctx.Arch().ArchType == android.Riscv64 {
658		s.Cfi = nil
659		s.Diag.Cfi = nil
660	}
661
662	// Disable CFI for musl
663	if ctx.toolchain().Musl() {
664		s.Cfi = nil
665		s.Diag.Cfi = nil
666	}
667
668	// Also disable CFI for VNDK variants of components
669	if ctx.isVndk() && ctx.useVndk() {
670		s.Cfi = nil
671		s.Diag.Cfi = nil
672	}
673
674	// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
675	// Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
676	if (ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
677		s.Hwaddress = nil
678	}
679
680	if ctx.staticBinary() {
681		s.Address = nil
682		s.Fuzzer = nil
683		s.Thread = nil
684	}
685
686	if Bool(s.All_undefined) {
687		s.Undefined = nil
688	}
689
690	if !ctx.toolchain().Is64Bit() {
691		// TSAN and SafeStack are not supported on 32-bit architectures
692		s.Thread = nil
693		s.Safestack = nil
694		// TODO(ccross): error for compile_multilib = "32"?
695	}
696
697	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
698		Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
699		Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap) || Bool(s.Memtag_stack)) {
700		sanitize.Properties.SanitizerEnabled = true
701	}
702
703	// Disable Scudo if ASan or TSan is enabled, or if it's disabled globally.
704	if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) || ctx.Config().DisableScudo() {
705		s.Scudo = nil
706	}
707
708	if Bool(s.Hwaddress) {
709		s.Address = nil
710		s.Thread = nil
711	}
712
713	// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
714	// mutually incompatible.
715	if Bool(s.Fuzzer) {
716		s.Cfi = nil
717	}
718}
719
720func toDisableImplicitIntegerChange(flags []string) bool {
721	// Returns true if any flag is fsanitize*integer, and there is
722	// no explicit flag about sanitize=implicit-integer-sign-change.
723	for _, f := range flags {
724		if strings.Contains(f, "sanitize=implicit-integer-sign-change") {
725			return false
726		}
727	}
728	for _, f := range flags {
729		if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
730			return true
731		}
732	}
733	return false
734}
735
736func toDisableUnsignedShiftBaseChange(flags []string) bool {
737	// Returns true if any flag is fsanitize*integer, and there is
738	// no explicit flag about sanitize=unsigned-shift-base.
739	for _, f := range flags {
740		if strings.Contains(f, "sanitize=unsigned-shift-base") {
741			return false
742		}
743	}
744	for _, f := range flags {
745		if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
746			return true
747		}
748	}
749	return false
750}
751
752func (s *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
753	if !s.Properties.SanitizerEnabled && !s.Properties.UbsanRuntimeDep {
754		return flags
755	}
756	sanProps := &s.Properties.SanitizeMutated
757
758	if Bool(sanProps.Address) {
759		if ctx.Arch().ArchType == android.Arm {
760			// Frame pointer based unwinder in ASan requires ARM frame setup.
761			// TODO: put in flags?
762			flags.RequiredInstructionSet = "arm"
763		}
764		flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...)
765		flags.Local.LdFlags = append(flags.Local.LdFlags, asanLdflags...)
766
767		if Bool(sanProps.Writeonly) {
768			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-instrument-reads=0")
769		}
770
771		if ctx.Host() {
772			// -nodefaultlibs (provided with libc++) prevents the driver from linking
773			// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
774			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-as-needed")
775		} else {
776			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-globals=0")
777			if ctx.bootstrap() {
778				flags.DynamicLinker = "/system/bin/bootstrap/linker_asan"
779			} else {
780				flags.DynamicLinker = "/system/bin/linker_asan"
781			}
782			if flags.Toolchain.Is64Bit() {
783				flags.DynamicLinker += "64"
784			}
785		}
786	}
787
788	if Bool(sanProps.Hwaddress) {
789		flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
790
791		for _, flag := range hwasanCommonflags {
792			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag)
793		}
794		for _, flag := range hwasanCommonflags {
795			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
796		}
797
798		if Bool(sanProps.Writeonly) {
799			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
800		}
801		if !ctx.staticBinary() && !ctx.Host() {
802			if ctx.bootstrap() {
803				flags.DynamicLinker = "/system/bin/bootstrap/linker_hwasan64"
804			} else {
805				flags.DynamicLinker = "/system/bin/linker_hwasan64"
806			}
807		}
808	}
809
810	if Bool(sanProps.Fuzzer) {
811		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize=fuzzer-no-link")
812
813		// TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
814		_, flags.Local.LdFlags = removeFromList("-flto", flags.Local.LdFlags)
815		_, flags.Local.CFlags = removeFromList("-flto", flags.Local.CFlags)
816		flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-lto")
817		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-lto")
818
819		// TODO(b/142430592): Upstream linker scripts for sanitizer runtime libraries
820		// discard the sancov_lowest_stack symbol, because it's emulated TLS (and thus
821		// doesn't match the linker script due to the "__emutls_v." prefix).
822		flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth")
823		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth")
824
825		// Disable fortify for fuzzing builds. Generally, we'll be building with
826		// UBSan or ASan here and the fortify checks pollute the stack traces.
827		flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE")
828
829		// Build fuzzer-sanitized libraries with an $ORIGIN DT_RUNPATH. Android's
830		// linker uses DT_RUNPATH, not DT_RPATH. When we deploy cc_fuzz targets and
831		// their libraries to /data/fuzz/<arch>/lib, any transient shared library gets
832		// the DT_RUNPATH from the shared library above it, and not the executable,
833		// meaning that the lookup falls back to the system. Adding the $ORIGIN to the
834		// DT_RUNPATH here means that transient shared libraries can be found
835		// colocated with their parents.
836		flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN`)
837	}
838
839	if Bool(sanProps.Cfi) {
840		if ctx.Arch().ArchType == android.Arm {
841			// __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
842			// to do this on a function basis, so force Thumb on the entire module.
843			flags.RequiredInstructionSet = "thumb"
844		}
845
846		flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
847		flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
848		if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
849			flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag)
850		}
851		// Only append the default visibility flag if -fvisibility has not already been set
852		// to hidden.
853		if !inList("-fvisibility=hidden", flags.Local.CFlags) {
854			flags.Local.CFlags = append(flags.Local.CFlags, "-fvisibility=default")
855		}
856		flags.Local.LdFlags = append(flags.Local.LdFlags, cfiLdflags...)
857
858		if ctx.staticBinary() {
859			_, flags.Local.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.CFlags)
860			_, flags.Local.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.LdFlags)
861		}
862	}
863
864	if Bool(sanProps.Memtag_stack) {
865		flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...)
866		// TODO(fmayer): remove -Wno-error once https://reviews.llvm.org/D127917 is in Android toolchain.
867		flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-error=frame-larger-than")
868		flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...)
869		flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...)
870		// This works around LLD complaining about the stack frame size.
871		// TODO(fmayer): remove once https://reviews.llvm.org/D127917 is in Android toolchain.
872		flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-fatal-warnings")
873	}
874
875	if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack)) && ctx.binary() {
876		if Bool(sanProps.Diag.Memtag_heap) {
877			flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=sync")
878		} else {
879			flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=async")
880		}
881	}
882
883	if Bool(sanProps.Integer_overflow) {
884		flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...)
885	}
886
887	if len(s.Properties.Sanitizers) > 0 {
888		sanitizeArg := "-fsanitize=" + strings.Join(s.Properties.Sanitizers, ",")
889		flags.Local.CFlags = append(flags.Local.CFlags, sanitizeArg)
890		flags.Local.AsFlags = append(flags.Local.AsFlags, sanitizeArg)
891		flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg)
892
893		if ctx.toolchain().Bionic() || ctx.toolchain().Musl() {
894			// Bionic and musl sanitizer runtimes have already been added as dependencies so that
895			// the right variant of the runtime will be used (with the "-android" or "-musl"
896			// suffixes), so don't let clang the runtime library.
897			flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-link-runtime")
898		} else {
899			// Host sanitizers only link symbols in the final executable, so
900			// there will always be undefined symbols in intermediate libraries.
901			_, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags)
902		}
903
904		if !ctx.toolchain().Bionic() {
905			// non-Bionic toolchain prebuilts are missing UBSan's vptr and function san.
906			// Musl toolchain prebuilts have vptr and function sanitizers, but enabling them
907			// implicitly enables RTTI which causes RTTI mismatch issues with dependencies.
908
909			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function")
910		}
911
912		if Bool(sanProps.Fuzzer) {
913			// When fuzzing, we wish to crash with diagnostics on any bug.
914			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
915		} else if ctx.Host() {
916			flags.Local.CFlags = append(flags.Local.CFlags, hostOnlySanitizeFlags...)
917		} else {
918			flags.Local.CFlags = append(flags.Local.CFlags, deviceOnlySanitizeFlags...)
919		}
920
921		if enableMinimalRuntime(s) {
922			flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " "))
923		}
924
925		// http://b/119329758, Android core does not boot up with this sanitizer yet.
926		if toDisableImplicitIntegerChange(flags.Local.CFlags) {
927			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change")
928		}
929		// http://b/171275751, Android doesn't build with this sanitizer yet.
930		if toDisableUnsignedShiftBaseChange(flags.Local.CFlags) {
931			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=unsigned-shift-base")
932		}
933	}
934
935	if len(s.Properties.DiagSanitizers) > 0 {
936		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(s.Properties.DiagSanitizers, ","))
937	}
938	// FIXME: enable RTTI if diag + (cfi or vptr)
939
940	if s.Properties.Sanitize.Recover != nil {
941		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-recover="+
942			strings.Join(s.Properties.Sanitize.Recover, ","))
943	}
944
945	if s.Properties.Sanitize.Diag.No_recover != nil {
946		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover="+
947			strings.Join(s.Properties.Sanitize.Diag.No_recover, ","))
948	}
949
950	blocklist := android.OptionalPathForModuleSrc(ctx, s.Properties.Sanitize.Blocklist)
951	if blocklist.Valid() {
952		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-ignorelist="+blocklist.String())
953		flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path())
954	}
955
956	return flags
957}
958
959func (s *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
960	// Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing
961	// both the sanitized and non-sanitized variants to make without a name conflict.
962	if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" {
963		if Bool(s.Properties.SanitizeMutated.Cfi) {
964			entries.SubName += ".cfi"
965		}
966		if Bool(s.Properties.SanitizeMutated.Hwaddress) {
967			entries.SubName += ".hwasan"
968		}
969		if Bool(s.Properties.SanitizeMutated.Scs) {
970			entries.SubName += ".scs"
971		}
972	}
973}
974
975func (s *sanitize) inSanitizerDir() bool {
976	return s.Properties.InSanitizerDir
977}
978
979// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties.
980func (s *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
981	switch t {
982	case Asan:
983		return s.Properties.SanitizeMutated.Address
984	case Hwasan:
985		return s.Properties.SanitizeMutated.Hwaddress
986	case tsan:
987		return s.Properties.SanitizeMutated.Thread
988	case intOverflow:
989		return s.Properties.SanitizeMutated.Integer_overflow
990	case cfi:
991		return s.Properties.SanitizeMutated.Cfi
992	case scs:
993		return s.Properties.SanitizeMutated.Scs
994	case Memtag_heap:
995		return s.Properties.SanitizeMutated.Memtag_heap
996	case Memtag_stack:
997		return s.Properties.SanitizeMutated.Memtag_stack
998	case Fuzzer:
999		return s.Properties.SanitizeMutated.Fuzzer
1000	default:
1001		panic(fmt.Errorf("unknown SanitizerType %d", t))
1002	}
1003}
1004
1005// isUnsanitizedVariant returns true if no sanitizers are enabled.
1006func (sanitize *sanitize) isUnsanitizedVariant() bool {
1007	return !sanitize.isSanitizerEnabled(Asan) &&
1008		!sanitize.isSanitizerEnabled(Hwasan) &&
1009		!sanitize.isSanitizerEnabled(tsan) &&
1010		!sanitize.isSanitizerEnabled(cfi) &&
1011		!sanitize.isSanitizerEnabled(scs) &&
1012		!sanitize.isSanitizerEnabled(Memtag_heap) &&
1013		!sanitize.isSanitizerEnabled(Memtag_stack) &&
1014		!sanitize.isSanitizerEnabled(Fuzzer)
1015}
1016
1017// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
1018func (sanitize *sanitize) isVariantOnProductionDevice() bool {
1019	return !sanitize.isSanitizerEnabled(Asan) &&
1020		!sanitize.isSanitizerEnabled(Hwasan) &&
1021		!sanitize.isSanitizerEnabled(tsan) &&
1022		!sanitize.isSanitizerEnabled(Fuzzer)
1023}
1024
1025func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) {
1026	bPtr := proptools.BoolPtr(b)
1027	if !b {
1028		bPtr = nil
1029	}
1030	switch t {
1031	case Asan:
1032		sanitize.Properties.SanitizeMutated.Address = bPtr
1033		// For ASAN variant, we need to disable Memtag_stack
1034		sanitize.Properties.SanitizeMutated.Memtag_stack = nil
1035	case Hwasan:
1036		sanitize.Properties.SanitizeMutated.Hwaddress = bPtr
1037		// For HWAsan variant, we need to disable Memtag_stack
1038		sanitize.Properties.SanitizeMutated.Memtag_stack = nil
1039	case tsan:
1040		sanitize.Properties.SanitizeMutated.Thread = bPtr
1041	case intOverflow:
1042		sanitize.Properties.SanitizeMutated.Integer_overflow = bPtr
1043	case cfi:
1044		sanitize.Properties.SanitizeMutated.Cfi = bPtr
1045	case scs:
1046		sanitize.Properties.SanitizeMutated.Scs = bPtr
1047	case Memtag_heap:
1048		sanitize.Properties.SanitizeMutated.Memtag_heap = bPtr
1049	case Memtag_stack:
1050		sanitize.Properties.SanitizeMutated.Memtag_stack = bPtr
1051		// We do not need to disable ASAN or HWASan here, as there is no Memtag_stack variant.
1052	case Fuzzer:
1053		sanitize.Properties.SanitizeMutated.Fuzzer = bPtr
1054	default:
1055		panic(fmt.Errorf("unknown SanitizerType %d", t))
1056	}
1057	if b {
1058		sanitize.Properties.SanitizerEnabled = true
1059	}
1060}
1061
1062// Check if the sanitizer is explicitly disabled (as opposed to nil by
1063// virtue of not being set).
1064func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool {
1065	if sanitize == nil {
1066		return false
1067	}
1068
1069	sanitizerVal := sanitize.getSanitizerBoolPtr(t)
1070	return sanitizerVal != nil && *sanitizerVal == false
1071}
1072
1073// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled)
1074// because enabling a sanitizer either directly (via the blueprint) or
1075// indirectly (via a mutator) sets the bool ptr to true, and you can't
1076// distinguish between the cases. It isn't needed though - both cases can be
1077// treated identically.
1078func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool {
1079	if sanitize == nil {
1080		return false
1081	}
1082
1083	sanitizerVal := sanitize.getSanitizerBoolPtr(t)
1084	return sanitizerVal != nil && *sanitizerVal == true
1085}
1086
1087// IsSanitizableDependencyTag returns true if the dependency tag is sanitizable.
1088func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
1089	switch t := tag.(type) {
1090	case dependencyTag:
1091		return t == reuseObjTag || t == objDepTag
1092	case libraryDependencyTag:
1093		return true
1094	default:
1095		return false
1096	}
1097}
1098
1099func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
1100	return IsSanitizableDependencyTag
1101}
1102
1103// Determines if the current module is a static library going to be captured
1104// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
1105// except for ones which explicitly disable cfi.
1106func needsCfiForVendorSnapshot(mctx android.BaseModuleContext) bool {
1107	if inList("hwaddress", mctx.Config().SanitizeDevice()) {
1108		// cfi will not be built if SANITIZE_TARGET=hwaddress is set
1109		return false
1110	}
1111
1112	if snapshot.IsVendorProprietaryModule(mctx) {
1113		return false
1114	}
1115
1116	c := mctx.Module().(PlatformSanitizeable)
1117
1118	if !c.InVendor() {
1119		return false
1120	}
1121
1122	if !c.StaticallyLinked() {
1123		return false
1124	}
1125
1126	if c.IsPrebuilt() {
1127		return false
1128	}
1129
1130	if !c.SanitizerSupported(cfi) {
1131		return false
1132	}
1133
1134	return c.SanitizePropDefined() &&
1135		!c.SanitizeNever() &&
1136		!c.IsSanitizerExplicitlyDisabled(cfi)
1137}
1138
1139type sanitizerSplitMutator struct {
1140	sanitizer SanitizerType
1141}
1142
1143// If an APEX is sanitized or not depends on whether it contains at least one
1144// sanitized module. Transition mutators cannot propagate information up the
1145// dependency graph this way, so we need an auxiliary mutator to do so.
1146func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.TopDownMutatorContext) {
1147	if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
1148		enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
1149		ctx.VisitDirectDeps(func(dep android.Module) {
1150			if c, ok := dep.(*Module); ok && c.sanitize.isSanitizerEnabled(s.sanitizer) {
1151				enabled = true
1152			}
1153		})
1154
1155		if enabled {
1156			sanitizeable.EnableSanitizer(s.sanitizer.name())
1157		}
1158	}
1159}
1160
1161func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string {
1162	if c, ok := ctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
1163		if s.sanitizer == cfi && needsCfiForVendorSnapshot(ctx) {
1164			return []string{"", s.sanitizer.variationName()}
1165		}
1166
1167		// If the given sanitizer is not requested in the .bp file for a module, it
1168		// won't automatically build the sanitized variation.
1169		if !c.IsSanitizerEnabled(s.sanitizer) {
1170			return []string{""}
1171		}
1172
1173		if c.Binary() {
1174			// If a sanitizer is enabled for a binary, we do not build the version
1175			// without the sanitizer
1176			return []string{s.sanitizer.variationName()}
1177		} else if c.StaticallyLinked() || c.Header() {
1178			// For static libraries, we build both versions. Some Make modules
1179			// apparently depend on this behavior.
1180			return []string{"", s.sanitizer.variationName()}
1181		} else {
1182			// We only build the requested variation of dynamic libraries
1183			return []string{s.sanitizer.variationName()}
1184		}
1185	}
1186
1187	if _, ok := ctx.Module().(JniSanitizeable); ok {
1188		// TODO: this should call into JniSanitizable.IsSanitizerEnabledForJni but
1189		// that is short-circuited for now
1190		return []string{""}
1191	}
1192
1193	// If an APEX has a sanitized dependency, we build the APEX in the sanitized
1194	// variation. This is useful because such APEXes require extra dependencies.
1195	if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
1196		enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
1197		if enabled {
1198			return []string{s.sanitizer.variationName()}
1199		} else {
1200			return []string{""}
1201		}
1202	}
1203
1204	if c, ok := ctx.Module().(*Module); ok {
1205		//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
1206
1207		// Check if it's a snapshot module supporting sanitizer
1208		if ss, ok := c.linker.(snapshotSanitizer); ok {
1209			if ss.isSanitizerAvailable(s.sanitizer) {
1210				return []string{"", s.sanitizer.variationName()}
1211			} else {
1212				return []string{""}
1213			}
1214		}
1215	}
1216
1217	return []string{""}
1218}
1219
1220func (s *sanitizerSplitMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
1221	if c, ok := ctx.Module().(PlatformSanitizeable); ok {
1222		if !c.SanitizableDepTagChecker()(ctx.DepTag()) {
1223			// If the dependency is through a non-sanitizable tag, use the
1224			// non-sanitized variation
1225			return ""
1226		}
1227
1228		return sourceVariation
1229	} else if _, ok := ctx.Module().(JniSanitizeable); ok {
1230		// TODO: this should call into JniSanitizable.IsSanitizerEnabledForJni but
1231		// that is short-circuited for now
1232		return ""
1233	} else {
1234		// Otherwise, do not rock the boat.
1235		return sourceVariation
1236	}
1237}
1238
1239func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
1240	if d, ok := ctx.Module().(PlatformSanitizeable); ok {
1241		if dm, ok := ctx.Module().(*Module); ok {
1242			if ss, ok := dm.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
1243				return incomingVariation
1244			}
1245		}
1246
1247		if !d.SanitizePropDefined() ||
1248			d.SanitizeNever() ||
1249			d.IsSanitizerExplicitlyDisabled(s.sanitizer) ||
1250			!d.SanitizerSupported(s.sanitizer) {
1251			// If a module opts out of a sanitizer, use its non-sanitized variation
1252			return ""
1253		}
1254
1255		// Binaries are always built in the variation they requested.
1256		if d.Binary() {
1257			if d.IsSanitizerEnabled(s.sanitizer) {
1258				return s.sanitizer.variationName()
1259			} else {
1260				return ""
1261			}
1262		}
1263
1264		// If a shared library requests to be sanitized, it will be built for that
1265		// sanitizer. Otherwise, some sanitizers propagate through shared library
1266		// dependency edges, some do not.
1267		if !d.StaticallyLinked() && !d.Header() {
1268			if d.IsSanitizerEnabled(s.sanitizer) {
1269				return s.sanitizer.variationName()
1270			}
1271
1272			// Some sanitizers do not propagate to shared dependencies
1273			if !s.sanitizer.shouldPropagateToSharedLibraryDeps() {
1274				return ""
1275			}
1276		}
1277
1278		// Static and header libraries inherit whether they are sanitized from the
1279		// module they are linked into
1280		return incomingVariation
1281	} else if d, ok := ctx.Module().(Sanitizeable); ok {
1282		// If an APEX contains a sanitized module, it will be built in the variation
1283		// corresponding to that sanitizer.
1284		enabled := d.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
1285		if enabled {
1286			return s.sanitizer.variationName()
1287		}
1288
1289		return incomingVariation
1290	}
1291
1292	return ""
1293}
1294
1295func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, variationName string) {
1296	sanitizerVariation := variationName == s.sanitizer.variationName()
1297
1298	if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
1299		sanitizerEnabled := c.IsSanitizerEnabled(s.sanitizer)
1300
1301		oneMakeVariation := false
1302		if c.StaticallyLinked() || c.Header() {
1303			if s.sanitizer != cfi && s.sanitizer != scs && s.sanitizer != Hwasan {
1304				// These sanitizers export only one variation to Make. For the rest,
1305				// Make targets can depend on both the sanitized and non-sanitized
1306				// versions.
1307				oneMakeVariation = true
1308			}
1309		} else if !c.Binary() {
1310			// Shared library. These are the sanitizers that do propagate through shared
1311			// library dependencies and therefore can cause multiple variations of a
1312			// shared library to be built.
1313			if s.sanitizer != cfi && s.sanitizer != Hwasan && s.sanitizer != scs && s.sanitizer != Asan {
1314				oneMakeVariation = true
1315			}
1316		}
1317
1318		if oneMakeVariation {
1319			if sanitizerEnabled != sanitizerVariation {
1320				c.SetPreventInstall()
1321				c.SetHideFromMake()
1322			}
1323		}
1324
1325		if sanitizerVariation {
1326			c.SetSanitizer(s.sanitizer, true)
1327
1328			// CFI is incompatible with ASAN so disable it in ASAN variations
1329			if s.sanitizer.incompatibleWithCfi() {
1330				cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
1331				if mctx.Device() && cfiSupported {
1332					c.SetSanitizer(cfi, false)
1333				}
1334			}
1335
1336			// locate the asan libraries under /data/asan
1337			if !c.Binary() && !c.StaticallyLinked() && !c.Header() && mctx.Device() && s.sanitizer == Asan && sanitizerEnabled {
1338				c.SetInSanitizerDir()
1339			}
1340
1341			if c.StaticallyLinked() && c.ExportedToMake() {
1342				if s.sanitizer == Hwasan {
1343					hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
1344				} else if s.sanitizer == cfi {
1345					cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
1346				}
1347			}
1348		} else if c.IsSanitizerEnabled(s.sanitizer) {
1349			// Disable the sanitizer for the non-sanitized variation
1350			c.SetSanitizer(s.sanitizer, false)
1351		}
1352	} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
1353		// If an APEX has sanitized dependencies, it gets a few more dependencies
1354		if sanitizerVariation {
1355			sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
1356		}
1357	} else if c, ok := mctx.Module().(*Module); ok {
1358		if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
1359			if !ss.isUnsanitizedVariant() {
1360				// Snapshot sanitizer may have only one variantion.
1361				// Skip exporting the module if it already has a sanitizer variation.
1362				c.SetPreventInstall()
1363				c.SetHideFromMake()
1364				return
1365			}
1366			c.linker.(snapshotSanitizer).setSanitizerVariation(s.sanitizer, sanitizerVariation)
1367
1368			// Export the static lib name to make
1369			if c.static() && c.ExportedToMake() {
1370				// use BaseModuleName which is the name for Make.
1371				if s.sanitizer == cfi {
1372					cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
1373				} else if s.sanitizer == Hwasan {
1374					hwasanStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
1375				}
1376			}
1377		}
1378	}
1379}
1380
1381func (c *Module) SanitizeNever() bool {
1382	return Bool(c.sanitize.Properties.SanitizeMutated.Never)
1383}
1384
1385func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool {
1386	return c.sanitize.isSanitizerExplicitlyDisabled(t)
1387}
1388
1389// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
1390func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
1391	// Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers.
1392	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
1393		isSanitizableDependencyTag := c.SanitizableDepTagChecker()
1394		mctx.WalkDeps(func(child, parent android.Module) bool {
1395			if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
1396				return false
1397			}
1398
1399			d, ok := child.(*Module)
1400			if !ok || !d.static() {
1401				return false
1402			}
1403			if d.sanitize != nil {
1404				if enableMinimalRuntime(d.sanitize) {
1405					// If a static dependency is built with the minimal runtime,
1406					// make sure we include the ubsan minimal runtime.
1407					c.sanitize.Properties.MinimalRuntimeDep = true
1408				} else if enableUbsanRuntime(d.sanitize) {
1409					// If a static dependency runs with full ubsan diagnostics,
1410					// make sure we include the ubsan runtime.
1411					c.sanitize.Properties.UbsanRuntimeDep = true
1412				}
1413
1414				if c.sanitize.Properties.MinimalRuntimeDep &&
1415					c.sanitize.Properties.UbsanRuntimeDep {
1416					// both flags that this mutator might set are true, so don't bother recursing
1417					return false
1418				}
1419
1420				if c.Os() == android.Linux {
1421					c.sanitize.Properties.BuiltinsDep = true
1422				}
1423
1424				return true
1425			}
1426
1427			if p, ok := d.linker.(*snapshotLibraryDecorator); ok {
1428				if Bool(p.properties.Sanitize_minimal_dep) {
1429					c.sanitize.Properties.MinimalRuntimeDep = true
1430				}
1431				if Bool(p.properties.Sanitize_ubsan_dep) {
1432					c.sanitize.Properties.UbsanRuntimeDep = true
1433				}
1434			}
1435
1436			return false
1437		})
1438	}
1439}
1440
1441// Add the dependency to the runtime library for each of the sanitizer variants
1442func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
1443	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
1444		if !c.Enabled() {
1445			return
1446		}
1447		var sanitizers []string
1448		var diagSanitizers []string
1449
1450		sanProps := &c.sanitize.Properties.SanitizeMutated
1451
1452		if Bool(sanProps.All_undefined) {
1453			sanitizers = append(sanitizers, "undefined")
1454		} else {
1455			if Bool(sanProps.Undefined) {
1456				sanitizers = append(sanitizers,
1457					"bool",
1458					"integer-divide-by-zero",
1459					"return",
1460					"returns-nonnull-attribute",
1461					"shift-exponent",
1462					"unreachable",
1463					"vla-bound",
1464					// TODO(danalbert): The following checks currently have compiler performance issues.
1465					//"alignment",
1466					//"bounds",
1467					//"enum",
1468					//"float-cast-overflow",
1469					//"float-divide-by-zero",
1470					//"nonnull-attribute",
1471					//"null",
1472					//"shift-base",
1473					//"signed-integer-overflow",
1474					// TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
1475					// https://llvm.org/PR19302
1476					// http://reviews.llvm.org/D6974
1477					// "object-size",
1478				)
1479			}
1480			sanitizers = append(sanitizers, sanProps.Misc_undefined...)
1481		}
1482
1483		if Bool(sanProps.Diag.Undefined) {
1484			diagSanitizers = append(diagSanitizers, "undefined")
1485		}
1486
1487		diagSanitizers = append(diagSanitizers, sanProps.Diag.Misc_undefined...)
1488
1489		if Bool(sanProps.Address) {
1490			sanitizers = append(sanitizers, "address")
1491			diagSanitizers = append(diagSanitizers, "address")
1492		}
1493
1494		if Bool(sanProps.Hwaddress) {
1495			sanitizers = append(sanitizers, "hwaddress")
1496		}
1497
1498		if Bool(sanProps.Thread) {
1499			sanitizers = append(sanitizers, "thread")
1500		}
1501
1502		if Bool(sanProps.Safestack) {
1503			sanitizers = append(sanitizers, "safe-stack")
1504		}
1505
1506		if Bool(sanProps.Cfi) {
1507			sanitizers = append(sanitizers, "cfi")
1508
1509			if Bool(sanProps.Diag.Cfi) {
1510				diagSanitizers = append(diagSanitizers, "cfi")
1511			}
1512		}
1513
1514		if Bool(sanProps.Integer_overflow) {
1515			sanitizers = append(sanitizers, "unsigned-integer-overflow")
1516			sanitizers = append(sanitizers, "signed-integer-overflow")
1517			if Bool(sanProps.Diag.Integer_overflow) {
1518				diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
1519				diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
1520			}
1521		}
1522
1523		if Bool(sanProps.Scudo) {
1524			sanitizers = append(sanitizers, "scudo")
1525		}
1526
1527		if Bool(sanProps.Scs) {
1528			sanitizers = append(sanitizers, "shadow-call-stack")
1529		}
1530
1531		if Bool(sanProps.Memtag_heap) && c.Binary() {
1532			sanitizers = append(sanitizers, "memtag-heap")
1533		}
1534
1535		if Bool(sanProps.Memtag_stack) {
1536			sanitizers = append(sanitizers, "memtag-stack")
1537		}
1538
1539		if Bool(sanProps.Fuzzer) {
1540			sanitizers = append(sanitizers, "fuzzer-no-link")
1541		}
1542
1543		// Save the list of sanitizers. These will be used again when generating
1544		// the build rules (for Cflags, etc.)
1545		c.sanitize.Properties.Sanitizers = sanitizers
1546		c.sanitize.Properties.DiagSanitizers = diagSanitizers
1547
1548		// TODO(b/150822854) Hosts have a different default behavior and assume the runtime library is used.
1549		if c.Host() {
1550			diagSanitizers = sanitizers
1551		}
1552
1553		addStaticDeps := func(dep string, hideSymbols bool) {
1554			// If we're using snapshots, redirect to snapshot whenever possible
1555			snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
1556			if lib, ok := snapshot.StaticLibs[dep]; ok {
1557				dep = lib
1558			}
1559
1560			// static executable gets static runtime libs
1561			depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: hideSymbols}
1562			variations := append(mctx.Target().Variations(),
1563				blueprint.Variation{Mutator: "link", Variation: "static"})
1564			if c.Device() {
1565				variations = append(variations, c.ImageVariation())
1566			}
1567			if c.UseSdk() {
1568				variations = append(variations,
1569					blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
1570			}
1571			mctx.AddFarVariationDependencies(variations, depTag, dep)
1572		}
1573
1574		// Determine the runtime library required
1575		runtimeSharedLibrary := ""
1576		toolchain := c.toolchain(mctx)
1577		if Bool(sanProps.Address) {
1578			if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
1579				// Use a static runtime for musl to match what clang does for glibc.
1580				addStaticDeps(config.AddressSanitizerStaticRuntimeLibrary(toolchain), false)
1581				addStaticDeps(config.AddressSanitizerCXXStaticRuntimeLibrary(toolchain), false)
1582			} else {
1583				runtimeSharedLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
1584			}
1585		} else if Bool(sanProps.Hwaddress) {
1586			if c.staticBinary() {
1587				addStaticDeps(config.HWAddressSanitizerStaticLibrary(toolchain), true)
1588				addStaticDeps("libdl", false)
1589			} else {
1590				runtimeSharedLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
1591			}
1592		} else if Bool(sanProps.Thread) {
1593			runtimeSharedLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
1594		} else if Bool(sanProps.Scudo) {
1595			if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
1596				runtimeSharedLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
1597			} else {
1598				runtimeSharedLibrary = config.ScudoRuntimeLibrary(toolchain)
1599			}
1600		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
1601			Bool(sanProps.Fuzzer) ||
1602			Bool(sanProps.Undefined) ||
1603			Bool(sanProps.All_undefined) {
1604			if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
1605				// Use a static runtime for static binaries.
1606				// Also use a static runtime for musl to match
1607				// what clang does for glibc.  Otherwise dlopening
1608				// libraries that depend on libclang_rt.ubsan_standalone.so
1609				// fails with:
1610				// Error relocating ...: initial-exec TLS resolves to dynamic definition
1611				addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)+".static", true)
1612			} else {
1613				runtimeSharedLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
1614			}
1615		}
1616
1617		if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep {
1618			addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), true)
1619		}
1620		if c.sanitize.Properties.BuiltinsDep {
1621			addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain), true)
1622		}
1623
1624		if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
1625			// UBSan is supported on non-bionic linux host builds as well
1626
1627			// Adding dependency to the runtime library. We are using *FarVariation*
1628			// because the runtime libraries themselves are not mutated by sanitizer
1629			// mutators and thus don't have sanitizer variants whereas this module
1630			// has been already mutated.
1631			//
1632			// Note that by adding dependency with {static|shared}DepTag, the lib is
1633			// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
1634			if c.staticBinary() {
1635				// Most sanitizers are either disabled for static binaries or have already
1636				// handled the static binary case above through a direct call to addStaticDeps.
1637				// If not, treat the runtime shared library as a static library and hope for
1638				// the best.
1639				addStaticDeps(runtimeSharedLibrary, true)
1640			} else if !c.static() && !c.Header() {
1641				// If we're using snapshots, redirect to snapshot whenever possible
1642				snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
1643				if lib, ok := snapshot.SharedLibs[runtimeSharedLibrary]; ok {
1644					runtimeSharedLibrary = lib
1645				}
1646
1647				// Skip apex dependency check for sharedLibraryDependency
1648				// when sanitizer diags are enabled. Skipping the check will allow
1649				// building with diag libraries without having to list the
1650				// dependency in Apex's allowed_deps file.
1651				diagEnabled := len(diagSanitizers) > 0
1652				// dynamic executable and shared libs get shared runtime libs
1653				depTag := libraryDependencyTag{
1654					Kind:  sharedLibraryDependency,
1655					Order: earlyLibraryDependency,
1656
1657					skipApexAllowedDependenciesCheck: diagEnabled,
1658				}
1659				variations := append(mctx.Target().Variations(),
1660					blueprint.Variation{Mutator: "link", Variation: "shared"})
1661				if c.Device() {
1662					variations = append(variations, c.ImageVariation())
1663				}
1664				if c.UseSdk() {
1665					variations = append(variations,
1666						blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
1667				}
1668				AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeSharedLibrary, "", true)
1669			}
1670			// static lib does not have dependency to the runtime library. The
1671			// dependency will be added to the executables or shared libs using
1672			// the static lib.
1673		}
1674	}
1675}
1676
1677type Sanitizeable interface {
1678	android.Module
1679	IsSanitizerEnabled(config android.Config, sanitizerName string) bool
1680	EnableSanitizer(sanitizerName string)
1681	AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
1682}
1683
1684type JniSanitizeable interface {
1685	android.Module
1686	IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool
1687}
1688
1689func (c *Module) MinimalRuntimeDep() bool {
1690	return c.sanitize.Properties.MinimalRuntimeDep
1691}
1692
1693func (c *Module) UbsanRuntimeDep() bool {
1694	return c.sanitize.Properties.UbsanRuntimeDep
1695}
1696
1697func (c *Module) SanitizePropDefined() bool {
1698	return c.sanitize != nil
1699}
1700
1701func (c *Module) IsSanitizerEnabled(t SanitizerType) bool {
1702	return c.sanitize.isSanitizerEnabled(t)
1703}
1704
1705func (c *Module) StaticallyLinked() bool {
1706	return c.static()
1707}
1708
1709func (c *Module) SetInSanitizerDir() {
1710	if c.sanitize != nil {
1711		c.sanitize.Properties.InSanitizerDir = true
1712	}
1713}
1714
1715func (c *Module) SetSanitizer(t SanitizerType, b bool) {
1716	if c.sanitize != nil {
1717		c.sanitize.SetSanitizer(t, b)
1718	}
1719}
1720
1721var _ PlatformSanitizeable = (*Module)(nil)
1722
1723type sanitizerStaticLibsMap struct {
1724	// libsMap contains one list of modules per each image and each arch.
1725	// e.g. libs[vendor]["arm"] contains arm modules installed to vendor
1726	libsMap       map[ImageVariantType]map[string][]string
1727	libsMapLock   sync.Mutex
1728	sanitizerType SanitizerType
1729}
1730
1731func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap {
1732	return &sanitizerStaticLibsMap{
1733		sanitizerType: t,
1734		libsMap:       make(map[ImageVariantType]map[string][]string),
1735	}
1736}
1737
1738// Add the current module to sanitizer static libs maps
1739// Each module should pass its exported name as names of Make and Soong can differ.
1740func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) {
1741	image := GetImageVariantType(c)
1742	arch := c.Module().Target().Arch.ArchType.String()
1743
1744	s.libsMapLock.Lock()
1745	defer s.libsMapLock.Unlock()
1746
1747	if _, ok := s.libsMap[image]; !ok {
1748		s.libsMap[image] = make(map[string][]string)
1749	}
1750
1751	s.libsMap[image][arch] = append(s.libsMap[image][arch], name)
1752}
1753
1754// Exports makefile variables in the following format:
1755// SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES
1756// e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES
1757// These are to be used by use_soong_sanitized_static_libraries.
1758// See build/make/core/binary.mk for more details.
1759func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
1760	for _, image := range android.SortedKeys(s.libsMap) {
1761		archMap := s.libsMap[ImageVariantType(image)]
1762		for _, arch := range android.SortedKeys(archMap) {
1763			libs := archMap[arch]
1764			sort.Strings(libs)
1765
1766			key := fmt.Sprintf(
1767				"SOONG_%s_%s_%s_STATIC_LIBRARIES",
1768				s.sanitizerType.variationName(),
1769				image, // already upper
1770				arch)
1771
1772			ctx.Strict(key, strings.Join(libs, " "))
1773		}
1774	}
1775}
1776
1777var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs")
1778
1779func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap {
1780	return config.Once(cfiStaticLibsKey, func() interface{} {
1781		return newSanitizerStaticLibsMap(cfi)
1782	}).(*sanitizerStaticLibsMap)
1783}
1784
1785var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs")
1786
1787func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
1788	return config.Once(hwasanStaticLibsKey, func() interface{} {
1789		return newSanitizerStaticLibsMap(Hwasan)
1790	}).(*sanitizerStaticLibsMap)
1791}
1792
1793func enableMinimalRuntime(sanitize *sanitize) bool {
1794	if sanitize.isSanitizerEnabled(Asan) {
1795		return false
1796	} else if sanitize.isSanitizerEnabled(Hwasan) {
1797		return false
1798	} else if sanitize.isSanitizerEnabled(Fuzzer) {
1799		return false
1800	}
1801
1802	if enableUbsanRuntime(sanitize) {
1803		return false
1804	}
1805
1806	sanitizeProps := &sanitize.Properties.SanitizeMutated
1807	if Bool(sanitizeProps.Diag.Cfi) {
1808		return false
1809	}
1810
1811	return Bool(sanitizeProps.Integer_overflow) ||
1812		len(sanitizeProps.Misc_undefined) > 0 ||
1813		Bool(sanitizeProps.Undefined) ||
1814		Bool(sanitizeProps.All_undefined)
1815}
1816
1817func (m *Module) UbsanRuntimeNeeded() bool {
1818	return enableUbsanRuntime(m.sanitize)
1819}
1820
1821func (m *Module) MinimalRuntimeNeeded() bool {
1822	return enableMinimalRuntime(m.sanitize)
1823}
1824
1825func enableUbsanRuntime(sanitize *sanitize) bool {
1826	sanitizeProps := &sanitize.Properties.SanitizeMutated
1827	return Bool(sanitizeProps.Diag.Integer_overflow) ||
1828		Bool(sanitizeProps.Diag.Undefined) ||
1829		len(sanitizeProps.Diag.Misc_undefined) > 0
1830}
1831
1832func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
1833	cfiStaticLibs(ctx.Config()).exportToMake(ctx)
1834}
1835
1836func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
1837	hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
1838}
1839
1840func BazelCcSanitizerToolchainVars(config android.Config) string {
1841	return android.BazelToolchainVars(config, exportedVars)
1842}
1843