github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/sanitize.go (about) 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 15 package cc 16 17 import ( 18 "fmt" 19 "io" 20 "sort" 21 "strings" 22 "sync" 23 24 "android/soong/android" 25 "android/soong/cc/config" 26 ) 27 28 var ( 29 // Any C flags added by sanitizer which libTooling tools may not 30 // understand also need to be added to ClangLibToolingUnknownCflags in 31 // cc/config/clang.go 32 33 asanCflags = []string{"-fno-omit-frame-pointer"} 34 asanLdflags = []string{"-Wl,-u,__asan_preinit"} 35 asanLibs = []string{"libasan"} 36 37 cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso", 38 "-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"} 39 cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi", 40 "-Wl,-plugin-opt,O1"} 41 cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map" 42 cfiStaticLibsMutex sync.Mutex 43 44 intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"} 45 minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer", "-fno-sanitize-recover=integer"} 46 ) 47 48 type sanitizerType int 49 50 func boolPtr(v bool) *bool { 51 if v { 52 return &v 53 } else { 54 return nil 55 } 56 } 57 58 const ( 59 asan sanitizerType = iota + 1 60 tsan 61 intOverflow 62 cfi 63 ) 64 65 func (t sanitizerType) String() string { 66 switch t { 67 case asan: 68 return "asan" 69 case tsan: 70 return "tsan" 71 case intOverflow: 72 return "intOverflow" 73 case cfi: 74 return "cfi" 75 default: 76 panic(fmt.Errorf("unknown sanitizerType %d", t)) 77 } 78 } 79 80 type SanitizeProperties struct { 81 // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer 82 Sanitize struct { 83 Never *bool `android:"arch_variant"` 84 85 // main sanitizers 86 Address *bool `android:"arch_variant"` 87 Thread *bool `android:"arch_variant"` 88 89 // local sanitizers 90 Undefined *bool `android:"arch_variant"` 91 All_undefined *bool `android:"arch_variant"` 92 Misc_undefined []string `android:"arch_variant"` 93 Coverage *bool `android:"arch_variant"` 94 Safestack *bool `android:"arch_variant"` 95 Cfi *bool `android:"arch_variant"` 96 Integer_overflow *bool `android:"arch_variant"` 97 98 // Sanitizers to run in the diagnostic mode (as opposed to the release mode). 99 // Replaces abort() on error with a human-readable error message. 100 // Address and Thread sanitizers always run in diagnostic mode. 101 Diag struct { 102 Undefined *bool `android:"arch_variant"` 103 Cfi *bool `android:"arch_variant"` 104 Integer_overflow *bool `android:"arch_variant"` 105 Misc_undefined []string `android:"arch_variant"` 106 } 107 108 // value to pass to -fsanitize-recover= 109 Recover []string 110 111 // value to pass to -fsanitize-blacklist 112 Blacklist *string 113 } `android:"arch_variant"` 114 115 SanitizerEnabled bool `blueprint:"mutated"` 116 SanitizeDep bool `blueprint:"mutated"` 117 MinimalRuntimeDep bool `blueprint:"mutated"` 118 InSanitizerDir bool `blueprint:"mutated"` 119 } 120 121 type sanitize struct { 122 Properties SanitizeProperties 123 124 runtimeLibrary string 125 androidMkRuntimeLibrary string 126 } 127 128 func init() { 129 android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider) 130 } 131 132 func (sanitize *sanitize) props() []interface{} { 133 return []interface{}{&sanitize.Properties} 134 } 135 136 func (sanitize *sanitize) begin(ctx BaseModuleContext) { 137 s := &sanitize.Properties.Sanitize 138 139 // Don't apply sanitizers to NDK code. 140 if ctx.useSdk() { 141 s.Never = BoolPtr(true) 142 } 143 144 // Never always wins. 145 if Bool(s.Never) { 146 return 147 } 148 149 var globalSanitizers []string 150 var globalSanitizersDiag []string 151 152 if ctx.clang() { 153 if ctx.Host() { 154 globalSanitizers = ctx.Config().SanitizeHost() 155 } else { 156 arches := ctx.Config().SanitizeDeviceArch() 157 if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) { 158 globalSanitizers = ctx.Config().SanitizeDevice() 159 globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag() 160 } 161 } 162 } 163 164 if len(globalSanitizers) > 0 { 165 var found bool 166 if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil { 167 s.All_undefined = boolPtr(true) 168 } 169 170 if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil { 171 s.Undefined = boolPtr(true) 172 } 173 174 if found, globalSanitizers = removeFromList("address", globalSanitizers); found { 175 if s.Address == nil { 176 s.Address = boolPtr(true) 177 } else if *s.Address == false { 178 // Coverage w/o address is an error. If globalSanitizers includes both, and the module 179 // disables address, then disable coverage as well. 180 _, globalSanitizers = removeFromList("coverage", globalSanitizers) 181 } 182 } 183 184 if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil { 185 s.Thread = boolPtr(true) 186 } 187 188 if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found && s.Coverage == nil { 189 s.Coverage = boolPtr(true) 190 } 191 192 if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil { 193 s.Safestack = boolPtr(true) 194 } 195 196 if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil { 197 if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) { 198 s.Cfi = boolPtr(true) 199 } 200 } 201 202 if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil { 203 if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) { 204 s.Integer_overflow = boolPtr(true) 205 } 206 } 207 208 if len(globalSanitizers) > 0 { 209 ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0]) 210 } 211 212 if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found && 213 s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) { 214 s.Diag.Integer_overflow = boolPtr(true) 215 } 216 217 if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found && 218 s.Diag.Cfi == nil && Bool(s.Cfi) { 219 s.Diag.Cfi = boolPtr(true) 220 } 221 222 if len(globalSanitizersDiag) > 0 { 223 ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0]) 224 } 225 } 226 227 // Enable CFI for all components in the include paths (for Aarch64 only) 228 if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 { 229 s.Cfi = boolPtr(true) 230 if inList("cfi", ctx.Config().SanitizeDeviceDiag()) { 231 s.Diag.Cfi = boolPtr(true) 232 } 233 } 234 235 // CFI needs gold linker, and mips toolchain does not have one. 236 if !ctx.Config().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 { 237 s.Cfi = nil 238 s.Diag.Cfi = nil 239 } 240 241 // Also disable CFI for arm32 until b/35157333 is fixed. 242 if ctx.Arch().ArchType == android.Arm { 243 s.Cfi = nil 244 s.Diag.Cfi = nil 245 } 246 247 // Also disable CFI if ASAN is enabled. 248 if Bool(s.Address) { 249 s.Cfi = nil 250 s.Diag.Cfi = nil 251 } 252 253 // Also disable CFI for host builds. 254 if ctx.Host() { 255 s.Cfi = nil 256 s.Diag.Cfi = nil 257 } 258 259 // Also disable CFI for VNDK variants of components 260 if ctx.isVndk() && ctx.useVndk() { 261 s.Cfi = nil 262 s.Diag.Cfi = nil 263 } 264 265 if ctx.staticBinary() { 266 s.Address = nil 267 s.Coverage = nil 268 s.Thread = nil 269 } 270 271 if Bool(s.All_undefined) { 272 s.Undefined = nil 273 } 274 275 if !ctx.toolchain().Is64Bit() { 276 // TSAN and SafeStack are not supported on 32-bit architectures 277 s.Thread = nil 278 s.Safestack = nil 279 // TODO(ccross): error for compile_multilib = "32"? 280 } 281 282 if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) || 283 Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0) { 284 sanitize.Properties.SanitizerEnabled = true 285 } 286 287 if Bool(s.Coverage) { 288 if !Bool(s.Address) { 289 ctx.ModuleErrorf(`Use of "coverage" also requires "address"`) 290 } 291 } 292 } 293 294 func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps { 295 if !sanitize.Properties.SanitizerEnabled { // || c.static() { 296 return deps 297 } 298 299 if ctx.Device() { 300 if Bool(sanitize.Properties.Sanitize.Address) { 301 deps.StaticLibs = append(deps.StaticLibs, asanLibs...) 302 } 303 } 304 305 return deps 306 } 307 308 func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { 309 minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a" 310 minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib 311 312 if ctx.Device() && sanitize.Properties.MinimalRuntimeDep { 313 flags.LdFlags = append(flags.LdFlags, minimalRuntimePath) 314 flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib) 315 } 316 if !sanitize.Properties.SanitizerEnabled { 317 return flags 318 } 319 320 if !ctx.clang() { 321 ctx.ModuleErrorf("Use of sanitizers requires clang") 322 } 323 324 var sanitizers []string 325 var diagSanitizers []string 326 327 if Bool(sanitize.Properties.Sanitize.All_undefined) { 328 sanitizers = append(sanitizers, "undefined") 329 } else { 330 if Bool(sanitize.Properties.Sanitize.Undefined) { 331 sanitizers = append(sanitizers, 332 "bool", 333 "integer-divide-by-zero", 334 "return", 335 "returns-nonnull-attribute", 336 "shift-exponent", 337 "unreachable", 338 "vla-bound", 339 // TODO(danalbert): The following checks currently have compiler performance issues. 340 //"alignment", 341 //"bounds", 342 //"enum", 343 //"float-cast-overflow", 344 //"float-divide-by-zero", 345 //"nonnull-attribute", 346 //"null", 347 //"shift-base", 348 //"signed-integer-overflow", 349 // TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on. 350 // https://llvm.org/PR19302 351 // http://reviews.llvm.org/D6974 352 // "object-size", 353 ) 354 } 355 sanitizers = append(sanitizers, sanitize.Properties.Sanitize.Misc_undefined...) 356 } 357 358 if Bool(sanitize.Properties.Sanitize.Diag.Undefined) { 359 diagSanitizers = append(diagSanitizers, "undefined") 360 } 361 362 diagSanitizers = append(diagSanitizers, sanitize.Properties.Sanitize.Diag.Misc_undefined...) 363 364 if Bool(sanitize.Properties.Sanitize.Address) { 365 if ctx.Arch().ArchType == android.Arm { 366 // Frame pointer based unwinder in ASan requires ARM frame setup. 367 // TODO: put in flags? 368 flags.RequiredInstructionSet = "arm" 369 } 370 flags.CFlags = append(flags.CFlags, asanCflags...) 371 flags.LdFlags = append(flags.LdFlags, asanLdflags...) 372 373 if ctx.Host() { 374 // -nodefaultlibs (provided with libc++) prevents the driver from linking 375 // libraries needed with -fsanitize=address. http://b/18650275 (WAI) 376 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-as-needed") 377 } else { 378 flags.CFlags = append(flags.CFlags, "-mllvm", "-asan-globals=0") 379 flags.DynamicLinker = "/system/bin/linker_asan" 380 if flags.Toolchain.Is64Bit() { 381 flags.DynamicLinker += "64" 382 } 383 } 384 sanitizers = append(sanitizers, "address") 385 diagSanitizers = append(diagSanitizers, "address") 386 } 387 388 if Bool(sanitize.Properties.Sanitize.Thread) { 389 sanitizers = append(sanitizers, "thread") 390 } 391 392 if Bool(sanitize.Properties.Sanitize.Coverage) { 393 flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp") 394 } 395 396 if Bool(sanitize.Properties.Sanitize.Safestack) { 397 sanitizers = append(sanitizers, "safe-stack") 398 } 399 400 if Bool(sanitize.Properties.Sanitize.Cfi) { 401 if ctx.Arch().ArchType == android.Arm { 402 // __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up 403 // to do this on a function basis, so force Thumb on the entire module. 404 flags.RequiredInstructionSet = "thumb" 405 } 406 sanitizers = append(sanitizers, "cfi") 407 408 flags.CFlags = append(flags.CFlags, cfiCflags...) 409 // Only append the default visibility flag if -fvisibility has not already been set 410 // to hidden. 411 if !inList("-fvisibility=hidden", flags.CFlags) { 412 flags.CFlags = append(flags.CFlags, "-fvisibility=default") 413 } 414 flags.LdFlags = append(flags.LdFlags, cfiLdflags...) 415 if ctx.Device() { 416 // Work around a bug in Clang. The CFI sanitizer requires LTO, and when 417 // LTO is enabled, the Clang driver fails to enable emutls for Android. 418 // See b/72706604 or https://github.com/android-ndk/ndk/issues/498. 419 flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-emulated-tls") 420 } 421 flags.ArGoldPlugin = true 422 if Bool(sanitize.Properties.Sanitize.Diag.Cfi) { 423 diagSanitizers = append(diagSanitizers, "cfi") 424 } 425 426 if ctx.staticBinary() { 427 _, flags.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.CFlags) 428 _, flags.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.LdFlags) 429 } 430 } 431 432 if Bool(sanitize.Properties.Sanitize.Integer_overflow) { 433 if !ctx.static() { 434 sanitizers = append(sanitizers, "unsigned-integer-overflow") 435 sanitizers = append(sanitizers, "signed-integer-overflow") 436 flags.CFlags = append(flags.CFlags, intOverflowCflags...) 437 if Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) { 438 diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow") 439 diagSanitizers = append(diagSanitizers, "signed-integer-overflow") 440 } 441 } 442 } 443 444 if len(sanitizers) > 0 { 445 sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",") 446 447 flags.CFlags = append(flags.CFlags, sanitizeArg) 448 if ctx.Host() { 449 flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all") 450 flags.LdFlags = append(flags.LdFlags, sanitizeArg) 451 // Host sanitizers only link symbols in the final executable, so 452 // there will always be undefined symbols in intermediate libraries. 453 _, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags) 454 } else { 455 flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort") 456 457 if enableMinimalRuntime(sanitize) { 458 flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " ")) 459 flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...) 460 flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib) 461 } 462 } 463 } 464 465 if len(diagSanitizers) > 0 { 466 flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap="+strings.Join(diagSanitizers, ",")) 467 } 468 // FIXME: enable RTTI if diag + (cfi or vptr) 469 470 if sanitize.Properties.Sanitize.Recover != nil { 471 flags.CFlags = append(flags.CFlags, "-fsanitize-recover="+ 472 strings.Join(sanitize.Properties.Sanitize.Recover, ",")) 473 } 474 475 // Link a runtime library if needed. 476 runtimeLibrary := "" 477 if Bool(sanitize.Properties.Sanitize.Address) { 478 runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain()) 479 } else if Bool(sanitize.Properties.Sanitize.Thread) { 480 runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain()) 481 } else if len(diagSanitizers) > 0 { 482 runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain()) 483 } 484 485 if runtimeLibrary != "" { 486 // ASan runtime library must be the first in the link order. 487 flags.libFlags = append([]string{ 488 "${config.ClangAsanLibDir}/" + runtimeLibrary + ctx.toolchain().ShlibSuffix(), 489 }, flags.libFlags...) 490 sanitize.runtimeLibrary = runtimeLibrary 491 492 // When linking against VNDK, use the vendor variant of the runtime lib 493 sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary 494 if ctx.useVndk() { 495 sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix 496 } 497 } 498 499 blacklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist) 500 if blacklist.Valid() { 501 flags.CFlags = append(flags.CFlags, "-fsanitize-blacklist="+blacklist.String()) 502 flags.CFlagsDeps = append(flags.CFlagsDeps, blacklist.Path()) 503 } 504 505 return flags 506 } 507 508 func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { 509 ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { 510 if sanitize.androidMkRuntimeLibrary != "" { 511 fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES += "+sanitize.androidMkRuntimeLibrary) 512 } 513 }) 514 515 // Add a suffix for CFI-enabled static libraries to allow surfacing both to make without a 516 // name conflict. 517 if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Cfi) { 518 ret.SubName += ".cfi" 519 } 520 } 521 522 func (sanitize *sanitize) inSanitizerDir() bool { 523 return sanitize.Properties.InSanitizerDir 524 } 525 526 func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool { 527 switch t { 528 case asan: 529 return sanitize.Properties.Sanitize.Address 530 case tsan: 531 return sanitize.Properties.Sanitize.Thread 532 case intOverflow: 533 return sanitize.Properties.Sanitize.Integer_overflow 534 case cfi: 535 return sanitize.Properties.Sanitize.Cfi 536 default: 537 panic(fmt.Errorf("unknown sanitizerType %d", t)) 538 } 539 } 540 541 func (sanitize *sanitize) isUnsanitizedVariant() bool { 542 return !sanitize.isSanitizerEnabled(asan) && 543 !sanitize.isSanitizerEnabled(tsan) && 544 !sanitize.isSanitizerEnabled(cfi) 545 } 546 547 func (sanitize *sanitize) isVariantOnProductionDevice() bool { 548 return !sanitize.isSanitizerEnabled(asan) && 549 !sanitize.isSanitizerEnabled(tsan) 550 } 551 552 func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { 553 switch t { 554 case asan: 555 sanitize.Properties.Sanitize.Address = boolPtr(b) 556 if !b { 557 sanitize.Properties.Sanitize.Coverage = nil 558 } 559 case tsan: 560 sanitize.Properties.Sanitize.Thread = boolPtr(b) 561 case intOverflow: 562 sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b) 563 case cfi: 564 sanitize.Properties.Sanitize.Cfi = boolPtr(b) 565 sanitize.Properties.Sanitize.Diag.Cfi = boolPtr(b) 566 default: 567 panic(fmt.Errorf("unknown sanitizerType %d", t)) 568 } 569 if b { 570 sanitize.Properties.SanitizerEnabled = true 571 } 572 } 573 574 // Check if the sanitizer is explicitly disabled (as opposed to nil by 575 // virtue of not being set). 576 func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool { 577 if sanitize == nil { 578 return false 579 } 580 581 sanitizerVal := sanitize.getSanitizerBoolPtr(t) 582 return sanitizerVal != nil && *sanitizerVal == false 583 } 584 585 // There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled) 586 // because enabling a sanitizer either directly (via the blueprint) or 587 // indirectly (via a mutator) sets the bool ptr to true, and you can't 588 // distinguish between the cases. It isn't needed though - both cases can be 589 // treated identically. 590 func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { 591 if sanitize == nil { 592 return false 593 } 594 595 sanitizerVal := sanitize.getSanitizerBoolPtr(t) 596 return sanitizerVal != nil && *sanitizerVal == true 597 } 598 599 // Propagate asan requirements down from binaries 600 func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) { 601 return func(mctx android.TopDownMutatorContext) { 602 if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) { 603 mctx.VisitDepsDepthFirst(func(module android.Module) { 604 if d, ok := module.(*Module); ok && d.sanitize != nil && 605 !Bool(d.sanitize.Properties.Sanitize.Never) && 606 !d.sanitize.isSanitizerExplicitlyDisabled(t) { 607 if (t == cfi && d.static()) || t != cfi { 608 d.sanitize.Properties.SanitizeDep = true 609 } 610 } 611 }) 612 } 613 } 614 } 615 616 // Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies. 617 func minimalRuntimeDepsMutator() func(android.TopDownMutatorContext) { 618 return func(mctx android.TopDownMutatorContext) { 619 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 620 mctx.VisitDepsDepthFirst(func(module android.Module) { 621 if d, ok := module.(*Module); ok && d.static() && d.sanitize != nil { 622 623 // If a static dependency will be built with the minimal runtime, 624 // make sure we include the ubsan minimal runtime. 625 if enableMinimalRuntime(d.sanitize) { 626 c.sanitize.Properties.MinimalRuntimeDep = true 627 } 628 } 629 }) 630 } 631 } 632 } 633 634 // Create sanitized variants for modules that need them 635 func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { 636 return func(mctx android.BottomUpMutatorContext) { 637 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 638 if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) { 639 modules := mctx.CreateVariations(t.String()) 640 modules[0].(*Module).sanitize.SetSanitizer(t, true) 641 } else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep { 642 // Save original sanitizer status before we assign values to variant 643 // 0 as that overwrites the original. 644 isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t) 645 646 modules := mctx.CreateVariations("", t.String()) 647 modules[0].(*Module).sanitize.SetSanitizer(t, false) 648 modules[1].(*Module).sanitize.SetSanitizer(t, true) 649 650 modules[0].(*Module).sanitize.Properties.SanitizeDep = false 651 modules[1].(*Module).sanitize.Properties.SanitizeDep = false 652 653 // We don't need both variants active for anything but CFI-enabled 654 // target static libraries, so suppress the appropriate variant in 655 // all other cases. 656 if t == cfi { 657 if c.static() { 658 if !mctx.Device() { 659 if isSanitizerEnabled { 660 modules[0].(*Module).Properties.PreventInstall = true 661 modules[0].(*Module).Properties.HideFromMake = true 662 } else { 663 modules[1].(*Module).Properties.PreventInstall = true 664 modules[1].(*Module).Properties.HideFromMake = true 665 } 666 } else { 667 cfiStaticLibs := cfiStaticLibs(mctx.Config()) 668 669 cfiStaticLibsMutex.Lock() 670 *cfiStaticLibs = append(*cfiStaticLibs, c.Name()) 671 cfiStaticLibsMutex.Unlock() 672 } 673 } else { 674 modules[0].(*Module).Properties.PreventInstall = true 675 modules[0].(*Module).Properties.HideFromMake = true 676 } 677 } else if t == asan { 678 if mctx.Device() { 679 // CFI and ASAN are currently mutually exclusive so disable 680 // CFI if this is an ASAN variant. 681 modules[1].(*Module).sanitize.Properties.InSanitizerDir = true 682 modules[1].(*Module).sanitize.SetSanitizer(cfi, false) 683 } 684 if isSanitizerEnabled { 685 modules[0].(*Module).Properties.PreventInstall = true 686 modules[0].(*Module).Properties.HideFromMake = true 687 } else { 688 modules[1].(*Module).Properties.PreventInstall = true 689 modules[1].(*Module).Properties.HideFromMake = true 690 } 691 } 692 } 693 c.sanitize.Properties.SanitizeDep = false 694 } 695 } 696 } 697 698 func cfiStaticLibs(config android.Config) *[]string { 699 return config.Once("cfiStaticLibs", func() interface{} { 700 return &[]string{} 701 }).(*[]string) 702 } 703 704 func enableMinimalRuntime(sanitize *sanitize) bool { 705 if !Bool(sanitize.Properties.Sanitize.Address) && 706 (Bool(sanitize.Properties.Sanitize.Integer_overflow) || 707 len(sanitize.Properties.Sanitize.Misc_undefined) > 0) && 708 !(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) || 709 Bool(sanitize.Properties.Sanitize.Diag.Cfi) || 710 len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) { 711 return true 712 } 713 return false 714 } 715 716 func cfiMakeVarsProvider(ctx android.MakeVarsContext) { 717 cfiStaticLibs := cfiStaticLibs(ctx.Config()) 718 sort.Strings(*cfiStaticLibs) 719 ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " ")) 720 }