summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dexdump/DexDump.c32
-rw-r--r--libdex/Android.mk1
-rw-r--r--libdex/DexFile.c276
-rw-r--r--libdex/DexFile.h8
-rw-r--r--libdex/DexOptData.c283
-rw-r--r--libdex/DexOptData.h43
-rw-r--r--vm/analysis/DexPrepare.c50
7 files changed, 376 insertions, 317 deletions
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index 33646bbce..714a0f86c 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -406,9 +406,9 @@ void dumpFileHeader(const DexFile* pDexFile)
printf("deps_offset : %d (0x%06x)\n",
pOptHeader->depsOffset, pOptHeader->depsOffset);
printf("deps_length : %d\n", pOptHeader->depsLength);
- printf("aux_offset : %d (0x%06x)\n",
- pOptHeader->auxOffset, pOptHeader->auxOffset);
- printf("aux_length : %d\n", pOptHeader->auxLength);
+ printf("opt_offset : %d (0x%06x)\n",
+ pOptHeader->optOffset, pOptHeader->optOffset);
+ printf("opt_length : %d\n", pOptHeader->optLength);
printf("flags : %08x\n", pOptHeader->flags);
printf("checksum : %08x\n", pOptHeader->checksum);
printf("\n");
@@ -449,33 +449,33 @@ void dumpFileHeader(const DexFile* pDexFile)
}
/*
- * Dump the "table of contents" for the aux area.
+ * Dump the "table of contents" for the opt area.
*/
-void dumpAuxDirectory(const DexFile* pDexFile)
+void dumpOptDirectory(const DexFile* pDexFile)
{
const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
if (pOptHeader == NULL)
return;
- printf("AUX section contents:\n");
+ printf("OPT section contents:\n");
- const u4* pAux = (const u4*) ((u1*) pOptHeader + pOptHeader->auxOffset);
+ const u4* pOpt = (const u4*) ((u1*) pOptHeader + pOptHeader->optOffset);
- if (*pAux == 0) {
+ if (*pOpt == 0) {
printf("(1.0 format, only class lookup table is present)\n\n");
return;
}
/*
- * The "aux" section is in "chunk" format: a 32-bit identifier, a 32-bit
+ * The "opt" section is in "chunk" format: a 32-bit identifier, a 32-bit
* length, then the data. Chunks start on 64-bit boundaries.
*/
- while (*pAux != kDexChunkEnd) {
+ while (*pOpt != kDexChunkEnd) {
const char* verboseStr;
- u4 size = *(pAux+1);
+ u4 size = *(pOpt+1);
- switch (*pAux) {
+ switch (*pOpt) {
case kDexChunkClassLookup:
verboseStr = "class lookup hash table";
break;
@@ -493,12 +493,12 @@ void dumpAuxDirectory(const DexFile* pDexFile)
break;
}
- printf("Chunk %08x (%c%c%c%c) - %s (%d bytes)\n", *pAux,
- *pAux >> 24, (char)(*pAux >> 16), (char)(*pAux >> 8), (char)*pAux,
+ printf("Chunk %08x (%c%c%c%c) - %s (%d bytes)\n", *pOpt,
+ *pOpt >> 24, (char)(*pOpt >> 16), (char)(*pOpt >> 8), (char)*pOpt,
verboseStr, size);
size = (size + 8 + 7) & ~7;
- pAux += size / sizeof(u4);
+ pOpt += size / sizeof(u4);
}
printf("\n");
}
@@ -1721,7 +1721,7 @@ void processDexFile(const char* fileName, DexFile* pDexFile)
if (gOptions.showFileHeaders) {
dumpFileHeader(pDexFile);
- dumpAuxDirectory(pDexFile);
+ dumpOptDirectory(pDexFile);
}
if (gOptions.outputFormat == OUTPUT_XML)
diff --git a/libdex/Android.mk b/libdex/Android.mk
index dfd9802d4..af33baf9d 100644
--- a/libdex/Android.mk
+++ b/libdex/Android.mk
@@ -21,6 +21,7 @@ dex_src_files := \
DexDataMap.c \
DexFile.c \
DexInlines.c \
+ DexOptData.c \
DexProto.c \
DexSwapVerify.c \
InstrUtils.c \
diff --git a/libdex/DexFile.c b/libdex/DexFile.c
index f6b0ffd9a..f997b9467 100644
--- a/libdex/DexFile.c
+++ b/libdex/DexFile.c
@@ -19,6 +19,7 @@
*/
#include "DexFile.h"
+#include "DexOptData.h"
#include "DexProto.h"
#include "DexCatch.h"
#include "Leb128.h"
@@ -33,9 +34,6 @@
#include <fcntl.h>
#include <errno.h>
-// fwd
-static u4 dexComputeOptChecksum(const DexOptHeader* pOptHeader);
-
/*
* Verifying checksums is good, but it slows things down and causes us to
@@ -480,259 +478,6 @@ void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data) {
pDexFile->pLinkData = (const DexLink*) (data + pHeader->linkOff);
}
-
-/*
- * Parse out an index map entry, advancing "*pData" and reducing "*pSize".
- */
-static bool parseIndexMapEntry(const u1** pData, u4* pSize, bool expanding,
- u4* pFullCount, u4* pReducedCount, const u2** pMap)
-{
- const u4* wordPtr = (const u4*) *pData;
- u4 size = *pSize;
- u4 mapCount;
-
- if (expanding) {
- if (size < 4)
- return false;
- mapCount = *pReducedCount = *wordPtr++;
- *pFullCount = (u4) -1;
- size -= sizeof(u4);
- } else {
- if (size < 8)
- return false;
- mapCount = *pFullCount = *wordPtr++;
- *pReducedCount = *wordPtr++;
- size -= sizeof(u4) * 2;
- }
-
- u4 mapSize = mapCount * sizeof(u2);
-
- if (size < mapSize)
- return false;
- *pMap = (const u2*) wordPtr;
- size -= mapSize;
-
- /* advance the pointer */
- const u1* ptr = (const u1*) wordPtr;
- ptr += (mapSize + 3) & ~0x3;
-
- /* update pass-by-reference values */
- *pData = (const u1*) ptr;
- *pSize = size;
-
- return true;
-}
-
-/*
- * Set up some pointers into the mapped data.
- *
- * See analysis/ReduceConstants.c for the data layout description.
- */
-static bool parseIndexMap(DexFile* pDexFile, const u1* data, u4 size,
- bool expanding)
-{
- if (!parseIndexMapEntry(&data, &size, expanding,
- &pDexFile->indexMap.classFullCount,
- &pDexFile->indexMap.classReducedCount,
- &pDexFile->indexMap.classMap))
- {
- return false;
- }
-
- if (!parseIndexMapEntry(&data, &size, expanding,
- &pDexFile->indexMap.methodFullCount,
- &pDexFile->indexMap.methodReducedCount,
- &pDexFile->indexMap.methodMap))
- {
- return false;
- }
-
- if (!parseIndexMapEntry(&data, &size, expanding,
- &pDexFile->indexMap.fieldFullCount,
- &pDexFile->indexMap.fieldReducedCount,
- &pDexFile->indexMap.fieldMap))
- {
- return false;
- }
-
- if (!parseIndexMapEntry(&data, &size, expanding,
- &pDexFile->indexMap.stringFullCount,
- &pDexFile->indexMap.stringReducedCount,
- &pDexFile->indexMap.stringMap))
- {
- return false;
- }
-
- if (expanding) {
- /*
- * The map includes the "reduced" counts; pull the original counts
- * out of the DexFile so that code has a consistent source.
- */
- assert(pDexFile->indexMap.classFullCount == (u4) -1);
- assert(pDexFile->indexMap.methodFullCount == (u4) -1);
- assert(pDexFile->indexMap.fieldFullCount == (u4) -1);
- assert(pDexFile->indexMap.stringFullCount == (u4) -1);
-
-#if 0 // TODO: not available yet -- do later or just skip this
- pDexFile->indexMap.classFullCount =
- pDexFile->pHeader->typeIdsSize;
- pDexFile->indexMap.methodFullCount =
- pDexFile->pHeader->methodIdsSize;
- pDexFile->indexMap.fieldFullCount =
- pDexFile->pHeader->fieldIdsSize;
- pDexFile->indexMap.stringFullCount =
- pDexFile->pHeader->stringIdsSize;
-#endif
- }
-
- LOGI("Class : %u %u %u\n",
- pDexFile->indexMap.classFullCount,
- pDexFile->indexMap.classReducedCount,
- pDexFile->indexMap.classMap[0]);
- LOGI("Method: %u %u %u\n",
- pDexFile->indexMap.methodFullCount,
- pDexFile->indexMap.methodReducedCount,
- pDexFile->indexMap.methodMap[0]);
- LOGI("Field : %u %u %u\n",
- pDexFile->indexMap.fieldFullCount,
- pDexFile->indexMap.fieldReducedCount,
- pDexFile->indexMap.fieldMap[0]);
- LOGI("String: %u %u %u\n",
- pDexFile->indexMap.stringFullCount,
- pDexFile->indexMap.stringReducedCount,
- pDexFile->indexMap.stringMap[0]);
-
- return true;
-}
-
-/*
- * Check to see if a given data pointer is a valid double-word-aligned
- * pointer into the given memory range (from start inclusive to end
- * exclusive). Returns true if valid.
- */
-static bool isValidPointer(const void* ptr, const void* start, const void* end)
-{
- return (ptr >= start) && (ptr < end) && (((u4) ptr & 7) == 0);
-}
-
-/*
- * Parse some auxillary data tables.
- *
- * v1.0 wrote a zero in the first 32 bits, followed by the DexClassLookup
- * table. Subsequent versions switched to the "chunk" format.
- */
-static bool parseAuxData(const u1* data, size_t length, DexFile* pDexFile)
-{
- const void* pAuxStart = data + pDexFile->pOptHeader->auxOffset;
- const void* pAuxEnd = data + length;
- const u4* pAux = pAuxStart;
- u4 auxLength = (const u1*) pAuxEnd - (const u1*) pAuxStart;
- u4 indexMapType = 0;
-
- /*
- * Make sure the aux data start is in range and aligned. This may
- * seem like a superfluous check, but (a) if the file got
- * truncated, it might turn out that pAux >= pAuxEnd; and (b)
- * if the aux data header got corrupted, pAux might not be
- * properly aligned. This test will catch both of these cases.
- */
- if (!isValidPointer(pAux, pAuxStart, pAuxEnd)) {
- LOGE("Bogus aux data start pointer\n");
- return false;
- }
-
- /* Make sure that the aux data length is a whole number of words. */
- if ((auxLength & 3) != 0) {
- LOGE("Unaligned aux data area end\n");
- return false;
- }
-
- /*
- * Make sure that the aux data area is large enough to have at least
- * one chunk header.
- */
- if (auxLength < 8) {
- LOGE("Undersized aux data area (%u)\n", auxLength);
- return false;
- }
-
- /* Process chunks until we see the end marker. */
- while (*pAux != kDexChunkEnd) {
- if (!isValidPointer(pAux + 2, pAuxStart, pAuxEnd)) {
- LOGE("Bogus aux data content pointer at offset %u\n",
- ((const u1*) pAux) - data);
- return false;
- }
-
- u4 size = *(pAux + 1);
- const u1* pAuxData = (const u1*) (pAux + 2);
-
- /*
- * The rounded size is 64-bit aligned and includes +8 for the
- * type/size header (which was extracted immediately above).
- */
- u4 roundedSize = (size + 8 + 7) & ~7;
- const u4* pNextAux = pAux + (roundedSize / sizeof(u4));
-
- if (!isValidPointer(pNextAux, pAuxStart, pAuxEnd)) {
- LOGE("Aux data area problem for chunk of size %u at offset %u\n",
- size, ((const u1*) pAux) - data);
- return false;
- }
-
- switch (*pAux) {
- case kDexChunkClassLookup:
- pDexFile->pClassLookup = (const DexClassLookup*) pAuxData;
- break;
- case kDexChunkReducingIndexMap:
- LOGI("+++ found reducing index map, size=%u\n", size);
- if (!parseIndexMap(pDexFile, pAuxData, size, false)) {
- LOGE("Failed parsing reducing index map\n");
- return false;
- }
- indexMapType = *pAux;
- break;
- case kDexChunkExpandingIndexMap:
- LOGI("+++ found expanding index map, size=%u\n", size);
- if (!parseIndexMap(pDexFile, pAuxData, size, true)) {
- LOGE("Failed parsing expanding index map\n");
- return false;
- }
- indexMapType = *pAux;
- break;
- case kDexChunkRegisterMaps:
- LOGV("+++ found register maps, size=%u\n", size);
- pDexFile->pRegisterMapPool = pAuxData;
- break;
- default:
- LOGI("Unknown chunk 0x%08x (%c%c%c%c), size=%d in aux data area\n",
- *pAux,
- (char) ((*pAux) >> 24), (char) ((*pAux) >> 16),
- (char) ((*pAux) >> 8), (char) (*pAux),
- size);
- break;
- }
-
- pAux = pNextAux;
- }
-
-#if 0 // TODO: propagate expected map type from the VM through the API
- /*
- * If we're configured to expect an index map, and we don't find one,
- * reject this DEX so we'll regenerate it. Also, if we found an
- * "expanding" map but we're not configured to use it, we have to fail
- * because the constants aren't usable without translation.
- */
- if (indexMapType != expectedIndexMapType) {
- LOGW("Incompatible index map configuration: found 0x%04x, need %d\n",
- indexMapType, DVM_REDUCE_CONSTANTS);
- return false;
- }
-#endif
-
- return true;
-}
-
/*
* Parse an optimized or unoptimized .dex file sitting in memory. This is
* called after the byte-ordering and structure alignment has been fixed up.
@@ -771,8 +516,8 @@ DexFile* dexFileParse(const u1* data, size_t length, int flags)
LOGV("Good opt header, DEX offset is %d, flags=0x%02x\n",
pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);
- /* locate some auxillary data tables */
- if (!parseAuxData(data, length, pDexFile))
+ /* parse the optimized dex file tables */
+ if (!dexParseOptData(data, length, pDexFile))
goto bail;
/* ignore the opt header and appended data from here on out */
@@ -950,21 +695,6 @@ u4 dexComputeChecksum(const DexHeader* pHeader)
}
/*
- * Compute the checksum on the data appended to the DEX file by dexopt.
- */
-static u4 dexComputeOptChecksum(const DexOptHeader* pOptHeader)
-{
- const u1* start = (const u1*) pOptHeader + pOptHeader->depsOffset;
- const u1* end = (const u1*) pOptHeader +
- pOptHeader->auxOffset + pOptHeader->auxLength;
-
- uLong adler = adler32(0L, Z_NULL, 0);
-
- return (u4) adler32(adler, start, end - start);
-}
-
-
-/*
* Compute the size, in bytes, of a DexCode.
*/
size_t dexGetDexCodeSize(const DexCode* pCode)
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index 2ce7ebd68..279650f88 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/*
* Access .dex (Dalvik Executable Format) files. The code here assumes that
* the DEX file has been rewritten (byte-swapped, word-aligned) and that
@@ -28,6 +29,7 @@
*
* All memory-mapped structures are 32-bit aligned unless otherwise noted.
*/
+
#ifndef _LIBDEX_DEXFILE
#define _LIBDEX_DEXFILE
@@ -480,11 +482,11 @@ typedef struct DexOptHeader {
u4 dexLength;
u4 depsOffset; /* offset of optimized DEX dependency table */
u4 depsLength;
- u4 auxOffset; /* file offset of pre-calc auxillary data */
- u4 auxLength;
+ u4 optOffset; /* file offset of optimized data tables */
+ u4 optLength;
u4 flags; /* some info flags */
- u4 checksum; /* adler32 checksum covering deps/aux */
+ u4 checksum; /* adler32 checksum covering deps/opt */
/* pad for 64-bit alignment if necessary */
} DexOptHeader;
diff --git a/libdex/DexOptData.c b/libdex/DexOptData.c
new file mode 100644
index 000000000..995b65529
--- /dev/null
+++ b/libdex/DexOptData.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Functions to parse and manipulate the additional data tables added
+ * to optimized .dex files.
+ */
+
+#include <zlib.h>
+
+#include "DexOptData.h"
+
+/*
+ * Check to see if a given data pointer is a valid double-word-aligned
+ * pointer into the given memory range (from start inclusive to end
+ * exclusive). Returns true if valid.
+ */
+static bool isValidPointer(const void* ptr, const void* start, const void* end)
+{
+ return (ptr >= start) && (ptr < end) && (((u4) ptr & 7) == 0);
+}
+
+/* (documented in header file) */
+u4 dexComputeOptChecksum(const DexOptHeader* pOptHeader)
+{
+ const u1* start = (const u1*) pOptHeader + pOptHeader->depsOffset;
+ const u1* end = (const u1*) pOptHeader +
+ pOptHeader->optOffset + pOptHeader->optLength;
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ return (u4) adler32(adler, start, end - start);
+}
+
+/*
+ * Parse out an index map entry, advancing "*pData" and reducing "*pSize".
+ */
+static bool parseIndexMapEntry(const u1** pData, u4* pSize, bool expanding,
+ u4* pFullCount, u4* pReducedCount, const u2** pMap)
+{
+ const u4* wordPtr = (const u4*) *pData;
+ u4 size = *pSize;
+ u4 mapCount;
+
+ if (expanding) {
+ if (size < 4)
+ return false;
+ mapCount = *pReducedCount = *wordPtr++;
+ *pFullCount = (u4) -1;
+ size -= sizeof(u4);
+ } else {
+ if (size < 8)
+ return false;
+ mapCount = *pFullCount = *wordPtr++;
+ *pReducedCount = *wordPtr++;
+ size -= sizeof(u4) * 2;
+ }
+
+ u4 mapSize = mapCount * sizeof(u2);
+
+ if (size < mapSize)
+ return false;
+ *pMap = (const u2*) wordPtr;
+ size -= mapSize;
+
+ /* advance the pointer */
+ const u1* ptr = (const u1*) wordPtr;
+ ptr += (mapSize + 3) & ~0x3;
+
+ /* update pass-by-reference values */
+ *pData = (const u1*) ptr;
+ *pSize = size;
+
+ return true;
+}
+
+/*
+ * Set up some pointers into the mapped data.
+ *
+ * See analysis/ReduceConstants.c for the data layout description.
+ */
+static bool parseIndexMap(DexFile* pDexFile, const u1* data, u4 size,
+ bool expanding)
+{
+ if (!parseIndexMapEntry(&data, &size, expanding,
+ &pDexFile->indexMap.classFullCount,
+ &pDexFile->indexMap.classReducedCount,
+ &pDexFile->indexMap.classMap))
+ {
+ return false;
+ }
+
+ if (!parseIndexMapEntry(&data, &size, expanding,
+ &pDexFile->indexMap.methodFullCount,
+ &pDexFile->indexMap.methodReducedCount,
+ &pDexFile->indexMap.methodMap))
+ {
+ return false;
+ }
+
+ if (!parseIndexMapEntry(&data, &size, expanding,
+ &pDexFile->indexMap.fieldFullCount,
+ &pDexFile->indexMap.fieldReducedCount,
+ &pDexFile->indexMap.fieldMap))
+ {
+ return false;
+ }
+
+ if (!parseIndexMapEntry(&data, &size, expanding,
+ &pDexFile->indexMap.stringFullCount,
+ &pDexFile->indexMap.stringReducedCount,
+ &pDexFile->indexMap.stringMap))
+ {
+ return false;
+ }
+
+ if (expanding) {
+ /*
+ * The map includes the "reduced" counts; pull the original counts
+ * out of the DexFile so that code has a consistent source.
+ */
+ assert(pDexFile->indexMap.classFullCount == (u4) -1);
+ assert(pDexFile->indexMap.methodFullCount == (u4) -1);
+ assert(pDexFile->indexMap.fieldFullCount == (u4) -1);
+ assert(pDexFile->indexMap.stringFullCount == (u4) -1);
+
+#if 0 // TODO: not available yet -- do later or just skip this
+ pDexFile->indexMap.classFullCount =
+ pDexFile->pHeader->typeIdsSize;
+ pDexFile->indexMap.methodFullCount =
+ pDexFile->pHeader->methodIdsSize;
+ pDexFile->indexMap.fieldFullCount =
+ pDexFile->pHeader->fieldIdsSize;
+ pDexFile->indexMap.stringFullCount =
+ pDexFile->pHeader->stringIdsSize;
+#endif
+ }
+
+ LOGI("Class : %u %u %u\n",
+ pDexFile->indexMap.classFullCount,
+ pDexFile->indexMap.classReducedCount,
+ pDexFile->indexMap.classMap[0]);
+ LOGI("Method: %u %u %u\n",
+ pDexFile->indexMap.methodFullCount,
+ pDexFile->indexMap.methodReducedCount,
+ pDexFile->indexMap.methodMap[0]);
+ LOGI("Field : %u %u %u\n",
+ pDexFile->indexMap.fieldFullCount,
+ pDexFile->indexMap.fieldReducedCount,
+ pDexFile->indexMap.fieldMap[0]);
+ LOGI("String: %u %u %u\n",
+ pDexFile->indexMap.stringFullCount,
+ pDexFile->indexMap.stringReducedCount,
+ pDexFile->indexMap.stringMap[0]);
+
+ return true;
+}
+
+/* (documented in header file) */
+bool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile)
+{
+ const void* pOptStart = data + pDexFile->pOptHeader->optOffset;
+ const void* pOptEnd = data + length;
+ const u4* pOpt = pOptStart;
+ u4 optLength = (const u1*) pOptEnd - (const u1*) pOptStart;
+ u4 indexMapType = 0;
+
+ /*
+ * Make sure the opt data start is in range and aligned. This may
+ * seem like a superfluous check, but (a) if the file got
+ * truncated, it might turn out that pOpt >= pOptEnd; and (b)
+ * if the opt data header got corrupted, pOpt might not be
+ * properly aligned. This test will catch both of these cases.
+ */
+ if (!isValidPointer(pOpt, pOptStart, pOptEnd)) {
+ LOGE("Bogus opt data start pointer\n");
+ return false;
+ }
+
+ /* Make sure that the opt data length is a whole number of words. */
+ if ((optLength & 3) != 0) {
+ LOGE("Unaligned opt data area end\n");
+ return false;
+ }
+
+ /*
+ * Make sure that the opt data area is large enough to have at least
+ * one chunk header.
+ */
+ if (optLength < 8) {
+ LOGE("Undersized opt data area (%u)\n", optLength);
+ return false;
+ }
+
+ /* Process chunks until we see the end marker. */
+ while (*pOpt != kDexChunkEnd) {
+ if (!isValidPointer(pOpt + 2, pOptStart, pOptEnd)) {
+ LOGE("Bogus opt data content pointer at offset %u\n",
+ ((const u1*) pOpt) - data);
+ return false;
+ }
+
+ u4 size = *(pOpt + 1);
+ const u1* pOptData = (const u1*) (pOpt + 2);
+
+ /*
+ * The rounded size is 64-bit aligned and includes +8 for the
+ * type/size header (which was extracted immediately above).
+ */
+ u4 roundedSize = (size + 8 + 7) & ~7;
+ const u4* pNextOpt = pOpt + (roundedSize / sizeof(u4));
+
+ if (!isValidPointer(pNextOpt, pOptStart, pOptEnd)) {
+ LOGE("Opt data area problem for chunk of size %u at offset %u\n",
+ size, ((const u1*) pOpt) - data);
+ return false;
+ }
+
+ switch (*pOpt) {
+ case kDexChunkClassLookup:
+ pDexFile->pClassLookup = (const DexClassLookup*) pOptData;
+ break;
+ case kDexChunkReducingIndexMap:
+ LOGI("+++ found reducing index map, size=%u\n", size);
+ if (!parseIndexMap(pDexFile, pOptData, size, false)) {
+ LOGE("Failed parsing reducing index map\n");
+ return false;
+ }
+ indexMapType = *pOpt;
+ break;
+ case kDexChunkExpandingIndexMap:
+ LOGI("+++ found expanding index map, size=%u\n", size);
+ if (!parseIndexMap(pDexFile, pOptData, size, true)) {
+ LOGE("Failed parsing expanding index map\n");
+ return false;
+ }
+ indexMapType = *pOpt;
+ break;
+ case kDexChunkRegisterMaps:
+ LOGV("+++ found register maps, size=%u\n", size);
+ pDexFile->pRegisterMapPool = pOptData;
+ break;
+ default:
+ LOGI("Unknown chunk 0x%08x (%c%c%c%c), size=%d in opt data area\n",
+ *pOpt,
+ (char) ((*pOpt) >> 24), (char) ((*pOpt) >> 16),
+ (char) ((*pOpt) >> 8), (char) (*pOpt),
+ size);
+ break;
+ }
+
+ pOpt = pNextOpt;
+ }
+
+#if 0 // TODO: propagate expected map type from the VM through the API
+ /*
+ * If we're configured to expect an index map, and we don't find one,
+ * reject this DEX so we'll regenerate it. Also, if we found an
+ * "expanding" map but we're not configured to use it, we have to fail
+ * because the constants aren't usable without translation.
+ */
+ if (indexMapType != expectedIndexMapType) {
+ LOGW("Incompatible index map configuration: found 0x%04x, need %d\n",
+ indexMapType, DVM_REDUCE_CONSTANTS);
+ return false;
+ }
+#endif
+
+ return true;
+}
diff --git a/libdex/DexOptData.h b/libdex/DexOptData.h
new file mode 100644
index 000000000..dc94df99d
--- /dev/null
+++ b/libdex/DexOptData.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Functions to parse and manipulate the additional data tables added
+ * to optimized .dex files.
+ */
+
+#ifndef _LIBDEX_DEXOPTDATA
+#define _LIBDEX_DEXOPTDATA
+
+#include <stdbool.h>
+#include "libdex/DexFile.h"
+
+/*
+ * Parse the optimized data tables in the given dex file.
+ *
+ * @param data pointer to the start of the entire dex file
+ * @param length length of the entire dex file, in bytes
+ * @param pDexFile pointer to the associated dex file structure
+ */
+bool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile);
+
+/*
+ * Compute the checksum of the optimized data tables pointed at by the given
+ * header.
+ */
+u4 dexComputeOptChecksum(const DexOptHeader* pOptHeader);
+
+#endif /* def _LIBDEX_DEXOPTDATA */
diff --git a/vm/analysis/DexPrepare.c b/vm/analysis/DexPrepare.c
index 8421f857e..e43042f24 100644
--- a/vm/analysis/DexPrepare.c
+++ b/vm/analysis/DexPrepare.c
@@ -51,7 +51,7 @@ static void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz,
const DexClassDef* pClassDef, bool doVerify, bool doOpt);
static void updateChecksum(u1* addr, int len, DexHeader* pHeader);
static int writeDependencies(int fd, u4 modWhen, u4 crc);
-static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,\
+static bool writeOptData(int fd, const DexClassLookup* pClassLookup,\
const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder);
static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum);
@@ -595,8 +595,8 @@ bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
}
/* get start offset, and adjust deps start for 64-bit alignment */
- off_t depsOffset, auxOffset, endOffset, adjOffset;
- int depsLength, auxLength;
+ off_t depsOffset, optOffset, endOffset, adjOffset;
+ int depsLength, optLength;
u4 optChecksum;
depsOffset = lseek(fd, 0, SEEK_END);
@@ -620,32 +620,32 @@ bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
goto bail;
}
- /* compute deps length, then adjust aux start for 64-bit alignment */
- auxOffset = lseek(fd, 0, SEEK_END);
- depsLength = auxOffset - depsOffset;
+ /* compute deps length, then adjust opt start for 64-bit alignment */
+ optOffset = lseek(fd, 0, SEEK_END);
+ depsLength = optOffset - depsOffset;
- adjOffset = (auxOffset + 7) & ~(0x07);
- if (adjOffset != auxOffset) {
- LOGV("Adjusting aux start from %d to %d\n",
- (int) auxOffset, (int) adjOffset);
- auxOffset = adjOffset;
- lseek(fd, auxOffset, SEEK_SET);
+ adjOffset = (optOffset + 7) & ~(0x07);
+ if (adjOffset != optOffset) {
+ LOGV("Adjusting opt start from %d to %d\n",
+ (int) optOffset, (int) adjOffset);
+ optOffset = adjOffset;
+ lseek(fd, optOffset, SEEK_SET);
}
/*
- * Append any auxillary pre-computed data structures.
+ * Append any optimized pre-computed data structures.
*/
- if (!writeAuxData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) {
- LOGW("Failed writing aux data\n");
+ if (!writeOptData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) {
+ LOGW("Failed writing opt data\n");
goto bail;
}
endOffset = lseek(fd, 0, SEEK_END);
- auxLength = endOffset - auxOffset;
+ optLength = endOffset - optOffset;
- /* compute checksum from start of deps to end of aux area */
+ /* compute checksum from start of deps to end of opt area */
if (!computeFileChecksum(fd, depsOffset,
- (auxOffset+auxLength) - depsOffset, &optChecksum))
+ (optOffset+optLength) - depsOffset, &optChecksum))
{
goto bail;
}
@@ -662,8 +662,8 @@ bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
optHdr.dexLength = (u4) dexLength;
optHdr.depsOffset = (u4) depsOffset;
optHdr.depsLength = (u4) depsLength;
- optHdr.auxOffset = (u4) auxOffset;
- optHdr.auxLength = (u4) auxLength;
+ optHdr.optOffset = (u4) optOffset;
+ optHdr.optLength = (u4) optLength;
optHdr.flags = headerFlags;
optHdr.checksum = optChecksum;
@@ -1334,13 +1334,13 @@ static bool writeChunk(int fd, u4 type, const void* data, size_t size)
header.ts.type = type;
header.ts.size = (u4) size;
if (sysWriteFully(fd, &header, sizeof(header),
- "DexOpt aux chunk header write") != 0)
+ "DexOpt opt chunk header write") != 0)
{
return false;
}
if (size > 0) {
- if (sysWriteFully(fd, data, size, "DexOpt aux chunk write") != 0)
+ if (sysWriteFully(fd, data, size, "DexOpt opt chunk write") != 0)
return false;
}
@@ -1357,14 +1357,14 @@ static bool writeChunk(int fd, u4 type, const void* data, size_t size)
}
/*
- * Write aux data.
+ * Write opt data.
*
* We have different pieces, some of which may be optional. To make the
* most effective use of space, we use a "chunk" format, with a 4-byte
* type and a 4-byte length. We guarantee 64-bit alignment for the data,
* so it can be used directly when the file is mapped for reading.
*/
-static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,
+static bool writeOptData(int fd, const DexClassLookup* pClassLookup,
const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder)
{
/* pre-computed class lookup hash table */
@@ -1442,7 +1442,7 @@ static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum)
/*
* Update the Adler-32 checksum stored in the DEX file. This covers the
* swapped and optimized DEX data, but does not include the opt header
- * or auxillary data.
+ * or optimized data.
*/
static void updateChecksum(u1* addr, int len, DexHeader* pHeader)
{