Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55405b61 authored by Kalesh Singh's avatar Kalesh Singh
Browse files

zipalign: Allow specifiying the target page size



Allow apps to specify the target page size for aligning their
uncompressed shared libraries.

This allows apps that want to support larger page sizes to do
so by specifiying the -P <pagesize_kb> flag.

However, apps built for 4k-only devices are unaffected as they
can continue to use -p flag for 4kB page alignment of uncompressed
shared libraries.

Bug: 276963821
Test: atest -c zipalign_tests
Change-Id: I890db067b8f898045f73e86788662f94a48af772
Signed-off-by: default avatarKalesh Singh <kaleshsingh@google.com>
parent 7e0aa046
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ cc_test_host {
        "libgmock",
    ],
    data: [
         "tests/data/apkWithUncompressedSharedLibs.zip",
         "tests/data/archiveWithOneDirectoryEntry.zip",
         "tests/data/diffOrders.zip",
         "tests/data/holes.zip",
+13 −12
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "ZipFile.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

@@ -36,17 +37,14 @@ static bool isDirectory(ZipEntry* entry) {
}

static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
    ZipEntry* pEntry) {

    static const int kPageAlignment = 4096;

    ZipEntry* pEntry, int pageSize) {
    if (!pageAlignSharedLibs) {
        return defaultAlignment;
    }

    const char* ext = strrchr(pEntry->getFileName(), '.');
    if (ext && strcmp(ext, ".so") == 0) {
        return kPageAlignment;
        return pageSize;
    }

    return defaultAlignment;
@@ -56,7 +54,7 @@ static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
 * Copy all entries from "pZin" to "pZout", aligning as needed.
 */
static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli,
    bool pageAlignSharedLibs)
    bool pageAlignSharedLibs, int pageSize)
{
    int numEntries = pZin->getNumEntries();
    ZipEntry* pEntry;
@@ -84,7 +82,8 @@ 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);
            const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry,
                                             pageSize);

            //printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n",
            //    pEntry->getFileName(), (long) pEntry->getFileOffset(),
@@ -107,7 +106,7 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfl
 * output file exists and "force" wasn't specified.
 */
int process(const char* inFileName, const char* outFileName,
    int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
    int alignment, bool force, bool zopfli, bool pageAlignSharedLibs, int pageSize)
{
    ZipFile zin, zout;

@@ -127,7 +126,7 @@ int process(const char* inFileName, const char* outFileName,
    }

    if (zin.open(inFileName, ZipFile::kOpenReadOnly) != OK) {
        fprintf(stderr, "Unable to open '%s' as zip archive\n", inFileName);
        fprintf(stderr, "Unable to open '%s' as zip archive: %s\n", inFileName, strerror(errno));
        return 1;
    }
    if (zout.open(outFileName,
@@ -138,7 +137,8 @@ int process(const char* inFileName, const char* outFileName,
        return 1;
    }

    int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs);
    int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs,
                              pageSize);
    if (result != 0) {
        printf("zipalign: failed rewriting '%s' to '%s'\n",
            inFileName, outFileName);
@@ -150,7 +150,7 @@ int process(const char* inFileName, const char* outFileName,
 * Verify the alignment of a zip archive.
 */
int verify(const char* fileName, int alignment, bool verbose,
    bool pageAlignSharedLibs)
    bool pageAlignSharedLibs, int pageSize)
{
    ZipFile zipFile;
    bool foundBad = false;
@@ -181,7 +181,8 @@ int verify(const char* fileName, int alignment, bool verbose,
            continue;
       } else {
            off_t offset = pEntry->getFileOffset();
            const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
            const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry,
                                             pageSize);
            if ((offset % alignTo) != 0) {
                if (verbose) {
                    printf("%8jd %s (BAD - %jd)\n",
+44 −7
Original line number Diff line number Diff line
@@ -34,15 +34,18 @@ 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] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
        "       zipalign -c [-p] [-v] <align> infile.zip\n\n" );
        "Usage: zipalign [-f] [-p] [-P <pagesize_kb>] [-v] [-z] <align> infile.zip outfile.zip\n"
        "       zipalign -c [-p] [-P <pagesize_kb>] [-v] <align> infile.zip\n\n" );
    fprintf(stderr,
        "  <align>: 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 uncompressed .so files\n");
    fprintf(stderr, "  -p: 4kb page-align uncompressed .so files\n");
    fprintf(stderr, "  -v: verbose output\n");
    fprintf(stderr, "  -z: recompress using Zopfli\n");
    fprintf(stderr, "  -P <pagesize_kb>: Align uncompressed .so files to the specified\n");
    fprintf(stderr, "                    page size. Valid values for <pagesize_kb> are 4, 16\n");
    fprintf(stderr, "                    and 64. '-P' cannot be used in combination with '-p'.\n");
}


@@ -57,12 +60,16 @@ int main(int argc, char* const argv[])
    bool verbose = false;
    bool zopfli = false;
    bool pageAlignSharedLibs = false;
    int pageSize = 4096;
    bool legacyPageAlignmentFlag = false;   // -p
    bool pageAlignmentFlag = false;         // -P <pagesize_kb>
    int result = 1;
    int alignment;
    char* endp;

    int opt;
    while ((opt = getopt(argc, argv, "fcpvz")) != -1) {

    while ((opt = getopt(argc, argv, "fcpvzP:")) != -1) {
        switch (opt) {
        case 'c':
            check = true;
@@ -77,7 +84,29 @@ int main(int argc, char* const argv[])
            zopfli = true;
            break;
        case 'p':
            legacyPageAlignmentFlag = true;
            pageAlignSharedLibs = true;
            pageSize = 4096;
            break;
        case 'P':
            pageAlignmentFlag = true;
            pageAlignSharedLibs = true;

            if (!optarg) {
                fprintf(stderr, "ERROR: -P requires an argument\n");
                wantUsage = true;
                goto bail;
            }

            pageSize = atoi(optarg);
            if (pageSize != 4 && pageSize != 16 && pageSize != 64) {
                fprintf(stderr, "ERROR: Invalid argument for -P: %s\n", optarg);
                wantUsage = true;
                goto bail;
            }

            pageSize *= 1024;  // Convert from kB to bytes.

            break;
        default:
            fprintf(stderr, "ERROR: unknown flag -%c\n", opt);
@@ -86,6 +115,13 @@ int main(int argc, char* const argv[])
        }
    }

    if (legacyPageAlignmentFlag && pageAlignmentFlag) {
            fprintf(stderr, "ERROR: Invalid options: '-P <pagesize_kb>' and '-p'"
                            "cannot be used in combination.\n");
            wantUsage = true;
            goto bail;
    }

    if (!((check && (argc - optind) == 2) || (!check && (argc - optind) == 3))) {
        wantUsage = true;
        goto bail;
@@ -100,14 +136,15 @@ int main(int argc, char* const argv[])

    if (check) {
        /* check existing archive for correct alignment */
        result = verify(argv[optind + 1], alignment, verbose, pageAlignSharedLibs);
        result = verify(argv[optind + 1], alignment, verbose, pageAlignSharedLibs, pageSize);
    } else {
        /* create the new archive */
        result = process(argv[optind + 1], argv[optind + 2], alignment, force, zopfli, pageAlignSharedLibs);
        result = process(argv[optind + 1], argv[optind + 2], alignment, force, zopfli,
                         pageAlignSharedLibs, pageSize);

        /* trust, but verify */
        if (result == 0) {
            result = verify(argv[optind + 2], alignment, verbose, pageAlignSharedLibs);
            result = verify(argv[optind + 2], alignment, verbose, pageAlignSharedLibs, pageSize);
        }
    }

+8 −4
Original line number Diff line number Diff line
@@ -25,24 +25,28 @@ namespace android {
 * - force  : Overwrite output if it exists, fail otherwise.
 * - zopfli : Recompress compressed entries with more efficient algorithm.
 *            Copy compressed entries as-is, and unaligned, otherwise.
 * - pageAlignSharedLibs: Align .so files to 4096 and other files to
 * - pageAlignSharedLibs: Align .so files to @pageSize and other files to
 *   alignTo, or all files to alignTo if false..
 * - pageSize: Specifies the page size of the target device. This is used
 *             to correctly page-align shared libraries.
 *
 * Returns 0 on success.
 */
int process(const char* input, const char* output, int alignTo, bool force,
    bool zopfli, bool pageAlignSharedLibs);
    bool zopfli, bool pageAlignSharedLibs, int pageSize);

/*
 * Verify the alignment of a zip archive.
 * - alignTo: Alignment (in bytes) for uncompressed entries.
 * - pageAlignSharedLibs: Align .so files to 4096 and other files to
 * - pageAlignSharedLibs: Align .so files to @pageSize and other files to
 *   alignTo, or all files to alignTo if false..
 * - pageSize: Specifies the page size of the target device. This is used
 *             to correctly page-align shared libraries.
 *
 * Returns 0 on success.
 */
int verify(const char* fileName, int alignTo, bool verbose,
    bool pageAlignSharedLibs);
    bool pageAlignSharedLibs, int pageSize);

} // namespace android

+1.64 KiB

File added.

No diff preview for this file type.

Loading