summaryrefslogtreecommitdiffstats
path: root/libdex/DexFile.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdex/DexFile.c')
-rw-r--r--libdex/DexFile.c276
1 files changed, 3 insertions, 273 deletions
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)