| /* |
| * Copyright (C) 2008 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 for dealing with try-catch info. |
| */ |
| |
| #include "DexCatch.h" |
| |
| /* Get the first handler offset for the given DexCode. |
| * It's not 0 because the handlers list is prefixed with its size |
| * (in entries) as a uleb128. */ |
| u4 dexGetFirstHandlerOffset(const DexCode* pCode) { |
| if (pCode->triesSize == 0) { |
| return 0; |
| } |
| |
| const u1* baseData = dexGetCatchHandlerData(pCode); |
| const u1* data = baseData; |
| |
| readUnsignedLeb128(&data); |
| |
| return data - baseData; |
| } |
| |
| /* Get count of handler lists for the given DexCode. */ |
| u4 dexGetHandlersSize(const DexCode* pCode) { |
| if (pCode->triesSize == 0) { |
| return 0; |
| } |
| |
| const u1* data = dexGetCatchHandlerData(pCode); |
| |
| return readUnsignedLeb128(&data); |
| } |
| |
| /* Helper for dexFindCatchHandlerOffset(), which does an actual search |
| * in the tries table. Returns -1 if there is no applicable handler. */ |
| int dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries, |
| u4 address) { |
| // Note: Signed type is important for max and min. |
| int min = 0; |
| int max = triesSize - 1; |
| |
| while (max >= min) { |
| int guess = (min + max) >> 1; |
| const DexTry* pTry = &pTries[guess]; |
| u4 start = pTry->startAddr; |
| |
| if (address < start) { |
| max = guess - 1; |
| continue; |
| } |
| |
| u4 end = start + pTry->insnCount; |
| |
| if (address >= end) { |
| min = guess + 1; |
| continue; |
| } |
| |
| // We have a winner! |
| return (int) pTry->handlerOff; |
| } |
| |
| // No match. |
| return -1; |
| } |
| |
| /* Get the handler offset just past the end of the one just iterated over. |
| * This ends the iteration if it wasn't already. */ |
| u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator, |
| const DexCode* pCode) { |
| while (dexCatchIteratorNext(pIterator) != NULL) /* empty */ ; |
| |
| return (u4) (pIterator->pEncodedData - dexGetCatchHandlerData(pCode)); |
| } |