diff options
author | Jesse Wilson <jessewilson@google.com> | 2011-09-18 12:53:38 -0400 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2013-04-30 10:44:41 -0700 |
commit | 0bbbba1aae8549e40b6e464db54d22769fa522fd (patch) | |
tree | 4c577ceea9255dca7853ebebd82bdd180757254c /dx | |
parent | fe107fb6e3f308ac5174ebdc5a794ee880c741d9 (diff) | |
download | android_dalvik-0bbbba1aae8549e40b6e464db54d22769fa522fd.tar.gz android_dalvik-0bbbba1aae8549e40b6e464db54d22769fa522fd.tar.bz2 android_dalvik-0bbbba1aae8549e40b6e464db54d22769fa522fd.zip |
Move dex utilities from dalvik/dx to libcore/dex
Change-Id: If0022a069ba3ac51ae5cdc4b0eabb6b913cd8afe
(cherry picked from commit 7b13a4d41243f81fe80a76e2ff2f877b53610446)
Conflicts:
dx/src/com/android/dex/Code.java
dx/src/com/android/dex/Dex.java
dx/src/com/android/dex/SizeOf.java
dx/src/com/android/dex/TableOfContents.java
Diffstat (limited to 'dx')
26 files changed, 1 insertions, 3134 deletions
diff --git a/dx/junit-tests/com/android/dex/EncodedValueReaderTest.java b/dx/junit-tests/com/android/dex/EncodedValueReaderTest.java deleted file mode 100644 index a4ca37672..000000000 --- a/dx/junit-tests/com/android/dex/EncodedValueReaderTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ByteArrayByteInput; -import junit.framework.TestCase; - -public final class EncodedValueReaderTest extends TestCase { - - public void testReadByte() { - assertEquals((byte) 0x80, readerOf(0, 0x80).readByte()); - assertEquals((byte) 0xff, readerOf(0, 0xff).readByte()); - assertEquals((byte) 0x00, readerOf(0, 0x00).readByte()); - assertEquals((byte) 0x01, readerOf(0, 0x01).readByte()); - assertEquals((byte) 0x7f, readerOf(0, 0x7f).readByte()); - } - - public void testReadShort() { - assertEquals((short) 0x8000, readerOf(34, 0x00, 0x80).readShort()); - assertEquals((short) 0, readerOf( 2, 0x00).readShort()); - assertEquals((short) 0xab, readerOf(34, 0xab, 0x00).readShort()); - assertEquals((short) 0xabcd, readerOf(34, 0xcd, 0xab).readShort()); - assertEquals((short) 0x7FFF, readerOf(34, 0xff, 0x7f).readShort()); - } - - public void testReadInt() { - assertEquals(0x80000000, readerOf(100, 0x00, 0x00, 0x00, 0x80).readInt()); - assertEquals( 0x00, readerOf( 4, 0x00).readInt()); - assertEquals( 0xab, readerOf( 36, 0xab, 0x00).readInt()); - assertEquals( 0xabcd, readerOf( 68, 0xcd, 0xab, 0x00).readInt()); - assertEquals( 0xabcdef, readerOf(100, 0xef, 0xcd, 0xab, 0x00).readInt()); - assertEquals(0xabcdef01, readerOf(100, 0x01, 0xef, 0xcd, 0xab).readInt()); - assertEquals(0x7fffffff, readerOf(100, 0xff, 0xff, 0xff, 127).readInt()); - } - - public void testReadLong() { - assertEquals(0x8000000000000000L, readerOf( -26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80).readLong()); - assertEquals( 0x00L, readerOf( 6, 0x00).readLong()); - assertEquals( 0xabL, readerOf( 38, 0xab, 0x00).readLong()); - assertEquals( 0xabcdL, readerOf( 70, 0xcd, 0xab, 0x00).readLong()); - assertEquals( 0xabcdefL, readerOf( 102, 0xef, 0xcd, 0xab, 0x00).readLong()); - assertEquals( 0xabcdef01L, readerOf(-122, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong()); - assertEquals( 0xabcdef0123L, readerOf( -90, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong()); - assertEquals( 0xabcdef012345L, readerOf( -58, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong()); - assertEquals( 0xabcdef01234567L, readerOf( -26, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong()); - assertEquals(0xabcdef0123456789L, readerOf( -26, 0x89, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab).readLong()); - assertEquals(0x7fffffffffffffffL, readerOf( -26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f).readLong()); - } - - public void testReadFloat() { - assertEquals(Float.NEGATIVE_INFINITY, readerOf(48, -128, -1).readFloat()); - assertEquals(Float.POSITIVE_INFINITY, readerOf(48, -128, 127).readFloat()); - assertEquals(Float.NaN, readerOf(48, -64, 127).readFloat()); - assertEquals(-0.0f, readerOf(16, -128).readFloat()); - assertEquals(0.0f, readerOf(16, 0).readFloat()); - assertEquals(0.5f, readerOf(16, 63).readFloat()); - assertEquals(1f, readerOf(48, -128, 63).readFloat()); - assertEquals(1.0E06f, readerOf(80, 36, 116, 73).readFloat()); - assertEquals(1.0E12f, readerOf(112, -91, -44, 104, 83).readFloat()); - } - - public void testReadDouble() { - assertEquals(Double.NEGATIVE_INFINITY, readerOf(49, -16, -1).readDouble()); - assertEquals(Double.POSITIVE_INFINITY, readerOf(49, -16, 127).readDouble()); - assertEquals(Double.NaN, readerOf(49, -8, 127).readDouble()); - assertEquals(-0.0, readerOf(17, -128).readDouble()); - assertEquals(0.0, readerOf(17, 0).readDouble()); - assertEquals(0.5, readerOf(49, -32, 63).readDouble()); - assertEquals(1.0, readerOf(49, -16, 63).readDouble()); - assertEquals(1.0E06, readerOf(113, -128, -124, 46, 65).readDouble()); - assertEquals(1.0E12, readerOf(-111, -94, -108, 26, 109, 66).readDouble()); - assertEquals(1.0E24, readerOf(-15, -76, -99, -39, 121, 67, 120, -22, 68).readDouble()); - } - - public void testReadChar() { - assertEquals('\u0000', readerOf( 3, 0x00).readChar()); - assertEquals('\u00ab', readerOf( 3, 0xab).readChar()); - assertEquals('\uabcd', readerOf(35, 0xcd, 0xab).readChar()); - assertEquals('\uffff', readerOf(35, 0xff, 0xff).readChar()); - } - - public void testReadBoolean() { - assertEquals(true, readerOf(63).readBoolean()); - assertEquals(false, readerOf(31).readBoolean()); - } - - public void testReadNull() { - readerOf(30).readNull(); - } - - public void testReadReference() { - assertEquals( 0xab, readerOf(0x17, 0xab).readString()); - assertEquals( 0xabcd, readerOf(0x37, 0xcd, 0xab).readString()); - assertEquals( 0xabcdef, readerOf(0x57, 0xef, 0xcd, 0xab).readString()); - assertEquals(0xabcdef01, readerOf(0x77, 0x01, 0xef, 0xcd, 0xab).readString()); - } - - public void testReadWrongType() { - try { - readerOf(0x17, 0xab).readField(); - fail(); - } catch (IllegalStateException expected) { - } - } - - private EncodedValueReader readerOf(int... bytes) { - byte[] data = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) { - data[i] = (byte) bytes[i]; - } - return new EncodedValueReader(new ByteArrayByteInput(data)); - } -} diff --git a/dx/src/Android.mk b/dx/src/Android.mk index 80d1b8541..678397f78 100644 --- a/dx/src/Android.mk +++ b/dx/src/Android.mk @@ -10,6 +10,7 @@ ifeq ($(TARGET_BUILD_APPS),) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_SRC_FILES += $(call all-java-files-under,../../../libcore/dex/src/main/java) LOCAL_JAR_MANIFEST := ../etc/manifest.txt LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= dx diff --git a/dx/src/com/android/dex/Annotation.java b/dx/src/com/android/dex/Annotation.java deleted file mode 100644 index e5ef9783b..000000000 --- a/dx/src/com/android/dex/Annotation.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import static com.android.dex.EncodedValueReader.ENCODED_ANNOTATION; - -/** - * An annotation. - */ -public final class Annotation implements Comparable<Annotation> { - private final Dex dex; - private final byte visibility; - private final EncodedValue encodedAnnotation; - - public Annotation(Dex dex, byte visibility, EncodedValue encodedAnnotation) { - this.dex = dex; - this.visibility = visibility; - this.encodedAnnotation = encodedAnnotation; - } - - public byte getVisibility() { - return visibility; - } - - public EncodedValueReader getReader() { - return new EncodedValueReader(encodedAnnotation, ENCODED_ANNOTATION); - } - - public int getTypeIndex() { - EncodedValueReader reader = getReader(); - reader.readAnnotation(); - return reader.getAnnotationType(); - } - - public void writeTo(Dex.Section out) { - out.writeByte(visibility); - encodedAnnotation.writeTo(out); - } - - @Override public int compareTo(Annotation other) { - return encodedAnnotation.compareTo(other.encodedAnnotation); - } - - @Override public String toString() { - return dex == null - ? visibility + " " + getTypeIndex() - : visibility + " " + dex.typeNames().get(getTypeIndex()); - } -} diff --git a/dx/src/com/android/dex/ClassData.java b/dx/src/com/android/dex/ClassData.java deleted file mode 100644 index 840756c5b..000000000 --- a/dx/src/com/android/dex/ClassData.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -public final class ClassData { - private final Field[] staticFields; - private final Field[] instanceFields; - private final Method[] directMethods; - private final Method[] virtualMethods; - - public ClassData(Field[] staticFields, Field[] instanceFields, - Method[] directMethods, Method[] virtualMethods) { - this.staticFields = staticFields; - this.instanceFields = instanceFields; - this.directMethods = directMethods; - this.virtualMethods = virtualMethods; - } - - public Field[] getStaticFields() { - return staticFields; - } - - public Field[] getInstanceFields() { - return instanceFields; - } - - public Method[] getDirectMethods() { - return directMethods; - } - - public Method[] getVirtualMethods() { - return virtualMethods; - } - - public Field[] allFields() { - Field[] result = new Field[staticFields.length + instanceFields.length]; - System.arraycopy(staticFields, 0, result, 0, staticFields.length); - System.arraycopy(instanceFields, 0, result, staticFields.length, instanceFields.length); - return result; - } - - public Method[] allMethods() { - Method[] result = new Method[directMethods.length + virtualMethods.length]; - System.arraycopy(directMethods, 0, result, 0, directMethods.length); - System.arraycopy(virtualMethods, 0, result, directMethods.length, virtualMethods.length); - return result; - } - - public static class Field { - private final int fieldIndex; - private final int accessFlags; - - public Field(int fieldIndex, int accessFlags) { - this.fieldIndex = fieldIndex; - this.accessFlags = accessFlags; - } - - public int getFieldIndex() { - return fieldIndex; - } - - public int getAccessFlags() { - return accessFlags; - } - } - - public static class Method { - private final int methodIndex; - private final int accessFlags; - private final int codeOffset; - - public Method(int methodIndex, int accessFlags, int codeOffset) { - this.methodIndex = methodIndex; - this.accessFlags = accessFlags; - this.codeOffset = codeOffset; - } - - public int getMethodIndex() { - return methodIndex; - } - - public int getAccessFlags() { - return accessFlags; - } - - public int getCodeOffset() { - return codeOffset; - } - } -} diff --git a/dx/src/com/android/dex/ClassDef.java b/dx/src/com/android/dex/ClassDef.java deleted file mode 100644 index b3225ec0e..000000000 --- a/dx/src/com/android/dex/ClassDef.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -/** - * A type definition. - */ -public final class ClassDef { - public static final int NO_INDEX = -1; - private final Dex buffer; - private final int offset; - private final int typeIndex; - private final int accessFlags; - private final int supertypeIndex; - private final int interfacesOffset; - private final int sourceFileIndex; - private final int annotationsOffset; - private final int classDataOffset; - private final int staticValuesOffset; - - public ClassDef(Dex buffer, int offset, int typeIndex, int accessFlags, - int supertypeIndex, int interfacesOffset, int sourceFileIndex, - int annotationsOffset, int classDataOffset, int staticValuesOffset) { - this.buffer = buffer; - this.offset = offset; - this.typeIndex = typeIndex; - this.accessFlags = accessFlags; - this.supertypeIndex = supertypeIndex; - this.interfacesOffset = interfacesOffset; - this.sourceFileIndex = sourceFileIndex; - this.annotationsOffset = annotationsOffset; - this.classDataOffset = classDataOffset; - this.staticValuesOffset = staticValuesOffset; - } - - public int getOffset() { - return offset; - } - - public int getTypeIndex() { - return typeIndex; - } - - public int getSupertypeIndex() { - return supertypeIndex; - } - - public int getInterfacesOffset() { - return interfacesOffset; - } - - public short[] getInterfaces() { - return buffer.readTypeList(interfacesOffset).getTypes(); - } - - public int getAccessFlags() { - return accessFlags; - } - - public int getSourceFileIndex() { - return sourceFileIndex; - } - - public int getAnnotationsOffset() { - return annotationsOffset; - } - - public int getClassDataOffset() { - return classDataOffset; - } - - public int getStaticValuesOffset() { - return staticValuesOffset; - } - - @Override public String toString() { - if (buffer == null) { - return typeIndex + " " + supertypeIndex; - } - - StringBuilder result = new StringBuilder(); - result.append(buffer.typeNames().get(typeIndex)); - if (supertypeIndex != NO_INDEX) { - result.append(" extends ").append(buffer.typeNames().get(supertypeIndex)); - } - return result.toString(); - } -} diff --git a/dx/src/com/android/dex/Code.java b/dx/src/com/android/dex/Code.java deleted file mode 100644 index 9258af795..000000000 --- a/dx/src/com/android/dex/Code.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -public final class Code { - private final int registersSize; - private final int insSize; - private final int outsSize; - private final int debugInfoOffset; - private final short[] instructions; - private final Try[] tries; - private final CatchHandler[] catchHandlers; - - public Code(int registersSize, int insSize, int outsSize, int debugInfoOffset, - short[] instructions, Try[] tries, CatchHandler[] catchHandlers) { - this.registersSize = registersSize; - this.insSize = insSize; - this.outsSize = outsSize; - this.debugInfoOffset = debugInfoOffset; - this.instructions = instructions; - this.tries = tries; - this.catchHandlers = catchHandlers; - } - - public int getRegistersSize() { - return registersSize; - } - - public int getInsSize() { - return insSize; - } - - public int getOutsSize() { - return outsSize; - } - - public int getDebugInfoOffset() { - return debugInfoOffset; - } - - public short[] getInstructions() { - return instructions; - } - - public Try[] getTries() { - return tries; - } - - public CatchHandler[] getCatchHandlers() { - return catchHandlers; - } - - public static class Try { - final int startAddress; - final int instructionCount; - final int catchHandlerIndex; - - Try(int startAddress, int instructionCount, int catchHandlerIndex) { - this.startAddress = startAddress; - this.instructionCount = instructionCount; - this.catchHandlerIndex = catchHandlerIndex; - } - - public int getStartAddress() { - return startAddress; - } - - public int getInstructionCount() { - return instructionCount; - } - - /** - * Returns this try's catch handler <strong>index</strong>. Note that - * this is distinct from the its catch handler <strong>offset</strong>. - */ - public int getCatchHandlerIndex() { - return catchHandlerIndex; - } - } - - public static class CatchHandler { - final int[] typeIndexes; - final int[] addresses; - final int catchAllAddress; - final int offset; - - public CatchHandler(int[] typeIndexes, int[] addresses, int catchAllAddress, int offset) { - this.typeIndexes = typeIndexes; - this.addresses = addresses; - this.catchAllAddress = catchAllAddress; - this.offset = offset; - } - - public int[] getTypeIndexes() { - return typeIndexes; - } - - public int[] getAddresses() { - return addresses; - } - - public int getCatchAllAddress() { - return catchAllAddress; - } - - public int getOffset() { - return offset; - } - } -} diff --git a/dx/src/com/android/dex/Dex.java b/dx/src/com/android/dex/Dex.java deleted file mode 100644 index 2395e50fa..000000000 --- a/dx/src/com/android/dex/Dex.java +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.Code.CatchHandler; -import com.android.dex.Code.Try; -import com.android.dex.util.ByteInput; -import com.android.dex.util.ByteOutput; -import com.android.dex.util.FileUtils; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UTFDataFormatException; -import java.util.AbstractList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * The bytes of a dex file in memory for reading and writing. All int offsets - * are unsigned. - */ -public final class Dex { - private byte[] data; - private final TableOfContents tableOfContents = new TableOfContents(); - private int length = 0; - - private final List<String> strings = new AbstractList<String>() { - @Override public String get(int index) { - checkBounds(index, tableOfContents.stringIds.size); - return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM)) - .readString(); - } - @Override public int size() { - return tableOfContents.stringIds.size; - } - }; - - private final List<Integer> typeIds = new AbstractList<Integer>() { - @Override public Integer get(int index) { - checkBounds(index, tableOfContents.typeIds.size); - return open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt(); - } - @Override public int size() { - return tableOfContents.typeIds.size; - } - }; - - private final List<String> typeNames = new AbstractList<String>() { - @Override public String get(int index) { - checkBounds(index, tableOfContents.typeIds.size); - return strings.get(typeIds.get(index)); - } - @Override public int size() { - return tableOfContents.typeIds.size; - } - }; - - private final List<ProtoId> protoIds = new AbstractList<ProtoId>() { - @Override public ProtoId get(int index) { - checkBounds(index, tableOfContents.protoIds.size); - return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index)) - .readProtoId(); - } - @Override public int size() { - return tableOfContents.protoIds.size; - } - }; - - private final List<FieldId> fieldIds = new AbstractList<FieldId>() { - @Override public FieldId get(int index) { - checkBounds(index, tableOfContents.fieldIds.size); - return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index)) - .readFieldId(); - } - @Override public int size() { - return tableOfContents.fieldIds.size; - } - }; - - private final List<MethodId> methodIds = new AbstractList<MethodId>() { - @Override public MethodId get(int index) { - checkBounds(index, tableOfContents.methodIds.size); - return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index)) - .readMethodId(); - } - @Override public int size() { - return tableOfContents.methodIds.size; - } - }; - - /** - * Creates a new dex buffer defining no classes. - */ - public Dex() { - this.data = new byte[0]; - } - - /** - * Creates a new dex buffer that reads from {@code data}. It is an error to - * modify {@code data} after using it to create a dex buffer. - */ - public Dex(byte[] data) throws IOException { - this.data = data; - this.length = data.length; - this.tableOfContents.readFrom(this); - } - - /** - * Creates a new dex buffer of the dex in {@code in}, and closes {@code in}. - */ - public Dex(InputStream in) throws IOException { - loadFrom(in); - } - - /** - * Creates a new dex buffer from the dex file {@code file}. - */ - public Dex(File file) throws IOException { - if (FileUtils.hasArchiveSuffix(file.getName())) { - ZipFile zipFile = new ZipFile(file); - ZipEntry entry = zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME); - if (entry != null) { - loadFrom(zipFile.getInputStream(entry)); - zipFile.close(); - } else { - throw new DexException("Expected " + DexFormat.DEX_IN_JAR_NAME + " in " + file); - } - } else if (file.getName().endsWith(".dex")) { - loadFrom(new FileInputStream(file)); - } else { - throw new DexException("unknown output extension: " + file); - } - } - - private void loadFrom(InputStream in) throws IOException { - ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); - byte[] buffer = new byte[8192]; - - int count; - while ((count = in.read(buffer)) != -1) { - bytesOut.write(buffer, 0, count); - } - in.close(); - - this.data = bytesOut.toByteArray(); - this.length = data.length; - this.tableOfContents.readFrom(this); - } - - private static void checkBounds(int index, int length) { - if (index < 0 || index >= length) { - throw new IndexOutOfBoundsException("index:" + index + ", length=" + length); - } - } - - public void writeTo(OutputStream out) throws IOException { - out.write(data); - } - - public void writeTo(File dexOut) throws IOException { - OutputStream out = new FileOutputStream(dexOut); - writeTo(out); - out.close(); - } - - public TableOfContents getTableOfContents() { - return tableOfContents; - } - - public Section open(int position) { - if (position < 0 || position > length) { - throw new IllegalArgumentException("position=" + position + " length=" + length); - } - return new Section(position); - } - - public Section appendSection(int maxByteCount, String name) { - int limit = fourByteAlign(length + maxByteCount); - Section result = new Section(name, length, limit); - length = limit; - return result; - } - - public void noMoreSections() { - data = new byte[length]; - } - - public int getLength() { - return length; - } - - public static int fourByteAlign(int position) { - return (position + 3) & ~3; - } - - public byte[] getBytes() { - return data; - } - - public List<String> strings() { - return strings; - } - - public List<Integer> typeIds() { - return typeIds; - } - - public List<String> typeNames() { - return typeNames; - } - - public List<ProtoId> protoIds() { - return protoIds; - } - - public List<FieldId> fieldIds() { - return fieldIds; - } - - public List<MethodId> methodIds() { - return methodIds; - } - - public Iterable<ClassDef> classDefs() { - return new Iterable<ClassDef>() { - public Iterator<ClassDef> iterator() { - if (!tableOfContents.classDefs.exists()) { - return Collections.<ClassDef>emptySet().iterator(); - } - return new Iterator<ClassDef>() { - private Dex.Section in = open(tableOfContents.classDefs.off); - private int count = 0; - - public boolean hasNext() { - return count < tableOfContents.classDefs.size; - } - public ClassDef next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - count++; - return in.readClassDef(); - } - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - public TypeList readTypeList(int offset) { - if (offset == 0) { - return TypeList.EMPTY; - } - return open(offset).readTypeList(); - } - - public ClassData readClassData(ClassDef classDef) { - int offset = classDef.getClassDataOffset(); - if (offset == 0) { - throw new IllegalArgumentException("offset == 0"); - } - return open(offset).readClassData(); - } - - public Code readCode(ClassData.Method method) { - int offset = method.getCodeOffset(); - if (offset == 0) { - throw new IllegalArgumentException("offset == 0"); - } - return open(offset).readCode(); - } - - public final class Section implements ByteInput, ByteOutput { - private final String name; - private int position; - private final int limit; - private final int initialPosition; - - private Section(String name, int position, int limit) { - this.name = name; - this.position = this.initialPosition = position; - this.limit = limit; - } - - private Section(int position) { - this("section", position, data.length); - } - - public int getPosition() { - return position; - } - - public int readInt() { - int result = (data[position] & 0xff) - | (data[position + 1] & 0xff) << 8 - | (data[position + 2] & 0xff) << 16 - | (data[position + 3] & 0xff) << 24; - position += 4; - return result; - } - - public short readShort() { - int result = (data[position] & 0xff) - | (data[position + 1] & 0xff) << 8; - position += 2; - return (short) result; - } - - public int readUnsignedShort() { - return readShort() & 0xffff; - } - - public byte readByte() { - return (byte) (data[position++] & 0xff); - } - - public byte[] readByteArray(int length) { - byte[] result = Arrays.copyOfRange(data, position, position + length); - position += length; - return result; - } - - public short[] readShortArray(int length) { - short[] result = new short[length]; - for (int i = 0; i < length; i++) { - result[i] = readShort(); - } - return result; - } - - public int readUleb128() { - return Leb128.readUnsignedLeb128(this); - } - - public int readUleb128p1() { - return Leb128.readUnsignedLeb128(this) - 1; - } - - public int readSleb128() { - return Leb128.readSignedLeb128(this); - } - - public TypeList readTypeList() { - int size = readInt(); - short[] types = new short[size]; - for (int i = 0; i < size; i++) { - types[i] = readShort(); - } - alignToFourBytes(); - return new TypeList(Dex.this, types); - } - - public String readString() { - int offset = readInt(); - int savedPosition = position; - position = offset; - try { - int expectedLength = readUleb128(); - String result = Mutf8.decode(this, new char[expectedLength]); - if (result.length() != expectedLength) { - throw new DexException("Declared length " + expectedLength - + " doesn't match decoded length of " + result.length()); - } - return result; - } catch (UTFDataFormatException e) { - throw new DexException(e); - } finally { - position = savedPosition; - } - } - - public FieldId readFieldId() { - int declaringClassIndex = readUnsignedShort(); - int typeIndex = readUnsignedShort(); - int nameIndex = readInt(); - return new FieldId(Dex.this, declaringClassIndex, typeIndex, nameIndex); - } - - public MethodId readMethodId() { - int declaringClassIndex = readUnsignedShort(); - int protoIndex = readUnsignedShort(); - int nameIndex = readInt(); - return new MethodId(Dex.this, declaringClassIndex, protoIndex, nameIndex); - } - - public ProtoId readProtoId() { - int shortyIndex = readInt(); - int returnTypeIndex = readInt(); - int parametersOffset = readInt(); - return new ProtoId(Dex.this, shortyIndex, returnTypeIndex, parametersOffset); - } - - public ClassDef readClassDef() { - int offset = getPosition(); - int type = readInt(); - int accessFlags = readInt(); - int supertype = readInt(); - int interfacesOffset = readInt(); - int sourceFileIndex = readInt(); - int annotationsOffset = readInt(); - int classDataOffset = readInt(); - int staticValuesOffset = readInt(); - return new ClassDef(Dex.this, offset, type, accessFlags, supertype, - interfacesOffset, sourceFileIndex, annotationsOffset, classDataOffset, - staticValuesOffset); - } - - private Code readCode() { - int registersSize = readUnsignedShort(); - int insSize = readUnsignedShort(); - int outsSize = readUnsignedShort(); - int triesSize = readUnsignedShort(); - int debugInfoOffset = readInt(); - int instructionsSize = readInt(); - short[] instructions = readShortArray(instructionsSize); - Try[] tries; - CatchHandler[] catchHandlers; - if (triesSize > 0) { - if (instructions.length % 2 == 1) { - readShort(); // padding - } - - /* - * We can't read the tries until we've read the catch handlers. - * Unfortunately they're in the opposite order in the dex file - * so we need to read them out-of-order. - */ - Section triesSection = open(position); - skip(triesSize * SizeOf.TRY_ITEM); - catchHandlers = readCatchHandlers(); - tries = triesSection.readTries(triesSize, catchHandlers); - } else { - tries = new Try[0]; - catchHandlers = new CatchHandler[0]; - } - return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions, - tries, catchHandlers); - } - - private CatchHandler[] readCatchHandlers() { - int baseOffset = position; - int catchHandlersSize = readUleb128(); - CatchHandler[] result = new CatchHandler[catchHandlersSize]; - for (int i = 0; i < catchHandlersSize; i++) { - int offset = position - baseOffset; - result[i] = readCatchHandler(offset); - } - return result; - } - - private Try[] readTries(int triesSize, CatchHandler[] catchHandlers) { - Try[] result = new Try[triesSize]; - for (int i = 0; i < triesSize; i++) { - int startAddress = readInt(); - int instructionCount = readUnsignedShort(); - int handlerOffset = readUnsignedShort(); - int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset); - result[i] = new Try(startAddress, instructionCount, catchHandlerIndex); - } - return result; - } - - private int findCatchHandlerIndex(CatchHandler[] catchHandlers, int offset) { - for (int i = 0; i < catchHandlers.length; i++) { - CatchHandler catchHandler = catchHandlers[i]; - if (catchHandler.getOffset() == offset) { - return i; - } - } - throw new IllegalArgumentException(); - } - - private CatchHandler readCatchHandler(int offset) { - int size = readSleb128(); - int handlersCount = Math.abs(size); - int[] typeIndexes = new int[handlersCount]; - int[] addresses = new int[handlersCount]; - for (int i = 0; i < handlersCount; i++) { - typeIndexes[i] = readUleb128(); - addresses[i] = readUleb128(); - } - int catchAllAddress = size <= 0 ? readUleb128() : -1; - return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset); - } - - private ClassData readClassData() { - int staticFieldsSize = readUleb128(); - int instanceFieldsSize = readUleb128(); - int directMethodsSize = readUleb128(); - int virtualMethodsSize = readUleb128(); - ClassData.Field[] staticFields = readFields(staticFieldsSize); - ClassData.Field[] instanceFields = readFields(instanceFieldsSize); - ClassData.Method[] directMethods = readMethods(directMethodsSize); - ClassData.Method[] virtualMethods = readMethods(virtualMethodsSize); - return new ClassData(staticFields, instanceFields, directMethods, virtualMethods); - } - - private ClassData.Field[] readFields(int count) { - ClassData.Field[] result = new ClassData.Field[count]; - int fieldIndex = 0; - for (int i = 0; i < count; i++) { - fieldIndex += readUleb128(); // field index diff - int accessFlags = readUleb128(); - result[i] = new ClassData.Field(fieldIndex, accessFlags); - } - return result; - } - - private ClassData.Method[] readMethods(int count) { - ClassData.Method[] result = new ClassData.Method[count]; - int methodIndex = 0; - for (int i = 0; i < count; i++) { - methodIndex += readUleb128(); // method index diff - int accessFlags = readUleb128(); - int codeOff = readUleb128(); - result[i] = new ClassData.Method(methodIndex, accessFlags, codeOff); - } - return result; - } - - public Annotation readAnnotation() { - byte visibility = readByte(); - int start = position; - new EncodedValueReader(this, EncodedValueReader.ENCODED_ANNOTATION).skipValue(); - int end = position; - return new Annotation(Dex.this, visibility, - new EncodedValue(Arrays.copyOfRange(data, start, end))); - } - - public EncodedValue readEncodedArray() { - int start = position; - new EncodedValueReader(this, EncodedValueReader.ENCODED_ARRAY).skipValue(); - int end = position; - return new EncodedValue(Arrays.copyOfRange(data, start, end)); - } - - private void ensureCapacity(int size) { - if (position + size > limit) { - throw new DexException("Section limit " + limit + " exceeded by " + name); - } - } - - public void skip(int count) { - if (count < 0) { - throw new IllegalArgumentException(); - } - ensureCapacity(count); - position += count; - } - - /** - * Writes 0x00 until the position is aligned to a multiple of 4. - */ - public void alignToFourBytes() { - int unalignedCount = position; - position = Dex.fourByteAlign(position); - for (int i = unalignedCount; i < position; i++) { - data[i] = 0; - } - } - - public void assertFourByteAligned() { - if ((position & 3) != 0) { - throw new IllegalStateException("Not four byte aligned!"); - } - } - - public void write(byte[] bytes) { - ensureCapacity(bytes.length); - System.arraycopy(bytes, 0, data, position, bytes.length); - position += bytes.length; - } - - public void writeByte(int b) { - ensureCapacity(1); - data[position++] = (byte) b; - } - - public void writeShort(short i) { - ensureCapacity(2); - data[position ] = (byte) i; - data[position + 1] = (byte) (i >>> 8); - position += 2; - } - - public void writeUnsignedShort(int i) { - short s = (short) i; - if (i != (s & 0xffff)) { - throw new IllegalArgumentException("Expected an unsigned short: " + i); - } - writeShort(s); - } - - public void write(short[] shorts) { - for (short s : shorts) { - writeShort(s); - } - } - - public void writeInt(int i) { - ensureCapacity(4); - data[position ] = (byte) i; - data[position + 1] = (byte) (i >>> 8); - data[position + 2] = (byte) (i >>> 16); - data[position + 3] = (byte) (i >>> 24); - position += 4; - } - - public void writeUleb128(int i) { - try { - Leb128.writeUnsignedLeb128(this, i); - ensureCapacity(0); - } catch (ArrayIndexOutOfBoundsException e) { - throw new DexException("Section limit " + limit + " exceeded by " + name); - } - } - - public void writeUleb128p1(int i) { - writeUleb128(i + 1); - } - - public void writeSleb128(int i) { - try { - Leb128.writeSignedLeb128(this, i); - ensureCapacity(0); - } catch (ArrayIndexOutOfBoundsException e) { - throw new DexException("Section limit " + limit + " exceeded by " + name); - } - } - - public void writeStringData(String value) { - try { - int length = value.length(); - writeUleb128(length); - write(Mutf8.encode(value)); - writeByte(0); - } catch (UTFDataFormatException e) { - throw new AssertionError(); - } - } - - public void writeTypeList(TypeList typeList) { - short[] types = typeList.getTypes(); - writeInt(types.length); - for (short type : types) { - writeShort(type); - } - alignToFourBytes(); - } - - /** - * Returns the number of bytes remaining in this section. - */ - public int remaining() { - return limit - position; - } - - /** - * Returns the number of bytes used by this section. - */ - public int used () { - return position - initialPosition; - } - } -} diff --git a/dx/src/com/android/dex/DexException.java b/dx/src/com/android/dex/DexException.java deleted file mode 100644 index a30a46f78..000000000 --- a/dx/src/com/android/dex/DexException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ExceptionWithContext; - -/** - * Thrown when there's a format problem reading, writing, or generally - * processing a dex file. - */ -public final class DexException extends ExceptionWithContext { - public DexException(String message) { - super(message); - } - - public DexException(Throwable cause) { - super(cause); - } -} diff --git a/dx/src/com/android/dex/DexFormat.java b/dx/src/com/android/dex/DexFormat.java deleted file mode 100644 index 85941fd46..000000000 --- a/dx/src/com/android/dex/DexFormat.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -/** - * Constants that show up in and are otherwise related to {@code .dex} - * files, and helper methods for same. - */ -public final class DexFormat { - private DexFormat() {} - - /** - * API level to target in order to produce the most modern file - * format - */ - public static final int API_CURRENT = 14; - - /** API level to target in order to suppress extended opcode usage */ - public static final int API_NO_EXTENDED_OPCODES = 13; - - /** - * file name of the primary {@code .dex} file inside an - * application or library {@code .jar} file - */ - public static final String DEX_IN_JAR_NAME = "classes.dex"; - - /** common prefix for all dex file "magic numbers" */ - public static final String MAGIC_PREFIX = "dex\n"; - - /** common suffix for all dex file "magic numbers" */ - public static final String MAGIC_SUFFIX = "\0"; - - /** dex file version number for the current format variant */ - public static final String VERSION_CURRENT = "036"; - - /** dex file version number for API level 13 and earlier */ - public static final String VERSION_FOR_API_13 = "035"; - - /** - * value used to indicate endianness of file contents - */ - public static final int ENDIAN_TAG = 0x12345678; - - /** - * Returns the API level corresponding to the given magic number, - * or {@code -1} if the given array is not a well-formed dex file - * magic number. - */ - public static int magicToApi(byte[] magic) { - if (magic.length != 8) { - return -1; - } - - if ((magic[0] != 'd') || (magic[1] != 'e') || (magic[2] != 'x') || (magic[3] != '\n') || - (magic[7] != '\0')) { - return -1; - } - - String version = "" + ((char) magic[4]) + ((char) magic[5]) +((char) magic[6]); - - if (version.equals(VERSION_CURRENT)) { - return API_CURRENT; - } else if (version.equals(VERSION_FOR_API_13)) { - return 13; - } - - return -1; - } - - /** - * Returns the magic number corresponding to the given target API level. - */ - public static String apiToMagic(int targetApiLevel) { - String version; - - if (targetApiLevel >= API_CURRENT) { - version = VERSION_CURRENT; - } else { - version = VERSION_FOR_API_13; - } - - return MAGIC_PREFIX + version + MAGIC_SUFFIX; - } -} diff --git a/dx/src/com/android/dex/EncodedValue.java b/dx/src/com/android/dex/EncodedValue.java deleted file mode 100644 index 8d0c3adcf..000000000 --- a/dx/src/com/android/dex/EncodedValue.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ByteArrayByteInput; -import com.android.dex.util.ByteInput; - -/** - * An encoded value or array. - */ -public final class EncodedValue implements Comparable<EncodedValue> { - private final byte[] data; - - public EncodedValue(byte[] data) { - this.data = data; - } - - public ByteInput asByteInput() { - return new ByteArrayByteInput(data); - } - - public byte[] getBytes() { - return data; - } - - public void writeTo(Dex.Section out) { - out.write(data); - } - - @Override public int compareTo(EncodedValue other) { - int size = Math.min(data.length, other.data.length); - for (int i = 0; i < size; i++) { - if (data[i] != other.data[i]) { - return (data[i] & 0xff) - (other.data[i] & 0xff); - } - } - return data.length - other.data.length; - } - - @Override public String toString() { - return Integer.toHexString(data[0] & 0xff) + "...(" + data.length + ")"; - } -} diff --git a/dx/src/com/android/dex/EncodedValueCodec.java b/dx/src/com/android/dex/EncodedValueCodec.java deleted file mode 100644 index 7fc172434..000000000 --- a/dx/src/com/android/dex/EncodedValueCodec.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ByteInput; -import com.android.dex.util.ByteOutput; - -/** - * Read and write {@code encoded_value} primitives. - */ -public final class EncodedValueCodec { - private EncodedValueCodec() { - } - - /** - * Writes a signed integral to {@code out}. - */ - public static void writeSignedIntegralValue(ByteOutput out, int type, long value) { - /* - * Figure out how many bits are needed to represent the value, - * including a sign bit: The bit count is subtracted from 65 - * and not 64 to account for the sign bit. The xor operation - * has the effect of leaving non-negative values alone and - * unary complementing negative values (so that a leading zero - * count always returns a useful number for our present - * purpose). - */ - int requiredBits = 65 - Long.numberOfLeadingZeros(value ^ (value >> 63)); - - // Round up the requiredBits to a number of bytes. - int requiredBytes = (requiredBits + 0x07) >> 3; - - /* - * Write the header byte, which includes the type and - * requiredBytes - 1. - */ - out.writeByte(type | ((requiredBytes - 1) << 5)); - - // Write the value, per se. - while (requiredBytes > 0) { - out.writeByte((byte) value); - value >>= 8; - requiredBytes--; - } - } - - /** - * Writes an unsigned integral to {@code out}. - */ - public static void writeUnsignedIntegralValue(ByteOutput out, int type, long value) { - // Figure out how many bits are needed to represent the value. - int requiredBits = 64 - Long.numberOfLeadingZeros(value); - if (requiredBits == 0) { - requiredBits = 1; - } - - // Round up the requiredBits to a number of bytes. - int requiredBytes = (requiredBits + 0x07) >> 3; - - /* - * Write the header byte, which includes the type and - * requiredBytes - 1. - */ - out.writeByte(type | ((requiredBytes - 1) << 5)); - - // Write the value, per se. - while (requiredBytes > 0) { - out.writeByte((byte) value); - value >>= 8; - requiredBytes--; - } - } - - /** - * Writes a right-zero-extended value to {@code out}. - */ - public static void writeRightZeroExtendedValue(ByteOutput out, int type, long value) { - // Figure out how many bits are needed to represent the value. - int requiredBits = 64 - Long.numberOfTrailingZeros(value); - if (requiredBits == 0) { - requiredBits = 1; - } - - // Round up the requiredBits to a number of bytes. - int requiredBytes = (requiredBits + 0x07) >> 3; - - // Scootch the first bits to be written down to the low-order bits. - value >>= 64 - (requiredBytes * 8); - - /* - * Write the header byte, which includes the type and - * requiredBytes - 1. - */ - out.writeByte(type | ((requiredBytes - 1) << 5)); - - // Write the value, per se. - while (requiredBytes > 0) { - out.writeByte((byte) value); - value >>= 8; - requiredBytes--; - } - } - - /** - * Read a signed integer. - * - * @param zwidth byte count minus one - */ - public static int readSignedInt(ByteInput in, int zwidth) { - int result = 0; - for (int i = zwidth; i >= 0; i--) { - result = (result >>> 8) | ((in.readByte() & 0xff) << 24); - } - result >>= (3 - zwidth) * 8; - return result; - } - - /** - * Read an unsigned integer. - * - * @param zwidth byte count minus one - * @param fillOnRight true to zero fill on the right; false on the left - */ - public static int readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight) { - int result = 0; - if (!fillOnRight) { - for (int i = zwidth; i >= 0; i--) { - result = (result >>> 8) | ((in.readByte() & 0xff) << 24); - } - result >>>= (3 - zwidth) * 8; - } else { - for (int i = zwidth; i >= 0; i--) { - result = (result >>> 8) | ((in.readByte() & 0xff) << 24); - } - } - return result; - } - - /** - * Read a signed long. - * - * @param zwidth byte count minus one - */ - public static long readSignedLong(ByteInput in, int zwidth) { - long result = 0; - for (int i = zwidth; i >= 0; i--) { - result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); - } - result >>= (7 - zwidth) * 8; - return result; - } - - /** - * Read an unsigned long. - * - * @param zwidth byte count minus one - * @param fillOnRight true to zero fill on the right; false on the left - */ - public static long readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight) { - long result = 0; - if (!fillOnRight) { - for (int i = zwidth; i >= 0; i--) { - result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); - } - result >>>= (7 - zwidth) * 8; - } else { - for (int i = zwidth; i >= 0; i--) { - result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); - } - } - return result; - } -} diff --git a/dx/src/com/android/dex/EncodedValueReader.java b/dx/src/com/android/dex/EncodedValueReader.java deleted file mode 100644 index a26346410..000000000 --- a/dx/src/com/android/dex/EncodedValueReader.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ByteInput; - -/** - * Pull parser for encoded values. - */ -public final class EncodedValueReader { - public static final int ENCODED_BYTE = 0x00; - public static final int ENCODED_SHORT = 0x02; - public static final int ENCODED_CHAR = 0x03; - public static final int ENCODED_INT = 0x04; - public static final int ENCODED_LONG = 0x06; - public static final int ENCODED_FLOAT = 0x10; - public static final int ENCODED_DOUBLE = 0x11; - public static final int ENCODED_STRING = 0x17; - public static final int ENCODED_TYPE = 0x18; - public static final int ENCODED_FIELD = 0x19; - public static final int ENCODED_ENUM = 0x1b; - public static final int ENCODED_METHOD = 0x1a; - public static final int ENCODED_ARRAY = 0x1c; - public static final int ENCODED_ANNOTATION = 0x1d; - public static final int ENCODED_NULL = 0x1e; - public static final int ENCODED_BOOLEAN = 0x1f; - - /** placeholder type if the type is not yet known */ - private static final int MUST_READ = -1; - - protected final ByteInput in; - private int type = MUST_READ; - private int annotationType; - private int arg; - - public EncodedValueReader(ByteInput in) { - this.in = in; - } - - public EncodedValueReader(EncodedValue in) { - this(in.asByteInput()); - } - - /** - * Creates a new encoded value reader whose only value is the specified - * known type. This is useful for encoded values without a type prefix, - * such as class_def_item's encoded_array or annotation_item's - * encoded_annotation. - */ - public EncodedValueReader(ByteInput in, int knownType) { - this.in = in; - this.type = knownType; - } - - public EncodedValueReader(EncodedValue in, int knownType) { - this(in.asByteInput(), knownType); - } - - /** - * Returns the type of the next value to read. - */ - public int peek() { - if (type == MUST_READ) { - int argAndType = in.readByte() & 0xff; - type = argAndType & 0x1f; - arg = (argAndType & 0xe0) >> 5; - } - return type; - } - - /** - * Begins reading the elements of an array, returning the array's size. The - * caller must follow up by calling a read method for each element in the - * array. For example, this reads a byte array: <pre> {@code - * int arraySize = readArray(); - * for (int i = 0, i < arraySize; i++) { - * readByte(); - * } - * }</pre> - */ - public int readArray() { - checkType(ENCODED_ARRAY); - type = MUST_READ; - return Leb128.readUnsignedLeb128(in); - } - - /** - * Begins reading the fields of an annotation, returning the number of - * fields. The caller must follow up by making alternating calls to {@link - * #readAnnotationName()} and another read method. For example, this reads - * an annotation whose fields are all bytes: <pre> {@code - * int fieldCount = readAnnotation(); - * int annotationType = getAnnotationType(); - * for (int i = 0; i < fieldCount; i++) { - * readAnnotationName(); - * readByte(); - * } - * }</pre> - */ - public int readAnnotation() { - checkType(ENCODED_ANNOTATION); - type = MUST_READ; - annotationType = Leb128.readUnsignedLeb128(in); - return Leb128.readUnsignedLeb128(in); - } - - /** - * Returns the type of the annotation just returned by {@link - * #readAnnotation()}. This method's value is undefined unless the most - * recent call was to {@link #readAnnotation()}. - */ - public int getAnnotationType() { - return annotationType; - } - - public int readAnnotationName() { - return Leb128.readUnsignedLeb128(in); - } - - public byte readByte() { - checkType(ENCODED_BYTE); - type = MUST_READ; - return (byte) EncodedValueCodec.readSignedInt(in, arg); - } - - public short readShort() { - checkType(ENCODED_SHORT); - type = MUST_READ; - return (short) EncodedValueCodec.readSignedInt(in, arg); - } - - public char readChar() { - checkType(ENCODED_CHAR); - type = MUST_READ; - return (char) EncodedValueCodec.readUnsignedInt(in, arg, false); - } - - public int readInt() { - checkType(ENCODED_INT); - type = MUST_READ; - return EncodedValueCodec.readSignedInt(in, arg); - } - - public long readLong() { - checkType(ENCODED_LONG); - type = MUST_READ; - return EncodedValueCodec.readSignedLong(in, arg); - } - - public float readFloat() { - checkType(ENCODED_FLOAT); - type = MUST_READ; - return Float.intBitsToFloat(EncodedValueCodec.readUnsignedInt(in, arg, true)); - } - - public double readDouble() { - checkType(ENCODED_DOUBLE); - type = MUST_READ; - return Double.longBitsToDouble(EncodedValueCodec.readUnsignedLong(in, arg, true)); - } - - public int readString() { - checkType(ENCODED_STRING); - type = MUST_READ; - return EncodedValueCodec.readUnsignedInt(in, arg, false); - } - - public int readType() { - checkType(ENCODED_TYPE); - type = MUST_READ; - return EncodedValueCodec.readUnsignedInt(in, arg, false); - } - - public int readField() { - checkType(ENCODED_FIELD); - type = MUST_READ; - return EncodedValueCodec.readUnsignedInt(in, arg, false); - } - - public int readEnum() { - checkType(ENCODED_ENUM); - type = MUST_READ; - return EncodedValueCodec.readUnsignedInt(in, arg, false); - } - - public int readMethod() { - checkType(ENCODED_METHOD); - type = MUST_READ; - return EncodedValueCodec.readUnsignedInt(in, arg, false); - } - - public void readNull() { - checkType(ENCODED_NULL); - type = MUST_READ; - } - - public boolean readBoolean() { - checkType(ENCODED_BOOLEAN); - type = MUST_READ; - return arg != 0; - } - - /** - * Skips a single value, including its nested values if it is an array or - * annotation. - */ - public void skipValue() { - switch (peek()) { - case ENCODED_BYTE: - readByte(); - break; - case ENCODED_SHORT: - readShort(); - break; - case ENCODED_CHAR: - readChar(); - break; - case ENCODED_INT: - readInt(); - break; - case ENCODED_LONG: - readLong(); - break; - case ENCODED_FLOAT: - readFloat(); - break; - case ENCODED_DOUBLE: - readDouble(); - break; - case ENCODED_STRING: - readString(); - break; - case ENCODED_TYPE: - readType(); - break; - case ENCODED_FIELD: - readField(); - break; - case ENCODED_ENUM: - readEnum(); - break; - case ENCODED_METHOD: - readMethod(); - break; - case ENCODED_ARRAY: - for (int i = 0, size = readArray(); i < size; i++) { - skipValue(); - } - break; - case ENCODED_ANNOTATION: - for (int i = 0, size = readAnnotation(); i < size; i++) { - readAnnotationName(); - skipValue(); - } - break; - case ENCODED_NULL: - readNull(); - break; - case ENCODED_BOOLEAN: - readBoolean(); - break; - default: - throw new DexException("Unexpected type: " + Integer.toHexString(type)); - } - } - - private void checkType(int expected) { - if (peek() != expected) { - throw new IllegalStateException("Expected array but was " - + Integer.toHexString(peek())); - } - } -} diff --git a/dx/src/com/android/dex/FieldId.java b/dx/src/com/android/dex/FieldId.java deleted file mode 100644 index 2f41708c8..000000000 --- a/dx/src/com/android/dex/FieldId.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.Unsigned; - -public final class FieldId implements Comparable<FieldId> { - private final Dex dex; - private final int declaringClassIndex; - private final int typeIndex; - private final int nameIndex; - - public FieldId(Dex dex, int declaringClassIndex, int typeIndex, int nameIndex) { - this.dex = dex; - this.declaringClassIndex = declaringClassIndex; - this.typeIndex = typeIndex; - this.nameIndex = nameIndex; - } - - public int getDeclaringClassIndex() { - return declaringClassIndex; - } - - public int getTypeIndex() { - return typeIndex; - } - - public int getNameIndex() { - return nameIndex; - } - - public int compareTo(FieldId other) { - if (declaringClassIndex != other.declaringClassIndex) { - return Unsigned.compare(declaringClassIndex, other.declaringClassIndex); - } - if (nameIndex != other.nameIndex) { - return Unsigned.compare(nameIndex, other.nameIndex); - } - return Unsigned.compare(typeIndex, other.typeIndex); // should always be 0 - } - - public void writeTo(Dex.Section out) { - out.writeUnsignedShort(declaringClassIndex); - out.writeUnsignedShort(typeIndex); - out.writeInt(nameIndex); - } - - @Override public String toString() { - if (dex == null) { - return declaringClassIndex + " " + typeIndex + " " + nameIndex; - } - return dex.typeNames().get(typeIndex) + "." + dex.strings().get(nameIndex); - } -} diff --git a/dx/src/com/android/dex/Leb128.java b/dx/src/com/android/dex/Leb128.java deleted file mode 100644 index 1a82e383e..000000000 --- a/dx/src/com/android/dex/Leb128.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ByteInput; -import com.android.dex.util.ByteOutput; - -/** - * Reads and writes DWARFv3 LEB 128 signed and unsigned integers. See DWARF v3 - * section 7.6. - */ -public final class Leb128 { - private Leb128() { - } - - /** - * Gets the number of bytes in the unsigned LEB128 encoding of the - * given value. - * - * @param value the value in question - * @return its write size, in bytes - */ - public static int unsignedLeb128Size(int value) { - // TODO: This could be much cleverer. - - int remaining = value >> 7; - int count = 0; - - while (remaining != 0) { - remaining >>= 7; - count++; - } - - return count + 1; - } - - /** - * Gets the number of bytes in the signed LEB128 encoding of the - * given value. - * - * @param value the value in question - * @return its write size, in bytes - */ - public static int signedLeb128Size(int value) { - // TODO: This could be much cleverer. - - int remaining = value >> 7; - int count = 0; - boolean hasMore = true; - int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; - - while (hasMore) { - hasMore = (remaining != end) - || ((remaining & 1) != ((value >> 6) & 1)); - - value = remaining; - remaining >>= 7; - count++; - } - - return count; - } - - /** - * Reads an signed integer from {@code in}. - */ - public static int readSignedLeb128(ByteInput in) { - int result = 0; - int cur; - int count = 0; - int signBits = -1; - - do { - cur = in.readByte() & 0xff; - result |= (cur & 0x7f) << (count * 7); - signBits <<= 7; - count++; - } while (((cur & 0x80) == 0x80) && count < 5); - - if ((cur & 0x80) == 0x80) { - throw new DexException("invalid LEB128 sequence"); - } - - // Sign extend if appropriate - if (((signBits >> 1) & result) != 0 ) { - result |= signBits; - } - - return result; - } - - /** - * Reads an unsigned integer from {@code in}. - */ - public static int readUnsignedLeb128(ByteInput in) { - int result = 0; - int cur; - int count = 0; - - do { - cur = in.readByte() & 0xff; - result |= (cur & 0x7f) << (count * 7); - count++; - } while (((cur & 0x80) == 0x80) && count < 5); - - if ((cur & 0x80) == 0x80) { - throw new DexException("invalid LEB128 sequence"); - } - - return result; - } - - /** - * Writes {@code value} as an unsigned integer to {@code out}, starting at - * {@code offset}. Returns the number of bytes written. - */ - public static void writeUnsignedLeb128(ByteOutput out, int value) { - int remaining = value >>> 7; - - while (remaining != 0) { - out.writeByte((byte) ((value & 0x7f) | 0x80)); - value = remaining; - remaining >>>= 7; - } - - out.writeByte((byte) (value & 0x7f)); - } - - /** - * Writes {@code value} as a signed integer to {@code out}, starting at - * {@code offset}. Returns the number of bytes written. - */ - public static void writeSignedLeb128(ByteOutput out, int value) { - int remaining = value >> 7; - boolean hasMore = true; - int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; - - while (hasMore) { - hasMore = (remaining != end) - || ((remaining & 1) != ((value >> 6) & 1)); - - out.writeByte((byte) ((value & 0x7f) | (hasMore ? 0x80 : 0))); - value = remaining; - remaining >>= 7; - } - } -} diff --git a/dx/src/com/android/dex/MethodId.java b/dx/src/com/android/dex/MethodId.java deleted file mode 100644 index e51874026..000000000 --- a/dx/src/com/android/dex/MethodId.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.Unsigned; - -public final class MethodId implements Comparable<MethodId> { - private final Dex dex; - private final int declaringClassIndex; - private final int protoIndex; - private final int nameIndex; - - public MethodId(Dex dex, int declaringClassIndex, int protoIndex, int nameIndex) { - this.dex = dex; - this.declaringClassIndex = declaringClassIndex; - this.protoIndex = protoIndex; - this.nameIndex = nameIndex; - } - - public int getDeclaringClassIndex() { - return declaringClassIndex; - } - - public int getProtoIndex() { - return protoIndex; - } - - public int getNameIndex() { - return nameIndex; - } - - public int compareTo(MethodId other) { - if (declaringClassIndex != other.declaringClassIndex) { - return Unsigned.compare(declaringClassIndex, other.declaringClassIndex); - } - if (nameIndex != other.nameIndex) { - return Unsigned.compare(nameIndex, other.nameIndex); - } - return Unsigned.compare(protoIndex, other.protoIndex); - } - - public void writeTo(Dex.Section out) { - out.writeUnsignedShort(declaringClassIndex); - out.writeUnsignedShort(protoIndex); - out.writeInt(nameIndex); - } - - @Override public String toString() { - if (dex == null) { - return declaringClassIndex + " " + protoIndex + " " + nameIndex; - } - return dex.typeNames().get(declaringClassIndex) - + "." + dex.strings().get(nameIndex) - + dex.readTypeList(dex.protoIds().get(protoIndex).getParametersOffset()); - } -} diff --git a/dx/src/com/android/dex/Mutf8.java b/dx/src/com/android/dex/Mutf8.java deleted file mode 100644 index c64da331b..000000000 --- a/dx/src/com/android/dex/Mutf8.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.ByteInput; -import java.io.UTFDataFormatException; - -/** - * Modified UTF-8 as described in the dex file format spec. - * - * <p>Derived from libcore's MUTF-8 encoder at java.nio.charset.ModifiedUtf8. - */ -public final class Mutf8 { - private Mutf8() {} - - /** - * Decodes bytes from {@code in} into {@code out} until a delimiter 0x00 is - * encountered. Returns a new string containing the decoded characters. - */ - public static String decode(ByteInput in, char[] out) throws UTFDataFormatException { - int s = 0; - while (true) { - char a = (char) (in.readByte() & 0xff); - if (a == 0) { - return new String(out, 0, s); - } - out[s] = a; - if (a < '\u0080') { - s++; - } else if ((a & 0xe0) == 0xc0) { - int b = in.readByte() & 0xff; - if ((b & 0xC0) != 0x80) { - throw new UTFDataFormatException("bad second byte"); - } - out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F)); - } else if ((a & 0xf0) == 0xe0) { - int b = in.readByte() & 0xff; - int c = in.readByte() & 0xff; - if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) { - throw new UTFDataFormatException("bad second or third byte"); - } - out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F)); - } else { - throw new UTFDataFormatException("bad byte"); - } - } - } - - /** - * Returns the number of bytes the modified UTF8 representation of 's' would take. - */ - private static long countBytes(String s, boolean shortLength) throws UTFDataFormatException { - long result = 0; - final int length = s.length(); - for (int i = 0; i < length; ++i) { - char ch = s.charAt(i); - if (ch != 0 && ch <= 127) { // U+0000 uses two bytes. - ++result; - } else if (ch <= 2047) { - result += 2; - } else { - result += 3; - } - if (shortLength && result > 65535) { - throw new UTFDataFormatException("String more than 65535 UTF bytes long"); - } - } - return result; - } - - /** - * Encodes the modified UTF-8 bytes corresponding to {@code s} into {@code - * dst}, starting at {@code offset}. - */ - public static void encode(byte[] dst, int offset, String s) { - final int length = s.length(); - for (int i = 0; i < length; i++) { - char ch = s.charAt(i); - if (ch != 0 && ch <= 127) { // U+0000 uses two bytes. - dst[offset++] = (byte) ch; - } else if (ch <= 2047) { - dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6))); - dst[offset++] = (byte) (0x80 | (0x3f & ch)); - } else { - dst[offset++] = (byte) (0xe0 | (0x0f & (ch >> 12))); - dst[offset++] = (byte) (0x80 | (0x3f & (ch >> 6))); - dst[offset++] = (byte) (0x80 | (0x3f & ch)); - } - } - } - - /** - * Returns an array containing the <i>modified UTF-8</i> form of {@code s}. - */ - public static byte[] encode(String s) throws UTFDataFormatException { - int utfCount = (int) countBytes(s, true); - byte[] result = new byte[utfCount]; - encode(result, 0, s); - return result; - } -} diff --git a/dx/src/com/android/dex/ProtoId.java b/dx/src/com/android/dex/ProtoId.java deleted file mode 100644 index 9d9f484f2..000000000 --- a/dx/src/com/android/dex/ProtoId.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.Unsigned; - -public final class ProtoId implements Comparable<ProtoId> { - private final Dex dex; - private final int shortyIndex; - private final int returnTypeIndex; - private final int parametersOffset; - - public ProtoId(Dex dex, int shortyIndex, int returnTypeIndex, int parametersOffset) { - this.dex = dex; - this.shortyIndex = shortyIndex; - this.returnTypeIndex = returnTypeIndex; - this.parametersOffset = parametersOffset; - } - - public int compareTo(ProtoId other) { - if (returnTypeIndex != other.returnTypeIndex) { - return Unsigned.compare(returnTypeIndex, other.returnTypeIndex); - } - return Unsigned.compare(parametersOffset, other.parametersOffset); - } - - public int getShortyIndex() { - return shortyIndex; - } - - public int getReturnTypeIndex() { - return returnTypeIndex; - } - - public int getParametersOffset() { - return parametersOffset; - } - - public void writeTo(Dex.Section out) { - out.writeInt(shortyIndex); - out.writeInt(returnTypeIndex); - out.writeInt(parametersOffset); - } - - @Override public String toString() { - if (dex == null) { - return shortyIndex + " " + returnTypeIndex + " " + parametersOffset; - } - - return dex.strings().get(shortyIndex) - + ": " + dex.typeNames().get(returnTypeIndex) - + " " + dex.readTypeList(parametersOffset); - } -} diff --git a/dx/src/com/android/dex/SizeOf.java b/dx/src/com/android/dex/SizeOf.java deleted file mode 100644 index 65fab565b..000000000 --- a/dx/src/com/android/dex/SizeOf.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -public final class SizeOf { - private SizeOf() {} - - public static final int UBYTE = 1; - public static final int USHORT = 2; - public static final int UINT = 4; - - public static final int SIGNATURE = UBYTE * 20; - - /** - * magic ubyte[8] - * checksum uint - * signature ubyte[20] - * file_size uint - * header_size uint - * endian_tag uint - * link_size uint - * link_off uint - * map_off uint - * string_ids_size uint - * string_ids_off uint - * type_ids_size uint - * type_ids_off uint - * proto_ids_size uint - * proto_ids_off uint - * field_ids_size uint - * field_ids_off uint - * method_ids_size uint - * method_ids_off uint - * class_defs_size uint - * class_defs_off uint - * data_size uint - * data_off uint - */ - public static final int HEADER_ITEM = (8 * UBYTE) + UINT + SIGNATURE + (20 * UINT); // 0x70 - - /** - * string_data_off uint - */ - public static final int STRING_ID_ITEM = UINT; - - /** - * descriptor_idx uint - */ - public static final int TYPE_ID_ITEM = UINT; - - /** - * type_idx ushort - */ - public static final int TYPE_ITEM = USHORT; - - /** - * shorty_idx uint - * return_type_idx uint - * return_type_idx uint - */ - public static final int PROTO_ID_ITEM = UINT + UINT + UINT; - - /** - * class_idx ushort - * type_idx/proto_idx ushort - * name_idx uint - */ - public static final int MEMBER_ID_ITEM = USHORT + USHORT + UINT; - - /** - * class_idx uint - * access_flags uint - * superclass_idx uint - * interfaces_off uint - * source_file_idx uint - * annotations_off uint - * class_data_off uint - * static_values_off uint - */ - public static final int CLASS_DEF_ITEM = 8 * UINT; - - /** - * type ushort - * unused ushort - * size uint - * offset uint - */ - public static final int MAP_ITEM = USHORT + USHORT + UINT + UINT; - - /** - * start_addr uint - * insn_count ushort - * handler_off ushort - */ - public static final int TRY_ITEM = UINT + USHORT + USHORT; -} diff --git a/dx/src/com/android/dex/TableOfContents.java b/dx/src/com/android/dex/TableOfContents.java deleted file mode 100644 index d1b87ac8f..000000000 --- a/dx/src/com/android/dex/TableOfContents.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -/** - * The file header and map. - */ -public final class TableOfContents { - - /* - * TODO: factor out ID constants. - */ - - public final Section header = new Section(0x0000); - public final Section stringIds = new Section(0x0001); - public final Section typeIds = new Section(0x0002); - public final Section protoIds = new Section(0x0003); - public final Section fieldIds = new Section(0x0004); - public final Section methodIds = new Section(0x0005); - public final Section classDefs = new Section(0x0006); - public final Section mapList = new Section(0x1000); - public final Section typeLists = new Section(0x1001); - public final Section annotationSetRefLists = new Section(0x1002); - public final Section annotationSets = new Section(0x1003); - public final Section classDatas = new Section(0x2000); - public final Section codes = new Section(0x2001); - public final Section stringDatas = new Section(0x2002); - public final Section debugInfos = new Section(0x2003); - public final Section annotations = new Section(0x2004); - public final Section encodedArrays = new Section(0x2005); - public final Section annotationsDirectories = new Section(0x2006); - public final Section[] sections = { - header, stringIds, typeIds, protoIds, fieldIds, methodIds, classDefs, mapList, - typeLists, annotationSetRefLists, annotationSets, classDatas, codes, stringDatas, - debugInfos, annotations, encodedArrays, annotationsDirectories - }; - - public int checksum; - public byte[] signature; - public int fileSize; - public int linkSize; - public int linkOff; - public int dataSize; - public int dataOff; - - public TableOfContents() { - signature = new byte[20]; - } - - public void readFrom(Dex dex) throws IOException { - readHeader(dex.open(0)); - readMap(dex.open(mapList.off)); - computeSizesFromOffsets(); - } - - private void readHeader(Dex.Section headerIn) throws UnsupportedEncodingException { - byte[] magic = headerIn.readByteArray(8); - int apiTarget = DexFormat.magicToApi(magic); - - if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) { - throw new DexException("Unexpected magic: " + Arrays.toString(magic)); - } - - checksum = headerIn.readInt(); - signature = headerIn.readByteArray(20); - fileSize = headerIn.readInt(); - int headerSize = headerIn.readInt(); - if (headerSize != SizeOf.HEADER_ITEM) { - throw new DexException("Unexpected header: 0x" + Integer.toHexString(headerSize)); - } - int endianTag = headerIn.readInt(); - if (endianTag != DexFormat.ENDIAN_TAG) { - throw new DexException("Unexpected endian tag: 0x" + Integer.toHexString(endianTag)); - } - linkSize = headerIn.readInt(); - linkOff = headerIn.readInt(); - mapList.off = headerIn.readInt(); - if (mapList.off == 0) { - throw new DexException("Cannot merge dex files that do not contain a map"); - } - stringIds.size = headerIn.readInt(); - stringIds.off = headerIn.readInt(); - typeIds.size = headerIn.readInt(); - typeIds.off = headerIn.readInt(); - protoIds.size = headerIn.readInt(); - protoIds.off = headerIn.readInt(); - fieldIds.size = headerIn.readInt(); - fieldIds.off = headerIn.readInt(); - methodIds.size = headerIn.readInt(); - methodIds.off = headerIn.readInt(); - classDefs.size = headerIn.readInt(); - classDefs.off = headerIn.readInt(); - dataSize = headerIn.readInt(); - dataOff = headerIn.readInt(); - } - - private void readMap(Dex.Section in) throws IOException { - int mapSize = in.readInt(); - Section previous = null; - for (int i = 0; i < mapSize; i++) { - short type = in.readShort(); - in.readShort(); // unused - Section section = getSection(type); - int size = in.readInt(); - int offset = in.readInt(); - - if ((section.size != 0 && section.size != size) - || (section.off != -1 && section.off != offset)) { - throw new DexException("Unexpected map value for 0x" + Integer.toHexString(type)); - } - - section.size = size; - section.off = offset; - - if (previous != null && previous.off > section.off) { - throw new DexException("Map is unsorted at " + previous + ", " + section); - } - - previous = section; - } - Arrays.sort(sections); - } - - public void computeSizesFromOffsets() { - int end = dataOff + dataSize; - for (int i = sections.length - 1; i >= 0; i--) { - Section section = sections[i]; - if (section.off == -1) { - continue; - } - if (section.off > end) { - throw new DexException("Map is unsorted at " + section); - } - section.byteCount = end - section.off; - end = section.off; - } - } - - private Section getSection(short type) { - for (Section section : sections) { - if (section.type == type) { - return section; - } - } - throw new IllegalArgumentException("No such map item: " + type); - } - - public void writeHeader(Dex.Section out) throws IOException { - out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8")); - out.writeInt(checksum); - out.write(signature); - out.writeInt(fileSize); - out.writeInt(SizeOf.HEADER_ITEM); - out.writeInt(DexFormat.ENDIAN_TAG); - out.writeInt(linkSize); - out.writeInt(linkOff); - out.writeInt(mapList.off); - out.writeInt(stringIds.size); - out.writeInt(stringIds.off); - out.writeInt(typeIds.size); - out.writeInt(typeIds.off); - out.writeInt(protoIds.size); - out.writeInt(protoIds.off); - out.writeInt(fieldIds.size); - out.writeInt(fieldIds.off); - out.writeInt(methodIds.size); - out.writeInt(methodIds.off); - out.writeInt(classDefs.size); - out.writeInt(classDefs.off); - out.writeInt(dataSize); - out.writeInt(dataOff); - } - - public void writeMap(Dex.Section out) throws IOException { - int count = 0; - for (Section section : sections) { - if (section.exists()) { - count++; - } - } - - out.writeInt(count); - for (Section section : sections) { - if (section.exists()) { - out.writeShort(section.type); - out.writeShort((short) 0); - out.writeInt(section.size); - out.writeInt(section.off); - } - } - } - - public static class Section implements Comparable<Section> { - public final short type; - public int size = 0; - public int off = -1; - public int byteCount = 0; - - public Section(int type) { - this.type = (short) type; - } - - public boolean exists() { - return size > 0; - } - - public int compareTo(Section section) { - if (off != section.off) { - return off < section.off ? -1 : 1; - } - return 0; - } - - @Override public String toString() { - return String.format("Section[type=%#x,off=%#x,size=%#x]", type, off, size); - } - } -} diff --git a/dx/src/com/android/dex/TypeList.java b/dx/src/com/android/dex/TypeList.java deleted file mode 100644 index aa1bf5832..000000000 --- a/dx/src/com/android/dex/TypeList.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex; - -import com.android.dex.util.Unsigned; - -public final class TypeList implements Comparable<TypeList> { - - public static final TypeList EMPTY = new TypeList(null, new short[0]); - - private final Dex dex; - private final short[] types; - - public TypeList(Dex dex, short[] types) { - this.dex = dex; - this.types = types; - } - - public short[] getTypes() { - return types; - } - - public int compareTo(TypeList other) { - for (int i = 0; i < types.length && i < other.types.length; i++) { - if (types[i] != other.types[i]) { - return Unsigned.compare(types[i], other.types[i]); - } - } - return Unsigned.compare(types.length, other.types.length); - } - - @Override public String toString() { - StringBuilder result = new StringBuilder(); - result.append("("); - for (int i = 0, typesLength = types.length; i < typesLength; i++) { - result.append(dex != null ? dex.typeNames().get(types[i]) : types[i]); - } - result.append(")"); - return result.toString(); - } -} diff --git a/dx/src/com/android/dex/util/ByteArrayByteInput.java b/dx/src/com/android/dex/util/ByteArrayByteInput.java deleted file mode 100644 index 889a936c5..000000000 --- a/dx/src/com/android/dex/util/ByteArrayByteInput.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex.util; - -public final class ByteArrayByteInput implements ByteInput { - - private final byte[] bytes; - private int position; - - public ByteArrayByteInput(byte... bytes) { - this.bytes = bytes; - } - - @Override public byte readByte() { - return bytes[position++]; - } -} diff --git a/dx/src/com/android/dex/util/ByteInput.java b/dx/src/com/android/dex/util/ByteInput.java deleted file mode 100644 index f1a719614..000000000 --- a/dx/src/com/android/dex/util/ByteInput.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex.util; - -/** - * A byte source. - */ -public interface ByteInput { - - /** - * Returns a byte. - * - * @throws IndexOutOfBoundsException if all bytes have been read. - */ - byte readByte(); -} diff --git a/dx/src/com/android/dex/util/ByteOutput.java b/dx/src/com/android/dex/util/ByteOutput.java deleted file mode 100644 index eb77040ec..000000000 --- a/dx/src/com/android/dex/util/ByteOutput.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex.util; - -/** - * A byte sink. - */ -public interface ByteOutput { - - /** - * Writes a byte. - * - * @throws IndexOutOfBoundsException if all bytes have been written. - */ - void writeByte(int i); -} diff --git a/dx/src/com/android/dex/util/ExceptionWithContext.java b/dx/src/com/android/dex/util/ExceptionWithContext.java deleted file mode 100644 index 5dfd95474..000000000 --- a/dx/src/com/android/dex/util/ExceptionWithContext.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex.util; - -import java.io.PrintStream; -import java.io.PrintWriter; - -/** - * Exception which carries around structured context. - */ -public class ExceptionWithContext extends RuntimeException { - /** {@code non-null;} human-oriented context of the exception */ - private StringBuffer context; - - /** - * Augments the given exception with the given context, and return the - * result. The result is either the given exception if it was an - * {@link ExceptionWithContext}, or a newly-constructed exception if it - * was not. - * - * @param ex {@code non-null;} the exception to augment - * @param str {@code non-null;} context to add - * @return {@code non-null;} an appropriate instance - */ - public static ExceptionWithContext withContext(Throwable ex, String str) { - ExceptionWithContext ewc; - - if (ex instanceof ExceptionWithContext) { - ewc = (ExceptionWithContext) ex; - } else { - ewc = new ExceptionWithContext(ex); - } - - ewc.addContext(str); - return ewc; - } - - /** - * Constructs an instance. - * - * @param message human-oriented message - */ - public ExceptionWithContext(String message) { - this(message, null); - } - - /** - * Constructs an instance. - * - * @param cause {@code null-ok;} exception that caused this one - */ - public ExceptionWithContext(Throwable cause) { - this(null, cause); - } - - /** - * Constructs an instance. - * - * @param message human-oriented message - * @param cause {@code null-ok;} exception that caused this one - */ - public ExceptionWithContext(String message, Throwable cause) { - super((message != null) ? message : - (cause != null) ? cause.getMessage() : null, - cause); - - if (cause instanceof ExceptionWithContext) { - String ctx = ((ExceptionWithContext) cause).context.toString(); - context = new StringBuffer(ctx.length() + 200); - context.append(ctx); - } else { - context = new StringBuffer(200); - } - } - - /** {@inheritDoc} */ - @Override - public void printStackTrace(PrintStream out) { - super.printStackTrace(out); - out.println(context); - } - - /** {@inheritDoc} */ - @Override - public void printStackTrace(PrintWriter out) { - super.printStackTrace(out); - out.println(context); - } - - /** - * Adds a line of context to this instance. - * - * @param str {@code non-null;} new context - */ - public void addContext(String str) { - if (str == null) { - throw new NullPointerException("str == null"); - } - - context.append(str); - if (!str.endsWith("\n")) { - context.append('\n'); - } - } - - /** - * Gets the context. - * - * @return {@code non-null;} the context - */ - public String getContext() { - return context.toString(); - } - - /** - * Prints the message and context. - * - * @param out {@code non-null;} where to print to - */ - public void printContext(PrintStream out) { - out.println(getMessage()); - out.print(context); - } - - /** - * Prints the message and context. - * - * @param out {@code non-null;} where to print to - */ - public void printContext(PrintWriter out) { - out.println(getMessage()); - out.print(context); - } -} diff --git a/dx/src/com/android/dex/util/FileUtils.java b/dx/src/com/android/dex/util/FileUtils.java deleted file mode 100644 index 4cea95c59..000000000 --- a/dx/src/com/android/dex/util/FileUtils.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -/** - * File I/O utilities. - */ -public final class FileUtils { - private FileUtils() { - } - - /** - * Reads the named file, translating {@link IOException} to a - * {@link RuntimeException} of some sort. - * - * @param fileName {@code non-null;} name of the file to read - * @return {@code non-null;} contents of the file - */ - public static byte[] readFile(String fileName) { - File file = new File(fileName); - return readFile(file); - } - - /** - * Reads the given file, translating {@link IOException} to a - * {@link RuntimeException} of some sort. - * - * @param file {@code non-null;} the file to read - * @return {@code non-null;} contents of the file - */ - public static byte[] readFile(File file) { - if (!file.exists()) { - throw new RuntimeException(file + ": file not found"); - } - - if (!file.isFile()) { - throw new RuntimeException(file + ": not a file"); - } - - if (!file.canRead()) { - throw new RuntimeException(file + ": file not readable"); - } - - long longLength = file.length(); - int length = (int) longLength; - if (length != longLength) { - throw new RuntimeException(file + ": file too long"); - } - - byte[] result = new byte[length]; - - try { - FileInputStream in = new FileInputStream(file); - int at = 0; - while (length > 0) { - int amt = in.read(result, at, length); - if (amt == -1) { - throw new RuntimeException(file + ": unexpected EOF"); - } - at += amt; - length -= amt; - } - in.close(); - } catch (IOException ex) { - throw new RuntimeException(file + ": trouble reading", ex); - } - - return result; - } - - /** - * Returns true if {@code fileName} names a .zip, .jar, or .apk. - */ - public static boolean hasArchiveSuffix(String fileName) { - return fileName.endsWith(".zip") - || fileName.endsWith(".jar") - || fileName.endsWith(".apk"); - } -} diff --git a/dx/src/com/android/dex/util/Unsigned.java b/dx/src/com/android/dex/util/Unsigned.java deleted file mode 100644 index cb50d0a40..000000000 --- a/dx/src/com/android/dex/util/Unsigned.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dex.util; - -/** - * Unsigned arithmetic over Java's signed types. - */ -public final class Unsigned { - private Unsigned() {} - - public static int compare(short ushortA, short ushortB) { - if (ushortA == ushortB) { - return 0; - } - int a = ushortA & 0xFFFF; - int b = ushortB & 0xFFFF; - return a < b ? -1 : 1; - } - - public static int compare(int uintA, int uintB) { - if (uintA == uintB) { - return 0; - } - long a = uintA & 0xFFFFFFFFL; - long b = uintB & 0xFFFFFFFFL; - return a < b ? -1 : 1; - } -} |