X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=vm%2Fanalysis%2FDexPrepare.c;h=d361290c9a87dfd6a86d8ada96a64569790a8007;hb=3f4b63f47f50f200538e83fa3fac06947afa08b4;hp=d9871c99b890a4208f2671cf16abd5688fbd8ec6;hpb=1425417379d8b7942b957245929240f0838fa538;p=android-x86%2Fdalvik.git diff --git a/vm/analysis/DexPrepare.c b/vm/analysis/DexPrepare.c index d9871c99b..d361290c9 100644 --- a/vm/analysis/DexPrepare.c +++ b/vm/analysis/DexPrepare.c @@ -51,8 +51,8 @@ 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,\ - const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder); +static bool writeOptData(int fd, const DexClassLookup* pClassLookup,\ + const RegisterMapBuilder* pRegMapBuilder); static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum); @@ -228,7 +228,8 @@ retry: * changes doing anything" purposes its best if we just make * everything crash when a DEX they're using gets updated. */ - LOGD("Stale deps in cache file; removing and retrying\n"); + LOGD("ODEX file is stale or bad; removing and retrying (%s)\n", + cacheFileName); if (ftruncate(fd, 0) != 0) { LOGW("Warning: unable to truncate cache file '%s': %s\n", cacheFileName, strerror(errno)); @@ -474,7 +475,6 @@ bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) { DexClassLookup* pClassLookup = NULL; - IndexMapSet* pIndexMapSet = NULL; RegisterMapBuilder* pRegMapBuilder = NULL; u4 headerFlags = 0; @@ -543,15 +543,6 @@ bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, success = false; } else { /* - * If configured to do so, scan the instructions, looking - * for ways to reduce the size of the resolved-constant table. - * This is done post-optimization, across the instructions - * in all methods in all classes (even the ones that failed - * to load). - */ - pIndexMapSet = dvmRewriteConstants(pDvmDex); - - /* * If configured to do so, generate register map output * for all verified classes. The register maps were * generated during verification, and will now be serialized. @@ -594,8 +585,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); @@ -619,32 +610,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, 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; } @@ -661,12 +652,14 @@ 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; + fsync(fd); /* ensure previous writes go before header is written */ + lseek(fd, 0, SEEK_SET); if (sysWriteFully(fd, &optHdr, sizeof(optHdr), "DexOpt opt header") != 0) goto bail; @@ -677,7 +670,6 @@ bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, //dvmRegisterMapDumpStats(); bail: - dvmFreeIndexMapSet(pIndexMapSet); dvmFreeRegisterMapBuilder(pRegMapBuilder); free(pClassLookup); return result; @@ -933,30 +925,38 @@ static void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, const char* classDescriptor; bool verified = false; + if (clazz->pDvmDex->pDexFile != pDexFile) { + /* + * The current DEX file defined a class that is also present in the + * bootstrap class path. The class loader favored the bootstrap + * version, which means that we have a pointer to a class that is + * (a) not the one we want to examine, and (b) mapped read-only, + * so we will seg fault if we try to rewrite instructions inside it. + */ + LOGD("DexOpt: not verifying/optimizing '%s': multiple definitions\n", + clazz->descriptor); + return; + } + classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); /* * First, try to verify it. */ if (doVerify) { - if (clazz->pDvmDex->pDexFile != pDexFile) { - LOGD("DexOpt: not verifying '%s': multiple definitions\n", - classDescriptor); + if (dvmVerifyClass(clazz)) { + /* + * Set the "is preverified" flag in the DexClassDef. We + * do it here, rather than in the ClassObject structure, + * because the DexClassDef is part of the odex file. + */ + assert((clazz->accessFlags & JAVA_FLAGS_MASK) == + pClassDef->accessFlags); + ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISPREVERIFIED; + verified = true; } else { - if (dvmVerifyClass(clazz)) { - /* - * Set the "is preverified" flag in the DexClassDef. We - * do it here, rather than in the ClassObject structure, - * because the DexClassDef is part of the odex file. - */ - assert((clazz->accessFlags & JAVA_FLAGS_MASK) == - pClassDef->accessFlags); - ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISPREVERIFIED; - verified = true; - } else { - // TODO: log when in verbose mode - LOGV("DexOpt: '%s' failed verification\n", classDescriptor); - } + // TODO: log when in verbose mode + LOGV("DexOpt: '%s' failed verification\n", classDescriptor); } } @@ -1067,13 +1067,22 @@ bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen, * Read and do trivial verification on the opt header. The header is * always in host byte order. */ - if (read(fd, &optHdr, sizeof(optHdr)) != sizeof(optHdr)) { + actual = read(fd, &optHdr, sizeof(optHdr)); + if (actual < 0) { LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno)); goto bail; + } else if (actual != sizeof(optHdr)) { + LOGE("DexOpt: failed reading opt header (got %d of %zd)\n", + (int) actual, sizeof(optHdr)); + goto bail; } magic = optHdr.magic; - if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) { + if (memcmp(magic, DEX_MAGIC, 4) == 0) { + /* somebody probably pointed us at the wrong file */ + LOGD("DexOpt: expected optimized DEX, found unoptimized\n"); + goto bail; + } else if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) { /* not a DEX file, or previous attempt was interrupted */ LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n", magic[0], magic[1], magic[2], magic[3]); @@ -1137,9 +1146,12 @@ bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen, goto bail; } actual = read(fd, depData, optHdr.depsLength); - if (actual != (ssize_t) optHdr.depsLength) { - LOGW("DexOpt: failed reading deps: %d of %d (err=%s)\n", - (int) actual, optHdr.depsLength, strerror(errno)); + if (actual < 0) { + LOGW("DexOpt: failed reading deps: %s\n", strerror(errno)); + goto bail; + } else if (actual != (ssize_t) optHdr.depsLength) { + LOGW("DexOpt: failed reading deps: got %d of %d\n", + (int) actual, optHdr.depsLength); goto bail; } @@ -1319,13 +1331,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; } @@ -1342,15 +1354,15 @@ 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, - const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder) +static bool writeOptData(int fd, const DexClassLookup* pClassLookup, + const RegisterMapBuilder* pRegMapBuilder) { /* pre-computed class lookup hash table */ if (!writeChunk(fd, (u4) kDexChunkClassLookup, @@ -1359,15 +1371,6 @@ static bool writeAuxData(int fd, const DexClassLookup* pClassLookup, return false; } - /* remapped constants (optional) */ - if (pIndexMapSet != NULL) { - if (!writeChunk(fd, pIndexMapSet->chunkType, - pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen)) - { - return false; - } - } - /* register maps (optional) */ if (pRegMapBuilder != NULL) { if (!writeChunk(fd, (u4) kDexChunkRegisterMaps, @@ -1427,7 +1430,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) {