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 "sync" 21 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/apex" 26 "android/soong/cc" 27) 28 29var supportedArches = []string{"arm", "arm64", "x86", "x86_64"} 30 31func globalFlags(ctx android.LoadHookContext) ([]string, []string) { 32 var cflags []string 33 var asflags []string 34 35 opt := ctx.Config().GetenvWithDefault("ART_NDEBUG_OPT_FLAG", "-O3") 36 cflags = append(cflags, opt) 37 38 tlab := false 39 40 gcType := ctx.Config().GetenvWithDefault("ART_DEFAULT_GC_TYPE", "CMS") 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 if tlab { 49 cflags = append(cflags, "-DART_USE_TLAB=1") 50 } 51 52 imtSize := ctx.Config().GetenvWithDefault("ART_IMT_SIZE", "43") 53 cflags = append(cflags, "-DIMT_SIZE="+imtSize) 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 if ctx.Config().IsEnvTrue("ART_TARGET_LINUX") { 136 cflags = append(cflags, "-DART_TARGET_LINUX") 137 } else { 138 cflags = append(cflags, "-DART_TARGET_ANDROID") 139 } 140 minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA", "-0x1000000") 141 maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA", "0x1000000") 142 cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta) 143 cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta) 144 145 return cflags 146} 147 148func hostFlags(ctx android.LoadHookContext) []string { 149 var cflags []string 150 hostFrameSizeLimit := 1736 151 if len(ctx.Config().SanitizeHost()) > 0 { 152 // art/test/137-cfi/cfi.cc 153 // error: stack frame size of 1944 bytes in function 'Java_Main_unwindInProcess' 154 hostFrameSizeLimit = 6400 155 } 156 cflags = append(cflags, 157 fmt.Sprintf("-Wframe-larger-than=%d", hostFrameSizeLimit), 158 fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", hostFrameSizeLimit), 159 ) 160 161 cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.Config().LibartImgHostBaseAddress()) 162 minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA", "-0x1000000") 163 maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA", "0x1000000") 164 cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta) 165 cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta) 166 167 if len(ctx.Config().SanitizeHost()) > 0 && !ctx.Config().IsEnvFalse("ART_ENABLE_ADDRESS_SANITIZER") { 168 // We enable full sanitization on the host by default. 169 cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 170 } 171 172 return cflags 173} 174 175func globalDefaults(ctx android.LoadHookContext) { 176 type props struct { 177 Target struct { 178 Android struct { 179 Cflags []string 180 } 181 Host struct { 182 Cflags []string 183 } 184 } 185 Cflags []string 186 Asflags []string 187 Sanitize struct { 188 Recover []string 189 } 190 } 191 192 p := &props{} 193 p.Cflags, p.Asflags = globalFlags(ctx) 194 p.Target.Android.Cflags = deviceFlags(ctx) 195 p.Target.Host.Cflags = hostFlags(ctx) 196 197 if ctx.Config().IsEnvTrue("ART_DEX_FILE_ACCESS_TRACKING") { 198 p.Cflags = append(p.Cflags, "-DART_DEX_FILE_ACCESS_TRACKING") 199 p.Sanitize.Recover = []string{ 200 "address", 201 } 202 } 203 204 ctx.AppendProperties(p) 205} 206 207func debugDefaults(ctx android.LoadHookContext) { 208 type props struct { 209 Cflags []string 210 } 211 212 p := &props{} 213 p.Cflags = debugFlags(ctx) 214 ctx.AppendProperties(p) 215} 216 217func customLinker(ctx android.LoadHookContext) { 218 linker := ctx.Config().Getenv("CUSTOM_TARGET_LINKER") 219 type props struct { 220 DynamicLinker string 221 } 222 223 p := &props{} 224 if linker != "" { 225 p.DynamicLinker = linker 226 } 227 228 ctx.AppendProperties(p) 229} 230 231func prefer32Bit(ctx android.LoadHookContext) { 232 type props struct { 233 Target struct { 234 Host struct { 235 Compile_multilib *string 236 } 237 } 238 } 239 240 p := &props{} 241 if ctx.Config().IsEnvTrue("HOST_PREFER_32_BIT") { 242 p.Target.Host.Compile_multilib = proptools.StringPtr("prefer32") 243 } 244 245 // Prepend to make it overridable in the blueprints. Note that it doesn't work 246 // to override the property in a cc_defaults module. 247 ctx.PrependProperties(p) 248} 249 250var testMapKey = android.NewOnceKey("artTests") 251 252func testMap(config android.Config) map[string][]string { 253 return config.Once(testMapKey, func() interface{} { 254 return make(map[string][]string) 255 }).(map[string][]string) 256} 257 258func testInstall(ctx android.InstallHookContext) { 259 testMap := testMap(ctx.Config()) 260 261 var name string 262 if ctx.Host() { 263 name = "host_" 264 } else { 265 name = "device_" 266 } 267 name += ctx.Arch().ArchType.String() + "_" + ctx.ModuleName() 268 269 artTestMutex.Lock() 270 defer artTestMutex.Unlock() 271 272 tests := testMap[name] 273 tests = append(tests, ctx.Path().ToMakePath().String()) 274 testMap[name] = tests 275} 276 277var artTestMutex sync.Mutex 278 279func init() { 280 artModuleTypes := []string{ 281 "art_cc_library", 282 "art_cc_library_static", 283 "art_cc_binary", 284 "art_cc_test", 285 "art_cc_test_library", 286 "art_cc_defaults", 287 "libart_cc_defaults", 288 "libart_static_cc_defaults", 289 "art_global_defaults", 290 "art_debug_defaults", 291 "art_apex_test_host", 292 } 293 android.AddNeverAllowRules( 294 android.NeverAllow(). 295 NotIn("art", "external/vixl"). 296 ModuleType(artModuleTypes...)) 297 298 android.RegisterModuleType("art_cc_library", artLibrary) 299 android.RegisterModuleType("art_cc_library_static", artStaticLibrary) 300 android.RegisterModuleType("art_cc_binary", artBinary) 301 android.RegisterModuleType("art_cc_test", artTest) 302 android.RegisterModuleType("art_cc_test_library", artTestLibrary) 303 android.RegisterModuleType("art_cc_defaults", artDefaultsFactory) 304 android.RegisterModuleType("libart_cc_defaults", libartDefaultsFactory) 305 android.RegisterModuleType("libart_static_cc_defaults", libartStaticDefaultsFactory) 306 android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory) 307 android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory) 308 309 // ART apex is special because it must include dexpreopt files for bootclasspath jars. 310 android.RegisterModuleType("art_apex", artApexBundleFactory) 311 android.RegisterModuleType("art_apex_test", artTestApexBundleFactory) 312 313 // TODO: This makes the module disable itself for host if HOST_PREFER_32_BIT is 314 // set. We need this because the multilib types of binaries listed in the apex 315 // rule must match the declared type. This is normally not difficult but HOST_PREFER_32_BIT 316 // changes this to 'prefer32' on all host binaries. Since HOST_PREFER_32_BIT is 317 // only used for testing we can just disable the module. 318 // See b/120617876 for more information. 319 android.RegisterModuleType("art_apex_test_host", artHostTestApexBundleFactory) 320} 321 322func artApexBundleFactory() android.Module { 323 return apex.ApexBundleFactory(false /*testApex*/, true /*artApex*/) 324} 325 326func artTestApexBundleFactory() android.Module { 327 return apex.ApexBundleFactory(true /*testApex*/, true /*artApex*/) 328} 329 330func artHostTestApexBundleFactory() android.Module { 331 module := apex.ApexBundleFactory(true /*testApex*/, true /*artApex*/) 332 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 333 if ctx.Config().IsEnvTrue("HOST_PREFER_32_BIT") { 334 type props struct { 335 Target struct { 336 Host struct { 337 Enabled *bool 338 } 339 } 340 } 341 342 p := &props{} 343 p.Target.Host.Enabled = proptools.BoolPtr(false) 344 ctx.AppendProperties(p) 345 log.Print("Disabling host build of " + ctx.ModuleName() + " for HOST_PREFER_32_BIT=true") 346 } 347 }) 348 349 return module 350} 351 352func artGlobalDefaultsFactory() android.Module { 353 module := artDefaultsFactory() 354 android.AddLoadHook(module, globalDefaults) 355 356 return module 357} 358 359func artDebugDefaultsFactory() android.Module { 360 module := artDefaultsFactory() 361 android.AddLoadHook(module, debugDefaults) 362 363 return module 364} 365 366func artDefaultsFactory() android.Module { 367 c := &codegenProperties{} 368 module := cc.DefaultsFactory(c) 369 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, staticAndSharedLibrary) }) 370 371 return module 372} 373 374func libartDefaultsFactory() android.Module { 375 c := &codegenProperties{} 376 module := cc.DefaultsFactory(c) 377 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, staticAndSharedLibrary) }) 378 379 return module 380} 381 382func libartStaticDefaultsFactory() android.Module { 383 c := &codegenProperties{} 384 module := cc.DefaultsFactory(c) 385 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, staticLibrary) }) 386 387 return module 388} 389 390func artLibrary() android.Module { 391 module := cc.LibraryFactory() 392 393 installCodegenCustomizer(module, staticAndSharedLibrary) 394 395 return module 396} 397 398func artStaticLibrary() android.Module { 399 module := cc.LibraryStaticFactory() 400 401 installCodegenCustomizer(module, staticLibrary) 402 403 return module 404} 405 406func artBinary() android.Module { 407 module := cc.BinaryFactory() 408 409 android.AddLoadHook(module, customLinker) 410 android.AddLoadHook(module, prefer32Bit) 411 return module 412} 413 414func artTest() android.Module { 415 module := cc.TestFactory() 416 417 installCodegenCustomizer(module, binary) 418 419 android.AddLoadHook(module, customLinker) 420 android.AddLoadHook(module, prefer32Bit) 421 android.AddInstallHook(module, testInstall) 422 return module 423} 424 425func artTestLibrary() android.Module { 426 module := cc.TestLibraryFactory() 427 428 installCodegenCustomizer(module, staticAndSharedLibrary) 429 430 android.AddLoadHook(module, prefer32Bit) 431 android.AddInstallHook(module, testInstall) 432 return module 433} 434