From 13e5965306212a9051772ff1d5bc3a88e5fb519a Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Wed, 23 Jul 2014 15:27:21 -0700 Subject: [PATCH] Store native libs aligned to PAGE_SIZE - Add a new flag to zipalign (-p) that page aligns shared libraries (zip entries ending with ".so") in the archive. - Add a new build variable LOCAL_PAGE_ALIGN_SHARED_LIBRARIES to turn on this behaviour in zipalign. - Add a new LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS to control zip behaviour. Bug: 8076853 Bug: 19330157 Co-Authored-By: Simon Baldwin Co-Authored-By: Dimitry Ivanov Change-Id: I1aa2c039bb2a590ae72f256acc9ba5401c2c59b1 --- core/clear_vars.mk | 2 ++ core/definitions.mk | 11 +++++---- core/package_internal.mk | 12 +++++++++- core/prebuilt_internal.mk | 1 + tools/zipalign/ZipAlign.cpp | 54 ++++++++++++++++++++++++++++++++++----------- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/core/clear_vars.mk b/core/clear_vars.mk index db48bd62f..cb32a84e0 100644 --- a/core/clear_vars.mk +++ b/core/clear_vars.mk @@ -20,6 +20,7 @@ LOCAL_UNSTRIPPED_PATH:= LOCAL_MODULE_CLASS:= LOCAL_MODULE_SUFFIX:= LOCAL_PACKAGE_NAME:= +LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES:= LOCAL_OVERRIDES_PACKAGES:= LOCAL_EXPORT_PACKAGE_RESOURCES:= LOCAL_MANIFEST_PACKAGE_NAME:= @@ -94,6 +95,7 @@ LOCAL_COMPRESS_MODULE_SYMBOLS:= LOCAL_STRIP_MODULE:= LOCAL_JNI_SHARED_LIBRARIES:= LOCAL_JNI_SHARED_LIBRARIES_ABI:= +LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS:= LOCAL_PREBUILT_JNI_LIBS:= LOCAL_JAR_MANIFEST:= LOCAL_INSTRUMENTATION_FOR:= diff --git a/core/definitions.mk b/core/definitions.mk index 984555620..6951af9e2 100644 --- a/core/definitions.mk +++ b/core/definitions.mk @@ -1837,7 +1837,7 @@ $(hide) mkdir -p $(addprefix $(dir $@)lib/,$(PRIVATE_JNI_SHARED_LIBRARIES_ABI)) $(foreach abi,$(PRIVATE_JNI_SHARED_LIBRARIES_ABI),\ $(call _add-jni-shared-libs-to-package-per-abi,$(abi),\ $(patsubst $(abi):%,%,$(filter $(abi):%,$(PRIVATE_JNI_SHARED_LIBRARIES))))) -$(hide) (cd $(dir $@) && zip -r $(notdir $@) lib) +$(hide) (cd $(dir $@) && zip -r $(PRIVATE_JNI_SHARED_LIBRARIES_ZIP_OPTIONS) $(notdir $@) lib) $(hide) rm -rf $(dir $@)lib endef @@ -1865,12 +1865,15 @@ $(hide) java -jar $(SIGNAPK_JAR) \ $(hide) mv $@.signed $@ endef -# Align STORED entries of a package on 4-byte boundaries -# to make them easier to mmap. +# Align STORED entries of a package on 4-byte boundaries to make them easier to mmap. # define align-package $(hide) mv $@ $@.unaligned -$(hide) $(ZIPALIGN) -f 4 $@.unaligned $@.aligned +$(hide) $(ZIPALIGN) \ + -f \ + $(if $(findstring true, $(PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES)),-p ,) \ + 4 \ + $@.unaligned $@.aligned $(hide) mv $@.aligned $@ endef diff --git a/core/package_internal.mk b/core/package_internal.mk index 49a6d9bb3..f5e6c25bf 100644 --- a/core/package_internal.mk +++ b/core/package_internal.mk @@ -63,6 +63,14 @@ ifeq ($(LOCAL_MODULE_TAGS),) LOCAL_MODULE_TAGS := optional endif +ifeq ($(LOCAL_PACKAGE_ALIGNMENT),) +LOCAL_PACKAGE_ALIGNMENT := $(DEFAULT_PACKAGE_ALIGNMENT) +endif + +ifeq ($(LOCAL_JNI_SHARED_LIBRARIES_PACKAGE_ALIGNMENT),) +LOCAL_JNI_SHARED_LIBRARIES_PACKAGE_ALIGNMENT := $(DEFAULT_JNI_SHARED_LIBRARIES_PACKAGE_ALIGNMENT) +endif + ifeq ($(filter tests, $(LOCAL_MODULE_TAGS)),) # Force localization check if it's not tagged as tests. LOCAL_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) -z @@ -373,6 +381,8 @@ $(LOCAL_BUILT_MODULE): $(AAPT) | $(ZIPALIGN) $(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis) # PRIVATE_JNI_SHARED_LIBRARIES_ABI is a list of ABI names. $(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis) +$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES_ZIP_OPTIONS := $(LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS) +$(LOCAL_BUILT_MODULE): PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES := $(LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES) ifneq ($(TARGET_BUILD_APPS),) # Include all resources for unbundled apps. LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true @@ -485,7 +495,7 @@ $(apk_jni_stripped) : $(LOCAL_BUILT_MODULE) | $(ZIPALIGN) @rm -rf $(dir $@) && mkdir -p $(dir $@) $(hide) cp $< $@ $(hide) zip -d $@ $(foreach f,$(PRIVATE_JNI_SHARED_LIBRARIES),\*/$(f)) - $(call align-package) + $(align-package) $(call dist-for-goals, apps_only, $(apk_jni_stripped):$(dist_subdir)/$(LOCAL_PACKAGE_NAME).apk) diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk index 2e0d2ef5c..73595134e 100644 --- a/core/prebuilt_internal.mk +++ b/core/prebuilt_internal.mk @@ -170,6 +170,7 @@ endif include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk ####################################### # Sign and align non-presigned .apks. +$(built_module) : PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES := $(LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES) $(built_module) : $(my_prebuilt_src_file) | $(ACP) $(ZIPALIGN) $(SIGNAPK_JAR) $(transform-prebuilt-to-target) ifdef extracted_jni_libs diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp index dc2826baa..191dd4112 100644 --- a/tools/zipalign/ZipAlign.cpp +++ b/tools/zipalign/ZipAlign.cpp @@ -32,20 +32,39 @@ void usage(void) fprintf(stderr, "Zip alignment utility\n"); fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n"); fprintf(stderr, - "Usage: zipalign [-f] [-v] [-z] infile.zip outfile.zip\n" - " zipalign -c [-v] infile.zip\n\n" ); + "Usage: zipalign [-f] [-p] [-v] [-z] infile.zip outfile.zip\n" + " zipalign -c [-v] infile.zip [list of files]\n\n" ); fprintf(stderr, " : alignment in bytes, e.g. '4' provides 32-bit alignment\n"); fprintf(stderr, " -c: check alignment only (does not modify file)\n"); fprintf(stderr, " -f: overwrite existing outfile.zip\n"); + fprintf(stderr, " -p: page align stored shared object: files\n"); fprintf(stderr, " -v: verbose output\n"); fprintf(stderr, " -z: recompress using Zopfli\n"); } +static const int kPageAlignment = 4096; + +static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment, + ZipEntry* pEntry) { + + if (!pageAlignSharedLibs) { + return defaultAlignment; + } + + const char* ext = strrchr(pEntry->getFileName(), '.'); + if (ext && strcmp(ext, ".so") == 0) { + return kPageAlignment; + } + + return defaultAlignment; +} + /* * Copy all entries from "pZin" to "pZout", aligning as needed. */ -static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli) +static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli, + bool pageAlignSharedLibs) { int numEntries = pZin->getNumEntries(); ZipEntry* pEntry; @@ -75,13 +94,15 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfl status = pZout->add(pZin, pEntry, padding, &pNewEntry); } } else { + const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry); + /* * Copy the entry, adjusting as required. We assume that the * file position in the new file will be equal to the file * position in the original. */ long newOffset = pEntry->getFileOffset() + bias; - padding = (alignment - (newOffset % alignment)) % alignment; + padding = (alignTo - (newOffset % alignTo)) % alignTo; //printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n", // pEntry->getFileName(), (long) pEntry->getFileOffset(), @@ -105,7 +126,7 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfl * output file exists and "force" wasn't specified. */ static int process(const char* inFileName, const char* outFileName, - int alignment, bool force, bool zopfli) + int alignment, bool force, bool zopfli, bool pageAlignSharedLibs) { ZipFile zin, zout; @@ -136,7 +157,7 @@ static int process(const char* inFileName, const char* outFileName, return 1; } - int result = copyAndAlign(&zin, &zout, alignment, zopfli); + int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs); if (result != 0) { printf("zipalign: failed rewriting '%s' to '%s'\n", inFileName, outFileName); @@ -147,7 +168,8 @@ static int process(const char* inFileName, const char* outFileName, /* * Verify the alignment of a zip archive. */ -static int verify(const char* fileName, int alignment, bool verbose) +static int verify(const char* fileName, int alignment, bool verbose, + bool pageAlignSharedLibs) { ZipFile zipFile; bool foundBad = false; @@ -172,11 +194,12 @@ static int verify(const char* fileName, int alignment, bool verbose) } } else { long offset = pEntry->getFileOffset(); - if ((offset % alignment) != 0) { + const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry); + if ((offset % alignTo) != 0) { if (verbose) { printf("%8ld %s (BAD - %ld)\n", (long) offset, pEntry->getFileName(), - offset % alignment); + offset % alignTo); } foundBad = true; } else { @@ -204,6 +227,7 @@ int main(int argc, char* const argv[]) bool force = false; bool verbose = false; bool zopfli = false; + bool pageAlignSharedLibs = false; int result = 1; int alignment; char* endp; @@ -233,6 +257,9 @@ int main(int argc, char* const argv[]) case 'z': zopfli = true; break; + case 'p': + pageAlignSharedLibs = true; + break; default: fprintf(stderr, "ERROR: unknown flag -%c\n", *cp); wantUsage = true; @@ -260,14 +287,15 @@ int main(int argc, char* const argv[]) if (check) { /* check existing archive for correct alignment */ - result = verify(argv[1], alignment, verbose); + result = verify(argv[1], alignment, verbose, pageAlignSharedLibs); } else { /* create the new archive */ - result = process(argv[1], argv[2], alignment, force, zopfli); + result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs); /* trust, but verify */ - if (result == 0) - result = verify(argv[2], alignment, verbose); + if (result == 0) { + result = verify(argv[2], alignment, verbose, pageAlignSharedLibs); + } } bail: -- 2.11.0