diff options
Diffstat (limited to 'libdex/DexFile.c')
| -rw-r--r-- | libdex/DexFile.c | 276 |
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) |
