11a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 21a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Copyright (C) 2008 The Android Open Source Project 31a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 41a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Licensed under the Apache License, Version 2.0 (the "License"); 51a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * you may not use this file except in compliance with the License. 61a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * You may obtain a copy of the License at 71a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 81a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * http://www.apache.org/licenses/LICENSE-2.0 91a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Unless required by applicable law or agreed to in writing, software 111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * distributed under the License is distributed on an "AS IS" BASIS, 121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * See the License for the specific language governing permissions and 141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * limitations under the License. 151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Access the contents of a .dex file. 191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "DexFile.h" 221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "DexOptData.h" 231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "DexProto.h" 241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "DexCatch.h" 251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "Leb128.h" 261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "sha1.h" 271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "ZipArchive.h" 281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <zlib.h> 301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <stdlib.h> 321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <stddef.h> 331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <string.h> 341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <fcntl.h> 351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <errno.h> 361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Verifying checksums is good, but it slows things down and causes us to 401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * touch every page. In the "optimized" world, it doesn't work at all, 411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * because we rewrite the contents. 421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const bool kVerifyChecksum = false; 441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const bool kVerifySignature = false; 451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* (documented in header) */ 471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikchar dexGetPrimitiveTypeDescriptorChar(PrimitiveType type) { 481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* string = dexGetPrimitiveTypeDescriptor(type); 491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return (string == NULL) ? '\0' : string[0]; 511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* (documented in header) */ 541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikconst char* dexGetPrimitiveTypeDescriptor(PrimitiveType type) { 551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (type) { 561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_VOID: return "V"; 571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_BOOLEAN: return "Z"; 581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_BYTE: return "B"; 591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_SHORT: return "S"; 601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_CHAR: return "C"; 611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_INT: return "I"; 621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_LONG: return "J"; 631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_FLOAT: return "F"; 641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_DOUBLE: return "D"; 651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: return NULL; 661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* (documented in header) */ 721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikconst char* dexGetBoxedTypeDescriptor(PrimitiveType type) { 731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (type) { 741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_VOID: return NULL; 751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_BOOLEAN: return "Ljava/lang/Boolean;"; 761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_BYTE: return "Ljava/lang/Byte;"; 771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_SHORT: return "Ljava/lang/Short;"; 781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_CHAR: return "Ljava/lang/Character;"; 791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_INT: return "Ljava/lang/Integer;"; 801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_LONG: return "Ljava/lang/Long;"; 811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_FLOAT: return "Ljava/lang/Float;"; 821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case PRIM_DOUBLE: return "Ljava/lang/Double;"; 831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: return NULL; 841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* (documented in header) */ 881a65052468068a4e9a859d185860510aa1d8cfd4Aart BikPrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar) { 891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (descriptorChar) { 901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'V': return PRIM_VOID; 911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'Z': return PRIM_BOOLEAN; 921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'B': return PRIM_BYTE; 931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'S': return PRIM_SHORT; 941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'C': return PRIM_CHAR; 951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'I': return PRIM_INT; 961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'J': return PRIM_LONG; 971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'F': return PRIM_FLOAT; 981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'D': return PRIM_DOUBLE; 991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: return PRIM_NOT; 1001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* Return the UTF-8 encoded string with the specified string_id index, 1041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * also filling in the UTF-16 size (number of 16-bit code points).*/ 1051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikconst char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx, 1061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4* utf16Size) { 1071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexStringId* pStringId = dexGetStringId(pDexFile, idx); 1081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff; 1091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *utf16Size = readUnsignedLeb128(&ptr); 1111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return (const char*) ptr; 1121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 1151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Format an SHA-1 digest for printing. tmpBuf must be able to hold at 1161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * least kSHA1DigestOutputLen bytes. 1171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikconst char* dvmSHA1DigestToStr(const unsigned char digest[], char* tmpBuf); 1191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 1211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Compute a SHA-1 digest on a range of bytes. 1221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void dexComputeSHA1Digest(const unsigned char* data, size_t length, 1241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik unsigned char digest[]) 1251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik SHA1_CTX context; 1271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik SHA1Init(&context); 1281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik SHA1Update(&context, data, length); 1291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik SHA1Final(digest, &context); 1301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 1331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Format the SHA-1 digest into the buffer, which must be able to hold at 1341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * least kSHA1DigestOutputLen bytes. Returns a pointer to the buffer, 1351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const char* dexSHA1DigestToStr(const unsigned char digest[],char* tmpBuf) 1371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik static const char hexDigit[] = "0123456789abcdef"; 1391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik char* cp; 1401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int i; 1411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik cp = tmpBuf; 1431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (i = 0; i < kSHA1DigestLen; i++) { 1441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *cp++ = hexDigit[digest[i] >> 4]; 1451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *cp++ = hexDigit[digest[i] & 0x0f]; 1461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *cp++ = '\0'; 1481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik assert(cp == tmpBuf + kSHA1DigestOutputLen); 1501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return tmpBuf; 1521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 1551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Compute a hash code on a UTF-8 string, for use with internal hash tables. 1561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 1571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * This may or may not be compatible with UTF-8 hash functions used inside 1581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * the Dalvik VM. 1591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 1601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * The basic "multiply by 31 and add" approach does better on class names 1611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * than most other things tried (e.g. adler32). 1621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic u4 classDescriptorHash(const char* str) 1641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 hash = 1; 1661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (*str != '\0') 1681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik hash = hash * 31 + *str++; 1691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return hash; 1711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 1741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Add an entry to the class lookup table. We hash the string and probe 1751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * until we find an open slot. 1761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void classLookupAdd(DexFile* pDexFile, DexClassLookup* pLookup, 1781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int stringOff, int classDefOff, int* pNumProbes) 1791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* classDescriptor = 1811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (const char*) (pDexFile->baseAddr + stringOff); 1821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexClassDef* pClassDef = 1831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (const DexClassDef*) (pDexFile->baseAddr + classDefOff); 1841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 hash = classDescriptorHash(classDescriptor); 1851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int mask = pLookup->numEntries-1; 1861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int idx = hash & mask; 1871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 1891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Find the first empty slot. We oversized the table, so this is 1901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * guaranteed to finish. 1911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int probes = 0; 1931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (pLookup->table[idx].classDescriptorOffset != 0) { 1941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik idx = (idx + 1) & mask; 1951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik probes++; 1961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik //if (probes > 1) 1981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // ALOGW("classLookupAdd: probes=%d", probes); 1991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pLookup->table[idx].classDescriptorHash = hash; 2011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pLookup->table[idx].classDescriptorOffset = stringOff; 2021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pLookup->table[idx].classDefOffset = classDefOff; 2031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *pNumProbes = probes; 2041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 2051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 2071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Create the class lookup hash table. 2081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 2091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Returns newly-allocated storage. 2101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 2111a65052468068a4e9a859d185860510aa1d8cfd4Aart BikDexClassLookup* dexCreateClassLookup(DexFile* pDexFile) 2121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 2131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexClassLookup* pLookup; 2141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int allocSize; 2151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int i, numEntries; 2161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int numProbes, totalProbes, maxProbes; 2171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik numProbes = totalProbes = maxProbes = 0; 2191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik assert(pDexFile != NULL); 2211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 2231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Using a factor of 3 results in far less probing than a factor of 2, 2241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * but almost doubles the flash storage requirements for the bootstrap 2251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * DEX files. The overall impact on class loading performance seems 2261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * to be minor. We could probably get some performance improvement by 2271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * using a secondary hash. 2281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 2291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik numEntries = dexRoundUpPower2(pDexFile->pHeader->classDefsSize * 2); 2301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik allocSize = offsetof(DexClassLookup, table) 2311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik + numEntries * sizeof(pLookup->table[0]); 2321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pLookup = (DexClassLookup*) calloc(1, allocSize); 2341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pLookup == NULL) 2351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 2361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pLookup->size = allocSize; 2371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pLookup->numEntries = numEntries; 2381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (i = 0; i < (int)pDexFile->pHeader->classDefsSize; i++) { 2401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexClassDef* pClassDef; 2411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* pString; 2421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pClassDef = dexGetClassDef(pDexFile, i); 2441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pString = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 2451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik classLookupAdd(pDexFile, pLookup, 2471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (u1*)pString - pDexFile->baseAddr, 2481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (u1*)pClassDef - pDexFile->baseAddr, &numProbes); 2491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (numProbes > maxProbes) 2511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik maxProbes = numProbes; 2521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik totalProbes += numProbes; 2531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGV("Class lookup: classes=%d slots=%d (%d%% occ) alloc=%d" 2561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik " total=%d max=%d", 2571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pHeader->classDefsSize, numEntries, 2581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (100 * pDexFile->pHeader->classDefsSize) / numEntries, 2591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik allocSize, totalProbes, maxProbes); 2601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return pLookup; 2621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 2631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 2661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Set up the basic raw data pointers of a DexFile. This function isn't 2671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * meant for general use. 2681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 2691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikvoid dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data) { 2701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexHeader *pHeader = (DexHeader*) data; 2711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->baseAddr = data; 2731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pHeader = pHeader; 2741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pStringIds = (const DexStringId*) (data + pHeader->stringIdsOff); 2751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pTypeIds = (const DexTypeId*) (data + pHeader->typeIdsOff); 2761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pFieldIds = (const DexFieldId*) (data + pHeader->fieldIdsOff); 2771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pMethodIds = (const DexMethodId*) (data + pHeader->methodIdsOff); 2781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pProtoIds = (const DexProtoId*) (data + pHeader->protoIdsOff); 2791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pClassDefs = (const DexClassDef*) (data + pHeader->classDefsOff); 2801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pLinkData = (const DexLink*) (data + pHeader->linkOff); 2811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 2821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 2841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Parse an optimized or unoptimized .dex file sitting in memory. This is 2851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * called after the byte-ordering and structure alignment has been fixed up. 2861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 2871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * On success, return a newly-allocated DexFile. 2881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 2891a65052468068a4e9a859d185860510aa1d8cfd4Aart BikDexFile* dexFileParse(const u1* data, size_t length, int flags) 2901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 2911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexFile* pDexFile = NULL; 2921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexHeader* pHeader; 2931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* magic; 2941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int result = -1; 2951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (length < sizeof(DexHeader)) { 2971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("too short to be a valid .dex"); 2981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; /* bad file format */ 2991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile = (DexFile*) malloc(sizeof(DexFile)); 3021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pDexFile == NULL) 3031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; /* alloc failure */ 3041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik memset(pDexFile, 0, sizeof(DexFile)); 3051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 3071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Peel off the optimized header. 3081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 3091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) { 3101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik magic = data; 3111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) { 3121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("bad opt version (0x%02x %02x %02x %02x)", 3131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik magic[4], magic[5], magic[6], magic[7]); 3141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pOptHeader = (const DexOptHeader*) data; 3181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGV("Good opt header, DEX offset is %d, flags=0x%02x", 3191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags); 3201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* parse the optimized dex file tables */ 3221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!dexParseOptData(data, length, pDexFile)) 3231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* ignore the opt header and appended data from here on out */ 3261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik data += pDexFile->pOptHeader->dexOffset; 3271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik length -= pDexFile->pOptHeader->dexOffset; 3281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pDexFile->pOptHeader->dexLength > length) { 3291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("File truncated? stored len=%d, rem len=%d", 3301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile->pOptHeader->dexLength, (int) length); 3311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik length = pDexFile->pOptHeader->dexLength; 3341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexFileSetupBasicPointers(pDexFile, data); 3371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pHeader = pDexFile->pHeader; 3381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!dexHasValidMagic(pHeader)) { 3401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 3441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Verify the checksum(s). This is reasonably quick, but does require 3451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * touching every byte in the DEX file. The base checksum changes after 3461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * byte-swapping and DEX optimization. 3471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 3481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (flags & kDexParseVerifyChecksum) { 3491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 adler = dexComputeChecksum(pHeader); 3501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (adler != pHeader->checksum) { 3511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("ERROR: bad checksum (%08x vs %08x)", 3521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik adler, pHeader->checksum); 3531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!(flags & kDexParseContinueOnError)) 3541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 3561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGV("+++ adler32 checksum (%08x) verified", adler); 3571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexOptHeader* pOptHeader = pDexFile->pOptHeader; 3601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pOptHeader != NULL) { 3611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik adler = dexComputeOptChecksum(pOptHeader); 3621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (adler != pOptHeader->checksum) { 3631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("ERROR: bad opt checksum (%08x vs %08x)", 3641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik adler, pOptHeader->checksum); 3651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!(flags & kDexParseContinueOnError)) 3661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 3681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGV("+++ adler32 opt checksum (%08x) verified", adler); 3691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 3741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Verify the SHA-1 digest. (Normally we don't want to do this -- 3751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * the digest is used to uniquely identify the original DEX file, and 3761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * can't be computed for verification after the DEX is byte-swapped 3771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * and optimized.) 3781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 3791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (kVerifySignature) { 3801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik unsigned char sha1Digest[kSHA1DigestLen]; 3811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) + 3821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik kSHA1DigestLen; 3831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest); 3851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) { 3861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik char tmpBuf1[kSHA1DigestOutputLen]; 3871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik char tmpBuf2[kSHA1DigestOutputLen]; 3881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("ERROR: bad SHA1 digest (%s vs %s)", 3891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexSHA1DigestToStr(sha1Digest, tmpBuf1), 3901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexSHA1DigestToStr(pHeader->signature, tmpBuf2)); 3911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!(flags & kDexParseContinueOnError)) 3921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 3931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 3941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGV("+++ sha1 digest verified"); 3951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pHeader->fileSize != length) { 3991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("ERROR: stored file size (%d) != expected (%d)", 4001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (int) pHeader->fileSize, (int) length); 4011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!(flags & kDexParseContinueOnError)) 4021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 4031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 4041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pHeader->classDefsSize == 0) { 4061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("ERROR: DEX file has no classes in it, failing"); 4071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik goto bail; 4081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 4091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 4111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Success! 4121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik result = 0; 4141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikbail: 4161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (result != 0 && pDexFile != NULL) { 4171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexFileFree(pDexFile); 4181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik pDexFile = NULL; 4191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 4201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return pDexFile; 4211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 4221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 4241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Free up the DexFile and any associated data structures. 4251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 4261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Note we may be called with a partially-initialized DexFile. 4271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikvoid dexFileFree(DexFile* pDexFile) 4291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 4301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pDexFile == NULL) 4311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 4321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik free(pDexFile); 4341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 4351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 4371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Look up a class definition entry by descriptor. 4381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 4391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * "descriptor" should look like "Landroid/debug/Stuff;". 4401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikconst DexClassDef* dexFindClass(const DexFile* pDexFile, 4421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* descriptor) 4431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 4441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexClassLookup* pLookup = pDexFile->pClassLookup; 4451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 hash; 4461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int idx, mask; 4471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik hash = classDescriptorHash(descriptor); 4491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik mask = pLookup->numEntries - 1; 4501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik idx = hash & mask; 4511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 4531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Search until we find a matching entry or an empty slot. 4541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (true) { 4561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int offset; 4571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik offset = pLookup->table[idx].classDescriptorOffset; 4591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (offset == 0) 4601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 4611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pLookup->table[idx].classDescriptorHash == hash) { 4631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* str; 4641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik str = (const char*) (pDexFile->baseAddr + offset); 4661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (strcmp(str, descriptor) == 0) { 4671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return (const DexClassDef*) 4681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik (pDexFile->baseAddr + pLookup->table[idx].classDefOffset); 4691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 4701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 4711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik idx = (idx + 1) & mask; 4731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 4741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 4751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 4781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Compute the DEX file checksum for a memory-mapped DEX file. 4791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4801a65052468068a4e9a859d185860510aa1d8cfd4Aart Biku4 dexComputeChecksum(const DexHeader* pHeader) 4811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 4821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* start = (const u1*) pHeader; 4831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik uLong adler = adler32(0L, Z_NULL, 0); 4851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 4861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return (u4) adler32(adler, start + nonSum, pHeader->fileSize - nonSum); 4881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 4891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 4901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 4911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Compute the size, in bytes, of a DexCode. 4921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4931a65052468068a4e9a859d185860510aa1d8cfd4Aart Biksize_t dexGetDexCodeSize(const DexCode* pCode) 4941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 4951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 4961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * The catch handler data is the last entry. It has a variable number 4971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * of variable-size pieces, so we need to create an iterator. 4981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 4991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 handlersSize; 5001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 offset; 5011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 ui; 5021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (pCode->triesSize != 0) { 5041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik handlersSize = dexGetHandlersSize(pCode); 5051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik offset = dexGetFirstHandlerOffset(pCode); 5061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 5071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik handlersSize = 0; 5081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik offset = 0; 5091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 5101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (ui = 0; ui < handlersSize; ui++) { 5121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexCatchIterator iterator; 5131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexCatchIteratorInit(&iterator, pCode, offset); 5141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik offset = dexCatchIteratorGetEndOffset(&iterator, pCode); 5151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 5161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* handlerData = dexGetCatchHandlerData(pCode); 5181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik //ALOGD("+++ pCode=%p handlerData=%p last offset=%d", 5201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // pCode, handlerData, offset); 5211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* return the size of the catch handler + everything before it */ 5231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return (handlerData - (u1*) pCode) + offset; 5241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 5251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 5271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Round up to the next highest power of 2. 5281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 5291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Found on http://graphics.stanford.edu/~seander/bithacks.html. 5301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 5311a65052468068a4e9a859d185860510aa1d8cfd4Aart Biku4 dexRoundUpPower2(u4 val) 5321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 5331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val--; 5341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val |= val >> 1; 5351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val |= val >> 2; 5361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val |= val >> 4; 5371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val |= val >> 8; 5381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val |= val >> 16; 5391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik val++; 5401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 5411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return val; 5421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 543