From 3a8130c797cd762427698f6a6245bba4c84c2e4b Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Tue, 27 Jul 2021 22:42:23 +0900 Subject: [PATCH] Prohibit static executable in APEX If a library is statically included in a static executable, it's behavior is different from the case where the same library is statically (or dynamically) linked to a non-static executable. To reduce the number of test configs that we need to consider, it is required to prohibit static executables in APEXes. Bug: 185971244 Test: m Change-Id: I0cd8fca669d55088e2329fef1f859eeb297502dd --- apex/apex.go | 30 ++++++++++++++++++++++++++++++ apex/apex_test.go | 30 +++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index 0857946ea..e8bb9b7ac 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1696,6 +1696,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkUpdatable(ctx) a.checkMinSdkVersion(ctx) a.checkStaticLinkingToStubLibraries(ctx) + a.checkStaticExecutables(ctx) if len(a.properties.Tests) > 0 && !a.testApex { ctx.PropertyErrorf("tests", "property allowed only in apex_test module type") return @@ -2487,6 +2488,35 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { }) } +// checkStaticExecutable ensures that executables in an APEX are not static. +func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) { + ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { + if ctx.OtherModuleDependencyTag(module) != executableTag { + return + } + if cc, ok := module.(*cc.Module); ok && cc.StaticExecutable() { + apex := a.ApexVariationName() + exec := ctx.OtherModuleName(module) + if isStaticExecutableAllowed(apex, exec) { + return + } + ctx.ModuleErrorf("executable %s is static", ctx.OtherModuleName(module)) + } + }) +} + +// A small list of exceptions where static executables are allowed in APEXes. +func isStaticExecutableAllowed(apex string, exec string) bool { + m := map[string][]string{ + "com.android.runtime": []string{ + "linker", + "linkerconfig", + }, + } + execNames, ok := m[apex] + return ok && android.InList(exec, execNames) +} + // Collect information for opening IDE project files in java/jdeps.go. func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) { dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...) diff --git a/apex/apex_test.go b/apex/apex_test.go index f58bf6cc5..1645c9978 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -374,7 +374,6 @@ func TestBasicApex(t *testing.T) { symlinks: ["foo_link_"], symlink_preferred_arch: true, system_shared_libs: [], - static_executable: true, stl: "none", apex_available: [ "myapex", "com.android.gki.*" ], } @@ -2494,7 +2493,6 @@ func TestFilesInSubDir(t *testing.T) { srcs: ["mylib.cpp"], relative_install_path: "foo/bar", system_shared_libs: [], - static_executable: true, stl: "none", apex_available: [ "myapex" ], } @@ -2554,7 +2552,6 @@ func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) { name: "mybin", relative_install_path: "foo/bar", system_shared_libs: [], - static_executable: true, stl: "none", apex_available: [ "myapex" ], native_bridge_supported: true, @@ -8188,6 +8185,33 @@ func TestApexJavaCoverage(t *testing.T) { } } +func TestProhibitStaticExecutable(t *testing.T) { + testApexError(t, `executable mybin is static`, ` + apex { + name: "myapex", + key: "myapex.key", + binaries: ["mybin"], + min_sdk_version: "29", + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_binary { + name: "mybin", + srcs: ["mylib.cpp"], + relative_install_path: "foo/bar", + static_executable: true, + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + } + `) +} + func TestMain(m *testing.M) { os.Exit(m.Run()) }