112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden/* 212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Copyright (C) 2009 The Android Open Source Project 312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Licensed under the Apache License, Version 2.0 (the "License"); 512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * you may not use this file except in compliance with the License. 612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * You may obtain a copy of the License at 712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * http://www.apache.org/licenses/LICENSE-2.0 912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 1012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Unless required by applicable law or agreed to in writing, software 1112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * distributed under the License is distributed on an "AS IS" BASIS, 1212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * See the License for the specific language governing permissions and 1412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * limitations under the License. 1512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 1612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 1712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFaddenpackage com.android.dexdeps; 1812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 1912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFaddenimport java.io.IOException; 2012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFaddenimport java.io.RandomAccessFile; 2112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFaddenimport java.util.Arrays; 2212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 2312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden/** 2412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Data extracted from a DEX file. 2512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 2612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFaddenpublic class DexData { 2712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private RandomAccessFile mDexFile; 2812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private HeaderItem mHeaderItem; 2912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private String[] mStrings; // strings from string_data_* 3012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private TypeIdItem[] mTypeIds; 3112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private ProtoIdItem[] mProtoIds; 3212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private FieldIdItem[] mFieldIds; 3312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private MethodIdItem[] mMethodIds; 3412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private ClassDefItem[] mClassDefs; 3512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 3612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private byte tmpBuf[] = new byte[4]; 3712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden private boolean isBigEndian = false; 3812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 3912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 4012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Constructs a new DexData for this file. 4112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 4212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public DexData(RandomAccessFile raf) { 4312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mDexFile = raf; 4412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 4512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 4612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 4712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the contents of the DEX file into our data structures. 4812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 4912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * @throws IOException if we encounter a problem while reading 5012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * @throws DexDataException if the DEX contents look bad 5112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 5212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public void load() throws IOException { 5312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden parseHeaderItem(); 5412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 5512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden loadStrings(); 5612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden loadTypeIds(); 5712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden loadProtoIds(); 5812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden loadFieldIds(); 5912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden loadMethodIds(); 6012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden loadClassDefs(); 6112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 6212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden markInternalClasses(); 6312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 6412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 6512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 6612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 6712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Parses the interesting bits out of the header. 6812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 6912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void parseHeaderItem() throws IOException { 7012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem = new HeaderItem(); 7112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 7212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(0); 7312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 7412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden byte[] magic = new byte[8]; 7512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden readBytes(magic); 7612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (!Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC)) { 7712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden System.err.println("Magic number is wrong -- are you sure " + 7812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden "this is a DEX file?"); 7912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden throw new DexDataException(); 8012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 8112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 8212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* 8312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Read the endian tag, so we properly swap things as we read 8412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * them from here on. 8512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 8612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(8+4+20+4+4); 8712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.endianTag = readInt(); 8812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (mHeaderItem.endianTag == HeaderItem.ENDIAN_CONSTANT) { 8912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* do nothing */ 9012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT){ 9112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* file is big-endian (!), reverse future reads */ 9212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden isBigEndian = true; 9312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } else { 9412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden System.err.println("Endian constant has unexpected value " + 9512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden Integer.toHexString(mHeaderItem.endianTag)); 9612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden throw new DexDataException(); 9712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 9812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 9912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(8+4+20); // magic, checksum, signature 10012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.fileSize = readInt(); 10112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.headerSize = readInt(); 10212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /*mHeaderItem.endianTag =*/ readInt(); 10312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /*mHeaderItem.linkSize =*/ readInt(); 10412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /*mHeaderItem.linkOff =*/ readInt(); 10512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /*mHeaderItem.mapOff =*/ readInt(); 10612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.stringIdsSize = readInt(); 10712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.stringIdsOff = readInt(); 10812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.typeIdsSize = readInt(); 10912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.typeIdsOff = readInt(); 11012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.protoIdsSize = readInt(); 11112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.protoIdsOff = readInt(); 11212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.fieldIdsSize = readInt(); 11312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.fieldIdsOff = readInt(); 11412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.methodIdsSize = readInt(); 11512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.methodIdsOff = readInt(); 11612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.classDefsSize = readInt(); 11712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mHeaderItem.classDefsOff = readInt(); 11812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /*mHeaderItem.dataSize =*/ readInt(); 11912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /*mHeaderItem.dataOff =*/ readInt(); 12012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 12112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 12212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 12312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the string table out of the DEX. 12412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 12512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * First we read all of the string_id_items, then we read all of the 12612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * string_data_item. Doing it this way should allow us to avoid 12712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * seeking around in the file. 12812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 12912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void loadStrings() throws IOException { 13012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = mHeaderItem.stringIdsSize; 13112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int stringOffsets[] = new int[count]; 13212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 13312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("reading " + count + " strings"); 13412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 13512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(mHeaderItem.stringIdsOff); 13612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 13712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden stringOffsets[i] = readInt(); 13812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 13912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 14012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mStrings = new String[count]; 14112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 14212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(stringOffsets[0]); 14312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 14412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(stringOffsets[i]); // should be a no-op 14512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mStrings[i] = readString(); 14612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("STR: " + i + ": " + mStrings[i]); 14712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 14812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 14912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 15012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 15112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the type ID list. 15212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 15312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void loadTypeIds() throws IOException { 15412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = mHeaderItem.typeIdsSize; 15512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mTypeIds = new TypeIdItem[count]; 15612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 15712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("reading " + count + " typeIds"); 15812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(mHeaderItem.typeIdsOff); 15912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 16012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mTypeIds[i] = new TypeIdItem(); 16112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mTypeIds[i].descriptorIdx = readInt(); 16212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 16312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println(i + ": " + mTypeIds[i].descriptorIdx + 16412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // " " + mStrings[mTypeIds[i].descriptorIdx]); 16512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 16612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 16712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 16812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 16912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the proto ID list. 17012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 17112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void loadProtoIds() throws IOException { 17212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = mHeaderItem.protoIdsSize; 17312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mProtoIds = new ProtoIdItem[count]; 17412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 17512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("reading " + count + " protoIds"); 17612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(mHeaderItem.protoIdsOff); 17712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 17812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* 17912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Read the proto ID items. 18012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 18112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 18212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mProtoIds[i] = new ProtoIdItem(); 18312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mProtoIds[i].shortyIdx = readInt(); 18412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mProtoIds[i].returnTypeIdx = readInt(); 18512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mProtoIds[i].parametersOff = readInt(); 18612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 18712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println(i + ": " + mProtoIds[i].shortyIdx + 18812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // " " + mStrings[mProtoIds[i].shortyIdx]); 18912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 19012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 19112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* 19212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Go back through and read the type lists. 19312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 19412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 19512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden ProtoIdItem protoId = mProtoIds[i]; 19612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 19712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int offset = protoId.parametersOff; 19812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 19912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (offset == 0) { 20012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden protoId.types = new int[0]; 20112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden continue; 20212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } else { 20312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(offset); 20412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int size = readInt(); // #of entries in list 20512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden protoId.types = new int[size]; 20612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 20712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int j = 0; j < size; j++) { 20812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden protoId.types[j] = readShort() & 0xffff; 20912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 21012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 21112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 21212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 21312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 21412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 21512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the field ID list. 21612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 21712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void loadFieldIds() throws IOException { 21812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = mHeaderItem.fieldIdsSize; 21912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mFieldIds = new FieldIdItem[count]; 22012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 22112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("reading " + count + " fieldIds"); 22212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(mHeaderItem.fieldIdsOff); 22312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 22412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mFieldIds[i] = new FieldIdItem(); 22512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mFieldIds[i].classIdx = readShort() & 0xffff; 22612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mFieldIds[i].typeIdx = readShort() & 0xffff; 22712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mFieldIds[i].nameIdx = readInt(); 22812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 22912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println(i + ": " + mFieldIds[i].nameIdx + 23012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // " " + mStrings[mFieldIds[i].nameIdx]); 23112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 23212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 23312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 23412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 23512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the method ID list. 23612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 23712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void loadMethodIds() throws IOException { 23812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = mHeaderItem.methodIdsSize; 23912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mMethodIds = new MethodIdItem[count]; 24012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 24112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("reading " + count + " methodIds"); 24212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(mHeaderItem.methodIdsOff); 24312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 24412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mMethodIds[i] = new MethodIdItem(); 24512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mMethodIds[i].classIdx = readShort() & 0xffff; 24612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mMethodIds[i].protoIdx = readShort() & 0xffff; 24712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mMethodIds[i].nameIdx = readInt(); 24812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 24912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println(i + ": " + mMethodIds[i].nameIdx + 25012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // " " + mStrings[mMethodIds[i].nameIdx]); 25112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 25212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 25312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 25412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 25512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Loads the class defs list. 25612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 25712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void loadClassDefs() throws IOException { 25812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = mHeaderItem.classDefsSize; 25912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mClassDefs = new ClassDefItem[count]; 26012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 26112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println("reading " + count + " classDefs"); 26212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden seek(mHeaderItem.classDefsOff); 26312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < count; i++) { 26412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mClassDefs[i] = new ClassDefItem(); 26512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mClassDefs[i].classIdx = readInt(); 26612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 26712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* access_flags = */ readInt(); 26812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* superclass_idx = */ readInt(); 26912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* interfaces_off = */ readInt(); 27012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* source_file_idx = */ readInt(); 27112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* annotations_off = */ readInt(); 27212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* class_data_off = */ readInt(); 27312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* static_values_off = */ readInt(); 27412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 27512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println(i + ": " + mClassDefs[i].classIdx + " " + 27612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // mStrings[mTypeIds[mClassDefs[i].classIdx].descriptorIdx]); 27712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 27812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 27912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 28012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 28112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Sets the "internal" flag on type IDs which are defined in the 28212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * DEX file or within the VM (e.g. primitive classes and arrays). 28312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 28412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void markInternalClasses() { 28512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = mClassDefs.length -1; i >= 0; i--) { 28612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mTypeIds[mClassDefs[i].classIdx].internal = true; 28712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 28812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 28912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < mTypeIds.length; i++) { 29012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden String className = mStrings[mTypeIds[i].descriptorIdx]; 29112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 29212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (className.length() == 1) { 29312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // primitive class 29412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mTypeIds[i].internal = true; 29512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } else if (className.charAt(0) == '[') { 29612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mTypeIds[i].internal = true; 29712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 29812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 29912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden //System.out.println(i + " " + 30012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // (mTypeIds[i].internal ? "INTERNAL" : "external") + " - " + 30112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden // mStrings[mTypeIds[i].descriptorIdx]); 30212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 30312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 30412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 30512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 30612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* 30712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * ======================================================================= 30812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Queries 30912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * ======================================================================= 31012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 31112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 31212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 313753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden * Returns the class name, given an index into the type_ids table. 31412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 315753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden private String classNameFromTypeIndex(int idx) { 316753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden return mStrings[mTypeIds[idx].descriptorIdx]; 31712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 31812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 31912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 320753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden * Returns an array of method argument type strings, given an index 321753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden * into the proto_ids table. 32212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 323753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden private String[] argArrayFromProtoIndex(int idx) { 324753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden ProtoIdItem protoId = mProtoIds[idx]; 325753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden String[] result = new String[protoId.types.length]; 32612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 327753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden for (int i = 0; i < protoId.types.length; i++) { 328753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden result[i] = mStrings[mTypeIds[protoId.types[i]].descriptorIdx]; 32912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 33012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 331753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden return result; 33212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 33312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 33412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 335753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden * Returns a string representing the method's return type, given an 336753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden * index into the proto_ids table. 33712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 338753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden private String returnTypeFromProtoIndex(int idx) { 33912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden ProtoIdItem protoId = mProtoIds[idx]; 340753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden return mStrings[mTypeIds[protoId.returnTypeIdx].descriptorIdx]; 34112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 34212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 34312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 344837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * Returns an array with all of the class references that don't 345837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * correspond to classes in the DEX file. Each class reference has 346837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * a list of the referenced fields and methods associated with 347837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * that class. 34812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 349837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden public ClassRef[] getExternalReferences() { 350837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden // create a sparse array of ClassRef that parallels mTypeIds 351837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden ClassRef[] sparseRefs = new ClassRef[mTypeIds.length]; 352837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden 353837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden // create entries for all externally-referenced classes 35412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int count = 0; 355837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden for (int i = 0; i < mTypeIds.length; i++) { 356837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden if (!mTypeIds[i].internal) { 357837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden sparseRefs[i] = 358837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden new ClassRef(mStrings[mTypeIds[i].descriptorIdx]); 35912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden count++; 360837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden } 36112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 36212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 363837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden // add fields and methods to the appropriate class entry 364837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden addExternalFieldReferences(sparseRefs); 365837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden addExternalMethodReferences(sparseRefs); 36612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 367837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden // crunch out the sparseness 368837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden ClassRef[] classRefs = new ClassRef[count]; 369837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden int idx = 0; 370837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden for (int i = 0; i < mTypeIds.length; i++) { 371837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden if (sparseRefs[i] != null) 372837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden classRefs[idx++] = sparseRefs[i]; 37312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 37412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 375837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden assert idx == count; 37612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 377837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden return classRefs; 37812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 37912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 38012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 381837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * Runs through the list of field references, inserting external 382837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * references into the appropriate ClassRef. 38312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 384837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden private void addExternalFieldReferences(ClassRef[] sparseRefs) { 385837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden for (int i = 0; i < mFieldIds.length; i++) { 386837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden if (!mTypeIds[mFieldIds[i].classIdx].internal) { 387837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden FieldIdItem fieldId = mFieldIds[i]; 388837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden FieldRef newFieldRef = new FieldRef( 389837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden classNameFromTypeIndex(fieldId.classIdx), 390837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden classNameFromTypeIndex(fieldId.typeIdx), 391837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden mStrings[fieldId.nameIdx]); 392837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden sparseRefs[mFieldIds[i].classIdx].addField(newFieldRef); 393837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden } 39412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 395837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden } 39612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 397837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden /** 398837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * Runs through the list of method references, inserting external 399837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden * references into the appropriate ClassRef. 400837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden */ 401837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden private void addExternalMethodReferences(ClassRef[] sparseRefs) { 40212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (int i = 0; i < mMethodIds.length; i++) { 40312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (!mTypeIds[mMethodIds[i].classIdx].internal) { 40412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden MethodIdItem methodId = mMethodIds[i]; 405837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden MethodRef newMethodRef = new MethodRef( 406837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden classNameFromTypeIndex(methodId.classIdx), 407837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden argArrayFromProtoIndex(methodId.protoIdx), 408837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden returnTypeFromProtoIndex(methodId.protoIdx), 409837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden mStrings[methodId.nameIdx]); 410837070dd1e39c87370239643f0df2e2ab9d41fc9Andy McFadden sparseRefs[mMethodIds[i].classIdx].addMethod(newMethodRef); 41112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 41212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 41312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 41412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 415753f32ab1db6de174a1de68210f9f30a1e327612Andy McFadden 41612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* 41712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * ======================================================================= 41812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Basic I/O functions 41912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * ======================================================================= 42012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 42112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 42212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 42312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Seeks the DEX file to the specified absolute position. 42412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 42512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void seek(int position) throws IOException { 42612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mDexFile.seek(position); 42712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 42812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 42912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 43012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Fills the buffer by reading bytes from the DEX file. 43112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 43212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden void readBytes(byte[] buffer) throws IOException { 43312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mDexFile.readFully(buffer); 43412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 43512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 43612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 43712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Reads a single signed byte value. 43812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 43912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden byte readByte() throws IOException { 44012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mDexFile.readFully(tmpBuf, 0, 1); 44112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return tmpBuf[0]; 44212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 44312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 44412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 44512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Reads a signed 16-bit integer, byte-swapping if necessary. 44612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 44712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden short readShort() throws IOException { 44812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mDexFile.readFully(tmpBuf, 0, 2); 44912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (isBigEndian) { 45012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return (short) ((tmpBuf[1] & 0xff) | ((tmpBuf[0] & 0xff) << 8)); 45112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } else { 45212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return (short) ((tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8)); 45312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 45412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 45512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 45612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 45712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Reads a signed 32-bit integer, byte-swapping if necessary. 45812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 45912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int readInt() throws IOException { 46012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden mDexFile.readFully(tmpBuf, 0, 4); 46112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 46212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (isBigEndian) { 46312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return (tmpBuf[3] & 0xff) | ((tmpBuf[2] & 0xff) << 8) | 46412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden ((tmpBuf[1] & 0xff) << 16) | ((tmpBuf[0] & 0xff) << 24); 46512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } else { 46612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return (tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8) | 46712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden ((tmpBuf[2] & 0xff) << 16) | ((tmpBuf[3] & 0xff) << 24); 46812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 46912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 47012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 47112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 47212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Reads a variable-length unsigned LEB128 value. Does not attempt to 47312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * verify that the value is valid. 47412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 47512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * @throws EOFException if we run off the end of the file 47612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 47712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int readUnsignedLeb128() throws IOException { 47812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int result = 0; 47912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden byte val; 48012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 48112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden do { 48212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden val = readByte(); 48312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden result = (result << 7) | (val & 0x7f); 48412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } while (val < 0); 48512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 48612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return result; 48712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 48812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 48912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 49012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Reads a UTF-8 string. 49112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 49212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * We don't know how long the UTF-8 string is, so we have to read one 49312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * byte at a time. We could make an educated guess based on the 49412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * utf16_size and seek back if we get it wrong, but seeking backward 49512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * may cause the underlying implementation to reload I/O buffers. 49612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 49712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden String readString() throws IOException { 49812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int utf16len = readUnsignedLeb128(); 49912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden byte inBuf[] = new byte[utf16len * 3]; // worst case 50012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden int idx; 50112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 50212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden for (idx = 0; idx < inBuf.length; idx++) { 50312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden byte val = readByte(); 50412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden if (val == 0) 50512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden break; 50612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden inBuf[idx] = val; 50712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 50812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 50912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden return new String(inBuf, 0, idx, "UTF-8"); 51012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 51112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 51212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 51312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* 51412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * ======================================================================= 51512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Internal "structure" declarations 51612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * ======================================================================= 51712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 51812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 51912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 52012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Holds the contents of a header_item. 52112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 52212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden static class HeaderItem { 52312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int fileSize; 52412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int headerSize; 52512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int endianTag; 52612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int stringIdsSize, stringIdsOff; 52712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int typeIdsSize, typeIdsOff; 52812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int protoIdsSize, protoIdsOff; 52912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int fieldIdsSize, fieldIdsOff; 53012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int methodIdsSize, methodIdsOff; 53112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int classDefsSize, classDefsOff; 53212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 53312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /* expected magic values */ 53412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public static final byte[] DEX_FILE_MAGIC = { 53512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00 }; 53612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public static final int ENDIAN_CONSTANT = 0x12345678; 53712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public static final int REVERSE_ENDIAN_CONSTANT = 0x78563412; 53812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 53912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 54012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 54112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Holds the contents of a type_id_item. 54212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 54312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * This is chiefly a list of indices into the string table. We need 54412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * some additional bits of data, such as whether or not the type ID 54512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * represents a class defined in this DEX, so we use an object for 54612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * each instead of a simple integer. (Could use a parallel array, but 54712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * since this is a desktop app it's not essential.) 54812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 54912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden static class TypeIdItem { 55012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int descriptorIdx; // index into string_ids 55112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 55212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public boolean internal; // defined within this DEX file? 55312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 55412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 55512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 55612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Holds the contents of a proto_id_item. 55712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 55812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden static class ProtoIdItem { 55912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int shortyIdx; // index into string_ids 56012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int returnTypeIdx; // index into type_ids 56112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int parametersOff; // file offset to a type_list 56212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 56312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int types[]; // contents of type list 56412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 56512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 56612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 56712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Holds the contents of a field_id_item. 56812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 56912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden static class FieldIdItem { 57012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int classIdx; // index into type_ids (defining class) 57112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int typeIdx; // index into type_ids (field type) 57212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int nameIdx; // index into string_ids 57312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 57412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 57512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 57612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Holds the contents of a method_id_item. 57712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 57812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden static class MethodIdItem { 57912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int classIdx; // index into type_ids 58012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int protoIdx; // index into proto_ids 58112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int nameIdx; // index into string_ids 58212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 58312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 58412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden /** 58512d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * Holds the contents of a class_def_item. 58612d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * 58712d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * We don't really need a class for this, but there's some stuff in 58812d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden * the class_def_item that we might want later. 58912d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden */ 59012d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden static class ClassDefItem { 59112d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden public int classIdx; // index into type_ids 59212d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden } 59312d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden} 59412d6d4c0ea192b6a924df0df1e3b14ce1ed5793bAndy McFadden 595