/* Find the handler associated with a given address, if any. * Initializes the given iterator and returns true if a match is * found. Returns false if there is no applicable handler. */ DEX_INLINE bool dexFindCatchHandler(DexCatchIterator *pIterator, const DexCode* pCode, u4 address) { u2 triesSize = pCode->triesSize; int offset = -1; // Short-circuit the overwhelmingly common cases. switch (triesSize) { case 0: { break; } case 1: { const DexTry* tries = dexGetTries(pCode); u4 start = tries[0].startAddr; if (address < start) { break; } u4 end = start + tries[0].insnCount; if (address >= end) { break; } offset = tries[0].handlerOff; break; } default: { offset = dexFindCatchHandlerOffset0(triesSize, dexGetTries(pCode), address); } } if (offset < 0) { dexCatchIteratorClear(pIterator); // This squelches warnings. return false; } else { dexCatchIteratorInit(pIterator, pCode, offset); return true; } }
/* * Dump the catches table associated with the code. */ void dumpCatches(DexFile* pDexFile, const DexCode* pCode) { u4 triesSize = pCode->triesSize; if (triesSize == 0) { printf(" catches : (none)\n"); return; } printf(" catches : %d\n", triesSize); const DexTry* pTries = dexGetTries(pCode); u4 i; for (i = 0; i < triesSize; i++) { const DexTry* pTry = &pTries[i]; u4 start = pTry->startAddr; u4 end = start + pTry->insnCount; DexCatchIterator iterator; printf(" 0x%04x - 0x%04x\n", start, end); dexCatchIteratorInit(&iterator, pCode, pTry->handlerOff); for (;;) { DexCatchHandler* handler = dexCatchIteratorNext(&iterator); const char* descriptor; if (handler == NULL) { break; } descriptor = (handler->typeIdx == kDexNoIndex) ? "<any>" : dexStringByTypeIdx(pDexFile, handler->typeIdx); printf(" %s -> 0x%04x\n", descriptor, handler->address); } } }
/* Set the "in try" flags for all instructions protected by "try" statements. Also sets the "branch target" flags for exception handlers. Call this after widths have been set in "insnFlags". Returns "false" if something in the exception table looks fishy, but we're expecting the exception table to be somewhat sane. 对被“try”声明保护的所有指令的设置"in try"标识。同时为异常句柄设置“branch target(分支目标)” 标识。 在宽度被设置“inFlags”后调用。 返回“false”,如果异常表中出现可疑的东西,我们期望它能有点理智。 */ static bool scanTryCatchBlocks(const Method* meth, InsnFlags* insnFlags) { u4 insnsSize = dvmGetMethodInsnsSize(meth); const DexCode* pCode = dvmGetMethodCode(meth); u4 triesSize = pCode->triesSize; const DexTry* pTries; u4 idx; if (triesSize == 0) { return true; } pTries = dexGetTries(pCode); for (idx = 0; idx < triesSize; idx++) { const DexTry* pTry = &pTries[idx]; u4 start = pTry->startAddr; u4 end = start + pTry->insnCount; u4 addr; if ((start >= end) || (start >= insnsSize) || (end > insnsSize)) { LOG_VFY_METH(meth, "VFY: bad exception entry: startAddr=%d endAddr=%d (size=%d)", start, end, insnsSize); return false; } if (dvmInsnGetWidth(insnFlags, start) == 0) { LOG_VFY_METH(meth, "VFY: 'try' block starts inside an instruction (%d)", start); return false; } for (addr = start; addr < end; addr += dvmInsnGetWidth(insnFlags, addr)) { assert(dvmInsnGetWidth(insnFlags, addr) != 0); dvmInsnSetInTry(insnFlags, addr, true); } } /* Iterate over each of the handlers to verify target addresses. */ u4 handlersSize = dexGetHandlersSize(pCode); u4 offset = dexGetFirstHandlerOffset(pCode); for (idx = 0; idx < handlersSize; idx++) { DexCatchIterator iterator; dexCatchIteratorInit(&iterator, pCode, offset); for (;;) { DexCatchHandler* handler = dexCatchIteratorNext(&iterator); u4 addr; if (handler == NULL) { break; } addr = handler->address; if (dvmInsnGetWidth(insnFlags, addr) == 0) { LOG_VFY_METH(meth, "VFY: exception handler starts at bad address (%d)", addr); return false; } dvmInsnSetBranchTarget(insnFlags, addr, true); } offset = dexCatchIteratorGetEndOffset(&iterator, pCode); } return true; }
/* Get the base of the encoded data for the given DexCode. */ DEX_INLINE const u1* dexGetCatchHandlerData(const DexCode* pCode) { const DexTry* pTries = dexGetTries(pCode); return (const u1*) &pTries[pCode->triesSize]; }