/* * Print the stack trace of the current thread's exception, as well as * the stack traces of any chained exceptions, to the log. We extract * the stored stack trace and process it internally instead of calling * interpreted code. */ void dvmLogExceptionStackTrace(void) { Object* exception = dvmThreadSelf()->exception; Object* cause; if (exception == NULL) { LOGW("tried to log a null exception?\n"); return; } for (;;) { logStackTraceOf(exception); cause = dvmGetExceptionCause(exception); if (cause == NULL) { break; } LOGI("Caused by:\n"); exception = cause; } }
/* * Alternate version of dvmResolveClass for use with verification and * optimization. Performs access checks on every resolve, and refuses * to acknowledge the existence of classes defined in more than one DEX * file. * * Exceptions caused by failures are cleared before returning. * * On failure, returns NULL, and sets *pFailure if pFailure is not NULL. */ ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx, VerifyError* pFailure) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; /* * Check the table first. If not there, do the lookup by name. */ resClass = dvmDexGetResolvedClass(pDvmDex, classIdx); if (resClass == NULL) { const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx); if (className[0] != '\0' && className[1] == '\0') { /* primitive type */ resClass = dvmFindPrimitiveClass(className[0]); } else { resClass = dvmFindClassNoInit(className, referrer->classLoader); } if (resClass == NULL) { /* not found, exception should be raised */ ALOGV("DexOpt: class %d (%s) not found", classIdx, dexStringByTypeIdx(pDvmDex->pDexFile, classIdx)); if (pFailure != NULL) { /* dig through the wrappers to find the original failure */ Object* excep = dvmGetException(dvmThreadSelf()); while (true) { Object* cause = dvmGetExceptionCause(excep); if (cause == NULL) break; excep = cause; } if (strcmp(excep->clazz->descriptor, "Ljava/lang/IncompatibleClassChangeError;") == 0) { *pFailure = VERIFY_ERROR_CLASS_CHANGE; } else { *pFailure = VERIFY_ERROR_NO_CLASS; } } dvmClearOptException(dvmThreadSelf()); return NULL; } /* * Add it to the resolved table so we're faster on the next lookup. */ dvmDexSetResolvedClass(pDvmDex, classIdx, resClass); } /* multiple definitions? */ if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) { ALOGI("DexOpt: not resolving ambiguous class '%s'", resClass->descriptor); if (pFailure != NULL) *pFailure = VERIFY_ERROR_NO_CLASS; return NULL; } /* access allowed? */ tweakLoader(referrer, resClass); bool allowed = dvmCheckClassAccess(referrer, resClass); untweakLoader(referrer, resClass); if (!allowed) { ALOGW("DexOpt: resolve class illegal access: %s -> %s", referrer->descriptor, resClass->descriptor); if (pFailure != NULL) *pFailure = VERIFY_ERROR_ACCESS_CLASS; return NULL; } return resClass; }