From 7556839772c7796ff4466ee5dd1168884d1240e7 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Fri, 20 Mar 2020 04:29:24 +0900 Subject: [PATCH] Enforce apex.min_sdk_version for bundled builds Previously, when Q-targeting apexes are bundled-built, they are built against the latest stubs. It was because unwinder is linked dynamically in R and APIs are provided by libc while Q apexes should run on Q where libc doesn't provide those APIs. To make Q apexes run on Q device, libc++ should be linked with static unwinder. But, because libc++ with static unwinder may cause problem on HWASAN build, Q apexes were built against the latest stubs for bundled build. However, Q apexes should be built against Q stubs. Now, only for HWASAN builds, Q apexes are built against the latest stubs (and native modules are not linked with static unwinder). Bug: 151912436 Test: TARGET_SANITIZE=hwaddress m => Q apexes(media, resolv, ..) are linked with the latest stubs m => Q apexes are linked with Q stubs, and Q apexes' libc++ is linked with static unwinder Merged-In: If32f1b547e6d93e3955c7521eec8aef5851f908c Change-Id: If32f1b547e6d93e3955c7521eec8aef5851f908c (cherry picked from commit 7406660685a9a085c433ba7081cc6984f66fa732) Exempt-From-Owner-Approval: cp from internal Change-Id: If32f1b547e6d93e3955c7521eec8aef5851f908c --- android/apex.go | 24 +++++++----------------- apex/apex_test.go | 23 ++++++++++++----------- cc/cc.go | 33 +++++++++++++++++++++++++-------- cc/testing.go | 14 ++++++++++++++ 4 files changed, 58 insertions(+), 36 deletions(-) diff --git a/android/apex.go b/android/apex.go index eabe05944..cbaf1c71a 100644 --- a/android/apex.go +++ b/android/apex.go @@ -92,12 +92,10 @@ type ApexModule interface { // APEX as this module DepIsInSameApex(ctx BaseModuleContext, dep Module) bool - // Returns the highest version which is <= min_sdk_version. - // For example, with min_sdk_version is 10 and versionList is [9,11] - // it returns 9. - ChooseSdkVersion(versionList []string, useLatest bool) (string, error) - - ShouldSupportAndroid10() bool + // Returns the highest version which is <= maxSdkVersion. + // For example, with maxSdkVersion is 10 and versionList is [9,11] + // it returns 9 as string + ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) } type ApexProperties struct { @@ -193,22 +191,14 @@ func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool return true } -func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, useLatest bool) (string, error) { - if useLatest { - return versionList[len(versionList)-1], nil - } - minSdkVersion := m.ApexProperties.Info.MinSdkVersion +func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error) { for i := range versionList { ver, _ := strconv.Atoi(versionList[len(versionList)-i-1]) - if ver <= minSdkVersion { + if ver <= maxSdkVersion { return versionList[len(versionList)-i-1], nil } } - return "", fmt.Errorf("min_sdk_version is set %v, but not found in %v", minSdkVersion, versionList) -} - -func (m *ApexModuleBase) ShouldSupportAndroid10() bool { - return !m.IsForPlatform() && (m.ApexProperties.Info.MinSdkVersion <= SdkVersion_Android10) + return "", fmt.Errorf("not found a version(<=%d) in versionList: %v", maxSdkVersion, versionList) } func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { diff --git a/apex/apex_test.go b/apex/apex_test.go index c01ba1459..b97e38d1d 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -882,7 +882,7 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) { shouldNotLink []string }{ { - name: "should link to test latest", + name: "should link to the latest", minSdkVersion: "current", shouldLink: "30", shouldNotLink: []string{"29"}, @@ -1222,7 +1222,7 @@ func TestPlatformUsesLatestStubsFromApexes(t *testing.T) { expectNoLink("libz", "shared", "libz", "shared") } -func TestQApexesUseLatestStubsInBundledBuilds(t *testing.T) { +func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) { ctx, _ := testApex(t, ` apex { name: "myapex", @@ -1249,16 +1249,18 @@ func TestQApexesUseLatestStubsInBundledBuilds(t *testing.T) { versions: ["29", "30"], }, } - `) + `, func(fs map[string][]byte, config android.Config) { + config.TestProductVariables.SanitizeDevice = []string{"hwaddress"} + }) expectLink := func(from, from_variant, to, to_variant string) { ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld") libFlags := ld.Args["libFlags"] ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - expectLink("libx", "shared_myapex", "libbar", "shared_30") + expectLink("libx", "shared_hwasan_myapex", "libbar", "shared_30") } -func TestQTargetApexUseStaticUnwinder(t *testing.T) { +func TestQTargetApexUsesStaticUnwinder(t *testing.T) { ctx, _ := testApex(t, ` apex { name: "myapex", @@ -1277,8 +1279,7 @@ func TestQTargetApexUseStaticUnwinder(t *testing.T) { name: "libx", apex_available: [ "myapex" ], } - - `, withUnbundledBuild) + `) // ensure apex variant of c++ is linked with static unwinder cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module) @@ -1289,7 +1290,7 @@ func TestQTargetApexUseStaticUnwinder(t *testing.T) { } func TestInvalidMinSdkVersion(t *testing.T) { - testApexError(t, `"libz" .*: min_sdk_version is set 29.*`, ` + testApexError(t, `"libz" .*: not found a version\(<=29\)`, ` apex { name: "myapex", key: "myapex.key", @@ -1319,9 +1320,9 @@ func TestInvalidMinSdkVersion(t *testing.T) { versions: ["30"], }, } - `, withUnbundledBuild) + `) - testApexError(t, `"myapex" .*: min_sdk_version: should be .*`, ` + testApexError(t, `"myapex" .*: min_sdk_version: should be "current" or `, ` apex { name: "myapex", key: "myapex.key", @@ -1842,7 +1843,7 @@ func TestMacro(t *testing.T) { // non-APEX variant does not have __ANDROID_APEX__ defined mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=10000") + ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__") // APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"] diff --git a/cc/cc.go b/cc/cc.go index de07229f9..88fede410 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -488,6 +488,9 @@ type Module struct { makeLinkType string // Kythe (source file indexer) paths for this compilation module kytheFiles android.Paths + + // For apex variants, this is set as apex.min_sdk_version + apexSdkVersion int } func (c *Module) Toc() android.OptionalPath { @@ -1209,7 +1212,7 @@ func (ctx *moduleContextImpl) apexName() string { } func (ctx *moduleContextImpl) apexSdkVersion() int { - return ctx.mod.ApexProperties.Info.MinSdkVersion + return ctx.mod.apexSdkVersion } func (ctx *moduleContextImpl) hasStubsVariants() bool { @@ -1847,7 +1850,10 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { }, depTag, lib) } - if deps.StaticUnwinderIfLegacy && ctx.Config().UnbundledBuild() { + // staticUnwinderDep is treated as staticDep for Q apexes + // so that native libraries/binaries are linked with static unwinder + // because Q libc doesn't have unwinder APIs + if deps.StaticUnwinderIfLegacy { actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "link", Variation: "static"}, }, staticUnwinderDepTag, staticUnwinder(actx)) @@ -2231,9 +2237,22 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } + // For the dependency from platform to apex, use the latest stubs + c.apexSdkVersion = android.FutureApiLevel + if !c.IsForPlatform() { + c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion + } + + if android.InList("hwaddress", ctx.Config().SanitizeDevice()) { + // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000) + // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)). + // (b/144430859) + c.apexSdkVersion = android.FutureApiLevel + } + if depTag == staticUnwinderDepTag { - // Use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859) - if c.ShouldSupportAndroid10() { + // Use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859) + if c.apexSdkVersion <= android.SdkVersion_Android10 { depTag = StaticDepTag } else { return @@ -2287,8 +2306,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // when to use (unspecified) stubs, check min_sdk_version and choose the right one if useThisDep && depIsStubs && !explicitlyVersioned { - useLatest := c.IsForPlatform() || (c.ShouldSupportAndroid10() && !ctx.Config().UnbundledBuild()) - versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), useLatest) + versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) return @@ -2311,8 +2329,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // if this is for use_vendor apex && dep has stubsVersions // apply the same rule of apex sdk enforcement to choose right version var err error - useLatest := c.ShouldSupportAndroid10() && !ctx.Config().UnbundledBuild() - versionToUse, err = c.ChooseSdkVersion(versions, useLatest) + versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) return diff --git a/cc/testing.go b/cc/testing.go index e9739ff23..f85795b33 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -67,6 +67,20 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { src: "", } + cc_prebuilt_library_shared { + name: "libclang_rt.hwasan-aarch64-android", + nocrt: true, + vendor_available: true, + recovery_available: true, + system_shared_libs: [], + stl: "none", + srcs: [""], + check_elf_files: false, + sanitize: { + never: true, + }, + } + toolchain_library { name: "libclang_rt.builtins-i686-android", vendor_available: true,