18405133a40e68eeaeff38b64af23426662852618Ben Gruver/*
28405133a40e68eeaeff38b64af23426662852618Ben Gruver * Copyright 2012, Google Inc.
38405133a40e68eeaeff38b64af23426662852618Ben Gruver * All rights reserved.
48405133a40e68eeaeff38b64af23426662852618Ben Gruver *
58405133a40e68eeaeff38b64af23426662852618Ben Gruver * Redistribution and use in source and binary forms, with or without
68405133a40e68eeaeff38b64af23426662852618Ben Gruver * modification, are permitted provided that the following conditions are
78405133a40e68eeaeff38b64af23426662852618Ben Gruver * met:
88405133a40e68eeaeff38b64af23426662852618Ben Gruver *
98405133a40e68eeaeff38b64af23426662852618Ben Gruver *     * Redistributions of source code must retain the above copyright
108405133a40e68eeaeff38b64af23426662852618Ben Gruver * notice, this list of conditions and the following disclaimer.
118405133a40e68eeaeff38b64af23426662852618Ben Gruver *     * Redistributions in binary form must reproduce the above
128405133a40e68eeaeff38b64af23426662852618Ben Gruver * copyright notice, this list of conditions and the following disclaimer
138405133a40e68eeaeff38b64af23426662852618Ben Gruver * in the documentation and/or other materials provided with the
148405133a40e68eeaeff38b64af23426662852618Ben Gruver * distribution.
158405133a40e68eeaeff38b64af23426662852618Ben Gruver *     * Neither the name of Google Inc. nor the names of its
168405133a40e68eeaeff38b64af23426662852618Ben Gruver * contributors may be used to endorse or promote products derived from
178405133a40e68eeaeff38b64af23426662852618Ben Gruver * this software without specific prior written permission.
188405133a40e68eeaeff38b64af23426662852618Ben Gruver *
198405133a40e68eeaeff38b64af23426662852618Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
208405133a40e68eeaeff38b64af23426662852618Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
218405133a40e68eeaeff38b64af23426662852618Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
228405133a40e68eeaeff38b64af23426662852618Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
238405133a40e68eeaeff38b64af23426662852618Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
248405133a40e68eeaeff38b64af23426662852618Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
258405133a40e68eeaeff38b64af23426662852618Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
268405133a40e68eeaeff38b64af23426662852618Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
278405133a40e68eeaeff38b64af23426662852618Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
288405133a40e68eeaeff38b64af23426662852618Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
298405133a40e68eeaeff38b64af23426662852618Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
308405133a40e68eeaeff38b64af23426662852618Ben Gruver */
318405133a40e68eeaeff38b64af23426662852618Ben Gruver
328405133a40e68eeaeff38b64af23426662852618Ben Gruverpackage org.jf.dexlib2.dexbacked;
338405133a40e68eeaeff38b64af23426662852618Ben Gruver
34d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruverimport com.google.common.io.ByteStreams;
3583f77f51aa888998486c0c9ad693047480b060b0Ben Gruverimport org.jf.dexlib2.Opcodes;
3690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport org.jf.dexlib2.ReferenceType;
371771f92aaf6e2d95c4504174803117712a9800bbBen Gruverimport org.jf.dexlib2.dexbacked.raw.*;
3890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference;
3990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference;
4090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport org.jf.dexlib2.dexbacked.reference.DexBackedStringReference;
4190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference;
4222c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport org.jf.dexlib2.dexbacked.util.FixedSizeSet;
438405133a40e68eeaeff38b64af23426662852618Ben Gruverimport org.jf.dexlib2.iface.DexFile;
4490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport org.jf.dexlib2.iface.reference.Reference;
454eefe294e4c664577982283cc64c415819a30c1eBen Gruverimport org.jf.dexlib2.util.DexUtil;
4684c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruverimport org.jf.util.ExceptionWithContext;
478405133a40e68eeaeff38b64af23426662852618Ben Gruver
488405133a40e68eeaeff38b64af23426662852618Ben Gruverimport javax.annotation.Nonnull;
4984c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruverimport javax.annotation.Nullable;
50d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruverimport java.io.IOException;
51d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruverimport java.io.InputStream;
5290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport java.util.AbstractList;
5390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruverimport java.util.List;
5422c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport java.util.Set;
558405133a40e68eeaeff38b64af23426662852618Ben Gruver
5612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruverpublic class DexBackedDexFile extends BaseDexBuffer implements DexFile {
57e202aeede5fb5fcc8de22601157b212eabb5f1c6Ben Gruver    @Nonnull private final Opcodes opcodes;
5883f77f51aa888998486c0c9ad693047480b060b0Ben Gruver
5912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int stringCount;
6012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int stringStartOffset;
6112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int typeCount;
6212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int typeStartOffset;
6312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int protoCount;
6412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int protoStartOffset;
6512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int fieldCount;
6612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int fieldStartOffset;
6712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int methodCount;
6812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int methodStartOffset;
6912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int classCount;
7012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    private final int classStartOffset;
7112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver
7231ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver    protected DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull byte[] buf, int offset, boolean verifyMagic) {
738920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver        super(buf, offset);
7484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
7583f77f51aa888998486c0c9ad693047480b060b0Ben Gruver        this.opcodes = opcodes;
7683f77f51aa888998486c0c9ad693047480b060b0Ben Gruver
77d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        if (verifyMagic) {
784eefe294e4c664577982283cc64c415819a30c1eBen Gruver            DexUtil.verifyDexHeader(buf, offset);
79d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        }
80d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
8112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        stringCount = readSmallUint(HeaderItem.STRING_COUNT_OFFSET);
8212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        stringStartOffset = readSmallUint(HeaderItem.STRING_START_OFFSET);
8312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        typeCount = readSmallUint(HeaderItem.TYPE_COUNT_OFFSET);
8412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        typeStartOffset = readSmallUint(HeaderItem.TYPE_START_OFFSET);
8512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        protoCount = readSmallUint(HeaderItem.PROTO_COUNT_OFFSET);
8612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        protoStartOffset = readSmallUint(HeaderItem.PROTO_START_OFFSET);
8712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        fieldCount = readSmallUint(HeaderItem.FIELD_COUNT_OFFSET);
8812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        fieldStartOffset = readSmallUint(HeaderItem.FIELD_START_OFFSET);
8912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        methodCount = readSmallUint(HeaderItem.METHOD_COUNT_OFFSET);
9012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        methodStartOffset = readSmallUint(HeaderItem.METHOD_START_OFFSET);
9112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        classCount = readSmallUint(HeaderItem.CLASS_COUNT_OFFSET);
9212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        classStartOffset = readSmallUint(HeaderItem.CLASS_START_OFFSET);
9312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
9484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
9583f77f51aa888998486c0c9ad693047480b060b0Ben Gruver    public DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull BaseDexBuffer buf) {
9641a5b4953cd4797a79c1f8d39a8f644d80c72707Ben Gruver        this(opcodes, buf.buf, buf.baseOffset);
97d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    }
98d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
9983f77f51aa888998486c0c9ad693047480b060b0Ben Gruver    public DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull byte[] buf, int offset) {
10083f77f51aa888998486c0c9ad693047480b060b0Ben Gruver        this(opcodes, buf, offset, false);
101d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    }
102d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
10383f77f51aa888998486c0c9ad693047480b060b0Ben Gruver    public DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull byte[] buf) {
10483f77f51aa888998486c0c9ad693047480b060b0Ben Gruver        this(opcodes, buf, 0, true);
105d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    }
106d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
10722a280710104cc6c51cbbfedcca08b4b1f481d5dBen Gruver    @Nonnull
10883f77f51aa888998486c0c9ad693047480b060b0Ben Gruver    public static DexBackedDexFile fromInputStream(@Nonnull Opcodes opcodes, @Nonnull InputStream is)
10983f77f51aa888998486c0c9ad693047480b060b0Ben Gruver            throws IOException {
1104eefe294e4c664577982283cc64c415819a30c1eBen Gruver        DexUtil.verifyDexHeader(is);
111d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
112d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        byte[] buf = ByteStreams.toByteArray(is);
11383f77f51aa888998486c0c9ad693047480b060b0Ben Gruver        return new DexBackedDexFile(opcodes, buf, 0, false);
11483f77f51aa888998486c0c9ad693047480b060b0Ben Gruver    }
11583f77f51aa888998486c0c9ad693047480b060b0Ben Gruver
116e202aeede5fb5fcc8de22601157b212eabb5f1c6Ben Gruver    @Override @Nonnull public Opcodes getOpcodes() {
11783f77f51aa888998486c0c9ad693047480b060b0Ben Gruver        return opcodes;
118d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    }
119d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
1208920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver    // Will only be true for a dalvik-style odex file
121d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    public boolean isOdexFile() {
122d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        return false;
123d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    }
124d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
1258920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver    // Will be true for both a dalvik-style odex file, and an art-style odex file embedded in an oat file
1268920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver    public boolean hasOdexOpcodes() {
1278920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver        return false;
1288920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver    }
1298920228819d4cd1cb016ba577b9c65a0cd798fd4Ben Gruver
13012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Nonnull
13112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Override
13212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public Set<? extends DexBackedClassDef> getClasses() {
13312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return new FixedSizeSet<DexBackedClassDef>() {
13412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            @Nonnull
13512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            @Override
13612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            public DexBackedClassDef readItem(int index) {
13712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver                return new DexBackedClassDef(DexBackedDexFile.this, getClassDefItemOffset(index));
1388405133a40e68eeaeff38b64af23426662852618Ben Gruver            }
13912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver
14012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            @Override
14112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            public int size() {
14212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver                return classCount;
14384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver            }
14412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        };
14512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
1468405133a40e68eeaeff38b64af23426662852618Ben Gruver
14712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getStringIdItemOffset(int stringIndex) {
14812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (stringIndex < 0 || stringIndex >= stringCount) {
149f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            throw new InvalidItemIndex(stringIndex, "String index out of bounds: %d", stringIndex);
15084c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
15112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE;
15212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
15384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
15412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getTypeIdItemOffset(int typeIndex) {
15512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (typeIndex < 0 || typeIndex >= typeCount) {
156f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            throw new InvalidItemIndex(typeIndex, "Type index out of bounds: %d", typeIndex);
15784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
15812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE;
15912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
16084c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
16112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getFieldIdItemOffset(int fieldIndex) {
16212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (fieldIndex < 0 || fieldIndex >= fieldCount) {
163f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            throw new InvalidItemIndex(fieldIndex, "Field index out of bounds: %d", fieldIndex);
16484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
16512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE;
16612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
16784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
16812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getMethodIdItemOffset(int methodIndex) {
16912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (methodIndex < 0 || methodIndex >= methodCount) {
170d3ba85b2ee46d14b13ccc17da6f261003f3a78dfBen Gruver            throw new InvalidItemIndex(methodIndex, "Method index out of bounds: %d", methodIndex);
17184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
17212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE;
17312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
17484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
17512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getProtoIdItemOffset(int protoIndex) {
17612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (protoIndex < 0 || protoIndex >= protoCount) {
177f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            throw new InvalidItemIndex(protoIndex, "Proto index out of bounds: %d", protoIndex);
17884c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
17912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE;
18012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
18184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
18212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getClassDefItemOffset(int classIndex) {
18312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (classIndex < 0 || classIndex >= classCount) {
184f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            throw new InvalidItemIndex(classIndex, "Class index out of bounds: %d", classIndex);
18584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
18612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE;
18712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
18884c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
18912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public int getClassCount() {
19012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return classCount;
19112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
19284c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
193d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    public int getStringCount() {
194d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver        return stringCount;
195d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    }
196d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver
197d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    public int getTypeCount() {
198d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver        return typeCount;
199d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    }
200d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver
201d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    public int getProtoCount() {
202d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver        return protoCount;
203d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    }
204d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver
205d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    public int getFieldCount() {
206d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver        return fieldCount;
207d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    }
208d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver
209d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    public int getMethodCount() {
210d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver        return methodCount;
211d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver    }
212d15e31526fe157bb4baaa0b4bb3b27b739d1a2beBen Gruver
21312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Nonnull
21412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public String getString(int stringIndex) {
21512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        int stringOffset = getStringIdItemOffset(stringIndex);
21612659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        int stringDataOffset = readSmallUint(stringOffset);
21712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        DexReader reader = readerAt(stringDataOffset);
21812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        int utf16Length = reader.readSmallUleb128();
21912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return reader.readString(utf16Length);
22012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
22184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
22212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Nullable
22312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public String getOptionalString(int stringIndex) {
22412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (stringIndex == -1) {
22512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            return null;
22684c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
22712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return getString(stringIndex);
22812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
22912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver
23012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Nonnull
23112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public String getType(int typeIndex) {
23212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        int typeOffset = getTypeIdItemOffset(typeIndex);
23312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        int stringIndex = readSmallUint(typeOffset);
23412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return getString(stringIndex);
23512659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
23684c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver
23712659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Nullable
23812659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public String getOptionalType(int typeIndex) {
23912659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        if (typeIndex == -1) {
24012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver            return null;
24184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        }
24212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return getType(typeIndex);
24312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    }
24412659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver
24590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    public List<DexBackedStringReference> getStrings() {
24690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        return new AbstractList<DexBackedStringReference>() {
24790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public DexBackedStringReference get(int index) {
24890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                if (index < 0 || index >= getStringCount()) {
24990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                    throw new IndexOutOfBoundsException();
25090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                }
25190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return new DexBackedStringReference(DexBackedDexFile.this, index);
25290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
25390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
25490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public int size() {
25590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getStringCount();
25690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
25790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        };
25890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    }
25990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
26090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    public List<DexBackedTypeReference> getTypes() {
26190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        return new AbstractList<DexBackedTypeReference>() {
26290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public DexBackedTypeReference get(int index) {
26390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                if (index < 0 || index >= getTypeCount()) {
26490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                    throw new IndexOutOfBoundsException();
26590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                }
26690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return new DexBackedTypeReference(DexBackedDexFile.this, index);
26790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
26890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
26990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public int size() {
27090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getTypeCount();
27190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
27290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        };
27390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    }
27490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
27590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    public List<DexBackedMethodReference> getMethods() {
27690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        return new AbstractList<DexBackedMethodReference>() {
27790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public DexBackedMethodReference get(int index) {
27890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                if (index < 0 || index >= getMethodCount()) {
27990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                    throw new IndexOutOfBoundsException();
28090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                }
28190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return new DexBackedMethodReference(DexBackedDexFile.this, index);
28290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
28390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
28490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public int size() {
28590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getMethodCount();
28690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
28790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        };
28890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    }
28990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
29090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    public List<DexBackedFieldReference> getFields() {
29190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        return new AbstractList<DexBackedFieldReference>() {
29290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public DexBackedFieldReference get(int index) {
29390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                if (index < 0 || index >= getFieldCount()) {
29490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                    throw new IndexOutOfBoundsException();
29590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                }
29690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return new DexBackedFieldReference(DexBackedDexFile.this, index);
29790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
29890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
29990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            @Override public int size() {
30090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getFieldCount();
30190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            }
30290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        };
30390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    }
30490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
30590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    public List<? extends Reference> getReferences(int referenceType) {
30690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        switch (referenceType) {
30790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            case ReferenceType.STRING:
30890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getStrings();
30990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            case ReferenceType.TYPE:
31090cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getTypes();
31190cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            case ReferenceType.METHOD:
31290cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getMethods();
31390cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            case ReferenceType.FIELD:
31490cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                return getFields();
31590cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver            default:
31690cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver                throw new IllegalArgumentException(String.format("Invalid reference type: %d", referenceType));
31790cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver        }
31890cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver    }
31990cacb9d0d153c06dcf5dd6c4887eeb50c8e93c2Ben Gruver
32012659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Override
32112659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    @Nonnull
32212659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver    public DexReader readerAt(int offset) {
32312659ec7db2876fee690a4192d6aefe71ac27b73Ben Gruver        return new DexReader(this, offset);
3248405133a40e68eeaeff38b64af23426662852618Ben Gruver    }
325d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
326d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    public static class NotADexFile extends RuntimeException {
327d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        public NotADexFile() {
328d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        }
329d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
330d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        public NotADexFile(Throwable cause) {
331d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver            super(cause);
332d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        }
333d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
334d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        public NotADexFile(String message) {
335d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver            super(message);
336d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        }
337d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver
338d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        public NotADexFile(String message, Throwable cause) {
339d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver            super(message, cause);
340d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver        }
341d45a6a60921ac27a4f13360a68e02e8f5fc28454Ben Gruver    }
342f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver
343f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver    public static class InvalidItemIndex extends ExceptionWithContext {
344f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        private final int itemIndex;
345f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver
346f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        public InvalidItemIndex(int itemIndex) {
347f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            super("");
348f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            this.itemIndex = itemIndex;
349f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        }
350f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver
351f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        public InvalidItemIndex(int itemIndex, String message, Object... formatArgs) {
352f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            super(message, formatArgs);
353f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            this.itemIndex = itemIndex;
354f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        }
355f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver
356f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        public int getInvalidIndex() {
357f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver            return itemIndex;
358f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver        }
359f7d6d5fadec6276246194a55b6aefe4815b50aceBen Gruver    }
3608405133a40e68eeaeff38b64af23426662852618Ben Gruver}
361