diff options
| -rw-r--r-- | dexdump/DexDump.c | 32 | ||||
| -rw-r--r-- | libdex/Android.mk | 1 | ||||
| -rw-r--r-- | libdex/DexFile.c | 276 | ||||
| -rw-r--r-- | libdex/DexFile.h | 8 | ||||
| -rw-r--r-- | libdex/DexOptData.c | 283 | ||||
| -rw-r--r-- | libdex/DexOptData.h | 43 | ||||
| -rw-r--r-- | vm/analysis/DexPrepare.c | 50 |
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) { |
