1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Functions for dealing with try-catch info. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef _LIBDEX_DEXCATCH 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _LIBDEX_DEXCATCH 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "DexFile.h" 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Leb128.h" 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Catch handler entry, used while iterating over catch_handler_items. 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DexCatchHandler { 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 typeIdx; /* type index of the caught exception type */ 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address; /* handler address */ 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DexCatchHandler; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 35de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro/* Get the first handler offset for the given DexCode. 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's not 0 because the handlers list is prefixed with its size 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (in entries) as a uleb128. */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 dexGetFirstHandlerOffset(const DexCode* pCode); 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Get count of handler lists for the given DexCode. */ 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 dexGetHandlersSize(const DexCode* pCode); 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Iterator over catch handler data. This structure should be treated as 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * opaque. 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DexCatchIterator { 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* pEncodedData; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool catchesAll; 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 countRemaining; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexCatchHandler handler; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DexCatchIterator; 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Initialize a DexCatchIterator to emptiness. This mostly exists to 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * squelch innocuous warnings. */ 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDEX_INLINE void dexCatchIteratorClear(DexCatchIterator* pIterator) { 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->pEncodedData = NULL; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->catchesAll = false; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->countRemaining = 0; 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->handler.typeIdx = 0; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->handler.address = 0; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Initialize a DexCatchIterator with a direct pointer to encoded handlers. */ 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDEX_INLINE void dexCatchIteratorInitToPointer(DexCatchIterator* pIterator, 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* pEncodedData) 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s4 count = readSignedLeb128(&pEncodedData); 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count <= 0) { 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->catchesAll = true; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count = -count; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->catchesAll = false; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->pEncodedData = pEncodedData; 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->countRemaining = count; 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Initialize a DexCatchIterator to a particular handler offset. */ 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDEX_INLINE void dexCatchIteratorInit(DexCatchIterator* pIterator, 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pCode, u4 offset) 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexCatchIteratorInitToPointer(pIterator, 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexGetCatchHandlerData(pCode) + offset); 87de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro} 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Get the next item from a DexCatchIterator. Returns NULL if at end. */ 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDEX_INLINE DexCatchHandler* dexCatchIteratorNext(DexCatchIterator* pIterator) { 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pIterator->countRemaining == 0) { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (! pIterator->catchesAll) { 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->catchesAll = false; 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->handler.typeIdx = kDexNoIndex; 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 typeIdx = readUnsignedLeb128(&pIterator->pEncodedData); 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->handler.typeIdx = typeIdx; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->countRemaining--; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pIterator->handler.address = readUnsignedLeb128(&pIterator->pEncodedData); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return &pIterator->handler; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Get the handler offset just past the end of the one just iterated over. 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This ends the iteration if it wasn't already. */ 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator, 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pCode); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Helper for dexFindCatchHandler(). Do not call directly. */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries, 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Find the handler associated with a given address, if any. 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initializes the given iterator and returns true if a match is 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * found. Returns false if there is no applicable handler. */ 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDEX_INLINE bool dexFindCatchHandler(DexCatchIterator *pIterator, 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pCode, u4 address) { 122de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro u2 triesSize = pCode->triesSize; 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = -1; 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Short-circuit the overwhelmingly common cases. 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (triesSize) { 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 0: { 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 1: { 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexTry* tries = dexGetTries(pCode); 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 start = tries[0].startAddr; 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address < start) { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 end = start + tries[0].insnCount; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address >= end) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 143de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset = tries[0].handlerOff; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset = dexFindCatchHandlerOffset0(triesSize, dexGetTries(pCode), 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project address); 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (offset < 0) { 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexCatchIteratorClear(pIterator); // This squelches warnings. 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexCatchIteratorInit(pIterator, pCode, offset); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 160de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro} 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 163