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