DexOptData.cpp revision e377ef62a40267ab16c2dd20cc5f4c63af6397cc
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{
33e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    return (ptr >= start) && (ptr < end) && (((u4) 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/*
49e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Parse out an index map entry, advancing "*pData" and reducing "*pSize".
50e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein */
51e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool parseIndexMapEntry(const u1** pData, u4* pSize, bool expanding,
52e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4* pFullCount, u4* pReducedCount, const u2** pMap)
53e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein{
54e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const u4* wordPtr = (const u4*) *pData;
55e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4 size = *pSize;
56e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4 mapCount;
57e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
58e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (expanding) {
59e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        if (size < 4)
60e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            return false;
61e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        mapCount = *pReducedCount = *wordPtr++;
62e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        *pFullCount = (u4) -1;
63e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        size -= sizeof(u4);
64e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    } else {
65e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        if (size < 8)
66e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            return false;
67e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        mapCount = *pFullCount = *wordPtr++;
68e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        *pReducedCount = *wordPtr++;
69e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        size -= sizeof(u4) * 2;
70e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
71e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
72e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4 mapSize = mapCount * sizeof(u2);
73e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
74e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (size < mapSize)
75e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
76e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    *pMap = (const u2*) wordPtr;
77e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    size -= mapSize;
78e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
79e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /* advance the pointer */
80e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const u1* ptr = (const u1*) wordPtr;
81e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    ptr += (mapSize + 3) & ~0x3;
82e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
83e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /* update pass-by-reference values */
84e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    *pData = (const u1*) ptr;
85e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    *pSize = size;
86e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
87e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    return true;
88e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein}
89e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
90e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/*
91e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Set up some pointers into the mapped data.
92e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein *
93e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * See analysis/ReduceConstants.c for the data layout description.
94e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein */
95e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool parseIndexMap(DexFile* pDexFile, const u1* data, u4 size,
96e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    bool expanding)
97e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein{
98e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (!parseIndexMapEntry(&data, &size, expanding,
99e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.classFullCount,
100e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.classReducedCount,
101e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.classMap))
102e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    {
103e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
104e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
105e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
106e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (!parseIndexMapEntry(&data, &size, expanding,
107e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.methodFullCount,
108e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.methodReducedCount,
109e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.methodMap))
110e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    {
111e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
112e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
113e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
114e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (!parseIndexMapEntry(&data, &size, expanding,
115e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.fieldFullCount,
116e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.fieldReducedCount,
117e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.fieldMap))
118e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    {
119e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
120e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
121e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
122e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (!parseIndexMapEntry(&data, &size, expanding,
123e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.stringFullCount,
124e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.stringReducedCount,
125e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            &pDexFile->indexMap.stringMap))
126e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    {
127e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
128e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
129e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
130e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (expanding) {
131e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        /*
132e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         * The map includes the "reduced" counts; pull the original counts
133e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         * out of the DexFile so that code has a consistent source.
134e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         */
135e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        assert(pDexFile->indexMap.classFullCount == (u4) -1);
136e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        assert(pDexFile->indexMap.methodFullCount == (u4) -1);
137e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        assert(pDexFile->indexMap.fieldFullCount == (u4) -1);
138e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        assert(pDexFile->indexMap.stringFullCount == (u4) -1);
139e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
140e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein#if 0   // TODO: not available yet -- do later or just skip this
141e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.classFullCount =
142e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pHeader->typeIdsSize;
143e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.methodFullCount =
144e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pHeader->methodIdsSize;
145e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.fieldFullCount =
146e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pHeader->fieldIdsSize;
147e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.stringFullCount =
148e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pHeader->stringIdsSize;
149e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein#endif
150e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
151e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
152e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    LOGI("Class : %u %u %u\n",
153e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.classFullCount,
154e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.classReducedCount,
155e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.classMap[0]);
156e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    LOGI("Method: %u %u %u\n",
157e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.methodFullCount,
158e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.methodReducedCount,
159e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.methodMap[0]);
160e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    LOGI("Field : %u %u %u\n",
161e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.fieldFullCount,
162e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.fieldReducedCount,
163e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.fieldMap[0]);
164e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    LOGI("String: %u %u %u\n",
165e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.stringFullCount,
166e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.stringReducedCount,
167e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pDexFile->indexMap.stringMap[0]);
168e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
169e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    return true;
170e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein}
171e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
172e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein/* (documented in header file) */
173e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinbool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile)
174e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein{
175e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const void* pOptStart = data + pDexFile->pOptHeader->optOffset;
176e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const void* pOptEnd = data + length;
177e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const u4* pOpt = pOptStart;
178e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4 optLength = (const u1*) pOptEnd - (const u1*) pOptStart;
179e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    u4 indexMapType = 0;
180e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
181e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /*
182e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * Make sure the opt data start is in range and aligned. This may
183e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * seem like a superfluous check, but (a) if the file got
184e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * truncated, it might turn out that pOpt >= pOptEnd; and (b)
185e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * if the opt data header got corrupted, pOpt might not be
186e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * properly aligned. This test will catch both of these cases.
187e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     */
188e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (!isValidPointer(pOpt, pOptStart, pOptEnd)) {
189e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        LOGE("Bogus opt data start pointer\n");
190e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
191e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
192e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
193e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /* Make sure that the opt data length is a whole number of words. */
194e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if ((optLength & 3) != 0) {
195e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        LOGE("Unaligned opt data area end\n");
196e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
197e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
198e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
199e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /*
200e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * Make sure that the opt data area is large enough to have at least
201e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * one chunk header.
202e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     */
203e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (optLength < 8) {
204e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        LOGE("Undersized opt data area (%u)\n", optLength);
205e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
206e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
207e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
208e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /* Process chunks until we see the end marker. */
209e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    while (*pOpt != kDexChunkEnd) {
210e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        if (!isValidPointer(pOpt + 2, pOptStart, pOptEnd)) {
211e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            LOGE("Bogus opt data content pointer at offset %u\n",
212e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                    ((const u1*) pOpt) - data);
213e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            return false;
214e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        }
215e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
216e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        u4 size = *(pOpt + 1);
217e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        const u1* pOptData = (const u1*) (pOpt + 2);
218e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
219e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        /*
220e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         * The rounded size is 64-bit aligned and includes +8 for the
221e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         * type/size header (which was extracted immediately above).
222e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein         */
223e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        u4 roundedSize = (size + 8 + 7) & ~7;
224e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        const u4* pNextOpt = pOpt + (roundedSize / sizeof(u4));
225e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
226e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        if (!isValidPointer(pNextOpt, pOptStart, pOptEnd)) {
227e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            LOGE("Opt data area problem for chunk of size %u at offset %u\n",
228e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                    size, ((const u1*) pOpt) - data);
229e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            return false;
230e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        }
231e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
232e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        switch (*pOpt) {
233e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        case kDexChunkClassLookup:
234e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pClassLookup = (const DexClassLookup*) pOptData;
235e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
236e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        case kDexChunkReducingIndexMap:
237e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            LOGI("+++ found reducing index map, size=%u\n", size);
238e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            if (!parseIndexMap(pDexFile, pOptData, size, false)) {
239e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                LOGE("Failed parsing reducing index map\n");
240e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                return false;
241e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            }
242e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            indexMapType = *pOpt;
243e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
244e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        case kDexChunkExpandingIndexMap:
245e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            LOGI("+++ found expanding index map, size=%u\n", size);
246e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            if (!parseIndexMap(pDexFile, pOptData, size, true)) {
247e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                LOGE("Failed parsing expanding index map\n");
248e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                return false;
249e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            }
250e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            indexMapType = *pOpt;
251e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
252e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        case kDexChunkRegisterMaps:
253e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            LOGV("+++ found register maps, size=%u\n", size);
254e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pDexFile->pRegisterMapPool = pOptData;
255e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
256e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        default:
257e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            LOGI("Unknown chunk 0x%08x (%c%c%c%c), size=%d in opt data area\n",
258e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                *pOpt,
259e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                (char) ((*pOpt) >> 24), (char) ((*pOpt) >> 16),
260e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                (char) ((*pOpt) >> 8),  (char)  (*pOpt),
261e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein                size);
262e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            break;
263e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        }
264e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
265e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pOpt = pNextOpt;
266e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
267e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
268e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein#if 0   // TODO: propagate expected map type from the VM through the API
269e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    /*
270e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * If we're configured to expect an index map, and we don't find one,
271e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * reject this DEX so we'll regenerate it.  Also, if we found an
272e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * "expanding" map but we're not configured to use it, we have to fail
273e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * because the constants aren't usable without translation.
274e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     */
275e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (indexMapType != expectedIndexMapType) {
276e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        LOGW("Incompatible index map configuration: found 0x%04x, need %d\n",
277e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            indexMapType, DVM_REDUCE_CONSTANTS);
278e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        return false;
279e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    }
280e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein#endif
281e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein
282e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    return true;
283e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein}
284