1418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// for details. All rights reserved. Use of this source code is governed by a 3418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// BSD-style license that can be found in the LICENSE file. 4418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpackage com.android.tools.r8.dex; 5418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 6418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport static com.android.tools.r8.utils.EncodedValueUtils.parseDouble; 7418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport static com.android.tools.r8.utils.EncodedValueUtils.parseFloat; 8418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport static com.android.tools.r8.utils.EncodedValueUtils.parseSigned; 9418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport static com.android.tools.r8.utils.EncodedValueUtils.parseUnsigned; 10418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 11f4a7dd77cef798fd0c3ef6d787f81f51297bd9a3Mads Agerimport com.android.tools.r8.Resource; 12418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.code.Instruction; 13418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.code.InstructionFactory; 14a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukovimport com.android.tools.r8.graph.ClassKind; 15418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.Descriptor; 16418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexAccessFlags; 17418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexAnnotation; 18418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexAnnotationElement; 19418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexAnnotationSet; 20418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexAnnotationSetRefList; 21418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexCallSite; 22418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexClass; 23418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexCode; 24418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexCode.Try; 25418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexCode.TryHandler; 26418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair; 27418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexDebugEvent; 28418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexDebugInfo; 29418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedAnnotation; 30418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedArray; 31418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedField; 32418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedMethod; 33418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexField; 34418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexItem; 35418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexItemFactory; 36418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMemberAnnotation; 37418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMemberAnnotation.DexFieldAnnotation; 38418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMemberAnnotation.DexMethodAnnotation; 39418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMemberAnnotation.DexParameterAnnotation; 40418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMethod; 41418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMethodHandle; 42418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMethodHandle.MethodHandleType; 43418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexProto; 44418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexString; 45418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexType; 46418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexTypeList; 47418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexValue; 48418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexValue.DexValueMethodHandle; 49418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexValue.DexValueMethodType; 50127cf8f5c1c98d408526ee6895fc3911689c9ad2Mads Agerimport com.android.tools.r8.graph.DexValue.DexValueNull; 51418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexValue.DexValueString; 52418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.OffsetToObjectMapping; 53418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.logging.Log; 54b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhutimport it.unimi.dsi.fastutil.ints.Int2ObjectMap; 55b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhutimport it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 56418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.io.ByteArrayOutputStream; 57418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.io.IOException; 5890c1804c404872c83fdb5b53a6d45406321cff5fLars Bakimport java.io.InputStream; 59418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.nio.ShortBuffer; 60418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.nio.file.Path; 61418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.ArrayList; 62418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.Arrays; 63418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.Hashtable; 64418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.List; 65418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.function.Consumer; 66418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.function.Supplier; 67418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 68418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpublic class DexFileReader { 69418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 70418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final int NO_INDEX = -1; 71418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexFile file; 72418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private final Segment[] segments; 73418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private int[] stringIDs; 74a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov private final ClassKind classKind; 75418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 76418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public static Segment[] parseMapFrom(Path file) throws IOException { 7790c1804c404872c83fdb5b53a6d45406321cff5fLars Bak return parseMapFrom(new DexFile(file.toString())); 7890c1804c404872c83fdb5b53a6d45406321cff5fLars Bak } 7990c1804c404872c83fdb5b53a6d45406321cff5fLars Bak 8090c1804c404872c83fdb5b53a6d45406321cff5fLars Bak public static Segment[] parseMapFrom(InputStream stream) throws IOException { 8190c1804c404872c83fdb5b53a6d45406321cff5fLars Bak return parseMapFrom(new DexFile(stream)); 8290c1804c404872c83fdb5b53a6d45406321cff5fLars Bak } 8390c1804c404872c83fdb5b53a6d45406321cff5fLars Bak 8490c1804c404872c83fdb5b53a6d45406321cff5fLars Bak private static Segment[] parseMapFrom(DexFile dex) throws IOException { 8590c1804c404872c83fdb5b53a6d45406321cff5fLars Bak DexFileReader reader = new DexFileReader(dex, ClassKind.PROGRAM, new DexItemFactory()); 8690c1804c404872c83fdb5b53a6d45406321cff5fLars Bak return reader.segments; 87418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 88418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 89418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public void close() { 90418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // This close behavior is needed to reduce peak memory usage of D8/R8. 91418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager indexedItems = null; 92418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager codes = null; 93418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager offsetMap = null; 94418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file = null; 95418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager stringIDs = null; 96418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 97418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 98418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Mapping from indexes to indexable dex items. 99418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private OffsetToObjectMapping indexedItems = new OffsetToObjectMapping(); 100418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 101418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Mapping from offset to code item; 102b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut private Int2ObjectMap<DexCode> codes = new Int2ObjectOpenHashMap<>(); 103418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 104418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Mapping from offset to dex item; 105b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut private Int2ObjectMap<Object> offsetMap = new Int2ObjectOpenHashMap<>(); 106418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 107418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Factory to canonicalize certain dexitems. 108418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private final DexItemFactory dexItemFactory; 109418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 110a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov public DexFileReader(DexFile file, ClassKind classKind, DexItemFactory dexItemFactory) { 111418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.file = file; 112418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.dexItemFactory = dexItemFactory; 113418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.setByteOrder(); 114418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager segments = parseMap(); 115418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager parseStringIDs(); 116a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov this.classKind = classKind; 117418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 118418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 119418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public OffsetToObjectMapping getIndexedItemsMap() { 120418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return indexedItems; 121418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 122418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 123418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager void addCodeItemsTo() { 124a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov if (classKind == ClassKind.LIBRARY) { 125418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Ignore contents of library files. 126418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return; 127418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 128418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_CODE_ITEM); 12924e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (segment.length == 0) { 130418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return; 131418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 132418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(segment.offset); 13324e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 134418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.align(4); // code items are 4 byte aligned. 135418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = file.position(); 136418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexCode code = parseCodeItem(); 137418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager codes.put(offset, code); // Update the file local offset to code mapping. 138418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 139418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 140418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 141418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexTypeList parseTypeList() { 142418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType[] result = new DexType[file.getUint()]; 143418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int j = 0; j < result.length; j++) { 144418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[j] = indexedItems.getType(file.getUshort()); 145418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 146418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexTypeList(result); 147418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 148418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 149418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexTypeList typeListAt(int offset) { 150b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut if (offset == 0) { 151b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut return DexTypeList.empty(); 152b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut } 153418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (DexTypeList) cacheAt(offset, this::parseTypeList); 154418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 155418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 156418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public DexValue parseEncodedValue() { 157418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int header = file.get() & 0xff; 158418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int valueArg = header >> 5; 159418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int valueType = header & 0x1f; 160418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager switch (valueType) { 161418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_BYTE: { 162418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert valueArg == 0; 163418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager byte value = (byte) parseSigned(file, 1); 164418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueByte.create(value); 165418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 166418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_SHORT: { 167418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 168418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager short value = (short) parseSigned(file, size); 169418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueShort.create(value); 170418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 171418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_CHAR: { 172418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 173418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager char value = (char) parseUnsigned(file, size); 174418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueChar.create(value); 175418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 176418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_INT: { 177418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 178418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int value = (int) parseSigned(file, size); 179418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueInt.create(value); 180418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 181418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_LONG: { 182418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 183418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager long value = parseSigned(file, size); 184418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueLong.create(value); 185418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 186418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_FLOAT: { 187418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 188418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueFloat.create(parseFloat(file, size)); 189418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 190418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_DOUBLE: { 191418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 192418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueDouble.create(parseDouble(file, size)); 193418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 194418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_STRING: { 195418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 196418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int index = (int) parseUnsigned(file, size); 197418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexString value = indexedItems.getString(index); 198418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueString(value); 199418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 200418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_TYPE: { 201418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 202418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType value = indexedItems.getType((int) parseUnsigned(file, size)); 203418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueType(value); 204418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 205418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_FIELD: { 206418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 207418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexField value = indexedItems.getField((int) parseUnsigned(file, size)); 208418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueField(value); 209418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 210418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_METHOD: { 211418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 212418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethod value = indexedItems.getMethod((int) parseUnsigned(file, size)); 213418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueMethod(value); 214418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 215418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_ENUM: { 216418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 217418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexField value = indexedItems.getField((int) parseUnsigned(file, size)); 218418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueEnum(value); 219418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 220418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_ARRAY: { 221418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert valueArg == 0; 222418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueArray(parseEncodedArrayValues()); 223418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 224418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_ANNOTATION: { 225418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert valueArg == 0; 226418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueAnnotation(parseEncodedAnnotation()); 227418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 228418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_NULL: { 229418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert valueArg == 0; 230127cf8f5c1c98d408526ee6895fc3911689c9ad2Mads Ager return DexValueNull.NULL; 231418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 232418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_BOOLEAN: { 233418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // 0 is false, and 1 is true. 234418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return DexValue.DexValueBoolean.create(valueArg != 0); 235418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 236418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_METHOD_TYPE: { 237418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 238418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexProto value = indexedItems.getProto((int) parseUnsigned(file, size)); 239418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueMethodType(value); 240418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 241418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case DexValue.VALUE_METHOD_HANDLE: { 242418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = valueArg + 1; 243418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethodHandle value = indexedItems.getMethodHandle((int) parseUnsigned(file, size)); 244418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexValue.DexValueMethodHandle(value); 245418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 246418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager default: 247418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager throw new IndexOutOfBoundsException(); 248418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 249418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 250418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 251418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexEncodedAnnotation parseEncodedAnnotation() { 252418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int typeIdx = file.getUleb128(); 253418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUleb128(); 254418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAnnotationElement[] elements = new DexAnnotationElement[size]; 255418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 256418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nameIdx = file.getUleb128(); 257418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexValue value = parseEncodedValue(); 258418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager elements[i] = new DexAnnotationElement(indexedItems.getString(nameIdx), value); 259418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 260418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexEncodedAnnotation(indexedItems.getType(typeIdx), elements); 261418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 262418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 263418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexValue[] parseEncodedArrayValues() { 264418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUleb128(); 265418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexValue[] values = new DexValue[size]; 266418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 267418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager values[i] = parseEncodedValue(); 268418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 269418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return values; 270418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 271418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 272418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 273418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexEncodedArray parseEncodedArray() { 274418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexEncodedArray(parseEncodedArrayValues()); 275418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 276418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 277418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexEncodedArray encodedArrayAt(int offset) { 278418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (DexEncodedArray) cacheAt(offset, this::parseEncodedArray); 279418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 280418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 281418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexFieldAnnotation[] parseFieldAnnotations(int size) { 282418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (size == 0) { 283418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 284418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 285418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] fieldIndices = new int[size]; 286418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] annotationOffsets = new int[size]; 287418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 288418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager fieldIndices[i] = file.getUint(); 289418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationOffsets[i] = file.getUint(); 290418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 291418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int saved = file.position(); 292418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFieldAnnotation[] result = new DexFieldAnnotation[size]; 293418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 294418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexField field = indexedItems.getField(fieldIndices[i]); 295418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAnnotationSet annotation = annotationSetAt(annotationOffsets[i]); 296418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[i] = new DexFieldAnnotation(field, annotation); 297418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 298418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(saved); 299418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return result; 300418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 301418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 302418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexMethodAnnotation[] parseMethodAnnotations(int size) { 303418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (size == 0) { 304418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 305418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 306418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] methodIndices = new int[size]; 307418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] annotationOffsets = new int[size]; 308418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 309418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager methodIndices[i] = file.getUint(); 310418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationOffsets[i] = file.getUint(); 311418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 312418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int saved = file.position(); 313418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethodAnnotation[] result = new DexMethodAnnotation[size]; 314418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 315418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethod method = indexedItems.getMethod(methodIndices[i]); 316418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAnnotationSet annotation = annotationSetAt(annotationOffsets[i]); 317418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[i] = new DexMethodAnnotation(method, annotation); 318418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 319418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(saved); 320418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return result; 321418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 322418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 323418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexAnnotationSetRefList annotationSetRefListAt(int offset) { 324418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (DexAnnotationSetRefList) cacheAt(offset, this::parseAnnotationSetRefList); 325418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 326418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 327418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexAnnotationSetRefList parseAnnotationSetRefList() { 328418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUint(); 329418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] annotationOffsets = new int[size]; 330418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 331418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationOffsets[i] = file.getUint(); 332418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 333418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAnnotationSet[] values = new DexAnnotationSet[size]; 334418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 335418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager values[i] = annotationSetAt(annotationOffsets[i]); 336418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 337418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexAnnotationSetRefList(values); 338418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 339418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 340418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexParameterAnnotation[] parseParameterAnnotations(int size) { 341418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (size == 0) { 342418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 343418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 344418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] methodIndices = new int[size]; 345418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] annotationOffsets = new int[size]; 346418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 347418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager methodIndices[i] = file.getUint(); 348418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationOffsets[i] = file.getUint(); 349418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 350418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int saved = file.position(); 351418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexParameterAnnotation[] result = new DexParameterAnnotation[size]; 352418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 353418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethod method = indexedItems.getMethod(methodIndices[i]); 354418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[i] = new DexParameterAnnotation( 355418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager method, 356418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationSetRefListAt(annotationOffsets[i])); 357418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 358418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(saved); 359418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return result; 360418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 361418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 362418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private <T> Object cacheAt(int offset, Supplier<T> function, Supplier<T> defaultValue) { 363418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (offset == 0) { 364418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return defaultValue.get(); 365418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 366418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return cacheAt(offset, function); 367418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 368418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 369418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private <T> Object cacheAt(int offset, Supplier<T> function) { 370b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut if (offset == 0) { 371b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut return null; // return null for offset zero. 372b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut } 373418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Object result = offsetMap.get(offset); 374b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut if (result != null) { 375b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut return result; // return the cached result. 376b17bb8d16da782186a30dc935a3ff12dca8abb09Stephan Herhut } 377418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Cache is empty so parse the structure. 378418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(offset); 379418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result = function.get(); 380418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Update the map. 381418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager offsetMap.put(offset, result); 382418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert offsetMap.get(offset) == result; 383418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return result; 384418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 385418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 386418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexAnnotation parseAnnotation() { 387418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (Log.ENABLED) { 388418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Log.verbose(getClass(), "Reading Annotation @ 0x%08x.", file.position()); 389418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 390418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int visibility = file.get(); 391418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexAnnotation(visibility, parseEncodedAnnotation()); 392418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 393418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 394418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexAnnotation annotationAt(int offset) { 395418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (DexAnnotation) cacheAt(offset, this::parseAnnotation); 396418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 397418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 398418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexAnnotationSet parseAnnotationSet() { 399418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (Log.ENABLED) { 400418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Log.verbose(getClass(), "Reading AnnotationSet @ 0x%08x.", file.position()); 401418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 402418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUint(); 403418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int[] annotationOffsets = new int[size]; 404418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 405418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationOffsets[i] = file.getUint(); 406418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 407418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAnnotation[] result = new DexAnnotation[size]; 408418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 409418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[i] = annotationAt(annotationOffsets[i]); 410418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 411418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexAnnotationSet(result); 412418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 413418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 414418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexAnnotationSet annotationSetAt(int offset) { 415418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (DexAnnotationSet) cacheAt(offset, this::parseAnnotationSet, DexAnnotationSet::empty); 416418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 417418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 418418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private AnnotationsDirectory annotationsDirectoryAt(int offset) { 419418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (AnnotationsDirectory) cacheAt(offset, this::parseAnnotationsDirectory, 420418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager AnnotationsDirectory::empty); 421418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 422418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 423418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private AnnotationsDirectory parseAnnotationsDirectory() { 424418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int classAnnotationsOff = file.getUint(); 425418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int fieldsSize = file.getUint(); 426418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int methodsSize = file.getUint(); 427418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int parametersSize = file.getUint(); 428418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final DexFieldAnnotation[] fields = parseFieldAnnotations(fieldsSize); 429418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final DexMethodAnnotation[] methods = parseMethodAnnotations(methodsSize); 430418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final DexParameterAnnotation[] parameters = parseParameterAnnotations(parametersSize); 431418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new AnnotationsDirectory( 432418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationSetAt(classAnnotationsOff), 433418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager fields, 434418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager methods, 435418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager parameters); 436418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 437418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 438418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexDebugInfo debugInfoAt(int offset) { 439418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return (DexDebugInfo) cacheAt(offset, this::parseDebugInfo); 440418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 441418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 442418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexDebugInfo parseDebugInfo() { 443418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int start = file.getUleb128(); 444418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int parametersSize = file.getUleb128(); 445418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexString[] parameters = new DexString[parametersSize]; 446418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < parametersSize; i++) { 447418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int index = file.getUleb128p1(); 448418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (index != NO_INDEX) { 449418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager parameters[i] = indexedItems.getString(index); 450418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 451418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 452418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager List<DexDebugEvent> events = new ArrayList<>(); 453418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int head = file.getUbyte(); head != Constants.DBG_END_SEQUENCE; head = file.getUbyte()) { 454418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager switch (head) { 455418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_ADVANCE_PC: 45639cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createAdvancePC(file.getUleb128())); 457418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 458418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_ADVANCE_LINE: 45939cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createAdvanceLine(file.getSleb128())); 460418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 461418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_START_LOCAL: { 462418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int registerNum = file.getUleb128(); 463418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nameIdx = file.getUleb128p1(); 464418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int typeIdx = file.getUleb128p1(); 465418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager events.add(new DexDebugEvent.StartLocal( 466418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager registerNum, 467418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager nameIdx == NO_INDEX ? null : indexedItems.getString(nameIdx), 468418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager typeIdx == NO_INDEX ? null : indexedItems.getType(typeIdx), 469418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager null)); 470418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 471418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 472418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_START_LOCAL_EXTENDED: { 473418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int registerNum = file.getUleb128(); 474418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nameIdx = file.getUleb128p1(); 475418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int typeIdx = file.getUleb128p1(); 476418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int sigIdx = file.getUleb128p1(); 477418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager events.add(new DexDebugEvent.StartLocal( 478418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager registerNum, 479418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager nameIdx == NO_INDEX ? null : indexedItems.getString(nameIdx), 480418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager typeIdx == NO_INDEX ? null : indexedItems.getType(typeIdx), 481418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager sigIdx == NO_INDEX ? null : indexedItems.getString(sigIdx))); 482418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 483418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 484418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_END_LOCAL: { 48539cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createEndLocal(file.getUleb128())); 486418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 487418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 488418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_RESTART_LOCAL: { 48939cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createRestartLocal(file.getUleb128())); 490418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 491418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 492418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_SET_PROLOGUE_END: { 49339cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createSetPrologueEnd()); 494418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 495418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 496418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_SET_EPILOGUE_BEGIN: { 49739cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createSetEpilogueBegin()); 498418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 499418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 500418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case Constants.DBG_SET_FILE: { 501418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nameIdx = file.getUleb128p1(); 502418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexString sourceFile = nameIdx == NO_INDEX ? null : indexedItems.getString(nameIdx); 50339cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createSetFile(sourceFile)); 504418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 505418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 506418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager default: { 507418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert head >= 0x0a && head <= 0xff; 50839cdb4cb692e28fb956bef615546f4899861f901Alan Leung events.add(dexItemFactory.createDefault(head)); 509418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 510418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 511418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 512418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexDebugInfo(start, parameters, events.toArray(new DexDebugEvent[events.size()])); 513418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 514418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 515418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static class MemberAnnotationIterator<S extends Descriptor<?, S>, T extends DexItem> { 516418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 517418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private int index = 0; 518418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private final DexMemberAnnotation<S, T>[] annotations; 519418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private final Supplier<T> emptyValue; 520418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 521418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private MemberAnnotationIterator(DexMemberAnnotation<S, T>[] annotations, 522418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Supplier<T> emptyValue) { 523418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.annotations = annotations; 524418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.emptyValue = emptyValue; 525418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 526418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 527418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Get the annotation set for an item. This method assumes that it is always called with 528418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // an item that is higher in the sorting order than the last item. 529418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager T getNextFor(S item) { 530418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // TODO(ager): We could use the indices from the file to make this search faster using 531418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // compareTo instead of slowCompareTo. That would require us to assign indices during 532418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // reading. Those indices should be cleared after reading to make sure that we resort 533418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // everything correctly at the end. 534418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager while (index < annotations.length && annotations[index].item.slowCompareTo(item) < 0) { 535418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager index++; 536418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 537418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (index >= annotations.length || !annotations[index].item.equals(item)) { 538418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return emptyValue.get(); 539418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 540418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return annotations[index].annotations; 541418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 542418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 543418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 544418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexEncodedField[] readFields(int size, DexFieldAnnotation[] annotations, 545418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexValue[] staticValues) { 546418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedField[] fields = new DexEncodedField[size]; 547418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int fieldIndex = 0; 548418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager MemberAnnotationIterator<DexField, DexAnnotationSet> annotationIterator = 549418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new MemberAnnotationIterator<>(annotations, DexAnnotationSet::empty); 550418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 551418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager fieldIndex += file.getUleb128(); 552418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexField field = indexedItems.getField(fieldIndex); 553418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAccessFlags accessFlags = new DexAccessFlags(file.getUleb128()); 554418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAnnotationSet fieldAnnotations = annotationIterator.getNextFor(field); 555418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexValue staticValue = null; 556418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (accessFlags.isStatic()) { 557418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (staticValues != null && i < staticValues.length) { 558418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager staticValue = staticValues[i]; 559418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } else { 560418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager staticValue = DexValue.defaultForType(field.type, dexItemFactory); 561418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 562418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 563418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager fields[i] = new DexEncodedField(field, accessFlags, fieldAnnotations, staticValue); 564418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 565418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return fields; 566418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 567418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 568418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexEncodedMethod[] readMethods(int size, DexMethodAnnotation[] annotations, 569418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexParameterAnnotation[] parameters, boolean skipCodes) { 570418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedMethod[] methods = new DexEncodedMethod[size]; 571418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int methodIndex = 0; 572418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager MemberAnnotationIterator<DexMethod, DexAnnotationSet> annotationIterator = 573418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new MemberAnnotationIterator<>(annotations, DexAnnotationSet::empty); 574418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager MemberAnnotationIterator<DexMethod, DexAnnotationSetRefList> parameterAnnotationsIterator = 575418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new MemberAnnotationIterator<>(parameters, DexAnnotationSetRefList::empty); 576418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 577418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager methodIndex += file.getUleb128(); 578418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAccessFlags accessFlags = new DexAccessFlags(file.getUleb128()); 579418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int codeOff = file.getUleb128(); 580418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexCode code = null; 581418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (!skipCodes) { 582418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert codeOff == 0 || codes.get(codeOff) != null; 583418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager code = codes.get(codeOff); 584418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 585418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethod method = indexedItems.getMethod(methodIndex); 586418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager methods[i] = new DexEncodedMethod(method, accessFlags, annotationIterator.getNextFor(method), 587418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager parameterAnnotationsIterator.getNextFor(method), code); 588418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 589418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return methods; 590418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 591418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 592418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager void addClassDefsTo(Consumer<DexClass> classCollection) { 593418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final Segment segment = lookupSegment(Constants.TYPE_CLASS_DEF_ITEM); 59424e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak final int length = segment.length; 59524e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak indexedItems.initializeClasses(length); 59624e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (length == 0) { 597418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return; 598418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 599418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(segment.offset); 600418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 60124e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] classIndices = new int[length]; 60224e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] accessFlags = new int[length]; 60324e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] superclassIndices = new int[length]; 60424e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] interfacesOffsets = new int[length]; 60524e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] sourceFileIndices = new int[length]; 60624e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] annotationsOffsets = new int[length]; 60724e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] classDataOffsets = new int[length]; 60824e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak int[] staticValuesOffsets = new int[length]; 609418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 61024e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < length; i++) { 611418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (Log.ENABLED) { 612418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Log.verbose(getClass(), "Reading ClassDef @ 0x%08x.", file.position()); 613418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 614418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager classIndices[i] = file.getUint(); 615418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager accessFlags[i] = file.getUint(); 616418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager superclassIndices[i] = file.getInt(); 617418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager interfacesOffsets[i] = file.getUint(); 618418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager sourceFileIndices[i] = file.getInt(); 619418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationsOffsets[i] = file.getUint(); 620418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager classDataOffsets[i] = file.getUint(); 621418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager staticValuesOffsets[i] = file.getUint(); 622418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 623418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 62424e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < length; i++) { 625418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int superclassIdx = superclassIndices[i]; 626418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType superclass = superclassIdx == NO_INDEX ? null : indexedItems.getType(superclassIdx); 627418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int srcIdx = sourceFileIndices[i]; 628418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexString source = srcIdx == NO_INDEX ? null : indexedItems.getString(srcIdx); 629418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // fix annotations. 630418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType type = indexedItems.getType(classIndices[i]); 631418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexAccessFlags flags = new DexAccessFlags(accessFlags[i]); 632418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexClass clazz; 633418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedField[] staticFields = DexEncodedField.EMPTY_ARRAY; 634418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedField[] instanceFields = DexEncodedField.EMPTY_ARRAY; 635418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedMethod[] directMethods = DexEncodedMethod.EMPTY_ARRAY; 636418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedMethod[] virtualMethods = DexEncodedMethod.EMPTY_ARRAY; 637418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager AnnotationsDirectory annotationsDirectory = annotationsDirectoryAt(annotationsOffsets[i]); 638418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (classDataOffsets[i] != 0) { 639418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedArray staticValues = encodedArrayAt(staticValuesOffsets[i]); 640418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 641418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(classDataOffsets[i]); 642418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int staticFieldsSize = file.getUleb128(); 643418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int instanceFieldsSize = file.getUleb128(); 644418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int directMethodsSize = file.getUleb128(); 645418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int virtualMethodsSize = file.getUleb128(); 646418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 647418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager staticFields = readFields(staticFieldsSize, annotationsDirectory.fields, 648418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager staticValues != null ? staticValues.values : null); 649418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager instanceFields = readFields(instanceFieldsSize, annotationsDirectory.fields, null); 650418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager directMethods = 651418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager readMethods( 652418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager directMethodsSize, 653418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationsDirectory.methods, 654418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationsDirectory.parameters, 655a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov classKind != ClassKind.PROGRAM); 656418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager virtualMethods = 657418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager readMethods( 658418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager virtualMethodsSize, 659418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationsDirectory.methods, 660418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationsDirectory.parameters, 661a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov classKind != ClassKind.PROGRAM); 662418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 663a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov clazz = classKind.create( 664418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager type, 665a60f2aa119b2ac6d5128683e6a98fd53334327f6Denis Vnukov Resource.Kind.DEX, 666418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager flags, 667418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager superclass, 668418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager typeListAt(interfacesOffsets[i]), 669418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager source, 670418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager annotationsDirectory.clazz, 671418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager staticFields, 672418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager instanceFields, 673418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager directMethods, 674418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager virtualMethods); 675418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager classCollection.accept(clazz); // Update the application object. 676418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 677418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 678418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 679418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private void parseStringIDs() { 680418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_STRING_ID_ITEM); 68124e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak stringIDs = new int[segment.length]; 68224e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (segment.length == 0) { 683418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return; 684418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 685418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(segment.offset); 68624e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 687418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager stringIDs[i] = file.getUint(); 688418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 689418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 690418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 691418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private Segment lookupSegment(int type) { 692418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (Segment s : segments) { 693418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (s.type == type) { 694418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return s; 695418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 696418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 697418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // If the segment doesn't exist, return an empty segment of this type. 698418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new Segment(type, 0, 0, 0); 699418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 700418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 701418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private Segment[] parseMap() { 702418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Read the segments information from the MAP. 703418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int mapOffset = file.getUint(Constants.MAP_OFF_OFFSET); 704418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(mapOffset); 705418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int mapSize = file.getUint(); 706418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final Segment[] result = new Segment[mapSize]; 707418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < mapSize; i++) { 708418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int type = file.getUshort(); 709418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int unused = file.getUshort(); 710418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUint(); 711418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = file.getUint(); 712418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[i] = new Segment(type, unused, size, offset); 713418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 714418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (Log.ENABLED) { 715418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < result.length; i++) { 716418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = result[i]; 717418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nextOffset = i < result.length - 1 ? result[i + 1].offset : segment.offset; 718418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Log.debug(this.getClass(), "Read segment 0x%04x @ 0x%08x #items %08d size 0x%08x.", 71924e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak segment.type, segment.offset, segment.length, nextOffset - segment.offset); 720418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 721418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 722418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < mapSize - 1; i++) { 723418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[i].setEnd(result[i + 1].offset); 724418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 725418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager result[mapSize - 1].setEnd(file.end()); 726418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return result; 727418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 728418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 729418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexCode parseCodeItem() { 730418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int registerSize = file.getUshort(); 731418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int insSize = file.getUshort(); 732418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int outsSize = file.getUshort(); 733418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int triesSize = file.getUshort(); 734418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int debugInfoOff = file.getUint(); 735418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int insnsSize = file.getUint(); 736418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager short[] code = new short[insnsSize]; 737418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Try[] tries = new Try[triesSize]; 738418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexCode.TryHandler[] handlers = null; 739418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 740418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (insnsSize != 0) { 741418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < insnsSize; i++) { 742418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager code[i] = file.getShort(); 743418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 744418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (insnsSize % 2 != 0) { 745418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.getUshort(); // Skip padding ushort 746418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 747418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (triesSize > 0) { 748418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Hashtable<Integer, Integer> handlerMap = new Hashtable<>(); 749418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // tries: try_item[tries_size]. 750418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < triesSize; i++) { 751418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int startAddr = file.getUint(); 752418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int insnCount = file.getUshort(); 753418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int handlerOff = file.getUshort(); 754418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager tries[i] = new Try(startAddr, insnCount, handlerOff); 755418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 756418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // handlers: encoded_catch_handler_list 757418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int encodedCatchHandlerListPosition = file.position(); 758418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // - size: uleb128 759418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUleb128(); 760418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager handlers = new TryHandler[size]; 761418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // - list: encoded_catch_handler[handlers_size] 762418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < size; i++) { 763418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // encoded_catch_handler 764418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int encodedCatchHandlerOffset = file.position() - encodedCatchHandlerListPosition; 765418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager handlerMap.put(encodedCatchHandlerOffset, i); 766418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // - size: sleb128 767418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int hsize = file.getSleb128(); 768418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int realHsize = Math.abs(hsize); 769418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // - handlers encoded_type_addr_pair[abs(size)] 770418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager TryHandler.TypeAddrPair pairs[] = new TryHandler.TypeAddrPair[realHsize]; 771418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int j = 0; j < realHsize; j++) { 772418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int typeIdx = file.getUleb128(); 773418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int addr = file.getUleb128(); 774418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager pairs[j] = new TypeAddrPair(indexedItems.getType(typeIdx), addr, 775418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager encodedCatchHandlerOffset); 776418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 777418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int catchAllAddr = -1; 778418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager if (hsize <= 0) { 779418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager catchAllAddr = file.getUleb128(); 780418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 781418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager handlers[i] = new TryHandler(pairs, catchAllAddr); 782418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 783418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Convert the handler offsets inside the Try objects to indexes. 784418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (Try t : tries) { 785418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager t.setHandlerIndex(handlerMap); 786418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 787418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 788418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 789418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Store and restore offset information around reading debug info. 790418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int saved = file.position(); 791418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexDebugInfo debugInfo = debugInfoAt(debugInfoOff); 792418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(saved); 793418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager InstructionFactory factory = new InstructionFactory(); 794418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Instruction[] instructions = 795418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager factory.readSequenceFrom(ShortBuffer.wrap(code), 0, code.length, indexedItems); 796418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return new DexCode( 797418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager registerSize, 798418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager insSize, 799418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager outsSize, 800418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager instructions, 801418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager tries, 802418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager handlers, 803418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager debugInfo, 804418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager factory.getHighestSortingString()); 805418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 806418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 807418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager static void populateIndexTables(DexFileReader fileReader) { 808418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // Populate structures that are already sorted upon read. 809418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateStrings(fileReader); // Depends on nothing. 810418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateTypes(fileReader); // Depends on Strings. 811418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateFields(fileReader); // Depends on Types, and Strings. 812418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateProtos(fileReader); // Depends on Types and Strings. 813418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateMethods(fileReader); // Depends on Protos, Types, and Strings. 814418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateMethodHandles(fileReader); // Depends on Methods and Fields 815418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFileReader.populateCallSites(fileReader); // Depends on MethodHandles 816418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 817418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 818418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateStrings(DexFileReader reader) { 819418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.initializeStrings(reader.stringIDs.length); 820418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager for (int i = 0; i < reader.stringIDs.length; i++) { 821418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setString(i, reader.stringAt(i)); 822418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 823418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 824418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 825418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateMethodHandles(DexFileReader reader) { 826418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = reader.lookupSegment(Constants.TYPE_METHOD_HANDLE_ITEM); 82724e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak reader.indexedItems.initializeMethodHandles(segment.length); 82824e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 829418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setMethodHandle(i, reader.methodHandleAt(i)); 830418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 831418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 832418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 833418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateCallSites(DexFileReader reader) { 834418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = reader.lookupSegment(Constants.TYPE_CALL_SITE_ID_ITEM); 83524e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak reader.indexedItems.initializeCallSites(segment.length); 83624e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 837418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setCallSites(i, reader.callSiteAt(i)); 838418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 839418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 840418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 841418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateTypes(DexFileReader reader) { 842418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = reader.lookupSegment(Constants.TYPE_TYPE_ID_ITEM); 84324e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak reader.indexedItems.initializeTypes(segment.length); 84424e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 845418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setType(i, reader.typeAt(i)); 846418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 847418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 848418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 849418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateFields(DexFileReader reader) { 850418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = reader.lookupSegment(Constants.TYPE_FIELD_ID_ITEM); 85124e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak reader.indexedItems.initializeFields(segment.length); 85224e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 853418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setField(i, reader.fieldAt(i)); 854418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 855418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 856418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 857418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateProtos(DexFileReader reader) { 858418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = reader.lookupSegment(Constants.TYPE_PROTO_ID_ITEM); 85924e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak reader.indexedItems.initializeProtos(segment.length); 86024e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 861418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setProto(i, reader.protoAt(i)); 862418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 863418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 864418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 865418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static void populateMethods(DexFileReader reader) { 866418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = reader.lookupSegment(Constants.TYPE_METHOD_ID_ITEM); 86724e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak reader.indexedItems.initializeMethods(segment.length); 86824e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak for (int i = 0; i < segment.length; i++) { 869418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager reader.indexedItems.setMethod(i, reader.methodAt(i)); 870418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 871418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 872418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 873418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexString stringAt(int index) { 874418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager final int offset = stringIDs[index]; 875418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(offset); 876418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int size = file.getUleb128(); 877418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager ByteArrayOutputStream os = new ByteArrayOutputStream(); 878418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager byte read; 879418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager do { 880418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager read = file.get(); 881418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager os.write(read); 882418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } while (read != 0); 883418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createString(size, os.toByteArray()); 884418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 885418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 886418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexType typeAt(int index) { 887418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_TYPE_ID_ITEM); 88824e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (index >= segment.length) { 889418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 890418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 891418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = segment.offset + (Constants.TYPE_TYPE_ID_ITEM_SIZE * index); 892418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int stringIndex = file.getUint(offset); 893418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createType(indexedItems.getString(stringIndex)); 894418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 895418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 896418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexField fieldAt(int index) { 897418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_FIELD_ID_ITEM); 89824e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (index >= segment.length) { 899418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 900418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 901418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = segment.offset + (Constants.TYPE_FIELD_ID_ITEM_SIZE * index); 902418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(offset); 903418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int classIndex = file.getUshort(); 904418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int typeIndex = file.getUshort(); 905418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nameIndex = file.getUint(); 906418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType clazz = indexedItems.getType(classIndex); 907418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType type = indexedItems.getType(typeIndex); 908418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexString name = indexedItems.getString(nameIndex); 909418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createField(clazz, type, name); 910418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 911418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 912418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexMethodHandle methodHandleAt(int index) { 913418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_METHOD_HANDLE_ITEM); 91424e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (index >= segment.length) { 915418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 916418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 917418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = segment.offset + (Constants.TYPE_METHOD_HANDLE_ITEM_SIZE * index); 918418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(offset); 919418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager MethodHandleType type = MethodHandleType.getKind(file.getUshort()); 920418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.getUshort(); // unused 921418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int indexFieldOrMethod = file.getUshort(); 922418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod; 923418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager switch (type) { 924418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case INSTANCE_GET: 925418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case INSTANCE_PUT: 926418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case STATIC_GET: 927418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case STATIC_PUT: { 928418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager fieldOrMethod = indexedItems.getField(indexFieldOrMethod); 929418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 930418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 931418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case INVOKE_INSTANCE: 932418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager case INVOKE_STATIC: { 933418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager fieldOrMethod = indexedItems.getMethod(indexFieldOrMethod); 934418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager break; 935418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 936418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager default: 937418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager throw new AssertionError("Method handle type unsupported in a dex file."); 938418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 939418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.getUshort(); // unused 940418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 941418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createMethodHandle(type, fieldOrMethod); 942418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 943418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 944418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexCallSite callSiteAt(int index) { 945418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_CALL_SITE_ID_ITEM); 94624e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (index >= segment.length) { 947418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 948418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 949418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int callSiteOffset = 950418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.getUint(segment.offset + (Constants.TYPE_CALL_SITE_ID_ITEM_SIZE * index)); 951418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexEncodedArray callSiteEncodedArray = encodedArrayAt(callSiteOffset); 952418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexValue[] values = callSiteEncodedArray.values; 953418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert values[0] instanceof DexValueMethodHandle; 954418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert values[1] instanceof DexValueString; 955418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager assert values[2] instanceof DexValueMethodType; 956418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 957418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createCallSite( 958418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager ((DexValueString) values[1]).value, 959418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager ((DexValueMethodType) values[2]).value, 960418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager ((DexValueMethodHandle) values[0]).value, 961418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager // 3 means first extra args 962418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Arrays.asList(Arrays.copyOfRange(values, 3, values.length))); 963418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 964418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 965418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexProto protoAt(int index) { 966418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_PROTO_ID_ITEM); 96724e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (index >= segment.length) { 968418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 969418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 970418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = segment.offset + (Constants.TYPE_PROTO_ID_ITEM_SIZE * index); 971418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(offset); 972418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int shortyIndex = file.getUint(); 973418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int returnTypeIndex = file.getUint(); 974418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int parametersOffsetIndex = file.getUint(); 975418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexString shorty = indexedItems.getString(shortyIndex); 976418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexType returnType = indexedItems.getType(returnTypeIndex); 977418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexTypeList parameters = typeListAt(parametersOffsetIndex); 978418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createProto(shorty, returnType, parameters); 979418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 980418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 981418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private DexMethod methodAt(int index) { 982418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager Segment segment = lookupSegment(Constants.TYPE_METHOD_ID_ITEM); 98324e0f5c8959e87bb7d0ecb461808c03abb0abc85Lars Bak if (index >= segment.length) { 984418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return null; 985418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 986418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int offset = segment.offset + (Constants.TYPE_METHOD_ID_ITEM_SIZE * index); 987418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager file.position(offset); 988418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int classIndex = file.getUshort(); 989418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int protoIndex = file.getUshort(); 990418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager int nameIndex = file.getUint(); 991418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return dexItemFactory.createMethod( 992418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager indexedItems.getType(classIndex), 993418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager indexedItems.getProto(protoIndex), 994418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager indexedItems.getString(nameIndex)); 995418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 996418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 997418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static class AnnotationsDirectory { 998418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 999418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static final DexParameterAnnotation[] NO_PARAMETER_ANNOTATIONS = 1000418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new DexParameterAnnotation[0]; 1001418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 1002418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static final DexFieldAnnotation[] NO_FIELD_ANNOTATIONS = 1003418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new DexFieldAnnotation[0]; 1004418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 1005418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static final DexMethodAnnotation[] NO_METHOD_ANNOTATIONS = 1006418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new DexMethodAnnotation[0]; 1007418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 1008418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager private static final AnnotationsDirectory THE_EMPTY_ANNOTATIONS_DIRECTORY = 1009418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager new AnnotationsDirectory(DexAnnotationSet.empty(), 1010418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager NO_FIELD_ANNOTATIONS, new DexMethodAnnotation[0], 1011418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager NO_PARAMETER_ANNOTATIONS); 1012418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 1013418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public final DexAnnotationSet clazz; 1014418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public final DexFieldAnnotation[] fields; 1015418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public final DexMethodAnnotation[] methods; 1016418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public final DexParameterAnnotation[] parameters; 1017418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 1018418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager AnnotationsDirectory(DexAnnotationSet clazz, 1019418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexFieldAnnotation[] fields, 1020418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexMethodAnnotation[] methods, 1021418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager DexParameterAnnotation[] parameters) { 1022418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.clazz = clazz == null ? DexAnnotationSet.empty() : clazz; 1023418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.fields = fields == null ? NO_FIELD_ANNOTATIONS : fields; 1024418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.methods = methods == null ? NO_METHOD_ANNOTATIONS : methods; 1025418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager this.parameters = parameters == null ? NO_PARAMETER_ANNOTATIONS : parameters; 1026418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 1027418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager 1028418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager public static AnnotationsDirectory empty() { 1029418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager return THE_EMPTY_ANNOTATIONS_DIRECTORY; 1030418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 1031418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager } 1032418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager} 1033