1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540 |
- // Copyright 2016 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package cc
- import (
- "fmt"
- "sort"
- "strings"
- "sync"
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
- "android/soong/android"
- "android/soong/cc/config"
- "android/soong/snapshot"
- )
- var (
- // Any C flags added by sanitizer which libTooling tools may not
- // understand also need to be added to ClangLibToolingUnknownCflags in
- // cc/config/clang.go
- asanCflags = []string{
- "-fno-omit-frame-pointer",
- }
- asanLdflags = []string{"-Wl,-u,__asan_preinit"}
- hwasanCflags = []string{
- "-fno-omit-frame-pointer",
- "-Wno-frame-larger-than=",
- "-fsanitize-hwaddress-abi=platform",
- }
- // ThinLTO performs codegen during link time, thus these flags need to
- // passed to both CFLAGS and LDFLAGS.
- hwasanCommonflags = []string{
- // The following improves debug location information
- // availability at the cost of its accuracy. It increases
- // the likelihood of a stack variable's frame offset
- // to be recorded in the debug info, which is important
- // for the quality of hwasan reports. The downside is a
- // higher number of "optimized out" stack variables.
- // b/112437883.
- "-instcombine-lower-dbg-declare=0",
- // TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
- // GlobalISel is the default at -O0 on aarch64.
- "--aarch64-enable-global-isel-at-O=-1",
- "-fast-isel=false",
- }
- cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
- "-fsanitize-ignorelist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
- // -flto and -fvisibility are required by clang when -fsanitize=cfi is
- // used, but have no effect on assembly files
- cfiAsflags = []string{"-flto", "-fvisibility=default"}
- cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
- "-Wl,-plugin-opt,O1"}
- cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
- intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
- minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
- "-fno-sanitize-recover=integer,undefined"}
- hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
- "export_memory_stats=0", "max_malloc_fill_size=0"}
- )
- type SanitizerType int
- const (
- Asan SanitizerType = iota + 1
- Hwasan
- tsan
- intOverflow
- scs
- Fuzzer
- Memtag_heap
- cfi // cfi is last to prevent it running before incompatible mutators
- )
- var Sanitizers = []SanitizerType{
- Asan,
- Hwasan,
- tsan,
- intOverflow,
- scs,
- Fuzzer,
- Memtag_heap,
- cfi, // cfi is last to prevent it running before incompatible mutators
- }
- // Name of the sanitizer variation for this sanitizer type
- func (t SanitizerType) variationName() string {
- switch t {
- case Asan:
- return "asan"
- case Hwasan:
- return "hwasan"
- case tsan:
- return "tsan"
- case intOverflow:
- return "intOverflow"
- case cfi:
- return "cfi"
- case scs:
- return "scs"
- case Memtag_heap:
- return "memtag_heap"
- case Fuzzer:
- return "fuzzer"
- default:
- panic(fmt.Errorf("unknown SanitizerType %d", t))
- }
- }
- // This is the sanitizer names in SANITIZE_[TARGET|HOST]
- func (t SanitizerType) name() string {
- switch t {
- case Asan:
- return "address"
- case Hwasan:
- return "hwaddress"
- case Memtag_heap:
- return "memtag_heap"
- case tsan:
- return "thread"
- case intOverflow:
- return "integer_overflow"
- case cfi:
- return "cfi"
- case scs:
- return "shadow-call-stack"
- case Fuzzer:
- return "fuzzer"
- default:
- panic(fmt.Errorf("unknown SanitizerType %d", t))
- }
- }
- func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) {
- switch t {
- case Asan, Hwasan, Fuzzer, scs, tsan, cfi:
- ctx.TopDown(t.variationName()+"_deps", sanitizerDepsMutator(t))
- ctx.BottomUp(t.variationName(), sanitizerMutator(t))
- case Memtag_heap, intOverflow:
- // do nothing
- default:
- panic(fmt.Errorf("unknown SanitizerType %d", t))
- }
- }
- func (*Module) SanitizerSupported(t SanitizerType) bool {
- switch t {
- case Asan:
- return true
- case Hwasan:
- return true
- case tsan:
- return true
- case intOverflow:
- return true
- case cfi:
- return true
- case scs:
- return true
- case Fuzzer:
- return true
- case Memtag_heap:
- return true
- default:
- return false
- }
- }
- // incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
- func (t SanitizerType) incompatibleWithCfi() bool {
- return t == Asan || t == Fuzzer || t == Hwasan
- }
- type SanitizeUserProps struct {
- // Prevent use of any sanitizers on this module
- Never *bool `android:"arch_variant"`
- // ASan (Address sanitizer), incompatible with static binaries.
- // Always runs in a diagnostic mode.
- // Use of address sanitizer disables cfi sanitizer.
- // Hwaddress sanitizer takes precedence over this sanitizer.
- Address *bool `android:"arch_variant"`
- // TSan (Thread sanitizer), incompatible with static binaries and 32 bit architectures.
- // Always runs in a diagnostic mode.
- // Use of thread sanitizer disables cfi and scudo sanitizers.
- // Hwaddress sanitizer takes precedence over this sanitizer.
- Thread *bool `android:"arch_variant"`
- // HWASan (Hardware Address sanitizer).
- // Use of hwasan sanitizer disables cfi, address, thread, and scudo sanitizers.
- Hwaddress *bool `android:"arch_variant"`
- // Undefined behavior sanitizer
- All_undefined *bool `android:"arch_variant"`
- // Subset of undefined behavior sanitizer
- Undefined *bool `android:"arch_variant"`
- // List of specific undefined behavior sanitizers to enable
- Misc_undefined []string `android:"arch_variant"`
- // Fuzzer, incompatible with static binaries.
- Fuzzer *bool `android:"arch_variant"`
- // safe-stack sanitizer, incompatible with 32-bit architectures.
- Safestack *bool `android:"arch_variant"`
- // cfi sanitizer, incompatible with asan, hwasan, fuzzer, or Darwin
- Cfi *bool `android:"arch_variant"`
- // signed/unsigned integer overflow sanitizer, incompatible with Darwin.
- Integer_overflow *bool `android:"arch_variant"`
- // scudo sanitizer, incompatible with asan, hwasan, tsan
- // This should not be used in Android 11+ : https://source.android.com/devices/tech/debug/scudo
- // deprecated
- Scudo *bool `android:"arch_variant"`
- // shadow-call-stack sanitizer, only available on arm64
- Scs *bool `android:"arch_variant"`
- // Memory-tagging, only available on arm64
- // if diag.memtag unset or false, enables async memory tagging
- Memtag_heap *bool `android:"arch_variant"`
- // A modifier for ASAN and HWASAN for write only instrumentation
- Writeonly *bool `android:"arch_variant"`
- // Sanitizers to run in the diagnostic mode (as opposed to the release mode).
- // Replaces abort() on error with a human-readable error message.
- // Address and Thread sanitizers always run in diagnostic mode.
- Diag struct {
- // Undefined behavior sanitizer, diagnostic mode
- Undefined *bool `android:"arch_variant"`
- // cfi sanitizer, diagnostic mode, incompatible with asan, hwasan, fuzzer, or Darwin
- Cfi *bool `android:"arch_variant"`
- // signed/unsigned integer overflow sanitizer, diagnostic mode, incompatible with Darwin.
- Integer_overflow *bool `android:"arch_variant"`
- // Memory-tagging, only available on arm64
- // requires sanitizer.memtag: true
- // if set, enables sync memory tagging
- Memtag_heap *bool `android:"arch_variant"`
- // List of specific undefined behavior sanitizers to enable in diagnostic mode
- Misc_undefined []string `android:"arch_variant"`
- // List of sanitizers to pass to -fno-sanitize-recover
- // results in only the first detected error for these sanitizers being reported and program then
- // exits with a non-zero exit code.
- No_recover []string `android:"arch_variant"`
- } `android:"arch_variant"`
- // Sanitizers to run with flag configuration specified
- Config struct {
- // Enables CFI support flags for assembly-heavy libraries
- Cfi_assembly_support *bool `android:"arch_variant"`
- } `android:"arch_variant"`
- // List of sanitizers to pass to -fsanitize-recover
- // allows execution to continue for these sanitizers to detect multiple errors rather than only
- // the first one
- Recover []string
- // value to pass to -fsanitize-ignorelist
- Blocklist *string
- }
- type SanitizeProperties struct {
- Sanitize SanitizeUserProps `android:"arch_variant"`
- SanitizerEnabled bool `blueprint:"mutated"`
- SanitizeDep bool `blueprint:"mutated"`
- MinimalRuntimeDep bool `blueprint:"mutated"`
- BuiltinsDep bool `blueprint:"mutated"`
- UbsanRuntimeDep bool `blueprint:"mutated"`
- InSanitizerDir bool `blueprint:"mutated"`
- Sanitizers []string `blueprint:"mutated"`
- DiagSanitizers []string `blueprint:"mutated"`
- }
- type sanitize struct {
- Properties SanitizeProperties
- }
- // Mark this tag with a check to see if apex dependency check should be skipped
- func (t libraryDependencyTag) SkipApexAllowedDependenciesCheck() bool {
- return t.skipApexAllowedDependenciesCheck
- }
- var _ android.SkipApexAllowedDependenciesCheck = (*libraryDependencyTag)(nil)
- func init() {
- android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
- android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
- }
- func (sanitize *sanitize) props() []interface{} {
- return []interface{}{&sanitize.Properties}
- }
- func (sanitize *sanitize) begin(ctx BaseModuleContext) {
- s := &sanitize.Properties.Sanitize
- // Don't apply sanitizers to NDK code.
- if ctx.useSdk() {
- s.Never = BoolPtr(true)
- }
- // Never always wins.
- if Bool(s.Never) {
- return
- }
- // cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap}).
- if ctx.testBinary() {
- if s.Memtag_heap == nil {
- s.Memtag_heap = proptools.BoolPtr(true)
- }
- if s.Diag.Memtag_heap == nil {
- s.Diag.Memtag_heap = proptools.BoolPtr(true)
- }
- }
- var globalSanitizers []string
- var globalSanitizersDiag []string
- if ctx.Host() {
- if !ctx.Windows() {
- globalSanitizers = ctx.Config().SanitizeHost()
- }
- } else {
- arches := ctx.Config().SanitizeDeviceArch()
- if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
- globalSanitizers = ctx.Config().SanitizeDevice()
- globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
- }
- }
- if len(globalSanitizers) > 0 {
- var found bool
- if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil {
- s.All_undefined = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil {
- s.Undefined = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil {
- s.Address = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
- s.Thread = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
- s.Fuzzer = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
- s.Safestack = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil {
- if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) {
- s.Cfi = proptools.BoolPtr(true)
- }
- }
- // Global integer_overflow builds do not support static libraries.
- if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil {
- if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && !ctx.static() {
- s.Integer_overflow = proptools.BoolPtr(true)
- }
- }
- if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil {
- s.Scudo = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
- s.Hwaddress = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("writeonly", globalSanitizers); found && s.Writeonly == nil {
- // Hwaddress and Address are set before, so we can check them here
- // If they aren't explicitly set in the blueprint/SANITIZE_(HOST|TARGET), they would be nil instead of false
- if s.Address == nil && s.Hwaddress == nil {
- ctx.ModuleErrorf("writeonly modifier cannot be used without 'address' or 'hwaddress'")
- }
- s.Writeonly = proptools.BoolPtr(true)
- }
- if found, globalSanitizers = removeFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil {
- if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) {
- s.Memtag_heap = proptools.BoolPtr(true)
- }
- }
- if len(globalSanitizers) > 0 {
- ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
- }
- // Global integer_overflow builds do not support static library diagnostics.
- if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found &&
- s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) && !ctx.static() {
- s.Diag.Integer_overflow = proptools.BoolPtr(true)
- }
- if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found &&
- s.Diag.Cfi == nil && Bool(s.Cfi) {
- s.Diag.Cfi = proptools.BoolPtr(true)
- }
- if found, globalSanitizersDiag = removeFromList("memtag_heap", globalSanitizersDiag); found &&
- s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) {
- s.Diag.Memtag_heap = proptools.BoolPtr(true)
- }
- if len(globalSanitizersDiag) > 0 {
- ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0])
- }
- }
- // Enable Memtag for all components in the include paths (for Aarch64 only)
- if ctx.Arch().ArchType == android.Arm64 {
- if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
- if s.Memtag_heap == nil {
- s.Memtag_heap = proptools.BoolPtr(true)
- }
- if s.Diag.Memtag_heap == nil {
- s.Diag.Memtag_heap = proptools.BoolPtr(true)
- }
- } else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) {
- if s.Memtag_heap == nil {
- s.Memtag_heap = proptools.BoolPtr(true)
- }
- }
- }
- // Enable CFI for non-host components in the include paths
- if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && !ctx.Host() {
- s.Cfi = proptools.BoolPtr(true)
- if inList("cfi", ctx.Config().SanitizeDeviceDiag()) {
- s.Diag.Cfi = proptools.BoolPtr(true)
- }
- }
- // Is CFI actually enabled?
- if !ctx.Config().EnableCFI() {
- s.Cfi = nil
- s.Diag.Cfi = nil
- }
- // HWASan requires AArch64 hardware feature (top-byte-ignore).
- if ctx.Arch().ArchType != android.Arm64 {
- s.Hwaddress = nil
- }
- // SCS is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 {
- s.Scs = nil
- }
- // Memtag_heap is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 {
- s.Memtag_heap = nil
- }
- // Also disable CFI if ASAN is enabled.
- if Bool(s.Address) || Bool(s.Hwaddress) {
- s.Cfi = nil
- s.Diag.Cfi = nil
- }
- // Disable sanitizers that depend on the UBSan runtime for windows/darwin/musl builds.
- if !ctx.Os().Linux() || ctx.Os() == android.LinuxMusl {
- s.Cfi = nil
- s.Diag.Cfi = nil
- s.Misc_undefined = nil
- s.Undefined = nil
- s.All_undefined = nil
- s.Integer_overflow = nil
- }
- // Also disable CFI for VNDK variants of components
- if ctx.isVndk() && ctx.useVndk() {
- if ctx.static() {
- // Cfi variant for static vndk should be captured as vendor snapshot,
- // so don't strictly disable Cfi.
- s.Cfi = nil
- s.Diag.Cfi = nil
- } else {
- s.Cfi = nil
- s.Diag.Cfi = nil
- }
- }
- // HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
- // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
- if (ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
- s.Hwaddress = nil
- }
- if ctx.staticBinary() {
- s.Address = nil
- s.Fuzzer = nil
- s.Thread = nil
- }
- if Bool(s.All_undefined) {
- s.Undefined = nil
- }
- if !ctx.toolchain().Is64Bit() {
- // TSAN and SafeStack are not supported on 32-bit architectures
- s.Thread = nil
- s.Safestack = nil
- // TODO(ccross): error for compile_multilib = "32"?
- }
- if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
- Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
- Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap)) {
- sanitize.Properties.SanitizerEnabled = true
- }
- // Disable Scudo if ASan or TSan is enabled, or if it's disabled globally.
- if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) || ctx.Config().DisableScudo() {
- s.Scudo = nil
- }
- if Bool(s.Hwaddress) {
- s.Address = nil
- s.Thread = nil
- }
- // TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
- // mutually incompatible.
- if Bool(s.Fuzzer) {
- s.Cfi = nil
- }
- }
- func toDisableImplicitIntegerChange(flags []string) bool {
- // Returns true if any flag is fsanitize*integer, and there is
- // no explicit flag about sanitize=implicit-integer-sign-change.
- for _, f := range flags {
- if strings.Contains(f, "sanitize=implicit-integer-sign-change") {
- return false
- }
- }
- for _, f := range flags {
- if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
- return true
- }
- }
- return false
- }
- func toDisableUnsignedShiftBaseChange(flags []string) bool {
- // Returns true if any flag is fsanitize*integer, and there is
- // no explicit flag about sanitize=unsigned-shift-base.
- for _, f := range flags {
- if strings.Contains(f, "sanitize=unsigned-shift-base") {
- return false
- }
- }
- for _, f := range flags {
- if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
- return true
- }
- }
- return false
- }
- func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
- minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
- if sanitize.Properties.MinimalRuntimeDep {
- flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,--exclude-libs,"+minimalRuntimeLib)
- }
- if !sanitize.Properties.SanitizerEnabled && !sanitize.Properties.UbsanRuntimeDep {
- return flags
- }
- if Bool(sanitize.Properties.Sanitize.Address) {
- if ctx.Arch().ArchType == android.Arm {
- // Frame pointer based unwinder in ASan requires ARM frame setup.
- // TODO: put in flags?
- flags.RequiredInstructionSet = "arm"
- }
- flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...)
- flags.Local.LdFlags = append(flags.Local.LdFlags, asanLdflags...)
- if Bool(sanitize.Properties.Sanitize.Writeonly) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-instrument-reads=0")
- }
- if ctx.Host() {
- // -nodefaultlibs (provided with libc++) prevents the driver from linking
- // libraries needed with -fsanitize=address. http://b/18650275 (WAI)
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-as-needed")
- } else {
- flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-globals=0")
- if ctx.bootstrap() {
- flags.DynamicLinker = "/system/bin/bootstrap/linker_asan"
- } else {
- flags.DynamicLinker = "/system/bin/linker_asan"
- }
- if flags.Toolchain.Is64Bit() {
- flags.DynamicLinker += "64"
- }
- }
- }
- if Bool(sanitize.Properties.Sanitize.Hwaddress) {
- flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
- for _, flag := range hwasanCommonflags {
- flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag)
- }
- for _, flag := range hwasanCommonflags {
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
- }
- if Bool(sanitize.Properties.Sanitize.Writeonly) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
- }
- }
- if Bool(sanitize.Properties.Sanitize.Fuzzer) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize=fuzzer-no-link")
- // TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
- _, flags.Local.LdFlags = removeFromList("-flto", flags.Local.LdFlags)
- _, flags.Local.CFlags = removeFromList("-flto", flags.Local.CFlags)
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-lto")
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-lto")
- // TODO(b/142430592): Upstream linker scripts for sanitizer runtime libraries
- // discard the sancov_lowest_stack symbol, because it's emulated TLS (and thus
- // doesn't match the linker script due to the "__emutls_v." prefix).
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth")
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth")
- // Disable fortify for fuzzing builds. Generally, we'll be building with
- // UBSan or ASan here and the fortify checks pollute the stack traces.
- flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE")
- // Build fuzzer-sanitized libraries with an $ORIGIN DT_RUNPATH. Android's
- // linker uses DT_RUNPATH, not DT_RPATH. When we deploy cc_fuzz targets and
- // their libraries to /data/fuzz/<arch>/lib, any transient shared library gets
- // the DT_RUNPATH from the shared library above it, and not the executable,
- // meaning that the lookup falls back to the system. Adding the $ORIGIN to the
- // DT_RUNPATH here means that transient shared libraries can be found
- // colocated with their parents.
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN`)
- }
- if Bool(sanitize.Properties.Sanitize.Cfi) {
- if ctx.Arch().ArchType == android.Arm {
- // __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
- // to do this on a function basis, so force Thumb on the entire module.
- flags.RequiredInstructionSet = "thumb"
- }
- flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
- flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
- if Bool(sanitize.Properties.Sanitize.Config.Cfi_assembly_support) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
- }
- // Only append the default visibility flag if -fvisibility has not already been set
- // to hidden.
- if !inList("-fvisibility=hidden", flags.Local.CFlags) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fvisibility=default")
- }
- flags.Local.LdFlags = append(flags.Local.LdFlags, cfiLdflags...)
- if ctx.staticBinary() {
- _, flags.Local.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.CFlags)
- _, flags.Local.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.LdFlags)
- }
- }
- if Bool(sanitize.Properties.Sanitize.Integer_overflow) {
- flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...)
- }
- if len(sanitize.Properties.Sanitizers) > 0 {
- sanitizeArg := "-fsanitize=" + strings.Join(sanitize.Properties.Sanitizers, ",")
- flags.Local.CFlags = append(flags.Local.CFlags, sanitizeArg)
- flags.Local.AsFlags = append(flags.Local.AsFlags, sanitizeArg)
- flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg)
- if ctx.toolchain().Bionic() {
- // Bionic sanitizer runtimes have already been added as dependencies so that
- // the right variant of the runtime will be used (with the "-android"
- // suffix), so don't let clang the runtime library.
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-link-runtime")
- } else {
- // Host sanitizers only link symbols in the final executable, so
- // there will always be undefined symbols in intermediate libraries.
- _, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags)
- // non-Bionic toolchain prebuilts are missing UBSan's vptr and function san
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function")
- }
- if enableMinimalRuntime(sanitize) {
- flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " "))
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
- }
- if Bool(sanitize.Properties.Sanitize.Fuzzer) {
- // When fuzzing, we wish to crash with diagnostics on any bug.
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
- } else if ctx.Host() {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover=all")
- } else {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
- }
- // http://b/119329758, Android core does not boot up with this sanitizer yet.
- if toDisableImplicitIntegerChange(flags.Local.CFlags) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change")
- }
- // http://b/171275751, Android doesn't build with this sanitizer yet.
- if toDisableUnsignedShiftBaseChange(flags.Local.CFlags) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=unsigned-shift-base")
- }
- }
- if len(sanitize.Properties.DiagSanitizers) > 0 {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(sanitize.Properties.DiagSanitizers, ","))
- }
- // FIXME: enable RTTI if diag + (cfi or vptr)
- if sanitize.Properties.Sanitize.Recover != nil {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-recover="+
- strings.Join(sanitize.Properties.Sanitize.Recover, ","))
- }
- if sanitize.Properties.Sanitize.Diag.No_recover != nil {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover="+
- strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
- }
- blocklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blocklist)
- if blocklist.Valid() {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-ignorelist="+blocklist.String())
- flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path())
- }
- return flags
- }
- func (sanitize *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- // Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing
- // both the sanitized and non-sanitized variants to make without a name conflict.
- if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" {
- if Bool(sanitize.Properties.Sanitize.Cfi) {
- entries.SubName += ".cfi"
- }
- if Bool(sanitize.Properties.Sanitize.Hwaddress) {
- entries.SubName += ".hwasan"
- }
- if Bool(sanitize.Properties.Sanitize.Scs) {
- entries.SubName += ".scs"
- }
- }
- }
- func (sanitize *sanitize) inSanitizerDir() bool {
- return sanitize.Properties.InSanitizerDir
- }
- // getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties.
- func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
- switch t {
- case Asan:
- return sanitize.Properties.Sanitize.Address
- case Hwasan:
- return sanitize.Properties.Sanitize.Hwaddress
- case tsan:
- return sanitize.Properties.Sanitize.Thread
- case intOverflow:
- return sanitize.Properties.Sanitize.Integer_overflow
- case cfi:
- return sanitize.Properties.Sanitize.Cfi
- case scs:
- return sanitize.Properties.Sanitize.Scs
- case Memtag_heap:
- return sanitize.Properties.Sanitize.Memtag_heap
- case Fuzzer:
- return sanitize.Properties.Sanitize.Fuzzer
- default:
- panic(fmt.Errorf("unknown SanitizerType %d", t))
- }
- }
- // isUnsanitizedVariant returns true if no sanitizers are enabled.
- func (sanitize *sanitize) isUnsanitizedVariant() bool {
- return !sanitize.isSanitizerEnabled(Asan) &&
- !sanitize.isSanitizerEnabled(Hwasan) &&
- !sanitize.isSanitizerEnabled(tsan) &&
- !sanitize.isSanitizerEnabled(cfi) &&
- !sanitize.isSanitizerEnabled(scs) &&
- !sanitize.isSanitizerEnabled(Memtag_heap) &&
- !sanitize.isSanitizerEnabled(Fuzzer)
- }
- // isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
- func (sanitize *sanitize) isVariantOnProductionDevice() bool {
- return !sanitize.isSanitizerEnabled(Asan) &&
- !sanitize.isSanitizerEnabled(Hwasan) &&
- !sanitize.isSanitizerEnabled(tsan) &&
- !sanitize.isSanitizerEnabled(Fuzzer)
- }
- func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) {
- bPtr := proptools.BoolPtr(b)
- if !b {
- bPtr = nil
- }
- switch t {
- case Asan:
- sanitize.Properties.Sanitize.Address = bPtr
- case Hwasan:
- sanitize.Properties.Sanitize.Hwaddress = bPtr
- case tsan:
- sanitize.Properties.Sanitize.Thread = bPtr
- case intOverflow:
- sanitize.Properties.Sanitize.Integer_overflow = bPtr
- case cfi:
- sanitize.Properties.Sanitize.Cfi = bPtr
- case scs:
- sanitize.Properties.Sanitize.Scs = bPtr
- case Memtag_heap:
- sanitize.Properties.Sanitize.Memtag_heap = bPtr
- case Fuzzer:
- sanitize.Properties.Sanitize.Fuzzer = bPtr
- default:
- panic(fmt.Errorf("unknown SanitizerType %d", t))
- }
- if b {
- sanitize.Properties.SanitizerEnabled = true
- }
- }
- // Check if the sanitizer is explicitly disabled (as opposed to nil by
- // virtue of not being set).
- func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool {
- if sanitize == nil {
- return false
- }
- sanitizerVal := sanitize.getSanitizerBoolPtr(t)
- return sanitizerVal != nil && *sanitizerVal == false
- }
- // There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled)
- // because enabling a sanitizer either directly (via the blueprint) or
- // indirectly (via a mutator) sets the bool ptr to true, and you can't
- // distinguish between the cases. It isn't needed though - both cases can be
- // treated identically.
- func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool {
- if sanitize == nil {
- return false
- }
- sanitizerVal := sanitize.getSanitizerBoolPtr(t)
- return sanitizerVal != nil && *sanitizerVal == true
- }
- // IsSanitizableDependencyTag returns true if the dependency tag is sanitizable.
- func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
- switch t := tag.(type) {
- case dependencyTag:
- return t == reuseObjTag || t == objDepTag
- case libraryDependencyTag:
- return true
- default:
- return false
- }
- }
- func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
- return IsSanitizableDependencyTag
- }
- // Determines if the current module is a static library going to be captured
- // as vendor snapshot. Such modules must create both cfi and non-cfi variants,
- // except for ones which explicitly disable cfi.
- func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
- if snapshot.IsVendorProprietaryModule(mctx) {
- return false
- }
- c := mctx.Module().(PlatformSanitizeable)
- if !c.InVendor() {
- return false
- }
- if !c.StaticallyLinked() {
- return false
- }
- if c.IsPrebuilt() {
- return false
- }
- if !c.SanitizerSupported(cfi) {
- return false
- }
- return c.SanitizePropDefined() &&
- !c.SanitizeNever() &&
- !c.IsSanitizerExplicitlyDisabled(cfi)
- }
- // Propagate sanitizer requirements down from binaries
- func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
- return func(mctx android.TopDownMutatorContext) {
- if c, ok := mctx.Module().(PlatformSanitizeable); ok {
- enabled := c.IsSanitizerEnabled(t)
- if t == cfi && needsCfiForVendorSnapshot(mctx) {
- // We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
- // determine defaultVariation in sanitizerMutator below.
- // Instead, just mark SanitizeDep to forcefully create cfi variant.
- enabled = true
- c.SetSanitizeDep(true)
- }
- if enabled {
- isSanitizableDependencyTag := c.SanitizableDepTagChecker()
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
- return false
- }
- if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
- !d.SanitizeNever() &&
- !d.IsSanitizerExplicitlyDisabled(t) {
- if t == cfi || t == Hwasan || t == scs || t == Asan {
- if d.StaticallyLinked() && d.SanitizerSupported(t) {
- // Rust does not support some of these sanitizers, so we need to check if it's
- // supported before setting this true.
- d.SetSanitizeDep(true)
- }
- } else {
- d.SetSanitizeDep(true)
- }
- }
- return true
- })
- }
- } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
- // If an APEX module includes a lib which is enabled for a sanitizer T, then
- // the APEX module is also enabled for the same sanitizer type.
- mctx.VisitDirectDeps(func(child android.Module) {
- if c, ok := child.(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
- sanitizeable.EnableSanitizer(t.name())
- }
- })
- }
- }
- }
- func (c *Module) SanitizeNever() bool {
- return Bool(c.sanitize.Properties.Sanitize.Never)
- }
- func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool {
- return c.sanitize.isSanitizerExplicitlyDisabled(t)
- }
- // Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
- func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
- // Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers.
- if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
- isSanitizableDependencyTag := c.SanitizableDepTagChecker()
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
- return false
- }
- d, ok := child.(*Module)
- if !ok || !d.static() {
- return false
- }
- if d.sanitize != nil {
- if enableMinimalRuntime(d.sanitize) {
- // If a static dependency is built with the minimal runtime,
- // make sure we include the ubsan minimal runtime.
- c.sanitize.Properties.MinimalRuntimeDep = true
- } else if enableUbsanRuntime(d.sanitize) {
- // If a static dependency runs with full ubsan diagnostics,
- // make sure we include the ubsan runtime.
- c.sanitize.Properties.UbsanRuntimeDep = true
- }
- if c.sanitize.Properties.MinimalRuntimeDep &&
- c.sanitize.Properties.UbsanRuntimeDep {
- // both flags that this mutator might set are true, so don't bother recursing
- return false
- }
- if c.Os() == android.Linux {
- c.sanitize.Properties.BuiltinsDep = true
- }
- return true
- }
- if p, ok := d.linker.(*snapshotLibraryDecorator); ok {
- if Bool(p.properties.Sanitize_minimal_dep) {
- c.sanitize.Properties.MinimalRuntimeDep = true
- }
- if Bool(p.properties.Sanitize_ubsan_dep) {
- c.sanitize.Properties.UbsanRuntimeDep = true
- }
- }
- return false
- })
- }
- }
- // Add the dependency to the runtime library for each of the sanitizer variants
- func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
- if !c.Enabled() {
- return
- }
- var sanitizers []string
- var diagSanitizers []string
- if Bool(c.sanitize.Properties.Sanitize.All_undefined) {
- sanitizers = append(sanitizers, "undefined")
- } else {
- if Bool(c.sanitize.Properties.Sanitize.Undefined) {
- sanitizers = append(sanitizers,
- "bool",
- "integer-divide-by-zero",
- "return",
- "returns-nonnull-attribute",
- "shift-exponent",
- "unreachable",
- "vla-bound",
- // TODO(danalbert): The following checks currently have compiler performance issues.
- //"alignment",
- //"bounds",
- //"enum",
- //"float-cast-overflow",
- //"float-divide-by-zero",
- //"nonnull-attribute",
- //"null",
- //"shift-base",
- //"signed-integer-overflow",
- // TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
- // https://llvm.org/PR19302
- // http://reviews.llvm.org/D6974
- // "object-size",
- )
- }
- sanitizers = append(sanitizers, c.sanitize.Properties.Sanitize.Misc_undefined...)
- }
- if Bool(c.sanitize.Properties.Sanitize.Diag.Undefined) {
- diagSanitizers = append(diagSanitizers, "undefined")
- }
- diagSanitizers = append(diagSanitizers, c.sanitize.Properties.Sanitize.Diag.Misc_undefined...)
- if Bool(c.sanitize.Properties.Sanitize.Address) {
- sanitizers = append(sanitizers, "address")
- diagSanitizers = append(diagSanitizers, "address")
- }
- if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
- sanitizers = append(sanitizers, "hwaddress")
- }
- if Bool(c.sanitize.Properties.Sanitize.Thread) {
- sanitizers = append(sanitizers, "thread")
- }
- if Bool(c.sanitize.Properties.Sanitize.Safestack) {
- sanitizers = append(sanitizers, "safe-stack")
- }
- if Bool(c.sanitize.Properties.Sanitize.Cfi) {
- sanitizers = append(sanitizers, "cfi")
- if Bool(c.sanitize.Properties.Sanitize.Diag.Cfi) {
- diagSanitizers = append(diagSanitizers, "cfi")
- }
- }
- if Bool(c.sanitize.Properties.Sanitize.Integer_overflow) {
- sanitizers = append(sanitizers, "unsigned-integer-overflow")
- sanitizers = append(sanitizers, "signed-integer-overflow")
- if Bool(c.sanitize.Properties.Sanitize.Diag.Integer_overflow) {
- diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
- diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
- }
- }
- if Bool(c.sanitize.Properties.Sanitize.Scudo) {
- sanitizers = append(sanitizers, "scudo")
- }
- if Bool(c.sanitize.Properties.Sanitize.Scs) {
- sanitizers = append(sanitizers, "shadow-call-stack")
- }
- if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.Binary() {
- noteDep := "note_memtag_heap_async"
- if Bool(c.sanitize.Properties.Sanitize.Diag.Memtag_heap) {
- noteDep = "note_memtag_heap_sync"
- }
- // If we're using snapshots, redirect to snapshot whenever possible
- // TODO(b/178470649): clean manual snapshot redirections
- snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
- if lib, ok := snapshot.StaticLibs[noteDep]; ok {
- noteDep = lib
- }
- depTag := StaticDepTag(true)
- variations := append(mctx.Target().Variations(),
- blueprint.Variation{Mutator: "link", Variation: "static"})
- if c.Device() {
- variations = append(variations, c.ImageVariation())
- }
- mctx.AddFarVariationDependencies(variations, depTag, noteDep)
- }
- if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
- sanitizers = append(sanitizers, "fuzzer-no-link")
- }
- // Save the list of sanitizers. These will be used again when generating
- // the build rules (for Cflags, etc.)
- c.sanitize.Properties.Sanitizers = sanitizers
- c.sanitize.Properties.DiagSanitizers = diagSanitizers
- // TODO(b/150822854) Hosts have a different default behavior and assume the runtime library is used.
- if c.Host() {
- diagSanitizers = sanitizers
- }
- // Determine the runtime library required
- runtimeLibrary := ""
- var extraStaticDeps []string
- toolchain := c.toolchain(mctx)
- if Bool(c.sanitize.Properties.Sanitize.Address) {
- runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
- } else if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
- if c.staticBinary() {
- runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain)
- extraStaticDeps = []string{"libdl"}
- } else {
- runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
- }
- } else if Bool(c.sanitize.Properties.Sanitize.Thread) {
- runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
- } else if Bool(c.sanitize.Properties.Sanitize.Scudo) {
- if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
- runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
- } else {
- runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
- }
- } else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
- Bool(c.sanitize.Properties.Sanitize.Fuzzer) ||
- Bool(c.sanitize.Properties.Sanitize.Undefined) ||
- Bool(c.sanitize.Properties.Sanitize.All_undefined) {
- runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
- if c.staticBinary() {
- runtimeLibrary += ".static"
- }
- }
- addStaticDeps := func(deps ...string) {
- // If we're using snapshots, redirect to snapshot whenever possible
- snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
- for idx, dep := range deps {
- if lib, ok := snapshot.StaticLibs[dep]; ok {
- deps[idx] = lib
- }
- }
- // static executable gets static runtime libs
- depTag := libraryDependencyTag{Kind: staticLibraryDependency}
- variations := append(mctx.Target().Variations(),
- blueprint.Variation{Mutator: "link", Variation: "static"})
- if c.Device() {
- variations = append(variations, c.ImageVariation())
- }
- if c.UseSdk() {
- variations = append(variations,
- blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
- }
- mctx.AddFarVariationDependencies(variations, depTag, deps...)
- }
- if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep {
- addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain))
- }
- if c.sanitize.Properties.BuiltinsDep {
- addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain))
- }
- if runtimeLibrary != "" && (toolchain.Bionic() || c.sanitize.Properties.UbsanRuntimeDep) {
- // UBSan is supported on non-bionic linux host builds as well
- // Adding dependency to the runtime library. We are using *FarVariation*
- // because the runtime libraries themselves are not mutated by sanitizer
- // mutators and thus don't have sanitizer variants whereas this module
- // has been already mutated.
- //
- // Note that by adding dependency with {static|shared}DepTag, the lib is
- // added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
- if c.staticBinary() {
- addStaticDeps(runtimeLibrary)
- addStaticDeps(extraStaticDeps...)
- } else if !c.static() && !c.Header() {
- // If we're using snapshots, redirect to snapshot whenever possible
- snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
- if lib, ok := snapshot.SharedLibs[runtimeLibrary]; ok {
- runtimeLibrary = lib
- }
- // Skip apex dependency check for sharedLibraryDependency
- // when sanitizer diags are enabled. Skipping the check will allow
- // building with diag libraries without having to list the
- // dependency in Apex's allowed_deps file.
- diagEnabled := len(diagSanitizers) > 0
- // dynamic executable and shared libs get shared runtime libs
- depTag := libraryDependencyTag{
- Kind: sharedLibraryDependency,
- Order: earlyLibraryDependency,
- skipApexAllowedDependenciesCheck: diagEnabled,
- }
- variations := append(mctx.Target().Variations(),
- blueprint.Variation{Mutator: "link", Variation: "shared"})
- if c.Device() {
- variations = append(variations, c.ImageVariation())
- }
- if c.UseSdk() {
- variations = append(variations,
- blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
- }
- AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeLibrary, "", true)
- }
- // static lib does not have dependency to the runtime library. The
- // dependency will be added to the executables or shared libs using
- // the static lib.
- }
- }
- }
- type Sanitizeable interface {
- android.Module
- IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool
- EnableSanitizer(sanitizerName string)
- AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
- }
- func (c *Module) MinimalRuntimeDep() bool {
- return c.sanitize.Properties.MinimalRuntimeDep
- }
- func (c *Module) UbsanRuntimeDep() bool {
- return c.sanitize.Properties.UbsanRuntimeDep
- }
- func (c *Module) SanitizePropDefined() bool {
- return c.sanitize != nil
- }
- func (c *Module) IsSanitizerEnabled(t SanitizerType) bool {
- return c.sanitize.isSanitizerEnabled(t)
- }
- func (c *Module) SanitizeDep() bool {
- return c.sanitize.Properties.SanitizeDep
- }
- func (c *Module) StaticallyLinked() bool {
- return c.static()
- }
- func (c *Module) SetInSanitizerDir() {
- if c.sanitize != nil {
- c.sanitize.Properties.InSanitizerDir = true
- }
- }
- func (c *Module) SetSanitizer(t SanitizerType, b bool) {
- if c.sanitize != nil {
- c.sanitize.SetSanitizer(t, b)
- }
- }
- func (c *Module) SetSanitizeDep(b bool) {
- if c.sanitize != nil {
- c.sanitize.Properties.SanitizeDep = b
- }
- }
- var _ PlatformSanitizeable = (*Module)(nil)
- // Create sanitized variants for modules that need them
- func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
- return func(mctx android.BottomUpMutatorContext) {
- if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
- // Make sure we're not setting CFI to any value if it's not supported.
- cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
- if c.Binary() && c.IsSanitizerEnabled(t) {
- modules := mctx.CreateVariations(t.variationName())
- modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
- } else if c.IsSanitizerEnabled(t) || c.SanitizeDep() {
- isSanitizerEnabled := c.IsSanitizerEnabled(t)
- if c.StaticallyLinked() || c.Header() || t == Fuzzer {
- // Static and header libs are split into non-sanitized and sanitized variants.
- // Shared libs are not split. However, for asan and fuzzer, we split even for shared
- // libs because a library sanitized for asan/fuzzer can't be linked from a library
- // that isn't sanitized for asan/fuzzer.
- //
- // Note for defaultVariation: since we don't split for shared libs but for static/header
- // libs, it is possible for the sanitized variant of a static/header lib to depend
- // on non-sanitized variant of a shared lib. Such unfulfilled variation causes an
- // error when the module is split. defaultVariation is the name of the variation that
- // will be used when such a dangling dependency occurs during the split of the current
- // module. By setting it to the name of the sanitized variation, the dangling dependency
- // is redirected to the sanitized variant of the dependent module.
- defaultVariation := t.variationName()
- // Not all PlatformSanitizeable modules support the CFI sanitizer
- mctx.SetDefaultDependencyVariation(&defaultVariation)
- modules := mctx.CreateVariations("", t.variationName())
- modules[0].(PlatformSanitizeable).SetSanitizer(t, false)
- modules[1].(PlatformSanitizeable).SetSanitizer(t, true)
- modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
- modules[1].(PlatformSanitizeable).SetSanitizeDep(false)
- if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
- // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
- // are incompatible with cfi
- modules[1].(PlatformSanitizeable).SetSanitizer(cfi, false)
- }
- // For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
- // to Make, because the sanitized version has a different suffix in name.
- // For other types of sanitizers, suppress the variation that is disabled.
- if t != cfi && t != scs && t != Hwasan {
- if isSanitizerEnabled {
- modules[0].(PlatformSanitizeable).SetPreventInstall()
- modules[0].(PlatformSanitizeable).SetHideFromMake()
- } else {
- modules[1].(PlatformSanitizeable).SetPreventInstall()
- modules[1].(PlatformSanitizeable).SetHideFromMake()
- }
- }
- // Export the static lib name to make
- if c.StaticallyLinked() && c.ExportedToMake() {
- if t == cfi {
- cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
- } else if t == Hwasan {
- hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
- }
- }
- } else {
- // Shared libs are not split. Only the sanitized variant is created.
- modules := mctx.CreateVariations(t.variationName())
- modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
- modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
- // locate the asan libraries under /data/asan
- if mctx.Device() && t == Asan && isSanitizerEnabled {
- modules[0].(PlatformSanitizeable).SetInSanitizerDir()
- }
- if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
- // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
- // are incompatible with cfi
- modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false)
- }
- }
- }
- c.SetSanitizeDep(false)
- } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
- // APEX modules fall here
- sanitizeable.AddSanitizerDependencies(mctx, t.name())
- mctx.CreateVariations(t.variationName())
- } else if c, ok := mctx.Module().(*Module); ok {
- //TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
- // Check if it's a snapshot module supporting sanitizer
- if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
- // Set default variation as above.
- defaultVariation := t.variationName()
- mctx.SetDefaultDependencyVariation(&defaultVariation)
- modules := mctx.CreateVariations("", t.variationName())
- modules[0].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, false)
- modules[1].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, true)
- // Export the static lib name to make
- if c.static() && c.ExportedToMake() {
- if t == cfi {
- // use BaseModuleName which is the name for Make.
- cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
- }
- }
- }
- }
- }
- }
- type sanitizerStaticLibsMap struct {
- // libsMap contains one list of modules per each image and each arch.
- // e.g. libs[vendor]["arm"] contains arm modules installed to vendor
- libsMap map[ImageVariantType]map[string][]string
- libsMapLock sync.Mutex
- sanitizerType SanitizerType
- }
- func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap {
- return &sanitizerStaticLibsMap{
- sanitizerType: t,
- libsMap: make(map[ImageVariantType]map[string][]string),
- }
- }
- // Add the current module to sanitizer static libs maps
- // Each module should pass its exported name as names of Make and Soong can differ.
- func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) {
- image := GetImageVariantType(c)
- arch := c.Module().Target().Arch.ArchType.String()
- s.libsMapLock.Lock()
- defer s.libsMapLock.Unlock()
- if _, ok := s.libsMap[image]; !ok {
- s.libsMap[image] = make(map[string][]string)
- }
- s.libsMap[image][arch] = append(s.libsMap[image][arch], name)
- }
- // Exports makefile variables in the following format:
- // SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES
- // e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES
- // These are to be used by use_soong_sanitized_static_libraries.
- // See build/make/core/binary.mk for more details.
- func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
- for _, image := range android.SortedStringKeys(s.libsMap) {
- archMap := s.libsMap[ImageVariantType(image)]
- for _, arch := range android.SortedStringKeys(archMap) {
- libs := archMap[arch]
- sort.Strings(libs)
- key := fmt.Sprintf(
- "SOONG_%s_%s_%s_STATIC_LIBRARIES",
- s.sanitizerType.variationName(),
- image, // already upper
- arch)
- ctx.Strict(key, strings.Join(libs, " "))
- }
- }
- }
- var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs")
- func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap {
- return config.Once(cfiStaticLibsKey, func() interface{} {
- return newSanitizerStaticLibsMap(cfi)
- }).(*sanitizerStaticLibsMap)
- }
- var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs")
- func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
- return config.Once(hwasanStaticLibsKey, func() interface{} {
- return newSanitizerStaticLibsMap(Hwasan)
- }).(*sanitizerStaticLibsMap)
- }
- func enableMinimalRuntime(sanitize *sanitize) bool {
- if !Bool(sanitize.Properties.Sanitize.Address) &&
- !Bool(sanitize.Properties.Sanitize.Hwaddress) &&
- !Bool(sanitize.Properties.Sanitize.Fuzzer) &&
- (Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
- len(sanitize.Properties.Sanitize.Misc_undefined) > 0 ||
- Bool(sanitize.Properties.Sanitize.Undefined) ||
- Bool(sanitize.Properties.Sanitize.All_undefined)) &&
- !(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
- Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
- Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
- len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
- return true
- }
- return false
- }
- func (m *Module) UbsanRuntimeNeeded() bool {
- return enableUbsanRuntime(m.sanitize)
- }
- func (m *Module) MinimalRuntimeNeeded() bool {
- return enableMinimalRuntime(m.sanitize)
- }
- func enableUbsanRuntime(sanitize *sanitize) bool {
- return Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
- Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
- len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0
- }
- func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
- cfiStaticLibs(ctx.Config()).exportToMake(ctx)
- }
- func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
- hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
- }
|