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