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 25 "android/soong/android" 26 "android/soong/cc/config" 27) 28 29var ( 30 // Any C flags added by sanitizer which libTooling tools may not 31 // understand also need to be added to ClangLibToolingUnknownCflags in 32 // cc/config/clang.go 33 34 asanCflags = []string{ 35 "-fno-omit-frame-pointer", 36 "-fno-experimental-new-pass-manager", 37 } 38 asanLdflags = []string{"-Wl,-u,__asan_preinit"} 39 40 hwasanCflags = []string{"-fno-omit-frame-pointer", "-Wno-frame-larger-than=", 41 "-fsanitize-hwaddress-abi=platform", 42 "-fno-experimental-new-pass-manager", 43 // The following improves debug location information 44 // availability at the cost of its accuracy. It increases 45 // the likelihood of a stack variable's frame offset 46 // to be recorded in the debug info, which is important 47 // for the quality of hwasan reports. The downside is a 48 // higher number of "optimized out" stack variables. 49 // b/112437883. 50 "-mllvm", "-instcombine-lower-dbg-declare=0", 51 // TODO(b/159343917): HWASan and GlobalISel don't play nicely, and 52 // GlobalISel is the default at -O0 on aarch64. 53 "-mllvm", "--aarch64-enable-global-isel-at-O=-1", 54 "-mllvm", "-fast-isel=false", 55 } 56 57 cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso", 58 "-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"} 59 // -flto and -fvisibility are required by clang when -fsanitize=cfi is 60 // used, but have no effect on assembly files 61 cfiAsflags = []string{"-flto", "-fvisibility=default"} 62 cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi", 63 "-Wl,-plugin-opt,O1"} 64 cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map" 65 cfiStaticLibsMutex sync.Mutex 66 hwasanStaticLibsMutex sync.Mutex 67 68 intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"} 69 70 minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined", 71 "-fno-sanitize-recover=integer,undefined"} 72 hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512", 73 "export_memory_stats=0", "max_malloc_fill_size=0"} 74) 75 76type sanitizerType int 77 78func boolPtr(v bool) *bool { 79 if v { 80 return &v 81 } else { 82 return nil 83 } 84} 85 86const ( 87 asan sanitizerType = iota + 1 88 hwasan 89 tsan 90 intOverflow 91 cfi 92 scs 93 fuzzer 94) 95 96// Name of the sanitizer variation for this sanitizer type 97func (t sanitizerType) variationName() string { 98 switch t { 99 case asan: 100 return "asan" 101 case hwasan: 102 return "hwasan" 103 case tsan: 104 return "tsan" 105 case intOverflow: 106 return "intOverflow" 107 case cfi: 108 return "cfi" 109 case scs: 110 return "scs" 111 case fuzzer: 112 return "fuzzer" 113 default: 114 panic(fmt.Errorf("unknown sanitizerType %d", t)) 115 } 116} 117 118// This is the sanitizer names in SANITIZE_[TARGET|HOST] 119func (t sanitizerType) name() string { 120 switch t { 121 case asan: 122 return "address" 123 case hwasan: 124 return "hwaddress" 125 case tsan: 126 return "thread" 127 case intOverflow: 128 return "integer_overflow" 129 case cfi: 130 return "cfi" 131 case scs: 132 return "shadow-call-stack" 133 case fuzzer: 134 return "fuzzer" 135 default: 136 panic(fmt.Errorf("unknown sanitizerType %d", t)) 137 } 138} 139 140func (t sanitizerType) incompatibleWithCfi() bool { 141 return t == asan || t == fuzzer || t == hwasan 142} 143 144type SanitizeProperties struct { 145 // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer 146 Sanitize struct { 147 Never *bool `android:"arch_variant"` 148 149 // main sanitizers 150 Address *bool `android:"arch_variant"` 151 Thread *bool `android:"arch_variant"` 152 Hwaddress *bool `android:"arch_variant"` 153 154 // local sanitizers 155 Undefined *bool `android:"arch_variant"` 156 All_undefined *bool `android:"arch_variant"` 157 Misc_undefined []string `android:"arch_variant"` 158 Fuzzer *bool `android:"arch_variant"` 159 Safestack *bool `android:"arch_variant"` 160 Cfi *bool `android:"arch_variant"` 161 Integer_overflow *bool `android:"arch_variant"` 162 Scudo *bool `android:"arch_variant"` 163 Scs *bool `android:"arch_variant"` 164 165 // Sanitizers to run in the diagnostic mode (as opposed to the release mode). 166 // Replaces abort() on error with a human-readable error message. 167 // Address and Thread sanitizers always run in diagnostic mode. 168 Diag struct { 169 Undefined *bool `android:"arch_variant"` 170 Cfi *bool `android:"arch_variant"` 171 Integer_overflow *bool `android:"arch_variant"` 172 Misc_undefined []string `android:"arch_variant"` 173 No_recover []string 174 } 175 176 // value to pass to -fsanitize-recover= 177 Recover []string 178 179 // value to pass to -fsanitize-blacklist 180 Blacklist *string 181 } `android:"arch_variant"` 182 183 SanitizerEnabled bool `blueprint:"mutated"` 184 SanitizeDep bool `blueprint:"mutated"` 185 MinimalRuntimeDep bool `blueprint:"mutated"` 186 BuiltinsDep bool `blueprint:"mutated"` 187 UbsanRuntimeDep bool `blueprint:"mutated"` 188 InSanitizerDir bool `blueprint:"mutated"` 189 Sanitizers []string `blueprint:"mutated"` 190 DiagSanitizers []string `blueprint:"mutated"` 191} 192 193type sanitize struct { 194 Properties SanitizeProperties 195} 196 197func init() { 198 android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider) 199 android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider) 200} 201 202func (sanitize *sanitize) props() []interface{} { 203 return []interface{}{&sanitize.Properties} 204} 205 206func (sanitize *sanitize) begin(ctx BaseModuleContext) { 207 s := &sanitize.Properties.Sanitize 208 209 // Don't apply sanitizers to NDK code. 210 if ctx.useSdk() { 211 s.Never = BoolPtr(true) 212 } 213 214 // Sanitizers do not work on Fuchsia yet. 215 if ctx.Fuchsia() { 216 s.Never = BoolPtr(true) 217 } 218 219 // Never always wins. 220 if Bool(s.Never) { 221 return 222 } 223 224 var globalSanitizers []string 225 var globalSanitizersDiag []string 226 227 if ctx.Host() { 228 if !ctx.Windows() { 229 globalSanitizers = ctx.Config().SanitizeHost() 230 } 231 } else { 232 arches := ctx.Config().SanitizeDeviceArch() 233 if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) { 234 globalSanitizers = ctx.Config().SanitizeDevice() 235 globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag() 236 } 237 } 238 239 if len(globalSanitizers) > 0 { 240 var found bool 241 if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil { 242 s.All_undefined = boolPtr(true) 243 } 244 245 if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil { 246 s.Undefined = boolPtr(true) 247 } 248 249 if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil { 250 s.Address = boolPtr(true) 251 } 252 253 if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil { 254 s.Thread = boolPtr(true) 255 } 256 257 if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil { 258 s.Fuzzer = boolPtr(true) 259 } 260 261 if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil { 262 s.Safestack = boolPtr(true) 263 } 264 265 if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil { 266 if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) { 267 s.Cfi = boolPtr(true) 268 } 269 } 270 271 // Global integer_overflow builds do not support static libraries. 272 if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil { 273 if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && !ctx.static() { 274 s.Integer_overflow = boolPtr(true) 275 } 276 } 277 278 if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil { 279 s.Scudo = boolPtr(true) 280 } 281 282 if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil { 283 s.Hwaddress = boolPtr(true) 284 } 285 286 if len(globalSanitizers) > 0 { 287 ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0]) 288 } 289 290 // Global integer_overflow builds do not support static library diagnostics. 291 if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found && 292 s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) && !ctx.static() { 293 s.Diag.Integer_overflow = boolPtr(true) 294 } 295 296 if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found && 297 s.Diag.Cfi == nil && Bool(s.Cfi) { 298 s.Diag.Cfi = boolPtr(true) 299 } 300 301 if len(globalSanitizersDiag) > 0 { 302 ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0]) 303 } 304 } 305 306 // Enable CFI for all components in the include paths (for Aarch64 only) 307 if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 { 308 s.Cfi = boolPtr(true) 309 if inList("cfi", ctx.Config().SanitizeDeviceDiag()) { 310 s.Diag.Cfi = boolPtr(true) 311 } 312 } 313 314 // CFI needs gold linker, and mips toolchain does not have one. 315 if !ctx.Config().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 { 316 s.Cfi = nil 317 s.Diag.Cfi = nil 318 } 319 320 // Also disable CFI for arm32 until b/35157333 is fixed. 321 if ctx.Arch().ArchType == android.Arm { 322 s.Cfi = nil 323 s.Diag.Cfi = nil 324 } 325 326 // HWASan requires AArch64 hardware feature (top-byte-ignore). 327 if ctx.Arch().ArchType != android.Arm64 { 328 s.Hwaddress = nil 329 } 330 331 // SCS is only implemented on AArch64. 332 if ctx.Arch().ArchType != android.Arm64 { 333 s.Scs = nil 334 } 335 336 // Also disable CFI if ASAN is enabled. 337 if Bool(s.Address) || Bool(s.Hwaddress) { 338 s.Cfi = nil 339 s.Diag.Cfi = nil 340 } 341 342 // Disable sanitizers that depend on the UBSan runtime for windows/darwin builds. 343 if !ctx.Os().Linux() { 344 s.Cfi = nil 345 s.Diag.Cfi = nil 346 s.Misc_undefined = nil 347 s.Undefined = nil 348 s.All_undefined = nil 349 s.Integer_overflow = nil 350 } 351 352 // Also disable CFI for VNDK variants of components 353 if ctx.isVndk() && ctx.useVndk() { 354 s.Cfi = nil 355 s.Diag.Cfi = nil 356 } 357 358 // Also disable CFI if building against snapshot. 359 vndkVersion := ctx.DeviceConfig().VndkVersion() 360 if ctx.useVndk() && vndkVersion != "current" && vndkVersion != "" { 361 s.Cfi = nil 362 } 363 364 // HWASan ramdisk (which is built from recovery) goes over some bootloader limit. 365 // Keep libc instrumented so that ramdisk / recovery can run hwasan-instrumented code if necessary. 366 if (ctx.inRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") { 367 s.Hwaddress = nil 368 } 369 370 if ctx.staticBinary() { 371 s.Address = nil 372 s.Fuzzer = nil 373 s.Thread = nil 374 } 375 376 if Bool(s.All_undefined) { 377 s.Undefined = nil 378 } 379 380 if !ctx.toolchain().Is64Bit() { 381 // TSAN and SafeStack are not supported on 32-bit architectures 382 s.Thread = nil 383 s.Safestack = nil 384 // TODO(ccross): error for compile_multilib = "32"? 385 } 386 387 if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) || 388 Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 || 389 Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) { 390 sanitize.Properties.SanitizerEnabled = true 391 } 392 393 // Disable Scudo if ASan or TSan is enabled, or if it's disabled globally. 394 if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) || ctx.Config().DisableScudo() { 395 s.Scudo = nil 396 } 397 398 if Bool(s.Hwaddress) { 399 s.Address = nil 400 s.Thread = nil 401 } 402 403 // TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is 404 // mutually incompatible. 405 if Bool(s.Fuzzer) { 406 s.Cfi = nil 407 } 408} 409 410func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps { 411 if !sanitize.Properties.SanitizerEnabled { // || c.static() { 412 return deps 413 } 414 415 if ctx.Device() { 416 if Bool(sanitize.Properties.Sanitize.Address) { 417 // Compiling asan and having libc_scudo in the same 418 // executable will cause the executable to crash. 419 // Remove libc_scudo since it is only used to override 420 // allocation functions which asan already overrides. 421 _, deps.SharedLibs = removeFromList("libc_scudo", deps.SharedLibs) 422 } 423 } 424 425 return deps 426} 427 428func toDisableImplicitIntegerChange(flags []string) bool { 429 // Returns true if any flag is fsanitize*integer, and there is 430 // no explicit flag about sanitize=implicit-integer-sign-change. 431 for _, f := range flags { 432 if strings.Contains(f, "sanitize=implicit-integer-sign-change") { 433 return false 434 } 435 } 436 for _, f := range flags { 437 if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") { 438 return true 439 } 440 } 441 return false 442} 443 444func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { 445 minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a" 446 minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib 447 builtinsRuntimeLib := config.BuiltinsRuntimeLibrary(ctx.toolchain()) + ".a" 448 builtinsRuntimePath := "${config.ClangAsanLibDir}/" + builtinsRuntimeLib 449 450 if sanitize.Properties.MinimalRuntimeDep { 451 flags.Local.LdFlags = append(flags.Local.LdFlags, 452 minimalRuntimePath, 453 "-Wl,--exclude-libs,"+minimalRuntimeLib) 454 } 455 456 if sanitize.Properties.BuiltinsDep { 457 flags.libFlags = append([]string{builtinsRuntimePath}, flags.libFlags...) 458 } 459 460 if !sanitize.Properties.SanitizerEnabled && !sanitize.Properties.UbsanRuntimeDep { 461 return flags 462 } 463 464 if Bool(sanitize.Properties.Sanitize.Address) { 465 if ctx.Arch().ArchType == android.Arm { 466 // Frame pointer based unwinder in ASan requires ARM frame setup. 467 // TODO: put in flags? 468 flags.RequiredInstructionSet = "arm" 469 } 470 flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...) 471 flags.Local.LdFlags = append(flags.Local.LdFlags, asanLdflags...) 472 473 if ctx.Host() { 474 // -nodefaultlibs (provided with libc++) prevents the driver from linking 475 // libraries needed with -fsanitize=address. http://b/18650275 (WAI) 476 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-as-needed") 477 } else { 478 flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-globals=0") 479 if ctx.bootstrap() { 480 flags.DynamicLinker = "/system/bin/bootstrap/linker_asan" 481 } else { 482 flags.DynamicLinker = "/system/bin/linker_asan" 483 } 484 if flags.Toolchain.Is64Bit() { 485 flags.DynamicLinker += "64" 486 } 487 } 488 } 489 490 if Bool(sanitize.Properties.Sanitize.Hwaddress) { 491 flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...) 492 } 493 494 if Bool(sanitize.Properties.Sanitize.Fuzzer) { 495 flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize=fuzzer-no-link") 496 497 // TODO(b/131771163): LTO and Fuzzer support is mutually incompatible. 498 _, flags.Local.LdFlags = removeFromList("-flto", flags.Local.LdFlags) 499 _, flags.Local.CFlags = removeFromList("-flto", flags.Local.CFlags) 500 flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-lto") 501 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-lto") 502 503 // TODO(b/142430592): Upstream linker scripts for sanitizer runtime libraries 504 // discard the sancov_lowest_stack symbol, because it's emulated TLS (and thus 505 // doesn't match the linker script due to the "__emutls_v." prefix). 506 flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth") 507 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth") 508 509 // TODO(b/133876586): Experimental PM breaks sanitizer coverage. 510 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-experimental-new-pass-manager") 511 512 // Disable fortify for fuzzing builds. Generally, we'll be building with 513 // UBSan or ASan here and the fortify checks pollute the stack traces. 514 flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE") 515 516 // Build fuzzer-sanitized libraries with an $ORIGIN DT_RUNPATH. Android's 517 // linker uses DT_RUNPATH, not DT_RPATH. When we deploy cc_fuzz targets and 518 // their libraries to /data/fuzz/<arch>/lib, any transient shared library gets 519 // the DT_RUNPATH from the shared library above it, and not the executable, 520 // meaning that the lookup falls back to the system. Adding the $ORIGIN to the 521 // DT_RUNPATH here means that transient shared libraries can be found 522 // colocated with their parents. 523 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN`) 524 } 525 526 if Bool(sanitize.Properties.Sanitize.Cfi) { 527 if ctx.Arch().ArchType == android.Arm { 528 // __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up 529 // to do this on a function basis, so force Thumb on the entire module. 530 flags.RequiredInstructionSet = "thumb" 531 } 532 533 flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...) 534 flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...) 535 // Only append the default visibility flag if -fvisibility has not already been set 536 // to hidden. 537 if !inList("-fvisibility=hidden", flags.Local.CFlags) { 538 flags.Local.CFlags = append(flags.Local.CFlags, "-fvisibility=default") 539 } 540 flags.Local.LdFlags = append(flags.Local.LdFlags, cfiLdflags...) 541 542 if ctx.staticBinary() { 543 _, flags.Local.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.CFlags) 544 _, flags.Local.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.LdFlags) 545 } 546 } 547 548 if Bool(sanitize.Properties.Sanitize.Integer_overflow) { 549 flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...) 550 } 551 552 if len(sanitize.Properties.Sanitizers) > 0 { 553 sanitizeArg := "-fsanitize=" + strings.Join(sanitize.Properties.Sanitizers, ",") 554 555 flags.Local.CFlags = append(flags.Local.CFlags, sanitizeArg) 556 flags.Local.AsFlags = append(flags.Local.AsFlags, sanitizeArg) 557 if ctx.Host() { 558 // Host sanitizers only link symbols in the final executable, so 559 // there will always be undefined symbols in intermediate libraries. 560 _, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags) 561 flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg) 562 563 // non-Bionic toolchain prebuilts are missing UBSan's vptr and function sanitizers 564 if !ctx.toolchain().Bionic() { 565 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function") 566 } 567 } 568 569 if enableMinimalRuntime(sanitize) { 570 flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " ")) 571 flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...) 572 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib) 573 if !ctx.toolchain().Bionic() { 574 flags.libFlags = append([]string{builtinsRuntimePath}, flags.libFlags...) 575 } 576 } 577 578 if Bool(sanitize.Properties.Sanitize.Fuzzer) { 579 // When fuzzing, we wish to crash with diagnostics on any bug. 580 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all") 581 } else if ctx.Host() { 582 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover=all") 583 } else { 584 flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort") 585 } 586 // http://b/119329758, Android core does not boot up with this sanitizer yet. 587 if toDisableImplicitIntegerChange(flags.Local.CFlags) { 588 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change") 589 } 590 } 591 592 if len(sanitize.Properties.DiagSanitizers) > 0 { 593 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(sanitize.Properties.DiagSanitizers, ",")) 594 } 595 // FIXME: enable RTTI if diag + (cfi or vptr) 596 597 if sanitize.Properties.Sanitize.Recover != nil { 598 flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-recover="+ 599 strings.Join(sanitize.Properties.Sanitize.Recover, ",")) 600 } 601 602 if sanitize.Properties.Sanitize.Diag.No_recover != nil { 603 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover="+ 604 strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ",")) 605 } 606 607 blacklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist) 608 if blacklist.Valid() { 609 flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-blacklist="+blacklist.String()) 610 flags.CFlagsDeps = append(flags.CFlagsDeps, blacklist.Path()) 611 } 612 613 return flags 614} 615 616func (sanitize *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { 617 // Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing 618 // both the sanitized and non-sanitized variants to make without a name conflict. 619 if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" { 620 if Bool(sanitize.Properties.Sanitize.Cfi) { 621 entries.SubName += ".cfi" 622 } 623 if Bool(sanitize.Properties.Sanitize.Hwaddress) { 624 entries.SubName += ".hwasan" 625 } 626 if Bool(sanitize.Properties.Sanitize.Scs) { 627 entries.SubName += ".scs" 628 } 629 } 630} 631 632func (sanitize *sanitize) inSanitizerDir() bool { 633 return sanitize.Properties.InSanitizerDir 634} 635 636func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool { 637 switch t { 638 case asan: 639 return sanitize.Properties.Sanitize.Address 640 case hwasan: 641 return sanitize.Properties.Sanitize.Hwaddress 642 case tsan: 643 return sanitize.Properties.Sanitize.Thread 644 case intOverflow: 645 return sanitize.Properties.Sanitize.Integer_overflow 646 case cfi: 647 return sanitize.Properties.Sanitize.Cfi 648 case scs: 649 return sanitize.Properties.Sanitize.Scs 650 case fuzzer: 651 return sanitize.Properties.Sanitize.Fuzzer 652 default: 653 panic(fmt.Errorf("unknown sanitizerType %d", t)) 654 } 655} 656 657func (sanitize *sanitize) isUnsanitizedVariant() bool { 658 return !sanitize.isSanitizerEnabled(asan) && 659 !sanitize.isSanitizerEnabled(hwasan) && 660 !sanitize.isSanitizerEnabled(tsan) && 661 !sanitize.isSanitizerEnabled(cfi) && 662 !sanitize.isSanitizerEnabled(scs) && 663 !sanitize.isSanitizerEnabled(fuzzer) 664} 665 666func (sanitize *sanitize) isVariantOnProductionDevice() bool { 667 return !sanitize.isSanitizerEnabled(asan) && 668 !sanitize.isSanitizerEnabled(hwasan) && 669 !sanitize.isSanitizerEnabled(tsan) && 670 !sanitize.isSanitizerEnabled(fuzzer) 671} 672 673func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { 674 switch t { 675 case asan: 676 sanitize.Properties.Sanitize.Address = boolPtr(b) 677 case hwasan: 678 sanitize.Properties.Sanitize.Hwaddress = boolPtr(b) 679 case tsan: 680 sanitize.Properties.Sanitize.Thread = boolPtr(b) 681 case intOverflow: 682 sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b) 683 case cfi: 684 sanitize.Properties.Sanitize.Cfi = boolPtr(b) 685 case scs: 686 sanitize.Properties.Sanitize.Scs = boolPtr(b) 687 case fuzzer: 688 sanitize.Properties.Sanitize.Fuzzer = boolPtr(b) 689 default: 690 panic(fmt.Errorf("unknown sanitizerType %d", t)) 691 } 692 if b { 693 sanitize.Properties.SanitizerEnabled = true 694 } 695} 696 697// Check if the sanitizer is explicitly disabled (as opposed to nil by 698// virtue of not being set). 699func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool { 700 if sanitize == nil { 701 return false 702 } 703 704 sanitizerVal := sanitize.getSanitizerBoolPtr(t) 705 return sanitizerVal != nil && *sanitizerVal == false 706} 707 708// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled) 709// because enabling a sanitizer either directly (via the blueprint) or 710// indirectly (via a mutator) sets the bool ptr to true, and you can't 711// distinguish between the cases. It isn't needed though - both cases can be 712// treated identically. 713func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { 714 if sanitize == nil { 715 return false 716 } 717 718 sanitizerVal := sanitize.getSanitizerBoolPtr(t) 719 return sanitizerVal != nil && *sanitizerVal == true 720} 721 722func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool { 723 t, ok := tag.(DependencyTag) 724 return ok && t.Library || t == reuseObjTag || t == objDepTag 725} 726 727// Propagate sanitizer requirements down from binaries 728func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) { 729 return func(mctx android.TopDownMutatorContext) { 730 if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) { 731 mctx.WalkDeps(func(child, parent android.Module) bool { 732 if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) { 733 return false 734 } 735 if d, ok := child.(*Module); ok && d.sanitize != nil && 736 !Bool(d.sanitize.Properties.Sanitize.Never) && 737 !d.sanitize.isSanitizerExplicitlyDisabled(t) { 738 if t == cfi || t == hwasan || t == scs { 739 if d.static() { 740 d.sanitize.Properties.SanitizeDep = true 741 } 742 } else { 743 d.sanitize.Properties.SanitizeDep = true 744 } 745 } 746 return true 747 }) 748 } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok { 749 // If an APEX module includes a lib which is enabled for a sanitizer T, then 750 // the APEX module is also enabled for the same sanitizer type. 751 mctx.VisitDirectDeps(func(child android.Module) { 752 if c, ok := child.(*Module); ok && c.sanitize.isSanitizerEnabled(t) { 753 sanitizeable.EnableSanitizer(t.name()) 754 } 755 }) 756 } 757 } 758} 759 760// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies. 761func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) { 762 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 763 mctx.WalkDeps(func(child, parent android.Module) bool { 764 if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) { 765 return false 766 } 767 768 d, ok := child.(*Module) 769 if !ok || !d.static() { 770 return false 771 } 772 if d.sanitize != nil { 773 if enableMinimalRuntime(d.sanitize) { 774 // If a static dependency is built with the minimal runtime, 775 // make sure we include the ubsan minimal runtime. 776 c.sanitize.Properties.MinimalRuntimeDep = true 777 } else if enableUbsanRuntime(d.sanitize) { 778 // If a static dependency runs with full ubsan diagnostics, 779 // make sure we include the ubsan runtime. 780 c.sanitize.Properties.UbsanRuntimeDep = true 781 } 782 783 if c.sanitize.Properties.MinimalRuntimeDep && 784 c.sanitize.Properties.UbsanRuntimeDep { 785 // both flags that this mutator might set are true, so don't bother recursing 786 return false 787 } 788 789 if c.Os() == android.Linux { 790 c.sanitize.Properties.BuiltinsDep = true 791 } 792 793 return true 794 } 795 796 if p, ok := d.linker.(*vendorSnapshotLibraryDecorator); ok { 797 if Bool(p.properties.Sanitize_minimal_dep) { 798 c.sanitize.Properties.MinimalRuntimeDep = true 799 } 800 if Bool(p.properties.Sanitize_ubsan_dep) { 801 c.sanitize.Properties.UbsanRuntimeDep = true 802 } 803 } 804 805 return false 806 }) 807 } 808} 809 810// Add the dependency to the runtime library for each of the sanitizer variants 811func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { 812 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 813 if !c.Enabled() { 814 return 815 } 816 var sanitizers []string 817 var diagSanitizers []string 818 819 if Bool(c.sanitize.Properties.Sanitize.All_undefined) { 820 sanitizers = append(sanitizers, "undefined") 821 } else { 822 if Bool(c.sanitize.Properties.Sanitize.Undefined) { 823 sanitizers = append(sanitizers, 824 "bool", 825 "integer-divide-by-zero", 826 "return", 827 "returns-nonnull-attribute", 828 "shift-exponent", 829 "unreachable", 830 "vla-bound", 831 // TODO(danalbert): The following checks currently have compiler performance issues. 832 //"alignment", 833 //"bounds", 834 //"enum", 835 //"float-cast-overflow", 836 //"float-divide-by-zero", 837 //"nonnull-attribute", 838 //"null", 839 //"shift-base", 840 //"signed-integer-overflow", 841 // TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on. 842 // https://llvm.org/PR19302 843 // http://reviews.llvm.org/D6974 844 // "object-size", 845 ) 846 } 847 sanitizers = append(sanitizers, c.sanitize.Properties.Sanitize.Misc_undefined...) 848 } 849 850 if Bool(c.sanitize.Properties.Sanitize.Diag.Undefined) { 851 diagSanitizers = append(diagSanitizers, "undefined") 852 } 853 854 diagSanitizers = append(diagSanitizers, c.sanitize.Properties.Sanitize.Diag.Misc_undefined...) 855 856 if Bool(c.sanitize.Properties.Sanitize.Address) { 857 sanitizers = append(sanitizers, "address") 858 diagSanitizers = append(diagSanitizers, "address") 859 } 860 861 if Bool(c.sanitize.Properties.Sanitize.Hwaddress) { 862 sanitizers = append(sanitizers, "hwaddress") 863 } 864 865 if Bool(c.sanitize.Properties.Sanitize.Thread) { 866 sanitizers = append(sanitizers, "thread") 867 } 868 869 if Bool(c.sanitize.Properties.Sanitize.Safestack) { 870 sanitizers = append(sanitizers, "safe-stack") 871 } 872 873 if Bool(c.sanitize.Properties.Sanitize.Cfi) { 874 sanitizers = append(sanitizers, "cfi") 875 876 if Bool(c.sanitize.Properties.Sanitize.Diag.Cfi) { 877 diagSanitizers = append(diagSanitizers, "cfi") 878 } 879 } 880 881 if Bool(c.sanitize.Properties.Sanitize.Integer_overflow) { 882 sanitizers = append(sanitizers, "unsigned-integer-overflow") 883 sanitizers = append(sanitizers, "signed-integer-overflow") 884 if Bool(c.sanitize.Properties.Sanitize.Diag.Integer_overflow) { 885 diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow") 886 diagSanitizers = append(diagSanitizers, "signed-integer-overflow") 887 } 888 } 889 890 if Bool(c.sanitize.Properties.Sanitize.Scudo) { 891 sanitizers = append(sanitizers, "scudo") 892 } 893 894 if Bool(c.sanitize.Properties.Sanitize.Scs) { 895 sanitizers = append(sanitizers, "shadow-call-stack") 896 } 897 898 if Bool(c.sanitize.Properties.Sanitize.Fuzzer) { 899 sanitizers = append(sanitizers, "fuzzer-no-link") 900 } 901 902 // Save the list of sanitizers. These will be used again when generating 903 // the build rules (for Cflags, etc.) 904 c.sanitize.Properties.Sanitizers = sanitizers 905 c.sanitize.Properties.DiagSanitizers = diagSanitizers 906 907 // TODO(b/150822854) Hosts have a different default behavior and assume the runtime library is used. 908 if c.Host() { 909 diagSanitizers = sanitizers 910 } 911 912 // Determine the runtime library required 913 runtimeLibrary := "" 914 var extraStaticDeps []string 915 toolchain := c.toolchain(mctx) 916 if Bool(c.sanitize.Properties.Sanitize.Address) { 917 runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain) 918 } else if Bool(c.sanitize.Properties.Sanitize.Hwaddress) { 919 if c.staticBinary() { 920 runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain) 921 extraStaticDeps = []string{"libdl"} 922 } else { 923 runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain) 924 } 925 } else if Bool(c.sanitize.Properties.Sanitize.Thread) { 926 runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain) 927 } else if Bool(c.sanitize.Properties.Sanitize.Scudo) { 928 if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep { 929 runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain) 930 } else { 931 runtimeLibrary = config.ScudoRuntimeLibrary(toolchain) 932 } 933 } else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep || 934 Bool(c.sanitize.Properties.Sanitize.Fuzzer) || 935 Bool(c.sanitize.Properties.Sanitize.Undefined) || 936 Bool(c.sanitize.Properties.Sanitize.All_undefined) { 937 runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain) 938 } 939 940 if runtimeLibrary != "" && (toolchain.Bionic() || c.sanitize.Properties.UbsanRuntimeDep) { 941 // UBSan is supported on non-bionic linux host builds as well 942 if isLlndkLibrary(runtimeLibrary, mctx.Config()) && !c.static() && c.UseVndk() { 943 runtimeLibrary = runtimeLibrary + llndkLibrarySuffix 944 } 945 946 // Adding dependency to the runtime library. We are using *FarVariation* 947 // because the runtime libraries themselves are not mutated by sanitizer 948 // mutators and thus don't have sanitizer variants whereas this module 949 // has been already mutated. 950 // 951 // Note that by adding dependency with {static|shared}DepTag, the lib is 952 // added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module 953 if c.staticBinary() { 954 deps := append(extraStaticDeps, runtimeLibrary) 955 // If we're using snapshots and in vendor, redirect to snapshot whenever possible 956 if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() { 957 snapshots := vendorSnapshotStaticLibs(mctx.Config()) 958 for idx, dep := range deps { 959 if lib, ok := snapshots.get(dep, mctx.Arch().ArchType); ok { 960 deps[idx] = lib 961 } 962 } 963 } 964 965 // static executable gets static runtime libs 966 mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ 967 {Mutator: "link", Variation: "static"}, 968 c.ImageVariation(), 969 }...), StaticDepTag, deps...) 970 } else if !c.static() && !c.header() { 971 // If we're using snapshots and in vendor, redirect to snapshot whenever possible 972 if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() { 973 snapshots := vendorSnapshotSharedLibs(mctx.Config()) 974 if lib, ok := snapshots.get(runtimeLibrary, mctx.Arch().ArchType); ok { 975 runtimeLibrary = lib 976 } 977 } 978 979 // dynamic executable and shared libs get shared runtime libs 980 mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ 981 {Mutator: "link", Variation: "shared"}, 982 c.ImageVariation(), 983 }...), earlySharedDepTag, runtimeLibrary) 984 } 985 // static lib does not have dependency to the runtime library. The 986 // dependency will be added to the executables or shared libs using 987 // the static lib. 988 } 989 } 990} 991 992type Sanitizeable interface { 993 android.Module 994 IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool 995 EnableSanitizer(sanitizerName string) 996} 997 998// Create sanitized variants for modules that need them 999func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { 1000 return func(mctx android.BottomUpMutatorContext) { 1001 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 1002 if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) { 1003 modules := mctx.CreateVariations(t.variationName()) 1004 modules[0].(*Module).sanitize.SetSanitizer(t, true) 1005 } else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep { 1006 isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t) 1007 if c.static() || c.header() || t == asan || t == fuzzer { 1008 // Static and header libs are split into non-sanitized and sanitized variants. 1009 // Shared libs are not split. However, for asan and fuzzer, we split even for shared 1010 // libs because a library sanitized for asan/fuzzer can't be linked from a library 1011 // that isn't sanitized for asan/fuzzer. 1012 // 1013 // Note for defaultVariation: since we don't split for shared libs but for static/header 1014 // libs, it is possible for the sanitized variant of a static/header lib to depend 1015 // on non-sanitized variant of a shared lib. Such unfulfilled variation causes an 1016 // error when the module is split. defaultVariation is the name of the variation that 1017 // will be used when such a dangling dependency occurs during the split of the current 1018 // module. By setting it to the name of the sanitized variation, the dangling dependency 1019 // is redirected to the sanitized variant of the dependent module. 1020 defaultVariation := t.variationName() 1021 mctx.SetDefaultDependencyVariation(&defaultVariation) 1022 modules := mctx.CreateVariations("", t.variationName()) 1023 modules[0].(*Module).sanitize.SetSanitizer(t, false) 1024 modules[1].(*Module).sanitize.SetSanitizer(t, true) 1025 modules[0].(*Module).sanitize.Properties.SanitizeDep = false 1026 modules[1].(*Module).sanitize.Properties.SanitizeDep = false 1027 1028 if mctx.Device() && t.incompatibleWithCfi() { 1029 // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that 1030 // are incompatible with cfi 1031 modules[1].(*Module).sanitize.SetSanitizer(cfi, false) 1032 } 1033 1034 // For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants 1035 // to Make, because the sanitized version has a different suffix in name. 1036 // For other types of sanitizers, suppress the variation that is disabled. 1037 if t != cfi && t != scs && t != hwasan { 1038 if isSanitizerEnabled { 1039 modules[0].(*Module).Properties.PreventInstall = true 1040 modules[0].(*Module).Properties.HideFromMake = true 1041 } else { 1042 modules[1].(*Module).Properties.PreventInstall = true 1043 modules[1].(*Module).Properties.HideFromMake = true 1044 } 1045 } 1046 1047 // Export the static lib name to make 1048 if c.static() && c.ExportedToMake() { 1049 if t == cfi { 1050 appendStringSync(c.Name(), cfiStaticLibs(mctx.Config()), &cfiStaticLibsMutex) 1051 } else if t == hwasan { 1052 if c.UseVndk() { 1053 appendStringSync(c.Name(), hwasanVendorStaticLibs(mctx.Config()), 1054 &hwasanStaticLibsMutex) 1055 } else { 1056 appendStringSync(c.Name(), hwasanStaticLibs(mctx.Config()), 1057 &hwasanStaticLibsMutex) 1058 } 1059 } 1060 } 1061 } else { 1062 // Shared libs are not split. Only the sanitized variant is created. 1063 modules := mctx.CreateVariations(t.variationName()) 1064 modules[0].(*Module).sanitize.SetSanitizer(t, true) 1065 modules[0].(*Module).sanitize.Properties.SanitizeDep = false 1066 1067 // locate the asan libraries under /data/asan 1068 if mctx.Device() && t == asan && isSanitizerEnabled { 1069 modules[0].(*Module).sanitize.Properties.InSanitizerDir = true 1070 } 1071 1072 if mctx.Device() && t.incompatibleWithCfi() { 1073 // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that 1074 // are incompatible with cfi 1075 modules[0].(*Module).sanitize.SetSanitizer(cfi, false) 1076 } 1077 } 1078 } 1079 c.sanitize.Properties.SanitizeDep = false 1080 } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) { 1081 // APEX modules fall here 1082 mctx.CreateVariations(t.variationName()) 1083 } 1084 } 1085} 1086 1087var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs") 1088 1089func cfiStaticLibs(config android.Config) *[]string { 1090 return config.Once(cfiStaticLibsKey, func() interface{} { 1091 return &[]string{} 1092 }).(*[]string) 1093} 1094 1095var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs") 1096 1097func hwasanStaticLibs(config android.Config) *[]string { 1098 return config.Once(hwasanStaticLibsKey, func() interface{} { 1099 return &[]string{} 1100 }).(*[]string) 1101} 1102 1103var hwasanVendorStaticLibsKey = android.NewOnceKey("hwasanVendorStaticLibs") 1104 1105func hwasanVendorStaticLibs(config android.Config) *[]string { 1106 return config.Once(hwasanVendorStaticLibsKey, func() interface{} { 1107 return &[]string{} 1108 }).(*[]string) 1109} 1110 1111func appendStringSync(item string, list *[]string, mutex *sync.Mutex) { 1112 mutex.Lock() 1113 *list = append(*list, item) 1114 mutex.Unlock() 1115} 1116 1117func enableMinimalRuntime(sanitize *sanitize) bool { 1118 if !Bool(sanitize.Properties.Sanitize.Address) && 1119 !Bool(sanitize.Properties.Sanitize.Hwaddress) && 1120 !Bool(sanitize.Properties.Sanitize.Fuzzer) && 1121 1122 (Bool(sanitize.Properties.Sanitize.Integer_overflow) || 1123 len(sanitize.Properties.Sanitize.Misc_undefined) > 0 || 1124 Bool(sanitize.Properties.Sanitize.Undefined) || 1125 Bool(sanitize.Properties.Sanitize.All_undefined)) && 1126 1127 !(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) || 1128 Bool(sanitize.Properties.Sanitize.Diag.Cfi) || 1129 Bool(sanitize.Properties.Sanitize.Diag.Undefined) || 1130 len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) { 1131 1132 return true 1133 } 1134 return false 1135} 1136 1137func enableUbsanRuntime(sanitize *sanitize) bool { 1138 return Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) || 1139 Bool(sanitize.Properties.Sanitize.Diag.Undefined) || 1140 len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0 1141} 1142 1143func cfiMakeVarsProvider(ctx android.MakeVarsContext) { 1144 cfiStaticLibs := cfiStaticLibs(ctx.Config()) 1145 sort.Strings(*cfiStaticLibs) 1146 ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " ")) 1147} 1148 1149func hwasanMakeVarsProvider(ctx android.MakeVarsContext) { 1150 hwasanStaticLibs := hwasanStaticLibs(ctx.Config()) 1151 sort.Strings(*hwasanStaticLibs) 1152 ctx.Strict("SOONG_HWASAN_STATIC_LIBRARIES", strings.Join(*hwasanStaticLibs, " ")) 1153 1154 hwasanVendorStaticLibs := hwasanVendorStaticLibs(ctx.Config()) 1155 sort.Strings(*hwasanVendorStaticLibs) 1156 ctx.Strict("SOONG_HWASAN_VENDOR_STATIC_LIBRARIES", strings.Join(*hwasanVendorStaticLibs, " ")) 1157} 1158