1e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/*
2e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Copyright (C) 2010 The Android Open Source Project
3e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein *
4e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Licensed under the Apache License, Version 2.0 (the "License");
5e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * you may not use this file except in compliance with the License.
6e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * You may obtain a copy of the License at
7e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein *
8e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein *      http://www.apache.org/licenses/LICENSE-2.0
9e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein *
10e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Unless required by applicable law or agreed to in writing, software
11e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * distributed under the License is distributed on an "AS IS" BASIS,
12e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * See the License for the specific language governing permissions and
14e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * limitations under the License.
15e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein */
16e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
17e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/*
18e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Functions to parse and manipulate the additional data tables added
19e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * to optimized .dex files.
20e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein */
21e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
22e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein#include <zlib.h>
23e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
24e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein#include "DexOptData.h"
25e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
26e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/*
27e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Check to see if a given data pointer is a valid double-word-aligned
28e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * pointer into the given memory range (from start inclusive to end
29e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * exclusive). Returns true if valid.
30e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein */
31e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool isValidPointer(const void* ptr, const void* start, const void* end)
32e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein{
33b210a9f9c7ae17e2028a86d9a4e9a3b35472862aSangWook Han    return (ptr >= start) && (ptr < end) && (((uintptr_t) ptr & 7) == 0);
34e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein}
35e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
36e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/* (documented in header file) */
37e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinu4 dexComputeOptChecksum(const DexOptHeader* pOptHeader)
38e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein{
39e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const u1* start = (const u1*) pOptHeader + pOptHeader->depsOffset;
40e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const u1* end = (const u1*) pOptHeader +
41e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pOptHeader->optOffset + pOptHeader->optLength;
42e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
43e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    uLong adler = adler32(0L, Z_NULL, 0);
44e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
45e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    return (u4) adler32(adler, start, end - start);
46e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein}
47e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
48e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/* (documented in header file) */
49e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinbool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile)
50e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein{
51e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const void* pOptStart = data + pDexFile->pOptHeader->optOffset;
52e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const void* pOptEnd = data + length;
53a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein    const u4* pOpt = (const u4*) pOptStart;
54e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4 optLength = (const u1*) pOptEnd - (const u1*) pOptStart;
55e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
56e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /*
57e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * Make sure the opt data start is in range and aligned. This may
58e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * seem like a superfluous check, but (a) if the file got
59e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * truncated, it might turn out that pOpt >= pOptEnd; and (b)
60e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * if the opt data header got corrupted, pOpt might not be
61e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * properly aligned. This test will catch both of these cases.
62e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     */
63e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (!isValidPointer(pOpt, pOptStart, pOptEnd)) {
64c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Bogus opt data start pointer");
65e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
66e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
67e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
68e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /* Make sure that the opt data length is a whole number of words. */
69e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if ((optLength & 3) != 0) {
70c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unaligned opt data area end");
71e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
72e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
73e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
74e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /*
75e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * Make sure that the opt data area is large enough to have at least
76e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * one chunk header.
77e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     */
78e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (optLength < 8) {
79c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Undersized opt data area (%u)", optLength);
80e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
81e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
82e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
83e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /* Process chunks until we see the end marker. */
84e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    while (*pOpt != kDexChunkEnd) {
85e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        if (!isValidPointer(pOpt + 2, pOptStart, pOptEnd)) {
86c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Bogus opt data content pointer at offset %u",
87e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                    ((const u1*) pOpt) - data);
88e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            return false;
89e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        }
90e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
91e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        u4 size = *(pOpt + 1);
92e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        const u1* pOptData = (const u1*) (pOpt + 2);
93e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
94e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        /*
95e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         * The rounded size is 64-bit aligned and includes +8 for the
96e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         * type/size header (which was extracted immediately above).
97e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         */
98e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        u4 roundedSize = (size + 8 + 7) & ~7;
99e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        const u4* pNextOpt = pOpt + (roundedSize / sizeof(u4));
100e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
101e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        if (!isValidPointer(pNextOpt, pOptStart, pOptEnd)) {
102c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Opt data area problem for chunk of size %u at offset %u",
103e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                    size, ((const u1*) pOpt) - data);
104e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            return false;
105e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        }
106e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
107e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        switch (*pOpt) {
108e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        case kDexChunkClassLookup:
109e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pClassLookup = (const DexClassLookup*) pOptData;
110e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
111e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        case kDexChunkRegisterMaps:
11292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("+++ found register maps, size=%u", size);
113e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pRegisterMapPool = pOptData;
114e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
115e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        default:
1164308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("Unknown chunk 0x%08x (%c%c%c%c), size=%d in opt data area",
117e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                *pOpt,
118e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                (char) ((*pOpt) >> 24), (char) ((*pOpt) >> 16),
119e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                (char) ((*pOpt) >> 8),  (char)  (*pOpt),
120e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                size);
121e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
122e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        }
123e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
124e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pOpt = pNextOpt;
125e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
126e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
127e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    return true;
128e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein}
129