Dex.java revision c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8b
12bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson/* 22bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Copyright (C) 2011 The Android Open Source Project 32bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 42bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 52bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * you may not use this file except in compliance with the License. 62bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * You may obtain a copy of the License at 72bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 82bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 92bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Unless required by applicable law or agreed to in writing, software 112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * See the License for the specific language governing permissions and 142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * limitations under the License. 152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonpackage com.android.dex; 182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport com.android.dex.util.ByteInput; 202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport com.android.dex.util.ByteOutput; 212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport com.android.dex.util.FileUtils; 222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.ByteArrayOutputStream; 232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.File; 242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.FileInputStream; 252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.FileOutputStream; 262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.IOException; 272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.InputStream; 282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.OutputStream; 292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.io.UTFDataFormatException; 30c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstromimport java.nio.ByteBuffer; 31c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstromimport java.nio.ByteOrder; 322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.AbstractList; 332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.Arrays; 342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.Collections; 352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.Iterator; 362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.List; 372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.NoSuchElementException; 382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.zip.ZipEntry; 392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport java.util.zip.ZipFile; 402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson/** 422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * The bytes of a dex file in memory for reading and writing. All int offsets 432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * are unsigned. 442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonpublic final class Dex { 462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private byte[] data; 472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final TableOfContents tableOfContents = new TableOfContents(); 482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private int length = 0; 492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final List<String> strings = new AbstractList<String>() { 512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public String get(int index) { 522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson checkBounds(index, tableOfContents.stringIds.size); 532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM)) 542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson .readString(); 552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public int size() { 572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents.stringIds.size; 582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final List<Integer> typeIds = new AbstractList<Integer>() { 622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public Integer get(int index) { 632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson checkBounds(index, tableOfContents.typeIds.size); 642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt(); 652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public int size() { 672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents.typeIds.size; 682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final List<String> typeNames = new AbstractList<String>() { 722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public String get(int index) { 732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson checkBounds(index, tableOfContents.typeIds.size); 742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return strings.get(typeIds.get(index)); 752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public int size() { 772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents.typeIds.size; 782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final List<ProtoId> protoIds = new AbstractList<ProtoId>() { 822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public ProtoId get(int index) { 832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson checkBounds(index, tableOfContents.protoIds.size); 842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index)) 852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson .readProtoId(); 862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public int size() { 882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents.protoIds.size; 892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final List<FieldId> fieldIds = new AbstractList<FieldId>() { 932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public FieldId get(int index) { 942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson checkBounds(index, tableOfContents.fieldIds.size); 952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index)) 962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson .readFieldId(); 972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public int size() { 992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents.fieldIds.size; 1002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 1022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final List<MethodId> methodIds = new AbstractList<MethodId>() { 1042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public MethodId get(int index) { 1052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson checkBounds(index, tableOfContents.methodIds.size); 1062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index)) 1072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson .readMethodId(); 1082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson @Override public int size() { 1102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents.methodIds.size; 1112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 1132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Creates a new dex buffer defining no classes. 1162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Dex() { 1182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.data = new byte[0]; 1192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Creates a new dex buffer that reads from {@code data}. It is an error to 1232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * modify {@code data} after using it to create a dex buffer. 1242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Dex(byte[] data) throws IOException { 1262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.data = data; 1272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.length = data.length; 1282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.tableOfContents.readFrom(this); 1292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Creates a new dex buffer of the dex in {@code in}, and closes {@code in}. 1332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Dex(InputStream in) throws IOException { 1352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson loadFrom(in); 1362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Creates a new dex buffer from the dex file {@code file}. 1402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Dex(File file) throws IOException { 1422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (FileUtils.hasArchiveSuffix(file.getName())) { 1432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ZipFile zipFile = new ZipFile(file); 1442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ZipEntry entry = zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME); 1452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (entry != null) { 1462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson loadFrom(zipFile.getInputStream(entry)); 1472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson zipFile.close(); 1482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } else { 1492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException("Expected " + DexFormat.DEX_IN_JAR_NAME + " in " + file); 1502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } else if (file.getName().endsWith(".dex")) { 1522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson loadFrom(new FileInputStream(file)); 1532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } else { 1542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException("unknown output extension: " + file); 1552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 158c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom /** 159c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom * Creates a new dex from the contents of {@code bytes}. This API supports 160c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom * both {@code .dex} and {@code .odex} input. 161c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom */ 162c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom public static Dex create(ByteBuffer bytes) throws IOException { 163c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom // if it's an .odex file, set position and limit to the .dex section 164c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom if (bytes.get(0) == 'd' 165c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom && bytes.get(1) == 'e' 166c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom && bytes.get(2) == 'y' 167c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom && bytes.get(3) == '\n') { 168c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom bytes.position(8); 169c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom bytes.order(ByteOrder.nativeOrder()); 170c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom int offset = bytes.getInt(); 171c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom int length = bytes.getInt(); 172c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom bytes.position(offset); 173c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom bytes.limit(offset + length); 174c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom } 175c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom 176c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom // TODO: don't copy the bytes; use the ByteBuffer directly 177c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom byte[] data = new byte[bytes.remaining()]; 178c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom bytes.get(data); 179c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom return new Dex(data); 180c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom } 181c69e85bfb7ddd6c4b0023ca29eeb0416087f9a8bBrian Carlstrom 1822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private void loadFrom(InputStream in) throws IOException { 1832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 1842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson byte[] buffer = new byte[8192]; 1852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int count; 1872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson while ((count = in.read(buffer)) != -1) { 1882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson bytesOut.write(buffer, 0, count); 1892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson in.close(); 1912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.data = bytesOut.toByteArray(); 1932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.length = data.length; 1942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.tableOfContents.readFrom(this); 1952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private static void checkBounds(int index, int length) { 1982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (index < 0 || index >= length) { 1992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new IndexOutOfBoundsException("index:" + index + ", length=" + length); 2002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeTo(OutputStream out) throws IOException { 2042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.write(data); 2052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeTo(File dexOut) throws IOException { 2082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson OutputStream out = new FileOutputStream(dexOut); 2092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeTo(out); 2102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.close(); 2112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public TableOfContents getTableOfContents() { 2142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return tableOfContents; 2152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Section open(int position) { 2182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (position < 0 || position > length) { 2192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new IllegalArgumentException("position=" + position + " length=" + length); 2202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new Section(position); 2222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Section appendSection(int maxByteCount, String name) { 2252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int limit = fourByteAlign(length + maxByteCount); 2262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson Section result = new Section(name, length, limit); 2272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson length = limit; 2282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 2292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void noMoreSections() { 2322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data = new byte[length]; 2332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int getLength() { 2362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return length; 2372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private static int fourByteAlign(int position) { 2402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return (position + 3) & ~3; 2412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public byte[] getBytes() { 2442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return data; 2452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public List<String> strings() { 2482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return strings; 2492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public List<Integer> typeIds() { 2522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return typeIds; 2532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public List<String> typeNames() { 2562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return typeNames; 2572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public List<ProtoId> protoIds() { 2602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return protoIds; 2612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public List<FieldId> fieldIds() { 2642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return fieldIds; 2652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public List<MethodId> methodIds() { 2682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return methodIds; 2692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Iterable<ClassDef> classDefs() { 2722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new Iterable<ClassDef>() { 2732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Iterator<ClassDef> iterator() { 2742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (!tableOfContents.classDefs.exists()) { 2752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return Collections.<ClassDef>emptySet().iterator(); 2762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new Iterator<ClassDef>() { 2782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private Dex.Section in = open(tableOfContents.classDefs.off); 2792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private int count = 0; 2802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public boolean hasNext() { 2822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return count < tableOfContents.classDefs.size; 2832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public ClassDef next() { 2852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (!hasNext()) { 2862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new NoSuchElementException(); 2872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson count++; 2892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return in.readClassDef(); 2902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void remove() { 2922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new UnsupportedOperationException(); 2932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 2952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson }; 2972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 2982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 2992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public TypeList readTypeList(int offset) { 3002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (offset == 0) { 3012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return TypeList.EMPTY; 3022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(offset).readTypeList(); 3042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public ClassData readClassData(ClassDef classDef) { 3072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int offset = classDef.getClassDataOffset(); 3082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (offset == 0) { 3092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new IllegalArgumentException("offset == 0"); 3102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(offset).readClassData(); 3122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Code readCode(ClassData.Method method) { 3152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int offset = method.getCodeOffset(); 3162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (offset == 0) { 3172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new IllegalArgumentException("offset == 0"); 3182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return open(offset).readCode(); 3202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public final class Section implements ByteInput, ByteOutput { 3232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final String name; 3242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private int position; 3252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private final int limit; 3262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private Section(String name, int position, int limit) { 3282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.name = name; 3292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.position = position; 3302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this.limit = limit; 3312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private Section(int position) { 3342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson this("section", position, data.length); 3352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int getPosition() { 3382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return position; 3392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int readInt() { 3422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int result = (data[position] & 0xff) 3432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson | (data[position + 1] & 0xff) << 8 3442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson | (data[position + 2] & 0xff) << 16 3452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson | (data[position + 3] & 0xff) << 24; 3462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position += 4; 3472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 3482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public short readShort() { 3512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int result = (data[position] & 0xff) 3522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson | (data[position + 1] & 0xff) << 8; 3532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position += 2; 3542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return (short) result; 3552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int readUnsignedShort() { 3582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return readShort() & 0xffff; 3592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public byte readByte() { 3622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return (byte) (data[position++] & 0xff); 3632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public byte[] readByteArray(int length) { 3662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson byte[] result = Arrays.copyOfRange(data, position, position + length); 3672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position += length; 3682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 3692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public short[] readShortArray(int length) { 3722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson short[] result = new short[length]; 3732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < length; i++) { 3742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result[i] = readShort(); 3752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 3772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int readUleb128() { 3802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return Leb128.readUnsignedLeb128(this); 3812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int readSleb128() { 3842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return Leb128.readSignedLeb128(this); 3852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public TypeList readTypeList() { 3882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int size = readInt(); 3892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson short[] types = new short[size]; 3902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < size; i++) { 3912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson types[i] = readShort(); 3922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson alignToFourBytes(); 3942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new TypeList(Dex.this, types); 3952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 3962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 3972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public String readString() { 3982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int offset = readInt(); 3992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int savedPosition = position; 4002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position = offset; 4012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson try { 4022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int expectedLength = readUleb128(); 4032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson String result = Mutf8.decode(this, new char[expectedLength]); 4042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (result.length() != expectedLength) { 4052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException("Declared length " + expectedLength 4062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson + " doesn't match decoded length of " + result.length()); 4072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 4092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } catch (UTFDataFormatException e) { 4102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException(e); 4112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } finally { 4122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position = savedPosition; 4132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public FieldId readFieldId() { 4172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int declaringClassIndex = readUnsignedShort(); 4182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int typeIndex = readUnsignedShort(); 4192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int nameIndex = readInt(); 4202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new FieldId(Dex.this, declaringClassIndex, typeIndex, nameIndex); 4212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public MethodId readMethodId() { 4242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int declaringClassIndex = readUnsignedShort(); 4252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int protoIndex = readUnsignedShort(); 4262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int nameIndex = readInt(); 4272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new MethodId(Dex.this, declaringClassIndex, protoIndex, nameIndex); 4282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public ProtoId readProtoId() { 4312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int shortyIndex = readInt(); 4322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int returnTypeIndex = readInt(); 4332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int parametersOffset = readInt(); 4342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new ProtoId(Dex.this, shortyIndex, returnTypeIndex, parametersOffset); 4352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public ClassDef readClassDef() { 4382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int offset = getPosition(); 4392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int type = readInt(); 4402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int accessFlags = readInt(); 4412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int supertype = readInt(); 4422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int interfacesOffset = readInt(); 4432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int sourceFileIndex = readInt(); 4442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int annotationsOffset = readInt(); 4452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int classDataOffset = readInt(); 4462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int staticValuesOffset = readInt(); 4472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new ClassDef(Dex.this, offset, type, accessFlags, supertype, 4482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson interfacesOffset, sourceFileIndex, annotationsOffset, classDataOffset, 4492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson staticValuesOffset); 4502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private Code readCode() { 4532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int registersSize = readUnsignedShort(); 4542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int insSize = readUnsignedShort(); 4552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int outsSize = readUnsignedShort(); 4562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int triesSize = readUnsignedShort(); 4572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int debugInfoOffset = readInt(); 4582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int instructionsSize = readInt(); 4592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson short[] instructions = readShortArray(instructionsSize); 4602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson Code.Try[] tries = new Code.Try[triesSize]; 4612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson Code.CatchHandler[] catchHandlers = new Code.CatchHandler[0]; 4622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (triesSize > 0) { 4632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (instructions.length % 2 == 1) { 4642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson readShort(); // padding 4652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < triesSize; i++) { 4682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int startAddress = readInt(); 4692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int instructionCount = readUnsignedShort(); 4702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int handlerOffset = readUnsignedShort(); 4712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson tries[i] = new Code.Try(startAddress, instructionCount, handlerOffset); 4722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int catchHandlersSize = readUleb128(); 4752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson catchHandlers = new Code.CatchHandler[catchHandlersSize]; 4762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < catchHandlersSize; i++) { 4772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson catchHandlers[i] = readCatchHandler(); 4782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions, 4812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson tries, catchHandlers); 4822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private Code.CatchHandler readCatchHandler() { 4852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int size = readSleb128(); 4862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int handlersCount = Math.abs(size); 4872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int[] typeIndexes = new int[handlersCount]; 4882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int[] addresses = new int[handlersCount]; 4892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < handlersCount; i++) { 4902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson typeIndexes[i] = readUleb128(); 4912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson addresses[i] = readUleb128(); 4922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int catchAllAddress = size <= 0 ? readUleb128() : -1; 4942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new Code.CatchHandler(typeIndexes, addresses, catchAllAddress); 4952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 4962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 4972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private ClassData readClassData() { 4982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int staticFieldsSize = readUleb128(); 4992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int instanceFieldsSize = readUleb128(); 5002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int directMethodsSize = readUleb128(); 5012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int virtualMethodsSize = readUleb128(); 5022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ClassData.Field[] staticFields = readFields(staticFieldsSize); 5032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ClassData.Field[] instanceFields = readFields(instanceFieldsSize); 5042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ClassData.Method[] directMethods = readMethods(directMethodsSize); 5052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ClassData.Method[] virtualMethods = readMethods(virtualMethodsSize); 5062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new ClassData(staticFields, instanceFields, directMethods, virtualMethods); 5072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private ClassData.Field[] readFields(int count) { 5102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ClassData.Field[] result = new ClassData.Field[count]; 5112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int fieldIndex = 0; 5122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < count; i++) { 5132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson fieldIndex += readUleb128(); // field index diff 5142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int accessFlags = readUleb128(); 5152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result[i] = new ClassData.Field(fieldIndex, accessFlags); 5162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 5182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private ClassData.Method[] readMethods(int count) { 5212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ClassData.Method[] result = new ClassData.Method[count]; 5222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int methodIndex = 0; 5232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = 0; i < count; i++) { 5242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson methodIndex += readUleb128(); // method index diff 5252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int accessFlags = readUleb128(); 5262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int codeOff = readUleb128(); 5272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result[i] = new ClassData.Method(methodIndex, accessFlags, codeOff); 5282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 5302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public Annotation readAnnotation() { 5332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson byte visibility = readByte(); 5342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int start = position; 5352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson new EncodedValueReader(this, EncodedValueReader.ENCODED_ANNOTATION).skipValue(); 5362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int end = position; 5372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new Annotation(Dex.this, visibility, 5382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson new EncodedValue(Arrays.copyOfRange(data, start, end))); 5392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public EncodedValue readEncodedArray() { 5422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int start = position; 5432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson new EncodedValueReader(this, EncodedValueReader.ENCODED_ARRAY).skipValue(); 5442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int end = position; 5452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return new EncodedValue(Arrays.copyOfRange(data, start, end)); 5462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private void ensureCapacity(int size) { 5492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (position + size > limit) { 5502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException("Section limit " + limit + " exceeded by " + name); 5512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 5552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Writes 0x00 until the position is aligned to a multiple of 4. 5562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 5572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void alignToFourBytes() { 5582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int unalignedCount = position; 5592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position = Dex.fourByteAlign(position); 5602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = unalignedCount; i < position; i++) { 5612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[i] = 0; 5622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void assertFourByteAligned() { 5662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if ((position & 3) != 0) { 5672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new IllegalStateException("Not four byte aligned!"); 5682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void write(byte[] bytes) { 5722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ensureCapacity(bytes.length); 5732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson System.arraycopy(bytes, 0, data, position, bytes.length); 5742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position += bytes.length; 5752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeByte(int b) { 5782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ensureCapacity(1); 5792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position++] = (byte) b; 5802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeShort(short i) { 5832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ensureCapacity(2); 5842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position ] = (byte) i; 5852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position + 1] = (byte) (i >>> 8); 5862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position += 2; 5872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeUnsignedShort(int i) { 5902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson short s = (short) i; 5912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (i != (s & 0xffff)) { 5922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new IllegalArgumentException("Expected an unsigned short: " + i); 5932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeShort(s); 5952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 5962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 5972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void write(short[] shorts) { 5982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (short s : shorts) { 5992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeShort(s); 6002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 6032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeInt(int i) { 6042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ensureCapacity(4); 6052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position ] = (byte) i; 6062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position + 1] = (byte) (i >>> 8); 6072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position + 2] = (byte) (i >>> 16); 6082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson data[position + 3] = (byte) (i >>> 24); 6092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson position += 4; 6102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 6122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeUleb128(int i) { 6132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson try { 6142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson Leb128.writeUnsignedLeb128(this, i); 6152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ensureCapacity(0); 6162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } catch (ArrayIndexOutOfBoundsException e) { 6172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException("Section limit " + limit + " exceeded by " + name); 6182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 6212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeSleb128(int i) { 6222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson try { 6232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson Leb128.writeSignedLeb128(this, i); 6242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson ensureCapacity(0); 6252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } catch (ArrayIndexOutOfBoundsException e) { 6262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new DexException("Section limit " + limit + " exceeded by " + name); 6272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 6302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeStringData(String value) { 6312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson try { 6322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int length = value.length(); 6332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeUleb128(length); 6342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson write(Mutf8.encode(value)); 6352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeByte(0); 6362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } catch (UTFDataFormatException e) { 6372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson throw new AssertionError(); 6382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 6412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public void writeTypeList(TypeList typeList) { 6422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson short[] types = typeList.getTypes(); 6432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeInt(types.length); 6442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (short type : types) { 6452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson writeShort(type); 6462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson alignToFourBytes(); 6482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 6502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 6512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Returns the number of bytes remaining in this section. 6522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 6532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public int remaining() { 6542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return limit - position; 6552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 6572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson} 658