auto import from //branches/cupcake_rel/...@138607
diff --git a/tools/dex-tools/src/dex/reader/DexAnnotationAttributeImpl.java b/tools/dex-tools/src/dex/reader/DexAnnotationAttributeImpl.java
new file mode 100644
index 0000000..deec93c
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexAnnotationAttributeImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+import dex.structure.DexEncodedValue;
+
+/* package */final class DexAnnotationAttributeImpl implements
+ DexAnnotationAttribute {
+ int nameIdx; // uleb128
+ DexEncodedValue value;// encoded_value
+ private String[] stringPool;
+ private DexBuffer buffer;
+ private final int[] typeIds;
+ private final FieldIdItem[] fieldIdItems;
+ private final DexAnnotation annotation;
+
+ public DexAnnotationAttributeImpl(DexBuffer buffer,
+ DexAnnotation annotation, int[] typeIds, String[] stringPool,
+ FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.annotation = annotation;
+ this.typeIds = typeIds;
+ this.stringPool = stringPool;
+ this.fieldIdItems = fieldIdItems;
+ parseValue();
+ }
+
+ private void parseValue() {
+ nameIdx = buffer.readUleb128();
+ value = new DexEncodedValueImpl(buffer, annotation, typeIds,
+ stringPool, fieldIdItems);
+ }
+
+ public String getName() {
+ return stringPool[nameIdx];
+ }
+
+ public DexEncodedValue getEncodedValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " " + getEncodedValue();
+ }
+
+ public DexAnnotation getAnnotation() {
+ return annotation;
+ }
+
+}
diff --git a/tools/dex-tools/src/dex/reader/DexAnnotationImpl.java b/tools/dex-tools/src/dex/reader/DexAnnotationImpl.java
new file mode 100644
index 0000000..49a93ae
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexAnnotationImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+
+import java.util.List;
+
+// FIXME provide special type for Signature annotation
+/* package */final class DexAnnotationImpl implements DexAnnotation {
+
+ private int offset;
+ private DexBuffer buffer;
+ private int[] typeIds;
+ private String[] stringPool;
+ private Visibility visibility;
+ private DexEncodedAnnotationImpl encodedAnnotation;
+
+ private TypeFormatter formatter = new TypeFormatter();
+ private final FieldIdItem[] fieldIdItems;
+
+ public DexAnnotationImpl(DexBuffer buffer, int offset, int[] typeIds,
+ String[] stringPool, FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.offset = offset;
+ this.typeIds = typeIds;
+ this.stringPool = stringPool;
+ this.fieldIdItems = fieldIdItems;
+ parseAnnotations();
+ }
+
+ private void parseAnnotations() {
+ buffer.setPosition(offset);
+ visibility = Visibility.get(buffer.readUByte());
+ encodedAnnotation = new DexEncodedAnnotationImpl(buffer, this, typeIds,
+ stringPool, fieldIdItems);
+ }
+
+ public List<DexAnnotationAttribute> getAttributes() {
+ return encodedAnnotation.getValue();
+ }
+
+ public String getTypeName() {
+ return encodedAnnotation.getTypeName();
+ }
+
+ public Visibility getVisibility() {
+ return visibility;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("@");
+ builder.append(formatter.format(encodedAnnotation.getTypeName()));
+ if (!getAttributes().isEmpty()) {
+ builder.append(" (");
+ for (DexAnnotationAttribute value : getAttributes()) {
+ builder.append(value.toString());
+ builder.append(" ");
+ }
+ builder.append(")");
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/tools/dex-tools/src/dex/reader/DexBuffer.java b/tools/dex-tools/src/dex/reader/DexBuffer.java
new file mode 100644
index 0000000..6292e28
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexBuffer.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public final class DexBuffer {
+
+ private ByteBuffer b;
+
+ public DexBuffer(String fileName) throws IOException {
+
+ // FIXME channel? allocate fix size?
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(fileName);
+
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = bis.read(buf)) > 0) {
+ bos.write(buf, 0, len);
+ }
+ byte[] bytes = bos.toByteArray();
+ initialize(ByteBuffer.wrap(bytes));
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ }
+
+ public DexBuffer(byte[] bytes) {
+ initialize(ByteBuffer.wrap(bytes));
+ }
+
+ private DexBuffer(ByteBuffer slice) {
+ initialize(slice);
+ }
+
+ private void initialize(ByteBuffer buffer) {
+ b = buffer.asReadOnlyBuffer();
+ b.clear();
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public void setPosition(int offset) {
+ b.position(offset);
+ }
+
+ public void readBytes(byte[] dst) {
+ b.get(dst, 0, dst.length);
+ }
+
+ /**
+ * FIXME make endian dependent
+ */
+ public int readUleb128() {
+ int endValue = 0;
+ int value = 0;
+ int nr = 0;
+ do {
+ value = (b.get() & 0xFF);
+ endValue |= ((value & 0x7F) << 7 * nr);// cut away left most bit
+ nr++;
+ } while ((value & 0x80) != 0); // highest bit set?
+ return endValue;
+ }
+
+ /**
+ * pre 0 < nBytes <=4
+ */
+ public int readInt(int nBytes) {
+ int endValue = 0;
+ int tmp = 0;
+ for (int i = 0; i < nBytes; i++) {
+ tmp = b.get() & 0xFF;
+ endValue |= (tmp << i * 8);
+ }
+ return endValue;
+ }
+
+ /**
+ * pre 0 < nBytes <=1 FIXME: Sign extension
+ */
+ public short readShort(int nBytes) {
+ short endValue = 0;
+ int tmp = 0;
+ for (int i = 0; i < nBytes; i++) {
+ tmp = b.get() & 0xFF;
+ endValue |= (tmp << i * 8);
+ }
+ return endValue;
+ }
+
+ /**
+ * pre 0 < nBytes <=1
+ */
+ public char readChar(int nBytes) {
+ char endValue = 0;
+ int tmp = 0;
+ for (int i = 0; i < nBytes; i++) {
+ tmp = b.get() & 0xFF;
+ endValue |= (tmp << i * 8);
+ }
+ return endValue;
+ }
+
+ /**
+ * pre 0 < nBytes <=7 FIXME: Sign extension
+ */
+ public long readLong(int nBytes) {
+ long endValue = 0;
+ int tmp = 0;
+ for (int i = 0; i < nBytes; i++) {
+ tmp = b.get() & 0xFF;
+ endValue |= (tmp << i * 8);
+ }
+ return endValue;
+ }
+
+ /**
+ * pre 0 < nBytes <=4
+ */
+ public float readFloat(int nBytes) {
+ int bits = readInt(nBytes);
+ int bytesToMove = (4 - nBytes) * 8;
+ bits <<= bytesToMove;
+ return Float.intBitsToFloat(bits);
+ }
+
+ // returns int form current position
+ public int readUInt() {
+ int value = b.getInt();
+ // assert value >= 0;
+ return value;
+ }
+
+ public int readUShort() {
+ return b.getShort() & 0xFFFF;
+ }
+
+ // returns byte form current position
+ public byte readUByte() {
+ return b.get();
+ }
+
+ public DexBuffer createCopy() {
+ return new DexBuffer(b.duplicate());
+ }
+
+ public double readDouble(int nBytes) {
+ long bits = readLong(nBytes);
+ int bytesToMove = (8 - nBytes) * 8;
+ bits <<= bytesToMove;
+ return Double.longBitsToDouble(bits);
+ }
+
+ public void skip(int nBytes) {
+ b.position(b.position() + nBytes);
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexClassImpl.java b/tools/dex-tools/src/dex/reader/DexClassImpl.java
new file mode 100644
index 0000000..f15e809
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexClassImpl.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import dex.reader.DexFileReader.ClassDefItem;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.reader.DexFileReader.MethodsIdItem;
+import dex.reader.DexFileReader.ProtIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexField;
+import dex.structure.DexMethod;
+
+/* package */final class DexClassImpl implements DexClass {
+ // constant
+ private final int NO_INDEX = -1;
+ // dex bytes
+ private final DexBuffer buffer;
+ // allready parsed
+ private final ClassDefItem classDefItem;
+ private final int[] typeIds;
+ private final String[] stringPool;
+ private ProtIdItem[] protoIdItems;
+ private FieldIdItem[] fieldIdItems;
+ private MethodsIdItem[] methodIdItems;
+
+ //
+ private List<DexField> fields;
+ private List<DexMethod> methods;
+ private List<String> interfaces;
+ private ClassDataItem classDataItem;
+ private AnnotationsDirectoryItem annotationDir;
+ private Map<Integer, FieldAnnotation> idToFieldAnnotation =
+ new HashMap<Integer, FieldAnnotation>();
+ private Map<Integer, MethodAnnotation> idToMethodAnnotation =
+ new HashMap<Integer, MethodAnnotation>();
+ private Map<Integer, ParameterAnnotation> idToParameterAnnotation =
+ new HashMap<Integer, ParameterAnnotation>();
+
+ private Set<DexAnnotation> annotations;
+ private TypeFormatter formatter = new TypeFormatter();
+
+ private boolean hasClassData;
+
+
+ public DexClassImpl(DexBuffer buffer, ClassDefItem classDefItem,
+ String[] stringPool, int[] typeIds, ProtIdItem[] protoIdItems,
+ FieldIdItem[] fieldIdItems, MethodsIdItem[] methodIdItems) {
+ this.buffer = buffer;
+ this.classDefItem = classDefItem;
+ this.stringPool = stringPool;
+ this.typeIds = typeIds;
+ this.protoIdItems = protoIdItems;
+ this.fieldIdItems = fieldIdItems;
+ this.methodIdItems = methodIdItems;
+ hasClassData = classDefItem.class_data_off != 0;
+ parseClassData();
+ parseAnnotationDirectory();
+ parseClassAnnotations();
+ }
+
+ static class AnnotationsDirectoryItem {
+ int class_annotations_off; // uint
+ int fields_size; // uint
+ int methods_size; // uint
+ int annotated_params_size; // uint
+ FieldAnnotation[] fieldAnnotations;
+ MethodAnnotation[] methodAnnotations;
+ ParameterAnnotation[] parameterAnnotations;
+ }
+
+ static class AnnotationSetItem {
+ int size;// uint
+ int[] annotationOffItem;
+ }
+
+ static class FieldAnnotation {
+ int fieldIdx;// uint
+ int annotationsOff;// uint
+ AnnotationSetItem[] annotationSetItems;
+ }
+
+ static class MethodAnnotation {
+ int methodIdx;// uint
+ int annotationsOff;// uint
+ AnnotationSetItem[] annotationSetItems;
+ }
+
+ static class ParameterAnnotation {
+ int methodIdx;// uint
+ int annotationsOff;// uint
+ // AnnotationSetRefListItem[] annotationSetRefListItems;
+ }
+
+ private void parseAnnotationDirectory() {
+ if (classDefItem.annotations_off != 0) {
+ buffer.setPosition(classDefItem.annotations_off);
+ annotationDir = new AnnotationsDirectoryItem();
+ annotationDir.class_annotations_off = buffer.readUInt();
+ annotationDir.fields_size = buffer.readUInt();
+ annotationDir.methods_size = buffer.readUInt();
+ annotationDir.annotated_params_size = buffer.readUInt();
+
+ if (annotationDir.fields_size != 0) {
+ annotationDir.fieldAnnotations =
+ new FieldAnnotation[annotationDir.fields_size];
+ for (int i = 0; i < annotationDir.fields_size; i++) {
+ annotationDir.fieldAnnotations[i] = new FieldAnnotation();
+ annotationDir.fieldAnnotations[i].fieldIdx = buffer
+ .readUInt();
+ annotationDir.fieldAnnotations[i].annotationsOff = buffer
+ .readUInt();
+ idToFieldAnnotation.put(
+ annotationDir.fieldAnnotations[i].fieldIdx,
+ annotationDir.fieldAnnotations[i]);
+ }
+ }
+ if (annotationDir.methods_size != 0) {
+ annotationDir.methodAnnotations =
+ new MethodAnnotation[annotationDir.methods_size];
+ for (int i = 0; i < annotationDir.methods_size; i++) {
+ annotationDir.methodAnnotations[i] = new MethodAnnotation();
+ annotationDir.methodAnnotations[i].methodIdx = buffer
+ .readUInt();
+ annotationDir.methodAnnotations[i].annotationsOff = buffer
+ .readUInt();
+ idToMethodAnnotation.put(
+ annotationDir.methodAnnotations[i].methodIdx,
+ annotationDir.methodAnnotations[i]);
+ }
+ }
+ if (annotationDir.annotated_params_size != 0) {
+ annotationDir.parameterAnnotations =
+ new ParameterAnnotation[annotationDir
+ .annotated_params_size];
+ for (int i = 0; i < annotationDir.annotated_params_size; i++) {
+ annotationDir.parameterAnnotations[i] =
+ new ParameterAnnotation();
+ annotationDir.parameterAnnotations[i].methodIdx = buffer
+ .readUInt();
+ annotationDir.parameterAnnotations[i].annotationsOff =
+ buffer.readUInt();
+ idToParameterAnnotation.put(
+ annotationDir.parameterAnnotations[i].methodIdx,
+ annotationDir.parameterAnnotations[i]);
+ }
+ }
+ }
+ }
+
+ static class ClassDataItem {
+ int static_fields_size;// uleb128
+ int instance_fields_size;// uleb128
+ int direct_methods_size;// uleb128
+ int virtual_methods_size;// uleb128
+ EncodedField[] staticFields;
+ EncodedField[] instanceFields;
+ EncodedMethod[] directMethods;
+ EncodedMethod[] virtualMethods;
+ }
+
+ static class EncodedField {
+ int field_idx_diff; // uleb128
+ int access_flags; // uleb128
+ }
+
+ static class EncodedMethod {
+ int method_idx_diff;// uleb128
+ int access_flags;// uleb128
+ int code_off; // uleb128
+ }
+
+ private void parseClassData() {
+ if (hasClassData) {
+ buffer.setPosition(classDefItem.class_data_off);
+ classDataItem = new ClassDataItem();
+ classDataItem.static_fields_size = buffer.readUleb128();
+ classDataItem.instance_fields_size = buffer.readUleb128();
+ classDataItem.direct_methods_size = buffer.readUleb128();
+ classDataItem.virtual_methods_size = buffer.readUleb128();
+ classDataItem.staticFields = parseFields(
+ classDataItem.static_fields_size);
+ classDataItem.instanceFields = parseFields(
+ classDataItem.instance_fields_size);
+ classDataItem.directMethods = parseMethods(
+ classDataItem.direct_methods_size);
+ classDataItem.virtualMethods = parseMethods(
+ classDataItem.virtual_methods_size);
+ }
+ }
+
+ private EncodedField[] parseFields(int size) {
+ EncodedField[] fields = new EncodedField[size];
+ for (int i = 0; i < fields.length; i++) {
+ fields[i] = new EncodedField();
+ fields[i].field_idx_diff = buffer.readUleb128();
+ fields[i].access_flags = buffer.readUleb128();
+ }
+ return fields;
+ }
+
+ private EncodedMethod[] parseMethods(int size) {
+ EncodedMethod[] methods = new EncodedMethod[size];
+ for (int i = 0; i < methods.length; i++) {
+ methods[i] = new EncodedMethod();
+ methods[i].method_idx_diff = buffer.readUleb128();
+ methods[i].access_flags = buffer.readUleb128();
+ methods[i].code_off = buffer.readUleb128();
+ }
+ return methods;
+ }
+
+ private void parseClassAnnotations() {
+ annotations = new HashSet<DexAnnotation>();
+ if (annotationDir != null && annotationDir.class_annotations_off != 0) {
+ buffer.setPosition(annotationDir.class_annotations_off);
+ final int size = buffer.readUInt();
+ for (int i = 0; i < size; i++) {
+ annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+ buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+ }
+ }
+ }
+
+ public synchronized List<DexField> getFields() {
+ if (fields == null) {
+ fields = new ArrayList<DexField>();
+ if (hasClassData) {
+ fields.addAll(getDexFields(classDataItem.staticFields));
+ fields.addAll(getDexFields(classDataItem.instanceFields));
+ }
+ }
+ return fields;
+ }
+
+ private List<DexField> getDexFields(EncodedField[] fields) {
+ List<DexField> dexFields = new ArrayList<DexField>(fields.length);
+ if (fields.length != 0) {
+ int fieldIdIdx = 0;
+ for (int i = 0; i < fields.length; i++) {
+ int accessFlags = fields[i].access_flags;
+ fieldIdIdx = (i == 0) ? fields[i].field_idx_diff : fieldIdIdx
+ + fields[i].field_idx_diff;
+ dexFields.add(new DexFieldImpl(buffer.createCopy(), this,
+ fieldIdItems[fieldIdIdx], accessFlags,
+ idToFieldAnnotation.get(fieldIdIdx), stringPool,
+ typeIds, fieldIdItems));
+ }
+ }
+ return dexFields;
+ }
+
+ public synchronized List<DexMethod> getMethods() {
+ if (methods == null) {
+ methods = new ArrayList<DexMethod>();
+ if (hasClassData) {
+ methods.addAll(getDexMethods(classDataItem.directMethods));
+ methods.addAll(getDexMethods(classDataItem.virtualMethods));
+ }
+ }
+ return methods;
+ }
+
+ private List<DexMethod> getDexMethods(EncodedMethod[] methods) {
+ List<DexMethod> dexMethods = new ArrayList<DexMethod>(methods.length);
+ if (methods.length != 0) {
+ int methodIdIdx = 0;
+ EncodedMethod method = null;
+ for (int i = 0; i < methods.length; i++) {
+ method = methods[i];
+ methodIdIdx = (i == 0) ? method.method_idx_diff : methodIdIdx
+ + method.method_idx_diff;
+ dexMethods.add(new DexMethodImpl(buffer, this,
+ methodIdItems[methodIdIdx],
+ protoIdItems[methodIdItems[methodIdIdx].proto_idx],
+ method.access_flags, idToMethodAnnotation
+ .get(methodIdIdx), idToParameterAnnotation
+ .get(methodIdIdx), stringPool, typeIds,
+ fieldIdItems));
+ }
+ }
+ return dexMethods;
+ }
+
+
+
+ public synchronized List<String> getInterfaces() {
+ if (interfaces == null) {
+ interfaces = new LinkedList<String>();
+ if (classDefItem.interfaces_off != 0) {
+ buffer.setPosition(classDefItem.interfaces_off);
+ int size = buffer.readUInt();
+ for (int i = 0; i < size; i++) {
+ interfaces.add(stringPool[typeIds[buffer.readUShort()]]);
+ }
+ }
+ }
+ return interfaces;
+ }
+
+ // returns null if no super class is present
+ public String getSuperClass() {
+ return classDefItem.superclass_idx == NO_INDEX ? null
+ : stringPool[typeIds[classDefItem.superclass_idx]];
+ }
+
+ public Set<DexAnnotation> getAnnotations() {
+ return annotations;
+ }
+
+ public String getName() {
+ return stringPool[typeIds[classDefItem.class_idx]];
+ }
+
+ public int getModifiers() {
+ return classDefItem.access_flags;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(formatter.formatAnnotations(getAnnotations()));
+ builder.append(Modifier.toString(getModifiers()));
+ builder.append(" class ");
+ builder.append(formatter.format(getName()));
+ if (getSuperClass() != null) {
+ builder.append(" extends ");
+ builder.append(formatter.format(getSuperClass()));
+ }
+ if (!getInterfaces().isEmpty()) {
+ builder.append(" implements ");
+ builder.append(formatter.format(getInterfaces()));
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/tools/dex-tools/src/dex/reader/DexEncodedAnnotationImpl.java b/tools/dex-tools/src/dex/reader/DexEncodedAnnotationImpl.java
new file mode 100644
index 0000000..0114ce3
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexEncodedAnnotationImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+import dex.structure.DexEncodedAnnotation;
+import dex.structure.DexEncodedValueType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* package */final class DexEncodedAnnotationImpl implements
+ DexEncodedAnnotation {
+
+ private List<DexAnnotationAttribute> values;
+ private final DexBuffer buffer;
+ private final int[] typeIds;
+ private final String[] stringPool;
+ private int typeIdx;
+ private final FieldIdItem[] fieldIdItems;
+ private final DexAnnotation annotation;
+
+ public DexEncodedAnnotationImpl(DexBuffer buffer, DexAnnotation annotation,
+ int[] typeIds, String[] stringPool, FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.annotation = annotation;
+ this.typeIds = typeIds;
+ this.stringPool = stringPool;
+ this.fieldIdItems = fieldIdItems;
+ parseEncodedAnnotation();
+ }
+
+ private void parseEncodedAnnotation() {
+ typeIdx = buffer.readUleb128();
+ int size = buffer.readUleb128();
+ values = new ArrayList<DexAnnotationAttribute>(size);
+ for (int j = 0; j < size; j++) {
+ values.add(new DexAnnotationAttributeImpl(buffer, annotation,
+ typeIds, stringPool, fieldIdItems));
+ }
+ }
+
+ public DexEncodedValueType getType() {
+ return DexEncodedValueType.VALUE_ANNOTATION;
+ }
+
+ public List<DexAnnotationAttribute> getValue() {
+ return values;
+ }
+
+ public String getTypeName() {
+ return stringPool[typeIds[typeIdx]];
+ }
+
+ @Override
+ public String toString() {
+ return getTypeName() + ":" + getValue();
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexEncodedValueImpl.java b/tools/dex-tools/src/dex/reader/DexEncodedValueImpl.java
new file mode 100644
index 0000000..82ba184
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexEncodedValueImpl.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import static dex.structure.DexEncodedValueType.*;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexEncodedValue;
+import dex.structure.DexEncodedValueType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* package */final class DexEncodedValueImpl implements DexEncodedValue {
+
+ private final DexBuffer buffer;
+ private byte typeAndValueArg;
+ private DexEncodedValueType type;
+ private String[] stringPool;
+ private Object value;
+ private int[] typeIds;
+ private final FieldIdItem[] fieldIdItems;
+ private final DexAnnotation annotation;
+
+ /**
+ *
+ * @param buffer
+ * the buffer with the correct position
+ * @param annotation
+ * @param stringPool
+ * @param fieldIdItems
+ */
+ public DexEncodedValueImpl(DexBuffer buffer, DexAnnotation annotation,
+ int[] typeIds, String[] stringPool, FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.annotation = annotation;
+ this.typeIds = typeIds;
+ this.stringPool = stringPool;
+ this.fieldIdItems = fieldIdItems;
+ parseValue();
+ }
+
+ private void parseValue() {
+ typeAndValueArg = buffer.readUByte();
+ type = DexEncodedValueType.get(typeAndValueArg);
+ int valueArg = DexEncodedValueType.valueArg(typeAndValueArg);
+ switch (type) {
+ case VALUE_BYTE:
+ value = getByteValue(valueArg);
+ break;
+ case VALUE_SHORT:
+ value = getShortValue(valueArg);
+ break;
+ case VALUE_CHAR:
+ value = getCharValue(valueArg);
+ break;
+ case VALUE_INT:
+ value = getIntValue(valueArg);
+ break;
+ case VALUE_LONG:
+ value = getLongValue(valueArg);
+ break;
+ case VALUE_FLOAT:
+ value = getFloatValue(valueArg);
+ break;
+ case VALUE_DOUBLE:
+ value = getDoubleValue(valueArg);
+ break;
+ case VALUE_STRING:
+ value = getStringValue(valueArg);
+ break;
+ case VALUE_TYPE:
+ value = getTypeValue(valueArg);
+ break;
+ case VALUE_FIELD:
+ value = getFieldValue(valueArg);
+ break;
+ case VALUE_METHOD:
+ value = getMethodValue(valueArg);
+ break;
+ case VALUE_ENUM:
+ value = getEnumValue(valueArg);
+ break;
+ case VALUE_ARRAY:
+ value = getArrayValue(valueArg);
+ break;
+ case VALUE_ANNOTATION:
+ value = getAnnotationValue(valueArg);
+ break;
+ case VALUE_NULL:
+ value = getNullValue(valueArg);
+ break;
+ case VALUE_BOOLEAN:
+ value = getBooleanValue(valueArg);
+ break;
+ default:
+ throw new IllegalArgumentException("DexEncodedValueType " + type
+ + " not recognized");
+ }
+ }
+
+ /**
+ * VALUE_BOOLEAN 0x1f boolean (0...1) (none) one-bit value; 0 for false and
+ * 1 for true. The bit is represented in the value_arg.
+ */
+ private Boolean getBooleanValue(int valueArg) {
+ return valueArg == 1;
+ }
+
+ /** VALUE_NULL 0x1e (none; must be 0) (none) null reference value */
+ private Object getNullValue(int valueArg) {
+ return null; // must be like that!
+ }
+
+ /**
+ * VALUE_ANNOTATION 0x1d (none; must be 0) encoded_annotation a
+ * sub-annotation, in the format specified by "encoded_annotation Format"
+ * below. The size of the value is implicit in the encoding.
+ */
+ private Object getAnnotationValue(int valueArg) {
+ // use the buffer directly to get adjusted offset
+ return new DexEncodedAnnotationImpl(buffer, annotation, typeIds,
+ stringPool, fieldIdItems);
+ }
+
+ /**
+ * VALUE_ARRAY 0x1c (none; must be 0) encoded_array an array of values, in
+ * the format specified by "encoded_array Format" below. The size of the
+ * value is implicit in the encoding.
+ */
+ private List<DexEncodedValue> getArrayValue(int valueArg) {
+ int size = buffer.readUleb128();
+ List<DexEncodedValue> values = new ArrayList<DexEncodedValue>(size);
+ for (int i = 0; i < size; i++) {
+ values.add(new DexEncodedValueImpl(buffer, annotation, typeIds,
+ stringPool, fieldIdItems));
+ }
+ return values;
+ }
+
+ /**
+ * VALUE_ENUM 0x1b size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+ * four-byte integer value, interpreted as an index into the field_ids
+ * section and representing the value of an enumerated type constant
+ */
+ private Object getEnumValue(int valueArg) {
+ int fieldOffset = buffer.readInt(valueArg + 1);
+ FieldIdItem fieldIdItem = fieldIdItems[fieldOffset];
+ // FORMAT La/b/E;!CONSTANT
+ String constantName = stringPool[fieldIdItem.name_idx];
+ String typeName = stringPool[typeIds[fieldIdItem.type_idx]];
+ return typeName + "!" + constantName;
+ }
+
+ /**
+ * VALUE_METHOD 0x1a size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+ * four-byte integer value, interpreted as an index into the method_ids
+ * section and representing a reflective method value
+ */
+ private Object getMethodValue(int valueArg) {
+ // FIXME lookup value
+ buffer.skip(valueArg + 1);
+ return null;
+ }
+
+ /**
+ * VALUE_FIELD 0x19 size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+ * four-byte integer value, interpreted as an index into the field_ids
+ * section and representing a reflective field value
+ */
+ private Object getFieldValue(int valueArg) {
+ int fieldOffset = buffer.readInt(valueArg + 1);
+ FieldIdItem fieldIdItem = fieldIdItems[fieldOffset];
+ // FORMAT La/b/E;!CONSTANT
+ String fieldName = stringPool[fieldIdItem.name_idx];
+ String typeName = stringPool[typeIds[fieldIdItem.type_idx]];
+ return typeName + "!" + fieldName;
+ }
+
+ /**
+ * VALUE_TYPE 0x18 size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+ * four-byte integer value, interpreted as an index into the type_ids
+ * section and representing a reflective type/class value
+ */
+ private Object getTypeValue(int valueArg) {
+ valueArg++; // size - 1 (0...3)
+ // FIXME SPEC!! states: unsigned (zero-extended) four-byte integer value
+ return stringPool[typeIds[buffer.readInt(valueArg)]];
+ }
+
+ /**
+ * VALUE_STRING 0x17 size - 1 (0...3) ubyte[size] unsigned (zero-extended)
+ * four-byte integer value, interpreted as an index into the string_ids
+ * section and representing a string value
+ */
+ private Object getStringValue(int valueArg) {
+ valueArg++;
+ return stringPool[buffer.readInt(valueArg)];
+ }
+
+ /**
+ * VALUE_DOUBLE 0x11 size - 1 (0...7) ubyte[size] eight-byte bit pattern,
+ * zero-extended to the right, and interpreted as an IEEE754 64-bit floating
+ * point value
+ */
+ private Object getDoubleValue(int valueArg) {
+ return buffer.readDouble(valueArg + 1);
+ }
+
+ /**
+ * VALUE_FLOAT 0x10 size - 1 (0...3) ubyte[size] four-byte bit pattern,
+ * zero-extended to the right, and interpreted as an IEEE754 32-bit floating
+ * point value
+ */
+ private Float getFloatValue(int valueArg) {
+ return buffer.readFloat(valueArg + 1);
+ }
+
+ /**
+ * VALUE_LONG 0x06 size - 1 (0...7) ubyte[size] signed eight-byte integer
+ * value, sign-extended
+ */
+ private Long getLongValue(int valueArg) {
+ return buffer.readLong(valueArg + 1);
+ }
+
+ /**
+ * VALUE_INT 0x04 size - 1 (0...3) ubyte[size] signed four-byte integer
+ * value, sign-extended
+ */
+ private Integer getIntValue(int valueArg) {
+ return buffer.readInt(valueArg + 1);
+ }
+
+ /**
+ * VALUE_CHAR 0x03 size - 1 (0...1) ubyte[size] unsigned two-byte integer
+ * value, zero-extended
+ */
+ private Character getCharValue(int valueArg) {
+ return buffer.readChar(valueArg + 1);
+ }
+
+ /**
+ * VALUE_SHORT 0x02 size - 1 (0...1) ubyte[size] signed two-byte integer
+ * value, sign-extended
+ */
+ private Short getShortValue(int valueArg) {
+ return buffer.readShort(valueArg + 1);
+ }
+
+ /**
+ * VALUE_BYTE 0x00 (none; must be 0) ubyte[1] signed one-byte integer value
+ */
+ private Byte getByteValue(int valueArg) {
+ assert valueArg == 0 : "Illegal valueArg for VALUE_BYTE: " + valueArg;
+ return null;
+ }
+
+ public DexEncodedValueType getType() {
+ return type;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("=");
+ if (type == VALUE_ARRAY) {
+ if (getValue() instanceof List<?>) {
+ List<?> values = (List<?>) getValue();
+ for (Object object : values) {
+ DexEncodedValue val = (DexEncodedValue) object;
+ builder.append(val.getValue());
+ }
+ }
+ } else {
+ builder.append(getValue());
+ }
+ return builder.toString();
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexFieldImpl.java b/tools/dex-tools/src/dex/reader/DexFieldImpl.java
new file mode 100644
index 0000000..f4a8c72
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexFieldImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexClassImpl.FieldAnnotation;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexField;
+
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+/* package */final class DexFieldImpl implements DexField {
+
+ private DexBuffer buffer;
+ private String[] stringPool;
+ private FieldIdItem fieldIdItem;
+ private int[] typeIds;
+ private final int accessFlags;
+ private Set<DexAnnotation> annotations;
+ private FieldAnnotation fieldAnnotation;
+ private TypeFormatter formatter = new TypeFormatter();
+ private final DexClass declaringClass;
+ private final FieldIdItem[] fieldIdItems;
+
+ public DexFieldImpl(DexBuffer buffer, DexClass declaringClass,
+ FieldIdItem fieldIdItem, int accessFlags,
+ FieldAnnotation fieldAnnotation, String[] stringPool,
+ int[] typeIds, FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.declaringClass = declaringClass;
+ this.fieldIdItem = fieldIdItem;
+ this.accessFlags = accessFlags;
+ this.fieldAnnotation = fieldAnnotation;
+ this.stringPool = stringPool;
+ this.typeIds = typeIds;
+ this.fieldIdItems = fieldIdItems;
+ parseAnnotations();
+ }
+
+ private void parseAnnotations() {
+ annotations = new HashSet<DexAnnotation>();
+ if (fieldAnnotation != null) {
+ buffer.setPosition(fieldAnnotation.annotationsOff);
+ final int size = buffer.readUInt();
+ for (int i = 0; i < size; i++) {
+ annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+ buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+ }
+ }
+ }
+
+ public String getName() {
+ return stringPool[fieldIdItem.name_idx];
+ }
+
+ public String getType() {
+ return stringPool[typeIds[fieldIdItem.type_idx]];
+ }
+
+ public int getModifiers() {
+ return accessFlags;
+ }
+
+ public synchronized Set<DexAnnotation> getAnnotations() {
+ return annotations;
+ }
+
+ public DexClass getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public boolean isEnumConstant() {
+ return (getModifiers() & 0x4000) > 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(formatter.formatAnnotations(getAnnotations()));
+ builder.append(Modifier.toString(getModifiers()));
+ builder.append(" ");
+ builder.append(formatter.format(getType()));
+ builder.append(" ");
+ builder.append(getName());
+ return builder.toString();
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexFileImpl.java b/tools/dex-tools/src/dex/reader/DexFileImpl.java
new file mode 100644
index 0000000..da066f1
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexFileImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.reader.DexFileReader.ClassDefItem;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.reader.DexFileReader.MethodsIdItem;
+import dex.reader.DexFileReader.ProtIdItem;
+import dex.structure.DexClass;
+import dex.structure.DexFile;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/* package */final class DexFileImpl implements DexFile {
+
+ private final String[] stringPool;
+ private final int[] typeIds;
+ private ProtIdItem[] protoIdItems;
+ private FieldIdItem[] fieldIdItems;
+ private MethodsIdItem[] methodIdItems;
+ private ClassDefItem[] classDefItems;
+ private final DexBuffer buffer;
+
+ private List<DexClass> classes = null;
+
+ public DexFileImpl(DexBuffer buffer, String[] stringPool, int[] typeIds,
+ ProtIdItem[] protoIds, FieldIdItem[] fieldIdItems,
+ MethodsIdItem[] methodIdItems, ClassDefItem[] classDefItems) {
+ this.buffer = buffer;
+ this.stringPool = stringPool;
+ this.typeIds = typeIds;
+ this.protoIdItems = protoIds;
+ this.fieldIdItems = fieldIdItems;
+ this.methodIdItems = methodIdItems;
+ this.classDefItems = classDefItems;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dex.reader.DexFile#getDefinedClasses()
+ */
+ public synchronized List<DexClass> getDefinedClasses() {
+ if (classes == null) {
+ classes = new ArrayList<DexClass>(classDefItems.length);
+ for (int i = 0; i < classDefItems.length; i++) {
+ classes.add(new DexClassImpl(buffer.createCopy(),
+ classDefItems[i], stringPool, typeIds, protoIdItems,
+ fieldIdItems, methodIdItems));
+ }
+ }
+ return classes;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ b.append("StringPool:\n").append(Arrays.toString(stringPool));
+ b.append("\nTypes:\n");
+ for (int i = 0; i < typeIds.length; i++) {
+ b.append(stringPool[typeIds[i]] + "\n");
+ }
+ b.append("\nProtos:\n").append(Arrays.toString(protoIdItems));
+ b.append("\nFields:\n").append(Arrays.toString(fieldIdItems));
+ b.append("\nMethods:\n").append(Arrays.toString(methodIdItems));
+ b.append("\nClasses:\n").append(Arrays.toString(classDefItems));
+ return b.toString();
+ }
+
+ public String getName() {
+ return "DexFile";
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexFileReader.java b/tools/dex-tools/src/dex/reader/DexFileReader.java
new file mode 100644
index 0000000..1fd17f6
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexFileReader.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.structure.DexFile;
+
+import java.util.Arrays;
+
+public final class DexFileReader {
+
+ // DEX constants
+ private int ENDIAN_CONSTANT = 0x12345678;
+ @SuppressWarnings("unused")
+ private int REVERSE_ENDIAN_CONSTANT = 0x78563412;
+ private final byte[] REF_MAGIC = new byte[] {
+ 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00};
+
+ // Header values
+ private DexBuffer b;
+ private byte[] magic = new byte[8];
+ @SuppressWarnings("unused")
+ private int checksum = 0;
+ private byte[] signature = new byte[20];
+ @SuppressWarnings("unused")
+ private int fileSize = 0;
+ @SuppressWarnings("unused")
+ private int headerSize = 0;
+ private int endianTag = 0;
+
+ // Indices of offset and size items
+ private static final int LINK = 0;
+ private static final int MAP = 1; // no size!
+ private static final int STRING_IDS = 2;
+ private static final int TYPE_IDS = 3;
+ private static final int PROTO_IDS = 4;
+ private static final int FIELD_IDS = 5;
+ private static final int METHOD_IDS = 6;
+ private static final int CLASS_DEFS = 7;
+ private static final int DATA = 8;
+
+ private int[] size = new int[9];
+ private int[] off = new int[9];
+
+
+ //
+ private String[] stringPool;
+ private int[] typeIds; // values are index of stringPool
+ private ProtIdItem[] protoIdItems;
+ private FieldIdItem[] fieldIdItems;
+ private MethodsIdItem[] methodIdItems;
+ private ClassDefItem[] classDefItems;
+
+ // starting buffer at zero
+ public DexFile read(DexBuffer buffer) {
+ this.b = buffer;
+ readMagic();
+ readChecksum();
+ readSignature();
+ readFileSize();
+ readHeaderSize();
+ readEndianTag();
+ readSize(LINK);
+ readOffset(LINK);
+ readOffset(MAP);
+ readSize(STRING_IDS);
+ readOffset(STRING_IDS);
+ readSize(TYPE_IDS);
+ readOffset(TYPE_IDS);
+ readSize(PROTO_IDS);
+ readOffset(PROTO_IDS);
+ readSize(FIELD_IDS);
+ readOffset(FIELD_IDS);
+ readSize(METHOD_IDS);
+ readOffset(METHOD_IDS);
+ readSize(CLASS_DEFS);
+ readOffset(CLASS_DEFS);
+ readSize(DATA);
+ readOffset(DATA);
+ // from now on, index is not automatically on the desired position
+ readStrings();
+ readTypeIds();
+ readProtos();
+ readFields();
+ readMethods();
+ readClasses();
+
+ return new DexFileImpl(b.createCopy(), stringPool, typeIds,
+ protoIdItems, fieldIdItems, methodIdItems, classDefItems);
+ }
+
+ // MAGIC (8, U_BYTE)
+ // "dex\n035\0"
+ private void readMagic() {
+ b.readBytes(magic);
+ assert Arrays.equals(magic, REF_MAGIC) : "Not a DEX file";
+ }
+
+ // CHECKSUM (1, U_INT)
+ private void readChecksum() {
+ checksum = b.readUInt();
+ }
+
+ // SIGNATURE (20, U_BYTE)
+ private void readSignature() {
+ b.readBytes(signature);
+ }
+
+ // FILE_SIZE (1, U_INT)
+ private void readFileSize() {
+ fileSize = b.readUInt();
+ }
+
+ // HEADER_SIZE (1, U_INT), //0x70
+ private void readHeaderSize() {
+ headerSize = b.readUInt();
+ }
+
+ // ENDIAN_TAG (1, U_INT), //ENDIAN_CONSTANT
+ private void readEndianTag() {
+ endianTag = b.readUInt();
+ // FIXME Support for big endian encoded dex files
+ assert endianTag == ENDIAN_CONSTANT : "Byteorder NOT in little endian";
+ }
+
+ private void readSize(int attribute) {
+ size[attribute] = b.readUInt();
+ }
+
+ private void readOffset(int attribute) {
+ off[attribute] = b.readUInt();
+ }
+
+ // reads the string pool
+ private void readStrings() {
+ int nStrings = size[STRING_IDS];
+ b.setPosition(off[STRING_IDS]); // the first string offset is here
+ int[] stringDataOffsets = new int[nStrings];
+
+ for (int i = 0; i < stringDataOffsets.length; i++) {
+ stringDataOffsets[i] = b.readUInt();
+ }
+
+ stringPool = new String[nStrings];
+ for (int i = 0; i < stringDataOffsets.length; i++) {
+ b.setPosition(stringDataOffsets[i]); // set buffer to offset
+ // Position
+ int lenght = b.readUleb128(); // read uleb128
+ byte[] values = new byte[lenght];
+ b.readBytes(values);
+ stringPool[i] = new String(values);
+ }
+ }
+
+ private void readTypeIds() {
+ int nTypes = size[TYPE_IDS];
+ b.setPosition(off[TYPE_IDS]); // the first element is here
+ typeIds = new int[nTypes];
+
+ for (int i = 0; i < typeIds.length; i++) {
+ typeIds[i] = b.readUInt();
+ }
+ }
+
+ static class ProtIdItem {
+ public int shorty_idx;
+ public int return_type_idx;
+ public int parameter_off;
+ }
+
+ private void readProtos() {
+ int nProtos = size[PROTO_IDS];
+ b.setPosition(off[PROTO_IDS]);
+ protoIdItems = new ProtIdItem[nProtos];
+
+ ProtIdItem item = null;
+ for (int i = 0; i < protoIdItems.length; i++) {
+ item = new ProtIdItem();
+ item.shorty_idx = b.readUInt();
+ item.return_type_idx = b.readUInt();
+ item.parameter_off = b.readUInt();
+ protoIdItems[i] = item;
+ }
+ }
+
+ static class FieldIdItem {
+ public int class_idx; // defining class : index of type_ids
+ public int type_idx; // type of field : index of type_ids
+ public int name_idx; // name of field : index into string id (or
+ // directly stringpool)
+ }
+
+ private void readFields() {
+ int nFields = size[FIELD_IDS];
+ b.setPosition(off[FIELD_IDS]);
+ fieldIdItems = new FieldIdItem[nFields];
+
+ FieldIdItem item = null;
+ for (int i = 0; i < fieldIdItems.length; i++) {
+ item = new FieldIdItem();
+ item.class_idx = b.readUShort();
+ item.type_idx = b.readUShort();
+ item.name_idx = b.readUInt();
+ fieldIdItems[i] = item;
+ }
+ }
+
+ static class MethodsIdItem {
+ public int class_idx; // defining class : index of typeIds
+ public int proto_idx; // proto of method : index of protoIdItems
+ public int name_idx; // name of method : index into string id (or
+ // directly stringpool)
+ }
+
+ private void readMethods() {
+ int nMethods = size[METHOD_IDS];
+ b.setPosition(off[METHOD_IDS]);
+ methodIdItems = new MethodsIdItem[nMethods];
+
+ MethodsIdItem item = null;
+ for (int i = 0; i < methodIdItems.length; i++) {
+ item = new MethodsIdItem();
+ item.class_idx = b.readUShort();
+ item.proto_idx = b.readUShort();
+ item.name_idx = b.readUInt();
+ methodIdItems[i] = item;
+ }
+ }
+
+ public static class ClassDefItem {
+ public int class_idx;
+ public int access_flags;
+ public int superclass_idx;
+ public int interfaces_off;
+ public int source_file_idx;
+ public int annotations_off;
+ public int class_data_off;
+ public int static_values_off;
+ }
+
+ private void readClasses() {
+ int nClassDefs = size[CLASS_DEFS];
+ b.setPosition(off[CLASS_DEFS]);
+ classDefItems = new ClassDefItem[nClassDefs];
+
+ ClassDefItem item = null;
+ for (int i = 0; i < classDefItems.length; i++) {
+ item = new ClassDefItem();
+ item.class_idx = b.readUInt();
+ item.access_flags = b.readUInt();
+ item.superclass_idx = b.readUInt();
+ item.interfaces_off = b.readUInt();
+ item.source_file_idx = b.readUInt();
+ item.annotations_off = b.readUInt();
+ item.class_data_off = b.readUInt();
+ item.static_values_off = b.readUInt();
+ classDefItems[i] = item;
+ }
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexMethodImpl.java b/tools/dex-tools/src/dex/reader/DexMethodImpl.java
new file mode 100644
index 0000000..21a19e5
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexMethodImpl.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import dex.reader.DexClassImpl.MethodAnnotation;
+import dex.reader.DexClassImpl.ParameterAnnotation;
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.reader.DexFileReader.MethodsIdItem;
+import dex.reader.DexFileReader.ProtIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexMethod;
+import dex.structure.DexParameter;
+
+/* package */final class DexMethodImpl implements DexMethod {
+
+ private DexBuffer buffer;
+ private MethodsIdItem methodsIdItem;
+ private String[] stringPool;
+ private int[] typeIds;
+ private ProtIdItem protoIdItem;
+ private List<DexParameter> parameters;
+ private final int accessFlags;
+ private final MethodAnnotation methodAnnotation;
+ private Set<DexAnnotation> annotations;
+ private final TypeFormatter formatter = new TypeFormatter();
+ private final DexClass declaringClass;
+ private final ParameterAnnotation parameterAnnotation;
+ private Map<Integer, Integer> parameterIdToIndex;
+ private final FieldIdItem[] fieldIdItems;
+
+ public DexMethodImpl(DexBuffer buffer, DexClass declaringClass,
+ MethodsIdItem methodsIdItem, ProtIdItem protoIdItem,
+ int accessFlags, MethodAnnotation methodAnnotation,
+ ParameterAnnotation parameterAnnotation, String[] stringPool,
+ int[] typeIds, FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.declaringClass = declaringClass;
+ this.methodsIdItem = methodsIdItem;
+ this.protoIdItem = protoIdItem;
+ this.accessFlags = accessFlags;
+ this.methodAnnotation = methodAnnotation;
+ this.parameterAnnotation = parameterAnnotation;
+ this.stringPool = stringPool;
+ this.typeIds = typeIds;
+ this.fieldIdItems = fieldIdItems;
+ parseAnnotations();
+ parseParameterAnnotations();
+ }
+
+ private void parseParameterAnnotations() {
+ parameterIdToIndex = new HashMap<Integer, Integer>();
+ if (parameterAnnotation != null) {
+ buffer.setPosition(parameterAnnotation.annotationsOff);
+ int numberOfParameters = buffer.readUInt();
+ for (int i = 0; i < numberOfParameters; i++) {
+ parameterIdToIndex.put(i, buffer.readUInt());
+ }
+ }
+ }
+
+ private void parseAnnotations() {
+ annotations = new HashSet<DexAnnotation>();
+ if (methodAnnotation != null) {
+ buffer.setPosition(methodAnnotation.annotationsOff);
+ final int size = buffer.readUInt();
+ for (int i = 0; i < size; i++) {
+ annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+ buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+ }
+ }
+ }
+
+ public String getName() {
+ return stringPool[methodsIdItem.name_idx];
+ }
+
+ public String getReturnType() {
+ return stringPool[typeIds[protoIdItem.return_type_idx]];
+ }
+
+ public synchronized List<DexParameter> getParameters() {
+ if (parameters == null) {
+ parameters = new LinkedList<DexParameter>();
+ if (protoIdItem.parameter_off != 0) {
+
+ buffer.setPosition(protoIdItem.parameter_off);
+ int size = buffer.readUInt();
+
+ int[] paramTypeIdx = new int[size];
+ for (int i = 0; i < size; i++) {
+ paramTypeIdx[i] = buffer.readUShort();
+ }
+ for (int i = 0; i < paramTypeIdx.length; i++) {
+ parameters.add(new DexParameterImpl(buffer.createCopy(),
+ stringPool[typeIds[paramTypeIdx[i]]],
+ parameterIdToIndex.get(i), typeIds, stringPool,
+ fieldIdItems));
+ }
+ }
+ }
+ return parameters;
+ }
+
+ public int getModifiers() {
+ return accessFlags;
+ }
+
+ public Set<DexAnnotation> getAnnotations() {
+ return annotations;
+ }
+
+ public DexClass getDeclaringClass() {
+ return declaringClass;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(formatter.formatAnnotations(getAnnotations()));
+ builder.append(Modifier.toString(getModifiers()));
+ builder.append(" ");
+ builder.append(formatter.format(getReturnType()));
+ builder.append(" ");
+ builder.append(getName());
+ builder.append("(");
+ List<DexParameter> parameters = getParameters();
+ for (DexParameter dexParameter : parameters) {
+ builder.append(formatter.formatAnnotations(dexParameter
+ .getAnnotations()));
+ builder.append(formatter.format(dexParameter.getTypeName()));
+ }
+ builder.append(")");
+ return builder.toString();
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/DexParameterImpl.java b/tools/dex-tools/src/dex/reader/DexParameterImpl.java
new file mode 100644
index 0000000..ec2db05
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/DexParameterImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import dex.reader.DexFileReader.FieldIdItem;
+import dex.structure.DexAnnotation;
+import dex.structure.DexParameter;
+
+public class DexParameterImpl implements DexParameter {
+
+ private final String typeName;
+ private final Integer annotationOffset;
+ private Set<DexAnnotation> annotations;
+ private final DexBuffer buffer;
+ private final int[] typeIds;
+ private final String[] stringPool;
+ private final FieldIdItem[] fieldIdItems;
+
+ public DexParameterImpl(DexBuffer buffer, String typeName,
+ Integer annotationOffset, int[] typeIds, String[] stringPool,
+ FieldIdItem[] fieldIdItems) {
+ this.buffer = buffer;
+ this.typeName = typeName;
+ this.annotationOffset = annotationOffset;
+ this.typeIds = typeIds;
+ this.stringPool = stringPool;
+ this.fieldIdItems = fieldIdItems;
+ parseAnnotations();
+ }
+
+ private void parseAnnotations() {
+ annotations = new HashSet<DexAnnotation>();
+ if (annotationOffset != null) {
+ buffer.setPosition(annotationOffset);
+ final int size = buffer.readUInt();
+ for (int i = 0; i < size; i++) {
+ annotations.add(new DexAnnotationImpl(buffer.createCopy(),
+ buffer.readUInt(), typeIds, stringPool, fieldIdItems));
+ }
+ }
+ }
+
+ public String getTypeName() {
+ return typeName;
+ }
+
+ public Set<DexAnnotation> getAnnotations() {
+ return annotations;
+ }
+
+ @Override
+ public String toString() {
+ return getTypeName();
+ }
+}
diff --git a/tools/dex-tools/src/dex/reader/TypeFormatter.java b/tools/dex-tools/src/dex/reader/TypeFormatter.java
new file mode 100644
index 0000000..f54b30f
--- /dev/null
+++ b/tools/dex-tools/src/dex/reader/TypeFormatter.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2009 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 dex.reader;
+
+import dex.structure.DexAnnotation;
+import dex.structure.DexClass;
+import dex.structure.DexField;
+import dex.structure.DexFile;
+import dex.structure.DexMethod;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <pre>
+ * TypeDescriptor := 'V' | FieldTypeDescriptor
+ * FieldTypeDescriptor := NonArrayFieldTypeDescriptor | ('[' * 1...255) NonArrayFieldTypeDescriptor
+ * NonArrayFieldTypeDescriptor := 'Z' | 'B' | 'S' | 'C' | 'I' | 'J' | 'F' | 'D' | 'L' FullClassName ';'
+ * </pre>
+ */
+public final class TypeFormatter {
+
+ /**
+ * V void; only valid for return types Z boolean B byte S short C char I int
+ * J long F float D double Lfully/qualified/Name; the class
+ * fully.qualified.Name [descriptor array of descriptor, usable recursively
+ * for arrays-of-arrays, though it is invalid to have more than 255
+ * dimensions.
+ */
+ public String format(String typeName) {
+ if (typeName.length() == 1) {
+ switch (typeName.charAt(0)) {
+ case 'V':
+ return "void";
+ case 'Z':
+ return "boolean";
+ case 'B':
+ return "byte";
+ case 'S':
+ return "short";
+ case 'C':
+ return "char";
+ case 'I':
+ return "int";
+ case 'J':
+ return "long";
+ case 'F':
+ return "float";
+ case 'D':
+ return "double";
+ }
+ } else {
+ if (typeName.startsWith("L")) {
+ return typeName.substring(1, typeName.length() - 1).replace(
+ "/", "."); // remove 'L' and ';', replace '/' with '.'
+ } else if (typeName.startsWith("[")) {
+ return format(typeName.substring(1)) + "[]";
+ }
+ }
+ System.err.println("Strange type in formatter: " + typeName);
+ return typeName;
+ }
+
+ public String format(List<String> typeNames) {
+ List<String> types = new ArrayList<String>(typeNames.size());
+ for (String type : typeNames) {
+ types.add(format(type));
+ }
+ return format(types, ", ");
+ }
+
+ public String formatAnnotations(Set<DexAnnotation> annotations) {
+ return format(new ArrayList<DexAnnotation>(annotations), "\n") + "\n";
+ }
+
+ private String format(List<?> elements, String separator) {
+ StringBuilder builder = new StringBuilder();
+ boolean first = true;
+ for (Object element : elements) {
+ if (!first) {
+ builder.append(separator);
+ }
+ builder.append(element.toString());
+ first = false;
+ }
+ return builder.toString();
+ }
+
+
+ public String formatDexFile(DexFile file) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("----------------DEX_FILE--------------\n\n");
+ builder.append("Filename: ").append(file.getName());
+ builder.append("\n-----------DEFINED_CLASSES------------\n\n");
+ for (DexClass dexClass : file.getDefinedClasses()) {
+ builder.append("\n________________CLASS________________\n\n");
+ builder.append(dexClass);
+ builder.append("\n\n----------------FIELDS----------------\n");
+ for (DexField field : dexClass.getFields()) {
+ builder.append(field).append("\n");
+ }
+ builder.append("----------------METHODS----------------\n");
+ for (DexMethod method : dexClass.getMethods()) {
+ builder.append(method).append("\n");
+ }
+ }
+ return builder.toString();
+ }
+}
diff --git a/tools/dex-tools/src/dex/structure/DexAnnotatedElement.java b/tools/dex-tools/src/dex/structure/DexAnnotatedElement.java
new file mode 100644
index 0000000..0b69ca8
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexAnnotatedElement.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.Set;
+
+/**
+ * {@code DexAnnotatedElement} is implemented by all Elements that could have
+ * attached annotations.
+ */
+public interface DexAnnotatedElement {
+
+ /**
+ * Returns a list of {@code DexAnnotation} elements.
+ *
+ * @return a list of {@code DexAnnotation} elements
+ */
+ Set<DexAnnotation> getAnnotations();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexAnnotation.java b/tools/dex-tools/src/dex/structure/DexAnnotation.java
new file mode 100644
index 0000000..9cd372d
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexAnnotation.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+/**
+ * {@code DexAnnotation} represents an annotation.
+ */
+public interface DexAnnotation {
+
+ /**
+ * {@code Visibility} indicates the retention of a {@code DexAnnotation}.
+ */
+ enum Visibility {
+ /**
+ * Intended only to be visible at build time (e.g., during compilation
+ * of other code).
+ */
+ VISIBILITY_BUILD((byte) 0x00),
+ /**
+ * Intended to be visible at runtime. FIXME missing words in spec
+ */
+ VISIBILITY_RUNTIME((byte) 0X01),
+ /**
+ * Intended to be visible at runtime, but only to the underlying system
+ * (and not to regular user code). FIXME missing words in spec
+ */
+ VISIBILITY_SYSTEM((byte) 0x02);
+
+ @SuppressWarnings("unused")
+ private byte value;
+
+ private Visibility(byte value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the {@code Visibility} identified by the given {@code byte}.
+ * pre: 0 <= {@code value} <=2
+ *
+ * @param value
+ * the {@code byte} value which identifies a {@code
+ * Visibility}
+ * @return the {@code Visibility} for the given {@code byte}
+ */
+ public static Visibility get(byte value) {
+ // FIXME loop and compare instead of switch?
+ switch (value) {
+ case 0x00:
+ return VISIBILITY_BUILD;
+ case 0x01:
+ return VISIBILITY_RUNTIME;
+ case 0x02:
+ return VISIBILITY_SYSTEM;
+ default:
+ throw new IllegalArgumentException("Visibility doesn't exist!");
+ }
+ }
+ }
+
+ /**
+ * Returns the {@code Visibility} of this {@code DexAnnotation}.
+ *
+ * @return the {@code Visibility} of this {@code DexAnnotation}
+ */
+ Visibility getVisibility();
+
+ /**
+ * Returns the attributes of this {@code DexAnnotation}.
+ *
+ * @return the attributes of this {@code DexAnnotation}
+ */
+ List<DexAnnotationAttribute> getAttributes();
+
+ /**
+ * Returns the class name of this {@code DexAnnotation}.
+ *
+ * @return the class name of this {@code DexAnnotation}
+ */
+ String getTypeName();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexAnnotationAttribute.java b/tools/dex-tools/src/dex/structure/DexAnnotationAttribute.java
new file mode 100644
index 0000000..4d51c08
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexAnnotationAttribute.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexAnnotationValue} is implemented by annotation values. In the
+ * following example:
+ *
+ * <pre>
+ * @Text(value="hello")
+ * </pre>
+ *
+ * 'value="hello"' is represented by a {@code DexAnnotationValue}. "value" is
+ * its name and "hello" is its encoded value.
+ */
+public interface DexAnnotationAttribute extends NamedElement {
+ /**
+ * Returns the encoded value of this {@code DexAnnotationValue}.
+ *
+ * @return the encoded value of this {@code DexAnnotationValue}
+ */
+ public DexEncodedValue getEncodedValue();
+
+ public DexAnnotation getAnnotation();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexClass.java b/tools/dex-tools/src/dex/structure/DexClass.java
new file mode 100644
index 0000000..198f4ee
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexClass.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+/**
+ * {@code DexClass} represents a class.
+ */
+public interface DexClass extends DexAnnotatedElement, WithModifiers,
+ NamedElement {
+ /**
+ * Returns a list containing the names of all implemented interfaces.
+ *
+ * @return a list containing the names of all implemented interfaces
+ */
+ List<String> getInterfaces();
+
+ /**
+ * Returns the name of the super class.
+ *
+ * @return the name of the super class, maybe {@code null}
+ */
+ String getSuperClass();
+
+ /**
+ * Returns a list containing all fields declared by this {@code DexClass}.
+ *
+ * @return a list containing all fields declared by this {@code DexClass}
+ */
+ List<DexField> getFields();
+
+ /**
+ * Returns a list containing all methods declared by this {@code DexClass}.
+ *
+ * @return a list containing all methods declared by this {@code DexClass}
+ */
+ List<DexMethod> getMethods();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexEncodedAnnotation.java b/tools/dex-tools/src/dex/structure/DexEncodedAnnotation.java
new file mode 100644
index 0000000..f31fe74
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexEncodedAnnotation.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+public interface DexEncodedAnnotation extends DexEncodedValue {
+ String getTypeName();
+
+ List<DexAnnotationAttribute> getValue();
+
+}
diff --git a/tools/dex-tools/src/dex/structure/DexEncodedValue.java b/tools/dex-tools/src/dex/structure/DexEncodedValue.java
new file mode 100644
index 0000000..1d09f34
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexEncodedValue.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexEncodedValue} represents an encoded value. The value of a {@code
+ * DexAnnotationValue} is encoded as {@code DexEncodedValue}.
+ */
+public interface DexEncodedValue {
+
+ /**
+ * Returns the type of this {@code DexEncodedValue}.
+ *
+ * @return the type of this {@code DexEncodedValue}
+ */
+ DexEncodedValueType getType();
+
+ /**
+ * Returns the value of this {@code DexEncodedValue}.
+ *
+ * @return the value of this {@code DexEncodedValue}
+ */
+ Object getValue();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexEncodedValueType.java b/tools/dex-tools/src/dex/structure/DexEncodedValueType.java
new file mode 100644
index 0000000..00560f3
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexEncodedValueType.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexEncodedValueType} represents the type of an {code DexEncodedValue}.
+ */
+public enum DexEncodedValueType {
+ /**
+ * <pre>
+ * VALUE_BYTE 0x00 (none; must be 0) ubyte[1]
+ * </pre>
+ *
+ * signed one-byte integer value
+ */
+ VALUE_BYTE((byte) 0x00),
+ /**
+ * <pre>
+ * VALUE_SHORT 0x02 size - 1 (0...1) ubyte[size]
+ * </pre>
+ *
+ * signed two-byte integer value, sign-extended
+ */
+ VALUE_SHORT((byte) 0x02),
+ /**
+ * <pre>
+ * VALUE_CHAR 0x03 size - 1 (0...1) ubyte[size]
+ * </pre>
+ *
+ * unsigned two-byte integer value, zero-extended
+ */
+ VALUE_CHAR((byte) 0x03),
+ /**
+ * <pre>
+ * VALUE_INT 0x04 size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * signed four-byte integer value, sign-extended
+ */
+ VALUE_INT((byte) 0x04),
+ /**
+ * <pre>
+ * VALUE_LONG 0x06 size - 1 (0...7) ubyte[size]
+ * </pre>
+ *
+ * signed eight-byte integer value, sign-extended
+ */
+ VALUE_LONG((byte) 0x06),
+ /**
+ * <pre>
+ * VALUE_FLOAT 0x10 size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * four-byte bit pattern, zero-extended to the right, and interpreted as an
+ * IEEE754 32-bit floating point value
+ */
+ VALUE_FLOAT((byte) 0x10),
+ /**
+ * <pre>
+ * VALUE_DOUBLE 0x11 size - 1 (0...7) ubyte[size]
+ * </pre>
+ *
+ * eight-byte bit pattern, zero-extended to the right, and interpreted as an
+ * IEEE754 64-bit floating point value
+ */
+ VALUE_DOUBLE((byte) 0x11),
+ /**
+ * <pre>
+ * VALUE_STRING 0x17 size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * unsigned (zero-extended) four-byte integer value, interpreted as an index
+ * into the string_ids section and representing a string value
+ */
+ VALUE_STRING((byte) 0x17),
+ /**
+ * <pre>
+ * VALUE_TYPE 0x18 size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * unsigned (zero-extended) four-byte integer value, interpreted as an index
+ * into the type_ids section and representing a reflective type/class value
+ */
+ VALUE_TYPE((byte) 0x18),
+ /**
+ * <pre>
+ * VALUE_FIELD 0x19 size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * unsigned (zero-extended) four-byte integer value, interpreted as an index
+ * into the field_ids section and representing a reflective field value
+ */
+ VALUE_FIELD((byte) 0x19),
+ /**
+ * <pre>
+ * VALUE_METHOD 0x1a size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * unsigned (zero-extended) four-byte integer value, interpreted as an index
+ * into the method_ids section and representing a reflective method value
+ */
+ VALUE_METHOD((byte) 0x1a),
+ /**
+ * <pre>
+ * VALUE_ENUM 0x1b size - 1 (0...3) ubyte[size]
+ * </pre>
+ *
+ * unsigned (zero-extended) four-byte integer value, interpreted as an index
+ * into the field_ids section and representing the value of an enumerated
+ * type constant
+ */
+ VALUE_ENUM((byte) 0x1b),
+ /**
+ * <pre>
+ * VALUE_ARRAY 0x1c (none; must be 0) encoded_array
+ * </pre>
+ *
+ * an array of values, in the format specified by "encoded_array Format"
+ * below. The size of the value is implicit in the encoding.
+ */
+ VALUE_ARRAY((byte) 0x1c),
+ /**
+ * <pre>
+ * VALUE_ANNOTATION 0x1d (none; must be 0) encoded_annotation
+ * </pre>
+ *
+ * a sub-annotation, in the format specified by "encoded_annotation Format"
+ * below. The size of the value is implicit in the encoding.
+ */
+ VALUE_ANNOTATION((byte) 0x1d),
+ /**
+ * <pre>
+ * VALUE_NULL 0x1e (none; must be 0) (none)
+ * </pre>
+ *
+ * null reference value
+ */
+ VALUE_NULL((byte) 0x1e),
+ /**
+ * <pre>
+ * VALUE_BOOLEAN 0x1f boolean (0...1) (none)
+ * </pre>
+ *
+ * one-bit value; 0 for false and 1 for true. The bit is represented in the
+ * value_arg.
+ */
+ VALUE_BOOLEAN((byte) 0x1f);
+
+ private byte value;
+
+ /**
+ * Creates a new instance of {@code DexEncodedValueType} using the provided
+ * byte.
+ * <p>
+ * Format: value := (value_arg << 5) | value_type
+ *
+ * @param value
+ * the {@code byte} containing the type and the value argument
+ */
+ private DexEncodedValueType(byte value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the {@code DexEncodedValueType} for the given {@code byte}.
+ *
+ * @param value
+ * the {@code byte} containing the type and the value argument
+ * @return the {@code DexEncodedValueType} for the given {@code byte}
+ */
+ public static DexEncodedValueType get(byte value) {
+ // FIXME don't loop -> switch to get performance boost
+ for (DexEncodedValueType type : values()) {
+ if (type.value == (value & 0x1F)) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("Type does not exist!");
+ }
+
+ /**
+ * Returns the value argument of the given {@code byte}.
+ * <p>
+ * Format: value := (value_arg << 5) | value_type
+ *
+ * @param value
+ * the {@code byte} containing the type and the value argument
+ * @return the value argument of the given {@code byte}
+ */
+ public static byte valueArg(byte value) {
+ return (byte) (value >>> 5);
+ }
+}
diff --git a/tools/dex-tools/src/dex/structure/DexField.java b/tools/dex-tools/src/dex/structure/DexField.java
new file mode 100644
index 0000000..419bfad
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexField.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexField} represents a field.
+ */
+public interface DexField extends DexAnnotatedElement, WithModifiers,
+ NamedElement {
+
+ /**
+ * Returns the name of the type of this {@code DexField}.
+ *
+ * @return the name of the type of this {@code DexField}
+ */
+ String getType();
+
+ DexClass getDeclaringClass();
+
+ boolean isEnumConstant();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexFile.java b/tools/dex-tools/src/dex/structure/DexFile.java
new file mode 100644
index 0000000..f7ee50e
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexFile.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+
+import java.util.List;
+
+/**
+ * {@code DexFile} represents a whole dex file, containing multiple classes.
+ */
+public interface DexFile extends NamedElement {
+
+ /**
+ * Returns a list of {@code DexClass} elements that are part of this {@code
+ * DexFile}.
+ *
+ * @return a list of {@code DexClass} elements that are part of this {@code
+ * DexFile}
+ */
+ public List<DexClass> getDefinedClasses();
+
+}
diff --git a/tools/dex-tools/src/dex/structure/DexInterface.java b/tools/dex-tools/src/dex/structure/DexInterface.java
new file mode 100644
index 0000000..639b14d
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexInterface.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code DexInterface} represents an interface.
+ */
+public interface DexInterface extends DexAnnotatedElement {
+}
diff --git a/tools/dex-tools/src/dex/structure/DexMethod.java b/tools/dex-tools/src/dex/structure/DexMethod.java
new file mode 100644
index 0000000..a2e3a09
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexMethod.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.util.List;
+
+/**
+ * {@code DexMethod} represents a method.
+ */
+public interface DexMethod extends WithModifiers, DexAnnotatedElement,
+ NamedElement {
+ /**
+ * Returns a list of strings representing the types of the parameters of
+ * this method.
+ *
+ * @return a list of strings representing the types of the parameters of
+ * this method
+ */
+ public List<DexParameter> getParameters();
+
+ public String getReturnType();
+
+ public DexClass getDeclaringClass();
+}
diff --git a/tools/dex-tools/src/dex/structure/DexParameter.java b/tools/dex-tools/src/dex/structure/DexParameter.java
new file mode 100644
index 0000000..22a21e0
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/DexParameter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+public interface DexParameter extends DexAnnotatedElement {
+ String getTypeName();
+}
diff --git a/tools/dex-tools/src/dex/structure/NamedElement.java b/tools/dex-tools/src/dex/structure/NamedElement.java
new file mode 100644
index 0000000..ab8b128
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/NamedElement.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+/**
+ * {@code NamedElement} represents an element with a name.
+ */
+public interface NamedElement {
+ /**
+ * Returns the name of this {@code NamedElement}.
+ *
+ * @return the name of this {@code NamedElement}
+ */
+ String getName();
+}
diff --git a/tools/dex-tools/src/dex/structure/WithModifiers.java b/tools/dex-tools/src/dex/structure/WithModifiers.java
new file mode 100644
index 0000000..804c461
--- /dev/null
+++ b/tools/dex-tools/src/dex/structure/WithModifiers.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 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 dex.structure;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * {@link WithModifiers} is implemented by all language elements that have
+ * modifiers.
+ */
+public interface WithModifiers {
+
+ /**
+ * The {@link Modifier} class should be used to decode the result.
+ *
+ * @return the modifiers for this member
+ *
+ * @see Modifier
+ */
+ int getModifiers();
+}