1// Copyright (C) 2016 The Android Open Source Project 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 art 16 17import ( 18 "fmt" 19 "path/filepath" 20 "strings" 21 "sync" 22 23 "github.com/google/blueprint/proptools" 24 25 "android/soong/android" 26 "android/soong/cc" 27 "android/soong/cc/config" 28) 29 30var supportedArches = []string{"arm", "arm64", "riscv64", "x86", "x86_64"} 31 32func globalFlags(ctx android.LoadHookContext) ([]string, []string) { 33 var cflags []string 34 var asflags []string 35 36 opt := ctx.Config().GetenvWithDefault("ART_NDEBUG_OPT_FLAG", "-O3") 37 cflags = append(cflags, opt) 38 39 tlab := false 40 gcType := ctx.Config().GetenvWithDefault("ART_DEFAULT_GC_TYPE", "CMC") 41 42 if ctx.Config().IsEnvTrue("ART_TEST_DEBUG_GC") { 43 gcType = "SS" 44 tlab = true 45 } 46 47 cflags = append(cflags, "-DART_DEFAULT_GC_TYPE_IS_"+gcType) 48 49 if ctx.Config().IsEnvTrue("ART_HEAP_POISONING") { 50 cflags = append(cflags, "-DART_HEAP_POISONING=1") 51 asflags = append(asflags, "-DART_HEAP_POISONING=1") 52 } 53 if ctx.Config().IsEnvTrue("ART_USE_CXX_INTERPRETER") { 54 cflags = append(cflags, "-DART_USE_CXX_INTERPRETER=1") 55 } 56 57 if !ctx.Config().IsEnvFalse("ART_USE_READ_BARRIER") && ctx.Config().ArtUseReadBarrier() { 58 // Used to change the read barrier type. Valid values are BAKER, TABLELOOKUP. 59 // The default is BAKER. 60 barrierType := ctx.Config().GetenvWithDefault("ART_READ_BARRIER_TYPE", "BAKER") 61 cflags = append(cflags, 62 "-DART_USE_READ_BARRIER=1", 63 "-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1") 64 asflags = append(asflags, 65 "-DART_USE_READ_BARRIER=1", 66 "-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1") 67 68 if !ctx.Config().IsEnvFalse("ART_USE_GENERATIONAL_CC") { 69 cflags = append(cflags, "-DART_USE_GENERATIONAL_CC=1") 70 } 71 // Force CC only if ART_USE_READ_BARRIER was set to true explicitly during 72 // build time. 73 if ctx.Config().IsEnvTrue("ART_USE_READ_BARRIER") { 74 cflags = append(cflags, "-DART_FORCE_USE_READ_BARRIER=1") 75 } 76 tlab = true 77 } else if gcType == "CMC" { 78 tlab = true 79 } 80 81 if tlab { 82 cflags = append(cflags, "-DART_USE_TLAB=1") 83 } 84 85 if ctx.Config().IsEnvTrue("ART_FORCE_TRY_PREDICATED_SIMD") { 86 cflags = append(cflags, "-DART_FORCE_TRY_PREDICATED_SIMD=1") 87 } 88 89 // We need larger stack overflow guards for ASAN, as the compiled code will have 90 // larger frame sizes. For simplicity, just use global not-target-specific cflags. 91 // Note: We increase this for both debug and non-debug, as the overflow gap will 92 // be compiled into managed code. We always preopt (and build core images) with 93 // the debug version. So make the gap consistent (and adjust for the worst). 94 if len(ctx.Config().SanitizeDevice()) > 0 || len(ctx.Config().SanitizeHost()) > 0 { 95 cflags = append(cflags, 96 "-DART_STACK_OVERFLOW_GAP_arm=16384", 97 "-DART_STACK_OVERFLOW_GAP_arm64=16384", 98 "-DART_STACK_OVERFLOW_GAP_riscv64=16384", 99 "-DART_STACK_OVERFLOW_GAP_x86=16384", 100 "-DART_STACK_OVERFLOW_GAP_x86_64=20480") 101 } else { 102 cflags = append(cflags, 103 "-DART_STACK_OVERFLOW_GAP_arm=8192", 104 "-DART_STACK_OVERFLOW_GAP_arm64=8192", 105 "-DART_STACK_OVERFLOW_GAP_riscv64=8192", 106 "-DART_STACK_OVERFLOW_GAP_x86=8192", 107 "-DART_STACK_OVERFLOW_GAP_x86_64=8192") 108 } 109 110 if ctx.Config().NoBionicPageSizeMacro() { 111 cflags = append(cflags, "-DART_PAGE_SIZE_AGNOSTIC=1") 112 } 113 114 if ctx.Config().IsEnvTrue("ART_ENABLE_ADDRESS_SANITIZER") { 115 // Used to enable full sanitization, i.e., user poisoning, under ASAN. 116 cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 117 asflags = append(asflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 118 } 119 120 if !ctx.Config().IsEnvFalse("USE_D8_DESUGAR") { 121 cflags = append(cflags, "-DUSE_D8_DESUGAR=1") 122 } 123 124 return cflags, asflags 125} 126 127func deviceFlags(ctx android.LoadHookContext) []string { 128 var cflags []string 129 deviceFrameSizeLimit := 1736 130 if len(ctx.Config().SanitizeDevice()) > 0 { 131 deviceFrameSizeLimit = 7400 132 } 133 cflags = append(cflags, 134 fmt.Sprintf("-Wframe-larger-than=%d", deviceFrameSizeLimit), 135 fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", deviceFrameSizeLimit), 136 ) 137 138 cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.Config().LibartImgDeviceBaseAddress()) 139 minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA", "(-0x1000000)") 140 maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA", "0x1000000") 141 cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta) 142 cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta) 143 144 return cflags 145} 146 147func hostFlags(ctx android.LoadHookContext) []string { 148 var cflags []string 149 hostFrameSizeLimit := 1736 150 if len(ctx.Config().SanitizeHost()) > 0 { 151 // art/test/137-cfi/cfi.cc 152 // error: stack frame size of 1944 bytes in function 'Java_Main_unwindInProcess' 153 // b/249586057, need larger stack frame for newer clang compilers 154 hostFrameSizeLimit = 10000 155 // cannot add "-fsanitize-address-use-after-return=never" everywhere, 156 // or some file like compiler_driver.o can have stack frame of 30072 bytes. 157 // cflags = append(cflags, "-fsanitize-address-use-after-return=never") 158 } 159 cflags = append(cflags, 160 fmt.Sprintf("-Wframe-larger-than=%d", hostFrameSizeLimit), 161 fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", hostFrameSizeLimit), 162 ) 163 164 cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.Config().LibartImgHostBaseAddress()) 165 minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA", "(-0x1000000)") 166 maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA", "0x1000000") 167 cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta) 168 cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta) 169 170 if len(ctx.Config().SanitizeHost()) > 0 && !ctx.Config().IsEnvFalse("ART_ENABLE_ADDRESS_SANITIZER") { 171 // We enable full sanitization on the host by default. 172 cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 173 } 174 175 clang_path := filepath.Join(config.ClangDefaultBase, ctx.Config().PrebuiltOS(), config.ClangDefaultVersion) 176 cflags = append(cflags, fmt.Sprintf("-DART_CLANG_PATH=\"%s\"", clang_path)) 177 178 return cflags 179} 180 181func globalDefaults(ctx android.LoadHookContext) { 182 type props struct { 183 Target struct { 184 Android struct { 185 Cflags []string 186 } 187 Host struct { 188 Cflags []string 189 } 190 } 191 Cflags []string 192 Asflags []string 193 Sanitize struct { 194 Recover []string 195 } 196 } 197 198 p := &props{} 199 p.Cflags, p.Asflags = globalFlags(ctx) 200 p.Target.Android.Cflags = deviceFlags(ctx) 201 p.Target.Host.Cflags = hostFlags(ctx) 202 203 if ctx.Config().IsEnvTrue("ART_DEX_FILE_ACCESS_TRACKING") { 204 p.Cflags = append(p.Cflags, "-DART_DEX_FILE_ACCESS_TRACKING") 205 p.Sanitize.Recover = []string{ 206 "address", 207 } 208 } 209 210 ctx.AppendProperties(p) 211} 212 213// Hook that adds flags that are implicit for all cc_art_* modules. 214func addImplicitFlags(ctx android.LoadHookContext) { 215 type props struct { 216 Target struct { 217 Android struct { 218 Cflags []string 219 } 220 } 221 } 222 223 p := &props{} 224 if ctx.Config().IsEnvTrue("ART_TARGET_LINUX") { 225 p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_LINUX"} 226 } else { 227 p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_ANDROID"} 228 } 229 230 ctx.AppendProperties(p) 231} 232 233func customLinker(ctx android.LoadHookContext) { 234 linker := ctx.Config().Getenv("CUSTOM_TARGET_LINKER") 235 type props struct { 236 DynamicLinker string 237 } 238 239 p := &props{} 240 if linker != "" { 241 p.DynamicLinker = linker 242 } 243 244 ctx.AppendProperties(p) 245} 246 247func prefer32Bit(ctx android.LoadHookContext) { 248 type props struct { 249 Target struct { 250 Host struct { 251 Compile_multilib *string 252 } 253 } 254 } 255 256 p := &props{} 257 if ctx.Config().IsEnvTrue("HOST_PREFER_32_BIT") { 258 p.Target.Host.Compile_multilib = proptools.StringPtr("prefer32") 259 } 260 261 // Prepend to make it overridable in the blueprints. Note that it doesn't work 262 // to override the property in a cc_defaults module. 263 ctx.PrependProperties(p) 264} 265 266var testMapKey = android.NewOnceKey("artTests") 267 268func testMap(config android.Config) map[string][]string { 269 return config.Once(testMapKey, func() interface{} { 270 return make(map[string][]string) 271 }).(map[string][]string) 272} 273 274func testInstall(ctx android.InstallHookContext) { 275 testMap := testMap(ctx.Config()) 276 277 var name string 278 if ctx.Host() { 279 name = "host_" 280 } else { 281 name = "device_" 282 } 283 name += ctx.Arch().ArchType.String() + "_" + ctx.ModuleName() 284 285 artTestMutex.Lock() 286 defer artTestMutex.Unlock() 287 288 tests := testMap[name] 289 tests = append(tests, ctx.Path().String()) 290 testMap[name] = tests 291} 292 293var testcasesContentKey = android.NewOnceKey("artTestcasesContent") 294 295func testcasesContent(config android.Config) map[string]string { 296 return config.Once(testcasesContentKey, func() interface{} { 297 return make(map[string]string) 298 }).(map[string]string) 299} 300 301// Binaries and libraries also need to be copied in the testcases directory for 302// running tests on host. This method adds module to the list of needed files. 303// The 'key' is the file in testcases and 'value' is the path to copy it from. 304// The actual copy will be done in make since soong does not do installations. 305func addTestcasesFile(ctx android.InstallHookContext) { 306 if ctx.Os() != ctx.Config().BuildOS || ctx.Target().HostCross || ctx.Module().IsSkipInstall() { 307 return 308 } 309 310 testcasesContent := testcasesContent(ctx.Config()) 311 312 artTestMutex.Lock() 313 defer artTestMutex.Unlock() 314 315 src := ctx.SrcPath().String() 316 path := strings.Split(ctx.Path().String(), "/") 317 // Keep last two parts of the install path (e.g. bin/dex2oat). 318 dst := strings.Join(path[len(path)-2:], "/") 319 if oldSrc, ok := testcasesContent[dst]; ok { 320 ctx.ModuleErrorf("Conflicting sources for %s: %s and %s", dst, oldSrc, src) 321 } 322 testcasesContent[dst] = src 323} 324 325var artTestMutex sync.Mutex 326 327func init() { 328 artModuleTypes := []string{ 329 "art_cc_library", 330 "art_cc_library_static", 331 "art_cc_binary", 332 "art_cc_test", 333 "art_cc_test_library", 334 "art_cc_defaults", 335 "art_global_defaults", 336 } 337 android.AddNeverAllowRules( 338 android.NeverAllow(). 339 NotIn("art", "external/vixl"). 340 ModuleType(artModuleTypes...)) 341 342 android.RegisterModuleType("art_cc_library", artLibrary) 343 android.RegisterModuleType("art_cc_library_static", artStaticLibrary) 344 android.RegisterModuleType("art_cc_binary", artBinary) 345 android.RegisterModuleType("art_cc_test", artTest) 346 android.RegisterModuleType("art_cc_test_library", artTestLibrary) 347 android.RegisterModuleType("art_cc_defaults", artDefaultsFactory) 348 android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory) 349} 350 351func artGlobalDefaultsFactory() android.Module { 352 module := artDefaultsFactory() 353 android.AddLoadHook(module, addImplicitFlags) 354 android.AddLoadHook(module, globalDefaults) 355 356 return module 357} 358 359func artDefaultsFactory() android.Module { 360 c := &codegenProperties{} 361 module := cc.DefaultsFactory(c) 362 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, staticAndSharedLibrary) }) 363 364 return module 365} 366 367func artLibrary() android.Module { 368 module := cc.LibraryFactory() 369 370 installCodegenCustomizer(module, staticAndSharedLibrary) 371 372 android.AddLoadHook(module, addImplicitFlags) 373 android.AddInstallHook(module, addTestcasesFile) 374 return module 375} 376 377func artStaticLibrary() android.Module { 378 module := cc.LibraryStaticFactory() 379 380 installCodegenCustomizer(module, staticLibrary) 381 382 android.AddLoadHook(module, addImplicitFlags) 383 return module 384} 385 386func artBinary() android.Module { 387 module := cc.BinaryFactory() 388 389 android.AddLoadHook(module, addImplicitFlags) 390 android.AddLoadHook(module, customLinker) 391 android.AddLoadHook(module, prefer32Bit) 392 android.AddInstallHook(module, addTestcasesFile) 393 return module 394} 395 396func artTest() android.Module { 397 module := cc.NewTest(android.HostAndDeviceSupported).Init() 398 399 installCodegenCustomizer(module, binary) 400 401 android.AddLoadHook(module, addImplicitFlags) 402 android.AddLoadHook(module, customLinker) 403 android.AddLoadHook(module, prefer32Bit) 404 android.AddInstallHook(module, testInstall) 405 return module 406} 407 408func artTestLibrary() android.Module { 409 module := cc.TestLibraryFactory() 410 411 installCodegenCustomizer(module, staticAndSharedLibrary) 412 413 android.AddLoadHook(module, addImplicitFlags) 414 android.AddLoadHook(module, prefer32Bit) 415 android.AddInstallHook(module, testInstall) 416 return module 417} 418