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