summaryrefslogtreecommitdiffstats
path: root/dx/src/com/android/dx/dex/file
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:14 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:14 -0800
commitf72d5de56a522ac3be03873bdde26f23a5eeeb3c (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /dx/src/com/android/dx/dex/file
parent31e30105703263782efd450d356cd67ea01af3b7 (diff)
downloadandroid_dalvik-f72d5de56a522ac3be03873bdde26f23a5eeeb3c.tar.gz
android_dalvik-f72d5de56a522ac3be03873bdde26f23a5eeeb3c.tar.bz2
android_dalvik-f72d5de56a522ac3be03873bdde26f23a5eeeb3c.zip
auto import from //depot/cupcake/@135843
Diffstat (limited to 'dx/src/com/android/dx/dex/file')
-rw-r--r--dx/src/com/android/dx/dex/file/AnnotationItem.java220
-rw-r--r--dx/src/com/android/dx/dex/file/AnnotationSetItem.java157
-rw-r--r--dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java80
-rw-r--r--dx/src/com/android/dx/dex/file/AnnotationUtils.java254
-rw-r--r--dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java385
-rw-r--r--dx/src/com/android/dx/dex/file/CatchStructs.java320
-rw-r--r--dx/src/com/android/dx/dex/file/ClassDataItem.java431
-rw-r--r--dx/src/com/android/dx/dex/file/ClassDefItem.java410
-rw-r--r--dx/src/com/android/dx/dex/file/ClassDefsSection.java187
-rw-r--r--dx/src/com/android/dx/dex/file/CodeItem.java335
-rw-r--r--dx/src/com/android/dx/dex/file/DebugInfoConstants.java154
-rw-r--r--dx/src/com/android/dx/dex/file/DebugInfoDecoder.java563
-rw-r--r--dx/src/com/android/dx/dex/file/DebugInfoEncoder.java1035
-rw-r--r--dx/src/com/android/dx/dex/file/DebugInfoItem.java170
-rw-r--r--dx/src/com/android/dx/dex/file/DexFile.java647
-rw-r--r--dx/src/com/android/dx/dex/file/EncodedArrayItem.java131
-rw-r--r--dx/src/com/android/dx/dex/file/EncodedField.java154
-rw-r--r--dx/src/com/android/dx/dex/file/EncodedMember.java86
-rw-r--r--dx/src/com/android/dx/dex/file/EncodedMethod.java196
-rw-r--r--dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java122
-rw-r--r--dx/src/com/android/dx/dex/file/FieldIdItem.java70
-rw-r--r--dx/src/com/android/dx/dex/file/FieldIdsSection.java137
-rw-r--r--dx/src/com/android/dx/dex/file/HeaderItem.java123
-rw-r--r--dx/src/com/android/dx/dex/file/HeaderSection.java63
-rw-r--r--dx/src/com/android/dx/dex/file/IdItem.java61
-rw-r--r--dx/src/com/android/dx/dex/file/IndexedItem.java81
-rw-r--r--dx/src/com/android/dx/dex/file/Item.java80
-rw-r--r--dx/src/com/android/dx/dex/file/ItemType.java97
-rw-r--r--dx/src/com/android/dx/dex/file/MapItem.java235
-rw-r--r--dx/src/com/android/dx/dex/file/MemberIdItem.java111
-rw-r--r--dx/src/com/android/dx/dex/file/MemberIdsSection.java44
-rw-r--r--dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java122
-rw-r--r--dx/src/com/android/dx/dex/file/MethodIdItem.java70
-rw-r--r--dx/src/com/android/dx/dex/file/MethodIdsSection.java137
-rw-r--r--dx/src/com/android/dx/dex/file/MixedItemSection.java362
-rw-r--r--dx/src/com/android/dx/dex/file/OffsettedItem.java313
-rw-r--r--dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java161
-rw-r--r--dx/src/com/android/dx/dex/file/ProtoIdItem.java162
-rw-r--r--dx/src/com/android/dx/dex/file/ProtoIdsSection.java140
-rw-r--r--dx/src/com/android/dx/dex/file/Section.java287
-rw-r--r--dx/src/com/android/dx/dex/file/Statistics.java195
-rw-r--r--dx/src/com/android/dx/dex/file/StringDataItem.java99
-rw-r--r--dx/src/com/android/dx/dex/file/StringIdItem.java128
-rw-r--r--dx/src/com/android/dx/dex/file/StringIdsSection.java210
-rw-r--r--dx/src/com/android/dx/dex/file/TypeIdItem.java72
-rw-r--r--dx/src/com/android/dx/dex/file/TypeIdsSection.java192
-rw-r--r--dx/src/com/android/dx/dex/file/TypeListItem.java122
-rw-r--r--dx/src/com/android/dx/dex/file/UniformItemSection.java112
-rw-r--r--dx/src/com/android/dx/dex/file/UniformListItem.java216
-rw-r--r--dx/src/com/android/dx/dex/file/ValueEncoder.java532
50 files changed, 0 insertions, 10771 deletions
diff --git a/dx/src/com/android/dx/dex/file/AnnotationItem.java b/dx/src/com/android/dx/dex/file/AnnotationItem.java
deleted file mode 100644
index 43ac36266..000000000
--- a/dx/src/com/android/dx/dex/file/AnnotationItem.java
+++ /dev/null
@@ -1,220 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.rop.annotation.AnnotationVisibility;
-import com.android.dx.rop.annotation.NameValuePair;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.ByteArrayAnnotatedOutput;
-import com.android.dx.util.AnnotatedOutput;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-/**
- * Single annotation, which consists of a type and a set of name-value
- * element pairs.
- */
-public final class AnnotationItem extends OffsettedItem {
- /** annotation visibility constant: visible at build time only */
- private static final int VISIBILITY_BUILD = 0;
-
- /** annotation visibility constant: visible at runtime */
- private static final int VISIBILITY_RUNTIME = 1;
-
- /** annotation visibility constant: visible at runtime only to system */
- private static final int VISIBILITY_SYSTEM = 2;
-
- /** the required alignment for instances of this class */
- private static final int ALIGNMENT = 1;
-
- /** non-null; unique instance of {@link #TypeIdSorter} */
- private static final TypeIdSorter TYPE_ID_SORTER = new TypeIdSorter();
-
- /** non-null; the annotation to represent */
- private final Annotation annotation;
-
- /**
- * null-ok; type reference for the annotation type; set during
- * {@link #addContents}
- */
- private TypeIdItem type;
-
- /**
- * null-ok; encoded form, ready for writing to a file; set during
- * {@link #place0}
- */
- private byte[] encodedForm;
-
- /**
- * Comparator that sorts (outer) instances by type id index.
- */
- private static class TypeIdSorter implements Comparator<AnnotationItem> {
- /** {@inheritDoc} */
- public int compare(AnnotationItem item1, AnnotationItem item2) {
- int index1 = item1.type.getIndex();
- int index2 = item2.type.getIndex();
-
- if (index1 < index2) {
- return -1;
- } else if (index1 > index2) {
- return 1;
- }
-
- return 0;
- }
- }
-
- /**
- * Sorts an array of instances, in place, by type id index,
- * ignoring all other aspects of the elements. This is only valid
- * to use after type id indices are known.
- *
- * @param array non-null; array to sort
- */
- public static void sortByTypeIdIndex(AnnotationItem[] array) {
- Arrays.sort(array, TYPE_ID_SORTER);
- }
-
- /**
- * Constructs an instance.
- *
- * @param annotation non-null; annotation to represent
- */
- public AnnotationItem(Annotation annotation) {
- /*
- * The write size isn't known up-front because (the variable-lengthed)
- * leb128 type is used to represent some things.
- */
- super(ALIGNMENT, -1);
-
- if (annotation == null) {
- throw new NullPointerException("annotation == null");
- }
-
- this.annotation = annotation;
- this.type = null;
- this.encodedForm = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_ANNOTATION_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return annotation.hashCode();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int compareTo0(OffsettedItem other) {
- AnnotationItem otherAnnotation = (AnnotationItem) other;
-
- return annotation.compareTo(otherAnnotation.annotation);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return annotation.toHuman();
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- type = file.getTypeIds().intern(annotation.getType());
- ValueEncoder.addContents(file, annotation);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- // Encode the data and note the size.
-
- ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
- ValueEncoder encoder = new ValueEncoder(addedTo.getFile(), out);
-
- encoder.writeAnnotation(annotation, false);
- encodedForm = out.toByteArray();
-
- // Add one for the visibility byte in front of the encoded annotation.
- setWriteSize(encodedForm.length + 1);
- }
-
- /**
- * Write a (listing file) annotation for this instance to the given
- * output, that consumes no bytes of output. This is for annotating
- * a reference to this instance at the point of the reference.
- *
- * @param out non-null; where to output to
- * @param prefix non-null; prefix for each line of output
- */
- public void annotateTo(AnnotatedOutput out, String prefix) {
- out.annotate(0, prefix + "visibility: " +
- annotation.getVisibility().toHuman());
- out.annotate(0, prefix + "type: " + annotation.getType().toHuman());
-
- for (NameValuePair pair : annotation.getNameValuePairs()) {
- CstUtf8 name = pair.getName();
- Constant value = pair.getValue();
-
- out.annotate(0, prefix + name.toHuman() + ": " +
- ValueEncoder.constantToHuman(value));
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
- AnnotationVisibility visibility = annotation.getVisibility();
-
- if (annotates) {
- out.annotate(0, offsetString() + " annotation");
- out.annotate(1, " visibility: VISBILITY_" + visibility);
- }
-
- switch (visibility) {
- case BUILD: out.writeByte(VISIBILITY_BUILD); break;
- case RUNTIME: out.writeByte(VISIBILITY_RUNTIME); break;
- case SYSTEM: out.writeByte(VISIBILITY_SYSTEM); break;
- default: {
- // EMBEDDED shouldn't appear at the top level.
- throw new RuntimeException("shouldn't happen");
- }
- }
-
- if (annotates) {
- /*
- * The output is to be annotated, so redo the work previously
- * done by place0(), except this time annotations will actually
- * get emitted.
- */
- ValueEncoder encoder = new ValueEncoder(file, out);
- encoder.writeAnnotation(annotation, true);
- } else {
- out.write(encodedForm);
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/AnnotationSetItem.java b/dx/src/com/android/dx/dex/file/AnnotationSetItem.java
deleted file mode 100644
index f03cc08d1..000000000
--- a/dx/src/com/android/dx/dex/file/AnnotationSetItem.java
+++ /dev/null
@@ -1,157 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotations;
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Set of annotations, where no annotation type appears more than once.
- */
-public final class AnnotationSetItem extends OffsettedItem {
- /** the required alignment for instances of this class */
- private static final int ALIGNMENT = 4;
-
- /** the size of an entry int the set: one <code>uint</code> */
- private static final int ENTRY_WRITE_SIZE = 4;
-
- /** non-null; the set of annotations */
- private final Annotations annotations;
-
- /**
- * non-null; set of annotations as individual items in an array.
- * <b>Note:</b> The contents have to get sorted by type id before
- * writing.
- */
- private final AnnotationItem[] items;
-
- /**
- * Constructs an instance.
- *
- * @param annotations non-null; set of annotations
- */
- public AnnotationSetItem(Annotations annotations) {
- super(ALIGNMENT, writeSize(annotations));
-
- this.annotations = annotations;
- this.items = new AnnotationItem[annotations.size()];
-
- int at = 0;
- for (Annotation a : annotations.getAnnotations()) {
- items[at] = new AnnotationItem(a);
- at++;
- }
- }
-
- /**
- * Gets the write size for the given set.
- *
- * @param annotations non-null; the set
- * @return &gt; 0; the write size
- */
- private static int writeSize(Annotations annotations) {
- // This includes an int size at the start of the list.
-
- try {
- return (annotations.size() * ENTRY_WRITE_SIZE) + 4;
- } catch (NullPointerException ex) {
- // Elucidate the exception.
- throw new NullPointerException("list == null");
- }
- }
-
- /**
- * Gets the underlying annotations of this instance
- *
- * @return non-null; the annotations
- */
- public Annotations getAnnotations() {
- return annotations;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return annotations.hashCode();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int compareTo0(OffsettedItem other) {
- AnnotationSetItem otherSet = (AnnotationSetItem) other;
-
- return annotations.compareTo(otherSet.annotations);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_ANNOTATION_SET_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return annotations.toString();
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- MixedItemSection byteData = file.getByteData();
- int size = items.length;
-
- for (int i = 0; i < size; i++) {
- items[i] = byteData.intern(items[i]);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- // Sort the array to be in type id index order.
- AnnotationItem.sortByTypeIdIndex(items);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
- int size = items.length;
-
- if (annotates) {
- out.annotate(0, offsetString() + " annotation set");
- out.annotate(4, " size: " + Hex.u4(size));
- }
-
- out.writeInt(size);
-
- for (int i = 0; i < size; i++) {
- AnnotationItem item = items[i];
- int offset = item.getAbsoluteOffset();
-
- if (annotates) {
- out.annotate(4, " entries[" + Integer.toHexString(i) + "]: " +
- Hex.u4(offset));
- items[i].annotateTo(out, " ");
- }
-
- out.writeInt(offset);
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java b/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java
deleted file mode 100644
index 422e2f019..000000000
--- a/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java
+++ /dev/null
@@ -1,80 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Indirect reference to an {@link AnnotationSetItem}.
- */
-public final class AnnotationSetRefItem extends OffsettedItem {
- /** the required alignment for instances of this class */
- private static final int ALIGNMENT = 4;
-
- /** write size of this class, in bytes */
- private static final int WRITE_SIZE = 4;
-
- /** non-null; the annotation set to refer to */
- private AnnotationSetItem annotations;
-
- /**
- * Constructs an instance.
- *
- * @param annotations non-null; the annotation set to refer to
- */
- public AnnotationSetRefItem(AnnotationSetItem annotations) {
- super(ALIGNMENT, WRITE_SIZE);
-
- if (annotations == null) {
- throw new NullPointerException("annotations == null");
- }
-
- this.annotations = annotations;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_ANNOTATION_SET_REF_ITEM;
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- MixedItemSection wordData = file.getWordData();
-
- annotations = wordData.intern(annotations);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return annotations.toHuman();
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- int annotationsOff = annotations.getAbsoluteOffset();
-
- if (out.annotates()) {
- out.annotate(4, " annotations_off: " + Hex.u4(annotationsOff));
- }
-
- out.writeInt(annotationsOff);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/AnnotationUtils.java b/dx/src/com/android/dx/dex/file/AnnotationUtils.java
deleted file mode 100644
index c9d796843..000000000
--- a/dx/src/com/android/dx/dex/file/AnnotationUtils.java
+++ /dev/null
@@ -1,254 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.rop.annotation.NameValuePair;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstInteger;
-import com.android.dx.rop.cst.CstKnownNull;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.Type;
-import com.android.dx.rop.type.TypeList;
-
-import java.util.ArrayList;
-
-import static com.android.dx.rop.annotation.AnnotationVisibility.*;
-
-/**
- * Utility class for dealing with annotations.
- */
-public final class AnnotationUtils {
- /** non-null; type for <code>AnnotationDefault</code> annotations */
- private static final CstType ANNOTATION_DEFAULT_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/AnnotationDefault;"));
-
- /** non-null; type for <code>EnclosingClass</code> annotations */
- private static final CstType ENCLOSING_CLASS_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/EnclosingClass;"));
-
- /** non-null; type for <code>EnclosingMethod</code> annotations */
- private static final CstType ENCLOSING_METHOD_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/EnclosingMethod;"));
-
- /** non-null; type for <code>InnerClass</code> annotations */
- private static final CstType INNER_CLASS_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/InnerClass;"));
-
- /** non-null; type for <code>MemberClasses</code> annotations */
- private static final CstType MEMBER_CLASSES_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/MemberClasses;"));
-
- /** non-null; type for <code>Signature</code> annotations */
- private static final CstType SIGNATURE_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/Signature;"));
-
- /** non-null; type for <code>Throws</code> annotations */
- private static final CstType THROWS_TYPE =
- CstType.intern(Type.intern("Ldalvik/annotation/Throws;"));
-
- /** non-null; the UTF-8 constant <code>"accessFlags"</code> */
- private static final CstUtf8 ACCESS_FLAGS_UTF = new CstUtf8("accessFlags");
-
- /** non-null; the UTF-8 constant <code>"name"</code> */
- private static final CstUtf8 NAME_UTF = new CstUtf8("name");
-
- /** non-null; the UTF-8 constant <code>"value"</code> */
- private static final CstUtf8 VALUE_UTF = new CstUtf8("value");
-
- /**
- * This class is uninstantiable.
- */
- private AnnotationUtils() {
- // This space intentionally left blank.
- }
-
- /**
- * Constructs a standard <code>AnnotationDefault</code> annotation.
- *
- * @param defaults non-null; the defaults, itself as an annotation
- * @return non-null; the constructed annotation
- */
- public static Annotation makeAnnotationDefault(Annotation defaults) {
- Annotation result = new Annotation(ANNOTATION_DEFAULT_TYPE, SYSTEM);
-
- result.put(new NameValuePair(VALUE_UTF, new CstAnnotation(defaults)));
- result.setImmutable();
- return result;
- }
-
- /**
- * Constructs a standard <code>EnclosingClass</code> annotation.
- *
- * @param clazz non-null; the enclosing class
- * @return non-null; the annotation
- */
- public static Annotation makeEnclosingClass(CstType clazz) {
- Annotation result = new Annotation(ENCLOSING_CLASS_TYPE, SYSTEM);
-
- result.put(new NameValuePair(VALUE_UTF, clazz));
- result.setImmutable();
- return result;
- }
-
- /**
- * Constructs a standard <code>EnclosingMethod</code> annotation.
- *
- * @param method non-null; the enclosing method
- * @return non-null; the annotation
- */
- public static Annotation makeEnclosingMethod(CstMethodRef method) {
- Annotation result = new Annotation(ENCLOSING_METHOD_TYPE, SYSTEM);
-
- result.put(new NameValuePair(VALUE_UTF, method));
- result.setImmutable();
- return result;
- }
-
- /**
- * Constructs a standard <code>InnerClass</code> annotation.
- *
- * @param name null-ok; the original name of the class, or
- * <code>null</code> to represent an anonymous class
- * @param accessFlags the original access flags
- * @return non-null; the annotation
- */
- public static Annotation makeInnerClass(CstUtf8 name, int accessFlags) {
- Annotation result = new Annotation(INNER_CLASS_TYPE, SYSTEM);
- Constant nameCst =
- (name != null) ? new CstString(name) : CstKnownNull.THE_ONE;
-
- result.put(new NameValuePair(NAME_UTF, nameCst));
- result.put(new NameValuePair(ACCESS_FLAGS_UTF,
- CstInteger.make(accessFlags)));
- result.setImmutable();
- return result;
- }
-
- /**
- * Constructs a standard <code>MemberClasses</code> annotation.
- *
- * @param types non-null; the list of (the types of) the member classes
- * @return non-null; the annotation
- */
- public static Annotation makeMemberClasses(TypeList types) {
- CstArray array = makeCstArray(types);
- Annotation result = new Annotation(MEMBER_CLASSES_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, array));
- result.setImmutable();
- return result;
- }
-
- /**
- * Constructs a standard <code>Signature</code> annotation.
- *
- * @param signature non-null; the signature string
- * @return non-null; the annotation
- */
- public static Annotation makeSignature(CstUtf8 signature) {
- Annotation result = new Annotation(SIGNATURE_TYPE, SYSTEM);
-
- /*
- * Split the string into pieces that are likely to be common
- * across many signatures and the rest of the file.
- */
-
- String raw = signature.getString();
- int rawLength = raw.length();
- ArrayList<String> pieces = new ArrayList<String>(20);
-
- for (int at = 0; at < rawLength; /*at*/) {
- char c = raw.charAt(at);
- int endAt = at + 1;
- if (c == 'L') {
- // Scan to ';' or '<'. Consume ';' but not '<'.
- while (endAt < rawLength) {
- c = raw.charAt(endAt);
- if (c == ';') {
- endAt++;
- break;
- } else if (c == '<') {
- break;
- }
- endAt++;
- }
- } else {
- // Scan to 'L' without consuming it.
- while (endAt < rawLength) {
- c = raw.charAt(endAt);
- if (c == 'L') {
- break;
- }
- endAt++;
- }
- }
-
- pieces.add(raw.substring(at, endAt));
- at = endAt;
- }
-
- int size = pieces.size();
- CstArray.List list = new CstArray.List(size);
-
- for (int i = 0; i < size; i++) {
- list.set(i, new CstString(pieces.get(i)));
- }
-
- list.setImmutable();
-
- result.put(new NameValuePair(VALUE_UTF, new CstArray(list)));
- result.setImmutable();
- return result;
- }
-
- /**
- * Constructs a standard <code>Throws</code> annotation.
- *
- * @param types non-null; the list of thrown types
- * @return non-null; the annotation
- */
- public static Annotation makeThrows(TypeList types) {
- CstArray array = makeCstArray(types);
- Annotation result = new Annotation(THROWS_TYPE, SYSTEM);
- result.put(new NameValuePair(VALUE_UTF, array));
- result.setImmutable();
- return result;
- }
-
- /**
- * Converts a {@link TypeList} to a {@link CstArray}.
- *
- * @param types non-null; the type list
- * @return non-null; the corresponding array constant
- */
- private static CstArray makeCstArray(TypeList types) {
- int size = types.size();
- CstArray.List list = new CstArray.List(size);
-
- for (int i = 0; i < size; i++) {
- list.set(i, CstType.intern(types.getType(i)));
- }
-
- list.setImmutable();
- return new CstArray(list);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java b/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java
deleted file mode 100644
index 4521e4c5b..000000000
--- a/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java
+++ /dev/null
@@ -1,385 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotations;
-import com.android.dx.rop.annotation.AnnotationsList;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-
-/**
- * Per-class directory of annotations.
- */
-public final class AnnotationsDirectoryItem extends OffsettedItem {
- /** the required alignment for instances of this class */
- private static final int ALIGNMENT = 4;
-
- /** write size of this class's header, in bytes */
- private static final int HEADER_SIZE = 16;
-
- /** write size of a list element, in bytes */
- private static final int ELEMENT_SIZE = 8;
-
- /** null-ok; the class-level annotations, if any */
- private AnnotationSetItem classAnnotations;
-
- /** null-ok; the annotated fields, if any */
- private ArrayList<FieldAnnotationStruct> fieldAnnotations;
-
- /** null-ok; the annotated methods, if any */
- private ArrayList<MethodAnnotationStruct> methodAnnotations;
-
- /** null-ok; the annotated parameters, if any */
- private ArrayList<ParameterAnnotationStruct> parameterAnnotations;
-
- /**
- * Constructs an empty instance.
- */
- public AnnotationsDirectoryItem() {
- super(ALIGNMENT, -1);
-
- classAnnotations = null;
- fieldAnnotations = null;
- methodAnnotations = null;
- parameterAnnotations = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
- }
-
- /**
- * Returns whether this item is empty (has no contents).
- *
- * @return <code>true</code> if this item is empty, or <code>false</code>
- * if not
- */
- public boolean isEmpty() {
- return (classAnnotations == null) &&
- (fieldAnnotations == null) &&
- (methodAnnotations == null) &&
- (parameterAnnotations == null);
- }
-
- /**
- * Returns whether this item is a candidate for interning. The only
- * interning candidates are ones that <i>only</i> have a non-null
- * set of class annotations, with no other lists.
- *
- * @return <code>true</code> if this is an interning candidate, or
- * <code>false</code> if not
- */
- public boolean isInternable() {
- return (classAnnotations != null) &&
- (fieldAnnotations == null) &&
- (methodAnnotations == null) &&
- (parameterAnnotations == null);
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- if (classAnnotations == null) {
- return 0;
- }
-
- return classAnnotations.hashCode();
- }
-
- /**
- * {@inheritDoc}
- *
- * <p><b>Note:</b>: This throws an exception if this item is not
- * internable.</p>
- *
- * @see #isInternable
- */
- @Override
- public int compareTo0(OffsettedItem other) {
- if (! isInternable()) {
- throw new UnsupportedOperationException("uninternable instance");
- }
-
- AnnotationsDirectoryItem otherDirectory =
- (AnnotationsDirectoryItem) other;
- return classAnnotations.compareTo(otherDirectory.classAnnotations);
- }
-
- /**
- * Sets the direct annotations on this instance. These are annotations
- * made on the class, per se, as opposed to on one of its members.
- * It is only valid to call this method at most once per instance.
- *
- * @param annotations non-null; annotations to set for this class
- */
- public void setClassAnnotations(Annotations annotations) {
- if (annotations == null) {
- throw new NullPointerException("annotations == null");
- }
-
- if (classAnnotations != null) {
- throw new UnsupportedOperationException(
- "class annotations already set");
- }
-
- classAnnotations = new AnnotationSetItem(annotations);
- }
-
- /**
- * Adds a field annotations item to this instance.
- *
- * @param field non-null; field in question
- * @param annotations non-null; associated annotations to add
- */
- public void addFieldAnnotations(CstFieldRef field,
- Annotations annotations) {
- if (fieldAnnotations == null) {
- fieldAnnotations = new ArrayList<FieldAnnotationStruct>();
- }
-
- fieldAnnotations.add(new FieldAnnotationStruct(field,
- new AnnotationSetItem(annotations)));
- }
-
- /**
- * Adds a method annotations item to this instance.
- *
- * @param method non-null; method in question
- * @param annotations non-null; associated annotations to add
- */
- public void addMethodAnnotations(CstMethodRef method,
- Annotations annotations) {
- if (methodAnnotations == null) {
- methodAnnotations = new ArrayList<MethodAnnotationStruct>();
- }
-
- methodAnnotations.add(new MethodAnnotationStruct(method,
- new AnnotationSetItem(annotations)));
- }
-
- /**
- * Adds a parameter annotations item to this instance.
- *
- * @param method non-null; method in question
- * @param list non-null; associated list of annotation sets to add
- */
- public void addParameterAnnotations(CstMethodRef method,
- AnnotationsList list) {
- if (parameterAnnotations == null) {
- parameterAnnotations = new ArrayList<ParameterAnnotationStruct>();
- }
-
- parameterAnnotations.add(new ParameterAnnotationStruct(method, list));
- }
-
- /**
- * Gets the method annotations for a given method, if any. This is
- * meant for use by debugging / dumping code.
- *
- * @param method non-null; the method
- * @return null-ok; the method annotations, if any
- */
- public Annotations getMethodAnnotations(CstMethodRef method) {
- if (methodAnnotations == null) {
- return null;
- }
-
- for (MethodAnnotationStruct item : methodAnnotations) {
- if (item.getMethod().equals(method)) {
- return item.getAnnotations();
- }
- }
-
- return null;
- }
-
- /**
- * Gets the parameter annotations for a given method, if any. This is
- * meant for use by debugging / dumping code.
- *
- * @param method non-null; the method
- * @return null-ok; the parameter annotations, if any
- */
- public AnnotationsList getParameterAnnotations(CstMethodRef method) {
- if (parameterAnnotations == null) {
- return null;
- }
-
- for (ParameterAnnotationStruct item : parameterAnnotations) {
- if (item.getMethod().equals(method)) {
- return item.getAnnotationsList();
- }
- }
-
- return null;
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- MixedItemSection wordData = file.getWordData();
-
- if (classAnnotations != null) {
- classAnnotations = wordData.intern(classAnnotations);
- }
-
- if (fieldAnnotations != null) {
- for (FieldAnnotationStruct item : fieldAnnotations) {
- item.addContents(file);
- }
- }
-
- if (methodAnnotations != null) {
- for (MethodAnnotationStruct item : methodAnnotations) {
- item.addContents(file);
- }
- }
-
- if (parameterAnnotations != null) {
- for (ParameterAnnotationStruct item : parameterAnnotations) {
- item.addContents(file);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- throw new RuntimeException("unsupported");
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- // We just need to set the write size here.
-
- int elementCount = listSize(fieldAnnotations)
- + listSize(methodAnnotations) + listSize(parameterAnnotations);
- setWriteSize(HEADER_SIZE + (elementCount * ELEMENT_SIZE));
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
- int classOff = OffsettedItem.getAbsoluteOffsetOr0(classAnnotations);
- int fieldsSize = listSize(fieldAnnotations);
- int methodsSize = listSize(methodAnnotations);
- int parametersSize = listSize(parameterAnnotations);
-
- if (annotates) {
- out.annotate(0, offsetString() + " annotations directory");
- out.annotate(4, " class_annotations_off: " + Hex.u4(classOff));
- out.annotate(4, " fields_size: " +
- Hex.u4(fieldsSize));
- out.annotate(4, " methods_size: " +
- Hex.u4(methodsSize));
- out.annotate(4, " parameters_size: " +
- Hex.u4(parametersSize));
- }
-
- out.writeInt(classOff);
- out.writeInt(fieldsSize);
- out.writeInt(methodsSize);
- out.writeInt(parametersSize);
-
- if (fieldsSize != 0) {
- Collections.sort(fieldAnnotations);
- if (annotates) {
- out.annotate(0, " fields:");
- }
- for (FieldAnnotationStruct item : fieldAnnotations) {
- item.writeTo(file, out);
- }
- }
-
- if (methodsSize != 0) {
- Collections.sort(methodAnnotations);
- if (annotates) {
- out.annotate(0, " methods:");
- }
- for (MethodAnnotationStruct item : methodAnnotations) {
- item.writeTo(file, out);
- }
- }
-
- if (parametersSize != 0) {
- Collections.sort(parameterAnnotations);
- if (annotates) {
- out.annotate(0, " parameters:");
- }
- for (ParameterAnnotationStruct item : parameterAnnotations) {
- item.writeTo(file, out);
- }
- }
- }
-
- /**
- * Gets the list size of the given list, or <code>0</code> if given
- * <code>null</code>.
- *
- * @param list null-ok; the list in question
- * @return &gt;= 0; its size
- */
- private static int listSize(ArrayList<?> list) {
- if (list == null) {
- return 0;
- }
-
- return list.size();
- }
-
- /**
- * Prints out the contents of this instance, in a debugging-friendly
- * way. This is meant to be called from {@link ClassDefItem#debugPrint}.
- *
- * @param out non-null; where to output to
- */
- /*package*/ void debugPrint(PrintWriter out) {
- if (classAnnotations != null) {
- out.println(" class annotations: " + classAnnotations);
- }
-
- if (fieldAnnotations != null) {
- out.println(" field annotations:");
- for (FieldAnnotationStruct item : fieldAnnotations) {
- out.println(" " + item.toHuman());
- }
- }
-
- if (methodAnnotations != null) {
- out.println(" method annotations:");
- for (MethodAnnotationStruct item : methodAnnotations) {
- out.println(" " + item.toHuman());
- }
- }
-
- if (parameterAnnotations != null) {
- out.println(" parameter annotations:");
- for (ParameterAnnotationStruct item : parameterAnnotations) {
- out.println(" " + item.toHuman());
- }
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/CatchStructs.java b/dx/src/com/android/dx/dex/file/CatchStructs.java
deleted file mode 100644
index b7abc3f53..000000000
--- a/dx/src/com/android/dx/dex/file/CatchStructs.java
+++ /dev/null
@@ -1,320 +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.dx.dex.file;
-
-import com.android.dx.dex.code.CatchHandlerList;
-import com.android.dx.dex.code.CatchTable;
-import com.android.dx.dex.code.DalvCode;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.type.Type;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ByteArrayAnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.io.PrintWriter;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * List of exception handlers (tuples of covered range, catch type,
- * handler address) for a particular piece of code. Instances of this
- * class correspond to a <code>try_item[]</code> and a
- * <code>catch_handler_item[]</code>.
- */
-public final class CatchStructs {
- /**
- * the size of a <code>try_item</code>: a <code>uint</code>
- * and two <code>ushort</code>s
- */
- private static final int TRY_ITEM_WRITE_SIZE = 4 + (2 * 2);
-
- /** non-null; code that contains the catches */
- private final DalvCode code;
-
- /**
- * null-ok; the underlying table; set in
- * {@link #finishProcessingIfNecessary}
- */
- private CatchTable table;
-
- /**
- * null-ok; the encoded handler list, if calculated; set in
- * {@link #encode}
- */
- private byte[] encodedHandlers;
-
- /**
- * length of the handlers header (encoded size), if known; used for
- * annotation
- */
- private int encodedHandlerHeaderSize;
-
- /**
- * null-ok; map from handler lists to byte offsets, if calculated; set in
- * {@link #encode}
- */
- private TreeMap<CatchHandlerList, Integer> handlerOffsets;
-
- /**
- * Constructs an instance.
- *
- * @param code non-null; code that contains the catches
- */
- public CatchStructs(DalvCode code) {
- this.code = code;
- this.table = null;
- this.encodedHandlers = null;
- this.encodedHandlerHeaderSize = 0;
- this.handlerOffsets = null;
- }
-
- /**
- * Finish processing the catches, if necessary.
- */
- private void finishProcessingIfNecessary() {
- if (table == null) {
- table = code.getCatches();
- }
- }
-
- /**
- * Gets the size of the tries list, in entries.
- *
- * @return &gt;= 0; the tries list size
- */
- public int triesSize() {
- finishProcessingIfNecessary();
- return table.size();
- }
-
- /**
- * Does a human-friendly dump of this instance.
- *
- * @param out non-null; where to dump
- * @param prefix non-null; prefix to attach to each line of output
- */
- public void debugPrint(PrintWriter out, String prefix) {
- annotateEntries(prefix, out, null);
- }
-
- /**
- * Encodes the handler lists.
- *
- * @param file non-null; file this instance is part of
- */
- public void encode(DexFile file) {
- finishProcessingIfNecessary();
-
- TypeIdsSection typeIds = file.getTypeIds();
- int size = table.size();
-
- handlerOffsets = new TreeMap<CatchHandlerList, Integer>();
-
- /*
- * First add a map entry for each unique list. The tree structure
- * will ensure they are sorted when we reiterate later.
- */
- for (int i = 0; i < size; i++) {
- handlerOffsets.put(table.get(i).getHandlers(), null);
- }
-
- if (handlerOffsets.size() > 65535) {
- throw new UnsupportedOperationException(
- "too many catch handlers");
- }
-
- ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
-
- // Write out the handlers "header" consisting of its size in entries.
- encodedHandlerHeaderSize =
- out.writeUnsignedLeb128(handlerOffsets.size());
-
- // Now write the lists out in order, noting the offset of each.
- for (Map.Entry<CatchHandlerList, Integer> mapping :
- handlerOffsets.entrySet()) {
- CatchHandlerList list = mapping.getKey();
- int listSize = list.size();
- boolean catchesAll = list.catchesAll();
-
- // Set the offset before we do any writing.
- mapping.setValue(out.getCursor());
-
- if (catchesAll) {
- // A size <= 0 means that the list ends with a catch-all.
- out.writeSignedLeb128(-(listSize - 1));
- listSize--;
- } else {
- out.writeSignedLeb128(listSize);
- }
-
- for (int i = 0; i < listSize; i++) {
- CatchHandlerList.Entry entry = list.get(i);
- out.writeUnsignedLeb128(
- typeIds.indexOf(entry.getExceptionType()));
- out.writeUnsignedLeb128(entry.getHandler());
- }
-
- if (catchesAll) {
- out.writeUnsignedLeb128(list.get(listSize).getHandler());
- }
- }
-
- encodedHandlers = out.toByteArray();
- }
-
- /**
- * Gets the write size of this instance, in bytes.
- *
- * @return &gt;= 0; the write size
- */
- public int writeSize() {
- return (triesSize() * TRY_ITEM_WRITE_SIZE) +
- + encodedHandlers.length;
- }
-
- /**
- * Writes this instance to the given stream.
- *
- * @param file non-null; file this instance is part of
- * @param out non-null; where to write to
- */
- public void writeTo(DexFile file, AnnotatedOutput out) {
- finishProcessingIfNecessary();
-
- TypeIdsSection typeIds = file.getTypeIds();
- int tableSize = table.size();
- int handlersSize = handlerOffsets.size();
-
- if (out.annotates()) {
- annotateEntries(" ", null, out);
- }
-
- for (int i = 0; i < tableSize; i++) {
- CatchTable.Entry one = table.get(i);
- int start = one.getStart();
- int end = one.getEnd();
- int insnCount = end - start;
-
- if (insnCount >= 65536) {
- throw new UnsupportedOperationException(
- "bogus exception range: " + Hex.u4(start) + ".." +
- Hex.u4(end));
- }
-
- out.writeInt(start);
- out.writeShort(insnCount);
- out.writeShort(handlerOffsets.get(one.getHandlers()));
- }
-
- out.write(encodedHandlers);
- }
-
- /**
- * Helper method to annotate or simply print the exception handlers.
- * Only one of <code>printTo</code> or <code>annotateTo</code> should
- * be non-null.
- *
- * @param prefix non-null; prefix for each line
- * @param printTo null-ok; where to print to
- * @param annotateTo null-ok; where to consume bytes and annotate to
- */
- private void annotateEntries(String prefix, PrintWriter printTo,
- AnnotatedOutput annotateTo) {
- finishProcessingIfNecessary();
-
- boolean consume = (annotateTo != null);
- int amt1 = consume ? 6 : 0;
- int amt2 = consume ? 2 : 0;
- int size = table.size();
- String subPrefix = prefix + " ";
-
- if (consume) {
- annotateTo.annotate(0, prefix + "tries:");
- } else {
- printTo.println(prefix + "tries:");
- }
-
- for (int i = 0; i < size; i++) {
- CatchTable.Entry entry = table.get(i);
- CatchHandlerList handlers = entry.getHandlers();
- String s1 = subPrefix + "try " + Hex.u2or4(entry.getStart())
- + ".." + Hex.u2or4(entry.getEnd());
- String s2 = handlers.toHuman(subPrefix, "");
-
- if (consume) {
- annotateTo.annotate(amt1, s1);
- annotateTo.annotate(amt2, s2);
- } else {
- printTo.println(s1);
- printTo.println(s2);
- }
- }
-
- if (! consume) {
- // Only emit the handler lists if we are consuming bytes.
- return;
- }
-
- annotateTo.annotate(0, prefix + "handlers:");
- annotateTo.annotate(encodedHandlerHeaderSize,
- subPrefix + "size: " + Hex.u2(handlerOffsets.size()));
-
- int lastOffset = 0;
- CatchHandlerList lastList = null;
-
- for (Map.Entry<CatchHandlerList, Integer> mapping :
- handlerOffsets.entrySet()) {
- CatchHandlerList list = mapping.getKey();
- int offset = mapping.getValue();
-
- if (lastList != null) {
- annotateAndConsumeHandlers(lastList, lastOffset,
- offset - lastOffset, subPrefix, printTo, annotateTo);
- }
-
- lastList = list;
- lastOffset = offset;
- }
-
- annotateAndConsumeHandlers(lastList, lastOffset,
- encodedHandlers.length - lastOffset,
- subPrefix, printTo, annotateTo);
- }
-
- /**
- * Helper for {@link #annotateEntries} to annotate a catch handler list
- * while consuming it.
- *
- * @param handlers non-null; handlers to annotate
- * @param offset &gt;= 0; the offset of this handler
- * @param size &gt;= 1; the number of bytes the handlers consume
- * @param prefix non-null; prefix for each line
- * @param printTo null-ok; where to print to
- * @param annotateTo non-null; where to annotate to
- */
- private static void annotateAndConsumeHandlers(CatchHandlerList handlers,
- int offset, int size, String prefix, PrintWriter printTo,
- AnnotatedOutput annotateTo) {
- String s = handlers.toHuman(prefix, Hex.u2(offset) + ": ");
-
- if (printTo != null) {
- printTo.println(s);
- }
-
- annotateTo.annotate(size, s);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/ClassDataItem.java b/dx/src/com/android/dx/dex/file/ClassDataItem.java
deleted file mode 100644
index 638daed21..000000000
--- a/dx/src/com/android/dx/dex/file/ClassDataItem.java
+++ /dev/null
@@ -1,431 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstLiteralBits;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.Zeroes;
-import com.android.dx.util.ByteArrayAnnotatedOutput;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.Writers;
-
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.HashMap;
-
-/**
- * Representation of all the parts of a Dalvik class that are generally
- * "inflated" into an in-memory representation at runtime. Instances of
- * this class are represented in a compact streamable form in a
- * <code>dex</code> file, as opposed to a random-access form.
- */
-public final class ClassDataItem extends OffsettedItem {
- /** non-null; what class this data is for, just for listing generation */
- private final CstType thisClass;
-
- /** non-null; list of static fields */
- private final ArrayList<EncodedField> staticFields;
-
- /** non-null; list of initial values for static fields */
- private final HashMap<EncodedField, Constant> staticValues;
-
- /** non-null; list of instance fields */
- private final ArrayList<EncodedField> instanceFields;
-
- /** non-null; list of direct methods */
- private final ArrayList<EncodedMethod> directMethods;
-
- /** non-null; list of virtual methods */
- private final ArrayList<EncodedMethod> virtualMethods;
-
- /** null-ok; static initializer list; set in {@link #addContents} */
- private CstArray staticValuesConstant;
-
- /**
- * null-ok; encoded form, ready for writing to a file; set during
- * {@link #place0}
- */
- private byte[] encodedForm;
-
- /**
- * Constructs an instance. Its sets of members are initially
- * empty.
- *
- * @param thisClass non-null; what class this data is for, just
- * for listing generation
- */
- public ClassDataItem(CstType thisClass) {
- super(1, -1);
-
- if (thisClass == null) {
- throw new NullPointerException("thisClass == null");
- }
-
- this.thisClass = thisClass;
- this.staticFields = new ArrayList<EncodedField>(20);
- this.staticValues = new HashMap<EncodedField, Constant>(40);
- this.instanceFields = new ArrayList<EncodedField>(20);
- this.directMethods = new ArrayList<EncodedMethod>(20);
- this.virtualMethods = new ArrayList<EncodedMethod>(20);
- this.staticValuesConstant = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_CLASS_DATA_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return toString();
- }
-
- /**
- * Returns whether this instance is empty.
- *
- * @return <code>true</code> if this instance is empty or
- * <code>false</code> if at least one element has been added to it
- */
- public boolean isEmpty() {
- return staticFields.isEmpty() && instanceFields.isEmpty()
- && directMethods.isEmpty() && virtualMethods.isEmpty();
- }
-
- /**
- * Adds a static field.
- *
- * @param field non-null; the field to add
- * @param value null-ok; initial value for the field, if any
- */
- public void addStaticField(EncodedField field, Constant value) {
- if (field == null) {
- throw new NullPointerException("field == null");
- }
-
- if (staticValuesConstant != null) {
- throw new UnsupportedOperationException(
- "static fields already sorted");
- }
-
- staticFields.add(field);
- staticValues.put(field, value);
- }
-
- /**
- * Adds an instance field.
- *
- * @param field non-null; the field to add
- */
- public void addInstanceField(EncodedField field) {
- if (field == null) {
- throw new NullPointerException("field == null");
- }
-
- instanceFields.add(field);
- }
-
- /**
- * Adds a direct (<code>static</code> and/or <code>private</code>) method.
- *
- * @param method non-null; the method to add
- */
- public void addDirectMethod(EncodedMethod method) {
- if (method == null) {
- throw new NullPointerException("method == null");
- }
-
- directMethods.add(method);
- }
-
- /**
- * Adds a virtual method.
- *
- * @param method non-null; the method to add
- */
- public void addVirtualMethod(EncodedMethod method) {
- if (method == null) {
- throw new NullPointerException("method == null");
- }
-
- virtualMethods.add(method);
- }
-
- /**
- * Gets all the methods in this class. The returned list is not linked
- * in any way to the underlying lists contained in this instance, but
- * the objects contained in the list are shared.
- *
- * @return non-null; list of all methods
- */
- public ArrayList<EncodedMethod> getMethods() {
- int sz = directMethods.size() + virtualMethods.size();
- ArrayList<EncodedMethod> result = new ArrayList<EncodedMethod>(sz);
-
- result.addAll(directMethods);
- result.addAll(virtualMethods);
-
- return result;
- }
-
-
- /**
- * Prints out the contents of this instance, in a debugging-friendly
- * way.
- *
- * @param out non-null; where to output to
- * @param verbose whether to be verbose with the output
- */
- public void debugPrint(Writer out, boolean verbose) {
- PrintWriter pw = Writers.printWriterFor(out);
-
- int sz = staticFields.size();
- for (int i = 0; i < sz; i++) {
- pw.println(" sfields[" + i + "]: " + staticFields.get(i));
- }
-
- sz = instanceFields.size();
- for (int i = 0; i < sz; i++) {
- pw.println(" ifields[" + i + "]: " + instanceFields.get(i));
- }
-
- sz = directMethods.size();
- for (int i = 0; i < sz; i++) {
- pw.println(" dmeths[" + i + "]:");
- directMethods.get(i).debugPrint(pw, verbose);
- }
-
- sz = virtualMethods.size();
- for (int i = 0; i < sz; i++) {
- pw.println(" vmeths[" + i + "]:");
- virtualMethods.get(i).debugPrint(pw, verbose);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- if (!staticFields.isEmpty()) {
- getStaticValuesConstant(); // Force the fields to be sorted.
- for (EncodedField field : staticFields) {
- field.addContents(file);
- }
- }
-
- if (!instanceFields.isEmpty()) {
- Collections.sort(instanceFields);
- for (EncodedField field : instanceFields) {
- field.addContents(file);
- }
- }
-
- if (!directMethods.isEmpty()) {
- Collections.sort(directMethods);
- for (EncodedMethod method : directMethods) {
- method.addContents(file);
- }
- }
-
- if (!virtualMethods.isEmpty()) {
- Collections.sort(virtualMethods);
- for (EncodedMethod method : virtualMethods) {
- method.addContents(file);
- }
- }
- }
-
- /**
- * Gets a {@link CstArray} corresponding to {@link #staticValues} if
- * it contains any non-zero non-<code>null</code> values.
- *
- * @return null-ok; the corresponding constant or <code>null</code> if
- * there are no values to encode
- */
- public CstArray getStaticValuesConstant() {
- if ((staticValuesConstant == null) && (staticFields.size() != 0)) {
- staticValuesConstant = makeStaticValuesConstant();
- }
-
- return staticValuesConstant;
- }
-
- /**
- * Gets a {@link CstArray} corresponding to {@link #staticValues} if
- * it contains any non-zero non-<code>null</code> values.
- *
- * @return null-ok; the corresponding constant or <code>null</code> if
- * there are no values to encode
- */
- private CstArray makeStaticValuesConstant() {
- // First sort the statics into their final order.
- Collections.sort(staticFields);
-
- /*
- * Get the size of staticValues minus any trailing zeros/nulls (both
- * nulls per se as well as instances of CstKnownNull).
- */
-
- int size = staticFields.size();
- while (size > 0) {
- EncodedField field = staticFields.get(size - 1);
- Constant cst = staticValues.get(field);
- if (cst instanceof CstLiteralBits) {
- // Note: CstKnownNull extends CstLiteralBits.
- if (((CstLiteralBits) cst).getLongBits() != 0) {
- break;
- }
- } else if (cst != null) {
- break;
- }
- size--;
- }
-
- if (size == 0) {
- return null;
- }
-
- // There is something worth encoding, so build up a result.
-
- CstArray.List list = new CstArray.List(size);
- for (int i = 0; i < size; i++) {
- EncodedField field = staticFields.get(i);
- Constant cst = staticValues.get(field);
- if (cst == null) {
- cst = Zeroes.zeroFor(field.getRef().getType());
- }
- list.set(i, cst);
- }
- list.setImmutable();
-
- return new CstArray(list);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- // Encode the data and note the size.
-
- ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
-
- encodeOutput(addedTo.getFile(), out);
- encodedForm = out.toByteArray();
- setWriteSize(encodedForm.length);
- }
-
- /**
- * Writes out the encoded form of this instance.
- *
- * @param file non-null; file this instance is part of
- * @param out non-null; where to write to
- */
- private void encodeOutput(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
- int svSize = (staticValuesConstant == null) ? 0 :
- staticValuesConstant.getList().size();
-
- if (annotates) {
- out.annotate(0, offsetString() + " class data for " +
- thisClass.toHuman());
- }
-
- encodeSize(file, out, "static_fields", staticFields.size());
- encodeSize(file, out, "instance_fields", instanceFields.size());
- encodeSize(file, out, "direct_methods", directMethods.size());
- encodeSize(file, out, "virtual_methods", virtualMethods.size());
-
- encodeList(file, out, "static_fields", staticFields);
- encodeList(file, out, "instance_fields", instanceFields);
- encodeList(file, out, "direct_methods", directMethods);
- encodeList(file, out, "virtual_methods", virtualMethods);
-
- if (annotates) {
- out.endAnnotation();
- }
- }
-
- /**
- * Helper for {@link #encodeOutput}, which writes out the given
- * size value, annotating it as well (if annotations are enabled).
- *
- * @param file non-null; file this instance is part of
- * @param out non-null; where to write to
- * @param label non-null; the label for the purposes of annotation
- * @param size &gt;= 0; the size to write
- */
- private static void encodeSize(DexFile file, AnnotatedOutput out,
- String label, int size) {
- if (out.annotates()) {
- out.annotate(String.format(" %-21s %08x", label + "_size:",
- size));
- }
-
- out.writeUnsignedLeb128(size);
- }
-
- /**
- * Helper for {@link #encodeOutput}, which writes out the given
- * list. It also annotates the items (if any and if annotations
- * are enabled).
- *
- * @param file non-null; file this instance is part of
- * @param out non-null; where to write to
- * @param label non-null; the label for the purposes of annotation
- * @param list non-null; the list in question
- */
- private static void encodeList(DexFile file, AnnotatedOutput out,
- String label, ArrayList<? extends EncodedMember> list) {
- int size = list.size();
- int lastIndex = 0;
-
- if (size == 0) {
- return;
- }
-
- if (out.annotates()) {
- out.annotate(0, " " + label + ":");
- }
-
- for (int i = 0; i < size; i++) {
- lastIndex = list.get(i).encode(file, out, lastIndex, i);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo0(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
-
- if (annotates) {
- /*
- * The output is to be annotated, so redo the work previously
- * done by place0(), except this time annotations will actually
- * get emitted.
- */
- encodeOutput(file, out);
- } else {
- out.write(encodedForm);
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/ClassDefItem.java b/dx/src/com/android/dx/dex/file/ClassDefItem.java
deleted file mode 100644
index 5a0b27c90..000000000
--- a/dx/src/com/android/dx/dex/file/ClassDefItem.java
+++ /dev/null
@@ -1,410 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotations;
-import com.android.dx.rop.annotation.AnnotationsList;
-import com.android.dx.rop.code.AccessFlags;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.StdTypeList;
-import com.android.dx.rop.type.TypeList;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.Writers;
-
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.TreeSet;
-
-/**
- * Representation of a Dalvik class, which is basically a set of
- * members (fields or methods) along with a few more pieces of
- * information.
- */
-public final class ClassDefItem extends IndexedItem {
- /** size of instances when written out to a file, in bytes */
- public static final int WRITE_SIZE = 32;
-
- /** non-null; type constant for this class */
- private final CstType thisClass;
-
- /** access flags */
- private final int accessFlags;
-
- /**
- * null-ok; superclass or <code>null</code> if this class is a/the
- * root class
- */
- private final CstType superclass;
-
- /** null-ok; list of implemented interfaces */
- private TypeListItem interfaces;
-
- /** null-ok; source file name or <code>null</code> if unknown */
- private final CstUtf8 sourceFile;
-
- /** non-null; associated class data object */
- private final ClassDataItem classData;
-
- /**
- * null-ok; item wrapper for the static values, initialized
- * in {@link #addContents}
- */
- private EncodedArrayItem staticValuesItem;
-
- /** non-null; annotations directory */
- private AnnotationsDirectoryItem annotationsDirectory;
-
- /**
- * Constructs an instance. Its sets of members and annotations are
- * initially empty.
- *
- * @param thisClass non-null; type constant for this class
- * @param accessFlags access flags
- * @param superclass null-ok; superclass or <code>null</code> if
- * this class is a/the root class
- * @param interfaces non-null; list of implemented interfaces
- * @param sourceFile null-ok; source file name or
- * <code>null</code> if unknown
- */
- public ClassDefItem(CstType thisClass, int accessFlags,
- CstType superclass, TypeList interfaces, CstUtf8 sourceFile) {
- if (thisClass == null) {
- throw new NullPointerException("thisClass == null");
- }
-
- /*
- * TODO: Maybe check accessFlags and superclass, at
- * least for easily-checked stuff?
- */
-
- if (interfaces == null) {
- throw new NullPointerException("interfaces == null");
- }
-
- this.thisClass = thisClass;
- this.accessFlags = accessFlags;
- this.superclass = superclass;
- this.interfaces =
- (interfaces.size() == 0) ? null : new TypeListItem(interfaces);
- this.sourceFile = sourceFile;
- this.classData = new ClassDataItem(thisClass);
- this.staticValuesItem = null;
- this.annotationsDirectory = new AnnotationsDirectoryItem();
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_CLASS_DEF_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- return WRITE_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- TypeIdsSection typeIds = file.getTypeIds();
- MixedItemSection byteData = file.getByteData();
- MixedItemSection wordData = file.getWordData();
- MixedItemSection typeLists = file.getTypeLists();
- StringIdsSection stringIds = file.getStringIds();
-
- typeIds.intern(thisClass);
-
- if (!classData.isEmpty()) {
- MixedItemSection classDataSection = file.getClassData();
- classDataSection.add(classData);
-
- CstArray staticValues = classData.getStaticValuesConstant();
- if (staticValues != null) {
- staticValuesItem =
- byteData.intern(new EncodedArrayItem(staticValues));
- }
- }
-
- if (superclass != null) {
- typeIds.intern(superclass);
- }
-
- if (interfaces != null) {
- interfaces = typeLists.intern(interfaces);
- }
-
- if (sourceFile != null) {
- stringIds.intern(sourceFile);
- }
-
- if (! annotationsDirectory.isEmpty()) {
- if (annotationsDirectory.isInternable()) {
- annotationsDirectory = wordData.intern(annotationsDirectory);
- } else {
- wordData.add(annotationsDirectory);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
- TypeIdsSection typeIds = file.getTypeIds();
- int classIdx = typeIds.indexOf(thisClass);
- int superIdx = (superclass == null) ? -1 :
- typeIds.indexOf(superclass);
- int interOff = OffsettedItem.getAbsoluteOffsetOr0(interfaces);
- int annoOff = annotationsDirectory.isEmpty() ? 0 :
- annotationsDirectory.getAbsoluteOffset();
- int sourceFileIdx = (sourceFile == null) ? -1 :
- file.getStringIds().indexOf(sourceFile);
- int dataOff = classData.isEmpty()? 0 : classData.getAbsoluteOffset();
- int staticValuesOff =
- OffsettedItem.getAbsoluteOffsetOr0(staticValuesItem);
-
- if (annotates) {
- out.annotate(0, indexString() + ' ' + thisClass.toHuman());
- out.annotate(4, " class_idx: " + Hex.u4(classIdx));
- out.annotate(4, " access_flags: " +
- AccessFlags.classString(accessFlags));
- out.annotate(4, " superclass_idx: " + Hex.u4(superIdx) +
- " // " + ((superclass == null) ? "<none>" :
- superclass.toHuman()));
- out.annotate(4, " interfaces_off: " + Hex.u4(interOff));
- if (interOff != 0) {
- TypeList list = interfaces.getList();
- int sz = list.size();
- for (int i = 0; i < sz; i++) {
- out.annotate(0, " " + list.getType(i).toHuman());
- }
- }
- out.annotate(4, " source_file_idx: " + Hex.u4(sourceFileIdx) +
- " // " + ((sourceFile == null) ? "<none>" :
- sourceFile.toHuman()));
- out.annotate(4, " annotations_off: " + Hex.u4(annoOff));
- out.annotate(4, " class_data_off: " + Hex.u4(dataOff));
- out.annotate(4, " static_values_off: " +
- Hex.u4(staticValuesOff));
- }
-
- out.writeInt(classIdx);
- out.writeInt(accessFlags);
- out.writeInt(superIdx);
- out.writeInt(interOff);
- out.writeInt(sourceFileIdx);
- out.writeInt(annoOff);
- out.writeInt(dataOff);
- out.writeInt(staticValuesOff);
- }
-
- /**
- * Gets the constant corresponding to this class.
- *
- * @return non-null; the constant
- */
- public CstType getThisClass() {
- return thisClass;
- }
-
- /**
- * Gets the access flags.
- *
- * @return the access flags
- */
- public int getAccessFlags() {
- return accessFlags;
- }
-
- /**
- * Gets the superclass.
- *
- * @return null-ok; the superclass or <code>null</code> if
- * this class is a/the root class
- */
- public CstType getSuperclass() {
- return superclass;
- }
-
- /**
- * Gets the list of interfaces implemented.
- *
- * @return non-null; the interfaces list
- */
- public TypeList getInterfaces() {
- if (interfaces == null) {
- return StdTypeList.EMPTY;
- }
-
- return interfaces.getList();
- }
-
- /**
- * Gets the source file name.
- *
- * @return null-ok; the source file name or <code>null</code> if unknown
- */
- public CstUtf8 getSourceFile() {
- return sourceFile;
- }
-
- /**
- * Adds a static field.
- *
- * @param field non-null; the field to add
- * @param value null-ok; initial value for the field, if any
- */
- public void addStaticField(EncodedField field, Constant value) {
- classData.addStaticField(field, value);
- }
-
- /**
- * Adds an instance field.
- *
- * @param field non-null; the field to add
- */
- public void addInstanceField(EncodedField field) {
- classData.addInstanceField(field);
- }
-
- /**
- * Adds a direct (<code>static</code> and/or <code>private</code>) method.
- *
- * @param method non-null; the method to add
- */
- public void addDirectMethod(EncodedMethod method) {
- classData.addDirectMethod(method);
- }
-
- /**
- * Adds a virtual method.
- *
- * @param method non-null; the method to add
- */
- public void addVirtualMethod(EncodedMethod method) {
- classData.addVirtualMethod(method);
- }
-
- /**
- * Gets all the methods in this class. The returned list is not linked
- * in any way to the underlying lists contained in this instance, but
- * the objects contained in the list are shared.
- *
- * @return non-null; list of all methods
- */
- public ArrayList<EncodedMethod> getMethods() {
- return classData.getMethods();
- }
-
- /**
- * Sets the direct annotations on this class. These are annotations
- * made on the class, per se, as opposed to on one of its members.
- * It is only valid to call this method at most once per instance.
- *
- * @param annotations non-null; annotations to set for this class
- */
- public void setClassAnnotations(Annotations annotations) {
- annotationsDirectory.setClassAnnotations(annotations);
- }
-
- /**
- * Adds a field annotations item to this class.
- *
- * @param field non-null; field in question
- * @param annotations non-null; associated annotations to add
- */
- public void addFieldAnnotations(CstFieldRef field,
- Annotations annotations) {
- annotationsDirectory.addFieldAnnotations(field, annotations);
- }
-
- /**
- * Adds a method annotations item to this class.
- *
- * @param method non-null; method in question
- * @param annotations non-null; associated annotations to add
- */
- public void addMethodAnnotations(CstMethodRef method,
- Annotations annotations) {
- annotationsDirectory.addMethodAnnotations(method, annotations);
- }
-
- /**
- * Adds a parameter annotations item to this class.
- *
- * @param method non-null; method in question
- * @param list non-null; associated list of annotation sets to add
- */
- public void addParameterAnnotations(CstMethodRef method,
- AnnotationsList list) {
- annotationsDirectory.addParameterAnnotations(method, list);
- }
-
- /**
- * Gets the method annotations for a given method, if any. This is
- * meant for use by debugging / dumping code.
- *
- * @param method non-null; the method
- * @return null-ok; the method annotations, if any
- */
- public Annotations getMethodAnnotations(CstMethodRef method) {
- return annotationsDirectory.getMethodAnnotations(method);
- }
-
- /**
- * Gets the parameter annotations for a given method, if any. This is
- * meant for use by debugging / dumping code.
- *
- * @param method non-null; the method
- * @return null-ok; the parameter annotations, if any
- */
- public AnnotationsList getParameterAnnotations(CstMethodRef method) {
- return annotationsDirectory.getParameterAnnotations(method);
- }
-
- /**
- * Prints out the contents of this instance, in a debugging-friendly
- * way.
- *
- * @param out non-null; where to output to
- * @param verbose whether to be verbose with the output
- */
- public void debugPrint(Writer out, boolean verbose) {
- PrintWriter pw = Writers.printWriterFor(out);
-
- pw.println(getClass().getName() + " {");
- pw.println(" accessFlags: " + Hex.u2(accessFlags));
- pw.println(" superclass: " + superclass);
- pw.println(" interfaces: " +
- ((interfaces == null) ? "<none>" : interfaces));
- pw.println(" sourceFile: " +
- ((sourceFile == null) ? "<none>" : sourceFile.toQuoted()));
-
- classData.debugPrint(out, verbose);
- annotationsDirectory.debugPrint(pw);
-
- pw.println("}");
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/ClassDefsSection.java b/dx/src/com/android/dx/dex/file/ClassDefsSection.java
deleted file mode 100644
index cf61b4732..000000000
--- a/dx/src/com/android/dx/dex/file/ClassDefsSection.java
+++ /dev/null
@@ -1,187 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.type.Type;
-import com.android.dx.rop.type.TypeList;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.TreeMap;
-
-/**
- * Class definitions list section of a <code>.dex</code> file.
- */
-public final class ClassDefsSection extends UniformItemSection {
- /**
- * non-null; map from type constants for classes to {@link
- * ClassDefItem} instances that define those classes
- */
- private final TreeMap<Type, ClassDefItem> classDefs;
-
- /** null-ok; ordered list of classes; set in {@link #orderItems} */
- private ArrayList<ClassDefItem> orderedDefs;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public ClassDefsSection(DexFile file) {
- super("class_defs", file, 4);
-
- classDefs = new TreeMap<Type, ClassDefItem>();
- orderedDefs = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- if (orderedDefs != null) {
- return orderedDefs;
- }
-
- return classDefs.values();
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- if (cst == null) {
- throw new NullPointerException("cst == null");
- }
-
- throwIfNotPrepared();
-
- Type type = ((CstType) cst).getClassType();
- IndexedItem result = classDefs.get(type);
-
- if (result == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return result;
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- int sz = classDefs.size();
- int offset = (sz == 0) ? 0 : getFileOffset();
-
- if (out.annotates()) {
- out.annotate(4, "class_defs_size: " + Hex.u4(sz));
- out.annotate(4, "class_defs_off: " + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Adds an element to this instance. It is illegal to attempt to add more
- * than one class with the same name.
- *
- * @param clazz non-null; the class def to add
- */
- public void add(ClassDefItem clazz) {
- Type type;
-
- try {
- type = clazz.getThisClass().getClassType();
- } catch (NullPointerException ex) {
- // Elucidate the exception.
- throw new NullPointerException("clazz == null");
- }
-
- throwIfPrepared();
-
- if (classDefs.get(type) != null) {
- throw new IllegalArgumentException("already added: " + type);
- }
-
- classDefs.put(type, clazz);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void orderItems() {
- int sz = classDefs.size();
- int idx = 0;
-
- orderedDefs = new ArrayList<ClassDefItem>(sz);
-
- /*
- * Iterate over all the classes, recursively assigning an
- * index to each, implicitly skipping the ones that have
- * already been assigned by the time this (top-level)
- * iteration reaches them.
- */
- for (Type type : classDefs.keySet()) {
- idx = orderItems0(type, idx, sz - idx);
- }
- }
-
- /**
- * Helper for {@link #orderItems}, which recursively assigns indices
- * to classes.
- *
- * @param type null-ok; type ref to assign, if any
- * @param idx &gt;= 0; the next index to assign
- * @param maxDepth maximum recursion depth; if negative, this will
- * throw an exception indicating class definition circularity
- * @return &gt;= 0; the next index to assign
- */
- private int orderItems0(Type type, int idx, int maxDepth) {
- ClassDefItem c = classDefs.get(type);
-
- if ((c == null) || (c.hasIndex())) {
- return idx;
- }
-
- if (maxDepth < 0) {
- throw new RuntimeException("class circularity with " + type);
- }
-
- maxDepth--;
-
- CstType superclassCst = c.getSuperclass();
- if (superclassCst != null) {
- Type superclass = superclassCst.getClassType();
- idx = orderItems0(superclass, idx, maxDepth);
- }
-
- TypeList interfaces = c.getInterfaces();
- int sz = interfaces.size();
- for (int i = 0; i < sz; i++) {
- idx = orderItems0(interfaces.getType(i), idx, maxDepth);
- }
-
- c.setIndex(idx);
- orderedDefs.add(c);
- return idx + 1;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/CodeItem.java b/dx/src/com/android/dx/dex/file/CodeItem.java
deleted file mode 100644
index dc0bb5272..000000000
--- a/dx/src/com/android/dx/dex/file/CodeItem.java
+++ /dev/null
@@ -1,335 +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.dx.dex.file;
-
-import com.android.dx.dex.code.CstInsn;
-import com.android.dx.dex.code.CatchTable;
-import com.android.dx.dex.code.DalvCode;
-import com.android.dx.dex.code.DalvInsn;
-import com.android.dx.dex.code.DalvInsnList;
-import com.android.dx.dex.code.LocalList;
-import com.android.dx.dex.code.PositionList;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstMemberRef;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.type.StdTypeList;
-import com.android.dx.rop.type.Type;
-import com.android.dx.rop.type.TypeList;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ExceptionWithContext;
-import com.android.dx.util.Hex;
-
-import java.io.PrintWriter;
-import java.util.HashSet;
-
-/**
- * Representation of all the parts needed for concrete methods in a
- * <code>dex</code> file.
- */
-public final class CodeItem extends OffsettedItem {
- /** file alignment of this class, in bytes */
- private static final int ALIGNMENT = 4;
-
- /** write size of the header of this class, in bytes */
- private static final int HEADER_SIZE = 16;
-
- /** non-null; method that this code implements */
- private final CstMethodRef ref;
-
- /** non-null; the bytecode instructions and associated data */
- private final DalvCode code;
-
- /** null-ok; the catches, if needed; set in {@link #addContents} */
- private CatchStructs catches;
-
- /** whether this instance is for a <code>static</code> method */
- private final boolean isStatic;
-
- /**
- * non-null; list of possibly-thrown exceptions; just used in
- * generating debugging output (listings)
- */
- private final TypeList throwsList;
-
- /**
- * null-ok; the debug info or <code>null</code> if there is none;
- * set in {@link #addContents}
- */
- private DebugInfoItem debugInfo;
-
- /**
- * Constructs an instance.
- *
- * @param ref non-null; method that this code implements
- * @param code non-null; the underlying code
- * @param isStatic whether this instance is for a <code>static</code>
- * method
- * @param throwsList non-null; list of possibly-thrown exceptions,
- * just used in generating debugging output (listings)
- */
- public CodeItem(CstMethodRef ref, DalvCode code, boolean isStatic,
- TypeList throwsList) {
- super(ALIGNMENT, -1);
-
- if (ref == null) {
- throw new NullPointerException("ref == null");
- }
-
- if (code == null) {
- throw new NullPointerException("code == null");
- }
-
- if (throwsList == null) {
- throw new NullPointerException("throwsList == null");
- }
-
- this.ref = ref;
- this.code = code;
- this.isStatic = isStatic;
- this.throwsList = throwsList;
- this.catches = null;
- this.debugInfo = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_CODE_ITEM;
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- MixedItemSection wordData = file.getWordData();
- MixedItemSection byteData = file.getByteData();
- TypeIdsSection typeIds = file.getTypeIds();
-
- if (code.hasPositions() || code.hasLocals()) {
- debugInfo = new DebugInfoItem(code, isStatic, ref);
- byteData.add(debugInfo);
- }
-
- if (code.hasAnyCatches()) {
- for (Type type : code.getCatchTypes()) {
- typeIds.intern(type);
- }
- catches = new CatchStructs(code);
- }
-
- for (Constant c : code.getInsnConstants()) {
- file.internIfAppropriate(c);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- return "CodeItem{" + toHuman() + "}";
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return ref.toHuman();
- }
-
- /**
- * Gets the reference to the method this instance implements.
- *
- * @return non-null; the method reference
- */
- public CstMethodRef getRef() {
- return ref;
- }
-
- /**
- * Does a human-friendly dump of this instance.
- *
- * @param out non-null; where to dump
- * @param prefix non-null; per-line prefix to use
- * @param verbose whether to be verbose with the output
- */
- public void debugPrint(PrintWriter out, String prefix, boolean verbose) {
- out.println(ref.toHuman() + ":");
-
- DalvInsnList insns = code.getInsns();
- out.println("regs: " + Hex.u2(getRegistersSize()) +
- "; ins: " + Hex.u2(getInsSize()) + "; outs: " +
- Hex.u2(getOutsSize()));
-
- insns.debugPrint(out, prefix, verbose);
-
- String prefix2 = prefix + " ";
-
- if (catches != null) {
- out.print(prefix);
- out.println("catches");
- catches.debugPrint(out, prefix2);
- }
-
- if (debugInfo != null) {
- out.print(prefix);
- out.println("debug info");
- debugInfo.debugPrint(out, prefix2);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- final DexFile file = addedTo.getFile();
- int catchesSize;
-
- /*
- * In order to get the catches and insns, all the code's
- * constants need to be assigned indices.
- */
- code.assignIndices(new DalvCode.AssignIndicesCallback() {
- public int getIndex(Constant cst) {
- IndexedItem item = file.findItemOrNull(cst);
- if (item == null) {
- return -1;
- }
- return item.getIndex();
- }
- });
-
- if (catches != null) {
- catches.encode(file);
- catchesSize = catches.writeSize();
- } else {
- catchesSize = 0;
- }
-
- /*
- * The write size includes the header, two bytes per code
- * unit, post-code padding if necessary, and however much
- * space the catches need.
- */
-
- int insnsSize = code.getInsns().codeSize();
- if ((insnsSize & 1) != 0) {
- insnsSize++;
- }
-
- setWriteSize(HEADER_SIZE + (insnsSize * 2) + catchesSize);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
- int regSz = getRegistersSize();
- int outsSz = getOutsSize();
- int insSz = getInsSize();
- int insnsSz = code.getInsns().codeSize();
- boolean needPadding = (insnsSz & 1) != 0;
- int triesSz = (catches == null) ? 0 : catches.triesSize();
- int debugOff = (debugInfo == null) ? 0 : debugInfo.getAbsoluteOffset();
-
- if (annotates) {
- out.annotate(0, offsetString() + ' ' + ref.toHuman());
- out.annotate(2, " registers_size: " + Hex.u2(regSz));
- out.annotate(2, " ins_size: " + Hex.u2(insSz));
- out.annotate(2, " outs_size: " + Hex.u2(outsSz));
- out.annotate(2, " tries_size: " + Hex.u2(triesSz));
- out.annotate(4, " debug_off: " + Hex.u4(debugOff));
- out.annotate(4, " insns_size: " + Hex.u4(insnsSz));
-
- // This isn't represented directly here, but it is useful to see.
- int size = throwsList.size();
- if (size != 0) {
- out.annotate(0, " throws " + StdTypeList.toHuman(throwsList));
- }
- }
-
- out.writeShort(regSz);
- out.writeShort(insSz);
- out.writeShort(outsSz);
- out.writeShort(triesSz);
- out.writeInt(debugOff);
- out.writeInt(insnsSz);
-
- writeCodes(file, out);
-
- if (catches != null) {
- if (needPadding) {
- if (annotates) {
- out.annotate(2, " padding: 0");
- }
- out.writeShort(0);
- }
-
- catches.writeTo(file, out);
- }
-
- if (annotates) {
- /*
- * These are pointed at in the code header (above), but it's less
- * distracting to expand on them at the bottom of the code.
- */
- if (debugInfo != null) {
- out.annotate(0, " debug info");
- debugInfo.annotateTo(file, out, " ");
- }
- }
- }
-
- /**
- * Helper for {@link #writeTo0} which writes out the actual bytecode.
- *
- * @param file non-null; file we are part of
- * @param out non-null; where to write to
- */
- private void writeCodes(DexFile file, AnnotatedOutput out) {
- DalvInsnList insns = code.getInsns();
-
- try {
- insns.writeTo(out);
- } catch (RuntimeException ex) {
- throw ExceptionWithContext.withContext(ex, "...while writing " +
- "instructions for " + ref.toHuman());
- }
- }
-
- /**
- * Get the in registers count.
- *
- * @return the count
- */
- private int getInsSize() {
- return ref.getParameterWordCount(isStatic);
- }
-
- /**
- * Get the out registers count.
- *
- * @return the count
- */
- private int getOutsSize() {
- return code.getInsns().getOutsSize();
- }
-
- /**
- * Get the total registers count.
- *
- * @return the count
- */
- private int getRegistersSize() {
- return code.getInsns().getRegistersSize();
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoConstants.java b/dx/src/com/android/dx/dex/file/DebugInfoConstants.java
deleted file mode 100644
index 010acb434..000000000
--- a/dx/src/com/android/dx/dex/file/DebugInfoConstants.java
+++ /dev/null
@@ -1,154 +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.dx.dex.file;
-
-/**
- * Constants for the dex debug info state machine format.
- */
-public interface DebugInfoConstants {
-
- /*
- * normal opcodes
- */
-
- /**
- * Terminates a debug info sequence for a method.<p>
- * Args: none
- *
- */
- static final int DBG_END_SEQUENCE = 0x00;
-
- /**
- * Advances the program counter/address register without emitting
- * a positions entry.<p>
- *
- * Args:
- * <ol>
- * <li>Unsigned LEB128 &mdash; amount to advance pc by
- * </ol>
- */
- static final int DBG_ADVANCE_PC = 0x01;
-
- /**
- * Advances the line register without emitting
- * a positions entry.<p>
- *
- * Args:
- * <ol>
- * <li>Signed LEB128 &mdash; amount to change line register by.
- * </ol>
- */
- static final int DBG_ADVANCE_LINE = 0x02;
-
- /**
- * Introduces a local variable at the current address.<p>
- *
- * Args:
- * <ol>
- * <li>Unsigned LEB128 &mdash; register that will contain local.
- * <li>Unsigned LEB128 &mdash; string index (shifted by 1) of local name.
- * <li>Unsigned LEB128 &mdash; type index (shifted by 1) of type.
- * </ol>
- */
- static final int DBG_START_LOCAL = 0x03;
-
- /**
- * Introduces a local variable at the current address with a type
- * signature specified.<p>
- *
- * Args:
- * <ol>
- * <li>Unsigned LEB128 &mdash; register that will contain local.
- * <li>Unsigned LEB128 &mdash; string index (shifted by 1) of local name.
- * <li>Unsigned LEB128 &mdash; type index (shifted by 1) of type.
- * <li>Unsigned LEB128 &mdash; string index (shifted by 1) of
- * type signature.
- * </ol>
- */
- static final int DBG_START_LOCAL_EXTENDED = 0x04;
-
- /**
- * Marks a currently-live local variable as out of scope at the
- * current address.<p>
- *
- * Args:
- * <ol>
- * <li>Unsigned LEB128 &mdash; register that contained local
- * </ol>
- */
- static final int DBG_END_LOCAL = 0x05;
-
- /**
- * Re-introduces a local variable at the current address. The name
- * and type are the same as the last local that was live in the specified
- * register.<p>
- *
- * Args:
- * <ol>
- * <li>Unsigned LEB128 &mdash; register to re-start.
- * </ol>
- */
- static final int DBG_RESTART_LOCAL = 0x06;
-
-
- /**
- * Sets the "prologue_end" state machine register, indicating that the
- * next position entry that is added should be considered the end of
- * a method prologue (an appropriate place for a method breakpoint).<p>
- *
- * The prologue_end register is cleared by any special (&gt= OPCODE_BASE)
- * opcode.
- */
- static final int DBG_SET_PROLOGUE_END = 0x07;
-
- /**
- * Sets the "epilogue_begin" state machine register, indicating that the
- * next position entry that is added should be considered the beginning of
- * a method epilogue (an appropriate place to suspend execution before
- * method exit).<p>
- *
- * The epilogue_begin register is cleared by any special (&gt= OPCODE_BASE)
- * opcode.
- */
- static final int DBG_SET_EPILOGUE_BEGIN = 0x08;
-
- /**
- * Sets the current file that that line numbers refer to. All subsequent
- * line number entries make reference to this source file name, instead
- * of the default name specified in code_item.
- *
- * Args:
- * <ol>
- * <li>Unsigned LEB128 &mdash; string index (shifted by 1) of source
- * file name.
- * </ol>
- */
- static final int DBG_SET_FILE = 0x09;
-
- /* IF YOU ADD A NEW OPCODE, increase OPCODE_BASE */
-
- /*
- * "special opcode" configuration, essentially what's found in
- * the line number program header in DWARFv3, Section 6.2.4
- */
-
- /** the smallest value a special opcode can take */
- static final int DBG_FIRST_SPECIAL = 0x0a;
- static final int DBG_LINE_BASE = -4;
- static final int DBG_LINE_RANGE = 15;
- // MIN_INSN_LENGTH is always 1
-}
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
deleted file mode 100644
index 519452b64..000000000
--- a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
+++ /dev/null
@@ -1,563 +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.dx.dex.file;
-
-import com.android.dx.dex.code.LocalList;
-import com.android.dx.dex.code.PositionList;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.Prototype;
-import com.android.dx.rop.type.StdTypeList;
-import com.android.dx.rop.type.Type;
-import com.android.dx.util.ExceptionWithContext;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.android.dx.dex.file.DebugInfoConstants.*;
-
-/**
- * A decoder for the dex debug info state machine format.
- * This code exists mostly as a reference implementation and test for
- * for the <code>DebugInfoEncoder</code>
- */
-public class DebugInfoDecoder {
- /** encoded debug info */
- private final byte[] encoded;
- /** positions decoded */
- private final ArrayList<PositionEntry> positions;
- /** locals decoded */
- private final ArrayList<LocalEntry> locals;
- /** size of code block in code units */
- private final int codesize;
- /** indexed by register, the last local variable live in a reg */
- private final LocalEntry[] lastEntryForReg;
- /** method descriptor of method this debug info is for */
- private final Prototype desc;
- /** true if method is static */
- private final boolean isStatic;
- /** dex file this debug info will be stored in */
- private final DexFile file;
- /**
- * register size, in register units, of the register space
- * used by this method
- */
- private final int regSize;
-
- /** current decoding state: line number */
- private int line = 1;
-
- /** current decoding state: bytecode address */
- private int address = 0;
-
- /** string index of the string "this" */
- private final int thisStringIdx;
-
- /**
- * Constructs an instance.
- *
- * @param encoded encoded debug info
- * @param codesize size of code block in code units
- * @param regSize register size, in register units, of the register space
- * used by this method
- * @param isStatic true if method is static
- * @param ref method descriptor of method this debug info is for
- * @param file dex file this debug info will be stored in
- */
- DebugInfoDecoder (byte[] encoded, int codesize, int regSize,
- boolean isStatic, CstMethodRef ref, DexFile file) {
-
- this.encoded = encoded;
- this.isStatic = isStatic;
- this.desc = ref.getPrototype();
- this.file = file;
- this.regSize = regSize;
-
- positions = new ArrayList();
- locals = new ArrayList();
- this.codesize = codesize;
- lastEntryForReg = new LocalEntry[regSize];
-
- thisStringIdx = file.getStringIds().indexOf(new CstUtf8("this"));
- }
-
- /**
- * An entry in the resulting postions table
- */
- static class PositionEntry {
- /** bytecode address */
- int address;
- /** line number */
- int line;
-
- PositionEntry(int address, int line) {
- this.address = address;
- this.line = line;
- }
- }
-
- /**
- * An entry in the resulting locals table
- */
- static class LocalEntry {
- LocalEntry(int start, int reg, int nameIndex, int typeIndex,
- int signatureIndex) {
- this.start = start;
- this.reg = reg;
- this.nameIndex = nameIndex;
- this.typeIndex = typeIndex;
- this.signatureIndex = signatureIndex;
- }
-
- /** start of address range */
- int start;
-
- /**
- * End of address range. Initialized to MAX_VALUE here but will
- * be set to no more than 1 + max bytecode address of method.
- */
- int end = Integer.MAX_VALUE;
-
- /** register number */
- int reg;
-
- /** index of name in strings table */
- int nameIndex;
-
- /** index of type in types table */
- int typeIndex;
-
- /** index of type signature in strings table */
- int signatureIndex;
-
- }
-
- /**
- * Gets the decoded positions list.
- * Valid after calling <code>decode</code>.
- *
- * @return positions list in ascending address order.
- */
- public List<PositionEntry> getPositionList() {
- return positions;
- }
-
- /**
- * Gets the decoded locals list, in ascending start-address order.
- * Valid after calling <code>decode</code>.
- *
- * @return locals list in ascending address order.
- */
- public List<LocalEntry> getLocals() {
- // TODO move this loop:
- // Any variable that didnt end ends now
- for (LocalEntry local: locals) {
- if (local.end == Integer.MAX_VALUE) {
- local.end = codesize;
- }
- }
- return locals;
- }
-
- /**
- * Decodes the debug info sequence.
- */
- public void decode() {
- try {
- decode0();
- } catch (Exception ex) {
- throw ExceptionWithContext.withContext(ex,
- "...while decoding debug info");
- }
- }
-
- /**
- * Reads a string index. String indicies are offset by 1, and a 0 value
- * in the stream (-1 as returned by this method) means "null"
- *
- * @param bs
- * @return index into file's string ids table, -1 means null
- * @throws IOException
- */
- private int readStringIndex(InputStream bs) throws IOException {
- int offsetIndex = readUnsignedLeb128(bs);
-
- return offsetIndex - 1;
- }
-
- /**
- * Gets the register that begins the method's parameter range (including
- * the 'this' parameter for non-static methods). The range continues until
- * <code>regSize</code>
- *
- * @return register as noted above.
- */
- private int getParamBase() {
- return regSize
- - desc.getParameterTypes().getWordCount() - (isStatic? 0 : 1);
- }
-
- private void decode0() throws IOException {
- ByteArrayInputStream bs = new ByteArrayInputStream(encoded);
-
- line = readUnsignedLeb128(bs);
- int szParams = readUnsignedLeb128(bs);
- StdTypeList params = desc.getParameterTypes();
- int curReg = getParamBase();
-
- if (szParams != params.size()) {
- throw new RuntimeException(
- "Mismatch between parameters_size and prototype");
- }
-
- if (!isStatic) {
- // Start off with implicit 'this' entry
- LocalEntry thisEntry
- = new LocalEntry(0, curReg, thisStringIdx, 0, 0);
- locals.add(thisEntry);
- lastEntryForReg[curReg] = thisEntry;
- curReg++;
- }
-
- for (int i = 0; i < szParams; i++) {
- Type paramType = params.getType(i);
- LocalEntry le;
-
- int nameIdx = readStringIndex(bs);
-
- if(nameIdx == -1) {
- // unnamed parameter
- } else {
- // final '0' should be idx of paramType.getDescriptor()
- le = new LocalEntry(0, curReg, nameIdx, 0, 0);
- locals.add(le);
- lastEntryForReg[curReg] = le;
- }
-
- curReg += paramType.getCategory();
- }
-
- for (;;) {
- int opcode = bs.read();
-
- if (opcode < 0) {
- throw new RuntimeException
- ("Reached end of debug stream without "
- + "encountering end marker");
- }
-
- switch (opcode) {
- case DBG_START_LOCAL: {
- int reg = readUnsignedLeb128(bs);
- int nameIdx = readStringIndex(bs);
- int typeIdx = readStringIndex(bs);
- LocalEntry le = new LocalEntry(
- address, reg, nameIdx, typeIdx, 0);
-
- // a "start" is implicitly the "end" of whatever was
- // previously defined in the register
- if (lastEntryForReg[reg] != null
- && lastEntryForReg[reg].end == Integer.MAX_VALUE) {
-
- lastEntryForReg[reg].end = address;
- }
-
- locals.add(le);
- lastEntryForReg[reg] = le;
- }
- break;
-
- case DBG_START_LOCAL_EXTENDED: {
- int reg = readUnsignedLeb128(bs);
- int nameIdx = readStringIndex(bs);
- int typeIdx = readStringIndex(bs);
- int sigIdx = readStringIndex(bs);
- LocalEntry le = new LocalEntry(
- address, reg, nameIdx, typeIdx, sigIdx);
-
- // a "start" is implicitly the "end" of whatever was
- // previously defined in the register
- if (lastEntryForReg[reg] != null
- && lastEntryForReg[reg].end == Integer.MAX_VALUE) {
-
- lastEntryForReg[reg].end = address;
-
- // A 0-length entry. Almost certainly a "this"
- // with a signature.
- if (lastEntryForReg[reg].start == address) {
- locals.remove(lastEntryForReg[reg]);
- }
- }
-
- locals.add(le);
- lastEntryForReg[reg] = le;
- }
- break;
-
- case DBG_RESTART_LOCAL: {
- int reg = readUnsignedLeb128(bs);
- LocalEntry prevle;
- LocalEntry le;
-
- try {
- prevle = lastEntryForReg[reg];
-
- if (lastEntryForReg[reg].end == Integer.MAX_VALUE) {
- throw new RuntimeException ("nonsensical "
- + "RESTART_LOCAL on live register v"+reg);
- }
- le = new LocalEntry(address, reg,
- prevle.nameIndex, prevle.typeIndex, 0);
-
- } catch (NullPointerException ex) {
- throw new RuntimeException
- ("Encountered RESTART_LOCAL on new v" +reg);
- }
-
- locals.add(le);
- lastEntryForReg[reg] = le;
- }
- break;
-
- case DBG_END_LOCAL: {
- int reg = readUnsignedLeb128(bs);
- boolean found = false;
- for (int i = locals.size() - 1; i >= 0; i--) {
- if (locals.get(i).reg == reg) {
- locals.get(i).end = address;
- found = true;
- break;
- }
- }
-
- if (!found) {
- throw new RuntimeException(
- "Encountered LOCAL_END without local start: v"
- + reg);
- }
- }
- break;
-
- case DBG_END_SEQUENCE:
- // all done
- return;
-
- case DBG_ADVANCE_PC:
- address += readUnsignedLeb128(bs);
- break;
-
- case DBG_ADVANCE_LINE:
- line += readSignedLeb128(bs);
- break;
-
- case DBG_SET_PROLOGUE_END:
- //TODO do something with this.
- break;
-
- case DBG_SET_EPILOGUE_BEGIN:
- //TODO do something with this.
- break;
-
- case DBG_SET_FILE:
- //TODO do something with this.
- break;
-
- default:
- if (opcode < DBG_FIRST_SPECIAL) {
- throw new RuntimeException(
- "Invalid extended opcode encountered "
- + opcode);
- }
-
- int adjopcode = opcode - DBG_FIRST_SPECIAL;
-
- address += adjopcode / DBG_LINE_RANGE;
- line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
-
- positions.add(new PositionEntry(address, line));
- break;
-
- }
- }
- }
-
- /**
- * Validates an encoded debug info stream against data used to encode it,
- * throwing an exception if they do not match. Used to validate the
- * encoder.
- *
- * @param linecodes encoded debug info
- * @param codeSize size of insn block in code units
- * @param countRegisters size of used register block in register units
- * @param pl position list to verify against
- * @param ll locals list to verify against.
- */
- public static void validateEncode(byte[] linecodes, int codeSize,
- int countRegisters, PositionList pl, LocalList ll,
- boolean isStatic, CstMethodRef ref, DexFile file) {
-
- try {
- validateEncode0(linecodes, codeSize, countRegisters,
- isStatic, ref, file, pl, ll);
- } catch (RuntimeException ex) {
-// System.err.println(ex.toString()
-// + " while processing " + ref.toHuman());
- throw ExceptionWithContext.withContext(ex,
- "while processing " + ref.toHuman());
- }
- }
-
-
- private static void validateEncode0(byte[] linecodes, int codeSize,
- int countRegisters, boolean isStatic, CstMethodRef ref,
- DexFile file, PositionList pl, LocalList ll) {
- DebugInfoDecoder decoder
- = new DebugInfoDecoder(linecodes, codeSize, countRegisters,
- isStatic, ref, file);
-
- decoder.decode();
-
- List<PositionEntry> decodedEntries;
-
- decodedEntries = decoder.getPositionList();
-
- if (decodedEntries.size() != pl.size()) {
- throw new RuntimeException(
- "Decoded positions table not same size was "
- + decodedEntries.size() + " expected " + pl.size());
- }
-
- for (PositionEntry entry: decodedEntries) {
- boolean found = false;
- for (int i = pl.size() - 1; i >= 0; i--) {
- PositionList.Entry ple = pl.get(i);
-
- if (entry.line == ple.getPosition().getLine()
- && entry.address == ple.getAddress()) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- throw new RuntimeException ("Could not match position entry: "
- + entry.address + ", " + entry.line);
- }
- }
-
- List<LocalEntry> decodedLocals;
-
- decodedLocals = decoder.getLocals();
-
- int paramBase = decoder.getParamBase();
-
- int matchedLocalsEntries = 0;
-
- for (LocalEntry entry: decodedLocals) {
- boolean found = false;
- for (int i = ll.size() - 1; i >= 0; i--) {
- LocalList.Entry le = ll.get(i);
-
- /*
- * If an entry is a method parameter, then the original
- * entry may not be marked as starting at 0. However, the
- * end address should still match.
- */
- if ((entry.start == le.getStart()
- || (entry.start == 0 && entry.reg >= paramBase))
- && entry.end == le.getEnd()
- && entry.reg == le.getRegister()) {
- found = true;
- matchedLocalsEntries++;
- break;
- }
- }
-
- if (!found) {
- throw new RuntimeException("Could not match local entry");
- }
- }
-
- if (matchedLocalsEntries != ll.size()) {
- throw new RuntimeException("Locals tables did not match");
- }
- }
-
- /**
- * Reads a DWARFv3-style signed LEB128 integer to the specified stream.
- * See DWARF v3 section 7.6. An invalid sequence produces an IOException.
- *
- * @param bs stream to input from
- * @return read value
- * @throws IOException on invalid sequence in addition to
- * those caused by the InputStream
- */
- public static int readSignedLeb128(InputStream bs) throws IOException {
- int result = 0;
- int cur;
- int count = 0;
- int signBits = -1;
-
- do {
- cur = bs.read();
- result |= (cur & 0x7f) << (count * 7);
- signBits <<= 7;
- count++;
- } while (((cur & 0x80) == 0x80) && count < 5);
-
- if ((cur & 0x80) == 0x80) {
- throw new IOException ("invalid LEB128 sequence");
- }
-
- // Sign extend if appropriate
- if (((signBits >> 1) & result) != 0 ) {
- result |= signBits;
- }
-
- return result;
- }
-
- /**
- * Reads a DWARFv3-style unsigned LEB128 integer to the specified stream.
- * See DWARF v3 section 7.6. An invalid sequence produces an IOException.
- *
- * @param bs stream to input from
- * @return read value, which should be treated as an unsigned value.
- * @throws IOException on invalid sequence in addition to
- * those caused by the InputStream
- */
- public static int readUnsignedLeb128(InputStream bs) throws IOException {
- int result = 0;
- int cur;
- int count = 0;
-
- do {
- cur = bs.read();
- result |= (cur & 0x7f) << (count * 7);
- count++;
- } while (((cur & 0x80) == 0x80) && count < 5);
-
- if ((cur & 0x80) == 0x80) {
- throw new IOException ("invalid LEB128 sequence");
- }
-
- return result;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
deleted file mode 100644
index 49781bdd8..000000000
--- a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
+++ /dev/null
@@ -1,1035 +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.dx.dex.file;
-
-import com.android.dx.dex.code.LocalList;
-import com.android.dx.dex.code.PositionList;
-import com.android.dx.rop.code.RegisterSpec;
-import com.android.dx.rop.code.SourcePosition;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.Prototype;
-import com.android.dx.rop.type.StdTypeList;
-import com.android.dx.rop.type.Type;
-import com.android.dx.util.ByteArrayAnnotatedOutput;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ExceptionWithContext;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.BitSet;
-
-import static com.android.dx.dex.file.DebugInfoConstants.*;
-
-/**
- * An encoder for the dex debug info state machine format. The format
- * for each method enrty is as follows:
- * <ol>
- * <li> signed LEB128: initial value for line register.
- * <li> n instances of signed LEB128: string indicies (offset by 1)
- * for each method argument in left-to-right order
- * with <code>this</code> excluded. A value of '0' indicates "no name"
- * <li> A sequence of special or normal opcodes as defined in
- * <code>DebugInfoConstants</code>.
- * <li> A single terminating <code>OP_END_SEQUENCE</code>
- * </ol>
- */
-public final class DebugInfoEncoder {
- private static final boolean DEBUG = false;
-
- /** null-ok; positions (line numbers) to encode */
- private final PositionList positionlist;
-
- /** null-ok; local variables to encode */
- private final LocalList locallist;
-
- private final ByteArrayAnnotatedOutput output;
- private final DexFile file;
- private final int codeSize;
- private final int regSize;
-
- private final Prototype desc;
- private final boolean isStatic;
-
- /** current encoding state: bytecode address */
- private int address = 0;
-
- /** current encoding state: line number */
- private int line = 1;
-
- /**
- * if non-null: the output to write annotations to. No normal
- * output is written to this.
- */
- private AnnotatedOutput annotateTo;
-
- /** if non-null: another possible output for annotations */
- private PrintWriter debugPrint;
-
- /** if non-null: the prefix for each annotation or debugPrint line */
- private String prefix;
-
- /** true if output should be consumed during annotation */
- private boolean shouldConsume;
-
- /** indexed by register; last local alive in register */
- private final LocalList.Entry[] lastEntryForReg;
-
- /**
- * Creates an instance.
- *
- * @param pl null-ok; positions (line numbers) to encode
- * @param ll null-ok; local variables to encode
- * @param file null-ok; may only be <code>null</code> if simply using
- * this class to do a debug print
- * @param codeSize
- * @param regSize
- * @param isStatic
- * @param ref
- */
- public DebugInfoEncoder(PositionList pl, LocalList ll,
- DexFile file, int codeSize, int regSize,
- boolean isStatic, CstMethodRef ref) {
- this.positionlist = pl;
- this.locallist = ll;
- this.file = file;
- output = new ByteArrayAnnotatedOutput();
- this.desc = ref.getPrototype();
- this.isStatic = isStatic;
-
- this.codeSize = codeSize;
- this.regSize = regSize;
-
- lastEntryForReg = new LocalList.Entry[regSize];
- }
-
- /**
- * Annotates or writes a message to the <code>debugPrint</code> writer
- * if applicable.
- *
- * @param length the number of bytes associated with this message
- * @param message the message itself
- */
- private void annotate(int length, String message) {
- if (prefix != null) {
- message = prefix + message;
- }
-
- if (annotateTo != null) {
- annotateTo.annotate(shouldConsume ? length : 0, message);
- }
-
- if (debugPrint != null) {
- debugPrint.println(message);
- }
- }
-
- /**
- * Converts this (PositionList, LocalList) pair into a state machine
- * sequence.
- *
- * @return encoded byte sequence without padding and
- * terminated with a <code>'\00'</code>
- */
- public byte[] convert() {
- try {
- byte[] ret;
- ret = convert0();
-
- if (DEBUG) {
- for (int i = 0 ; i < ret.length; i++) {
- System.err.printf("byte %02x\n", (0xff & ret[i]));
- }
- }
-
- return ret;
- } catch (IOException ex) {
- throw ExceptionWithContext
- .withContext(ex, "...while encoding debug info");
- }
- }
-
- /**
- * Converts and produces annotations on a stream. Does not write
- * actual bits to the <code>AnnotatedOutput</code>.
- *
- * @param prefix null-ok; prefix to attach to each line of output
- * @param debugPrint null-ok; if specified, an alternate output for
- * annotations
- * @param out null-ok; if specified, where annotations should go
- * @param consume whether to claim to have consumed output for
- * <code>out</code>
- * @return output sequence
- */
- public byte[] convertAndAnnotate(String prefix, PrintWriter debugPrint,
- AnnotatedOutput out, boolean consume) {
- this.prefix = prefix;
- this.debugPrint = debugPrint;
- annotateTo = out;
- shouldConsume = consume;
-
- byte[] result = convert();
-
- return result;
- }
-
- private byte[] convert0() throws IOException {
- ArrayList<PositionList.Entry> sortedPositions = buildSortedPositions();
- ArrayList<LocalList.Entry> sortedLocalsStart = buildLocalsStart();
-
- // Parameter locals are removed from sortedLocalsStart here.
- ArrayList<LocalList.Entry> methodArgs
- = extractMethodArguments(sortedLocalsStart);
-
- ArrayList<LocalList.Entry> sortedLocalsEnd
- = buildLocalsEnd(sortedLocalsStart);
-
- emitHeader(sortedPositions, methodArgs);
-
- // TODO: Make this mark the actual prologue end.
- output.writeByte(DBG_SET_PROLOGUE_END);
-
- if (annotateTo != null || debugPrint != null) {
- annotate(1, String.format("%04x: prologue end",address));
- }
-
- int szp = sortedPositions.size();
- int szl = sortedLocalsStart.size();
-
- // Current index in sortedPositions
- int curp = 0;
- // Current index in sortedLocalsStart
- int curls = 0;
- // Current index in sortedLocalsEnd
- int curle = 0;
-
- for (;;) {
- /*
- * Emit any information for the current address.
- */
-
- curle = emitLocalEndsAtAddress(curle, sortedLocalsEnd, curls,
- sortedLocalsStart);
-
- /*
- * Our locals-sorted-by-range-end has reached the end
- * of the code block. Ignore everything else.
- */
- if (address == codeSize) {
- curle = szl;
- }
-
- curls = emitLocalStartsAtAddress(curls, sortedLocalsStart);
-
- curp = emitPositionsAtAddress(curp, sortedPositions);
-
- /*
- * Figure out what the next important address is.
- */
-
- int nextAddrLS = Integer.MAX_VALUE; // local start
- int nextAddrLE = Integer.MAX_VALUE; // local end
- int nextAddrP = Integer.MAX_VALUE; // position (line number)
-
- if (curls < szl) {
- nextAddrLS = sortedLocalsStart.get(curls).getStart();
- }
-
- if (curle < szl) {
- nextAddrLE = sortedLocalsEnd.get(curle).getEnd();
- }
-
- if (curp < szp) {
- nextAddrP = sortedPositions.get(curp).getAddress();
- }
-
- int next = Math.min(nextAddrP, Math.min(nextAddrLS, nextAddrLE));
-
- // No next important address == done.
- if (next == Integer.MAX_VALUE) {
- break;
- }
-
- /*
- * If the only work remaining are local ends at the end of the
- * block, stop here. Those are implied anyway.
- */
- if (next == codeSize
- && nextAddrLS == Integer.MAX_VALUE
- && nextAddrP == Integer.MAX_VALUE) {
- break;
- }
-
- if (next == nextAddrP) {
- // Combined advance PC + position entry
- emitPosition(sortedPositions.get(curp++));
- } else {
- emitAdvancePc(next - address);
- }
- }
-
- emitEndSequence();
-
- return output.toByteArray();
- }
-
- /**
- * Emits all local ends that occur at the current <code>address</code>
- *
- * @param curle Current index in sortedLocalsEnd
- * @param sortedLocalsEnd Locals, sorted by ascending end address
- * @param curls Current index in sortedLocalsStart
- * @param sortedLocalsStart Locals, sorted by ascending start address
- * @return new value for <code>curle</code>
- * @throws IOException
- */
- private int emitLocalEndsAtAddress(int curle,
- ArrayList<LocalList.Entry> sortedLocalsEnd, int curls,
- ArrayList<LocalList.Entry> sortedLocalsStart)
- throws IOException {
-
- int szl = sortedLocalsEnd.size();
-
- // Ignore "local ends" at end of code.
- while (curle < szl
- && sortedLocalsEnd.get(curle).getEnd() == address
- && address != codeSize) {
-
- boolean skipLocalEnd = false;
-
- /*
- * Check to see if there's a range-start that appears at
- * the same address for the same register. If so, the
- * end-range is implicit so skip it.
- */
- for (int j = curls; j < szl
- && sortedLocalsStart.get(j).getStart() == address
- ; j++) {
-
- if (sortedLocalsStart.get(j).getRegister()
- == sortedLocalsEnd.get(curle).getRegister()) {
- skipLocalEnd = true;
-
- if (DEBUG) {
- System.err.printf("skip local end v%d\n",
- sortedLocalsEnd.get(curle).getRegister());
- }
- break;
- }
- }
-
- if (!skipLocalEnd) {
- emitLocalEnd(sortedLocalsEnd.get(curle));
- }
-
- curle++;
- }
- return curle;
- }
-
- /**
- * Emits all local starts that occur at the current <code>address</code>
- *
- * @param curls Current index in sortedLocalsStart
- * @param sortedLocalsStart Locals, sorted by ascending start address
- * @return new value for <code>curls</code>
- * @throws IOException
- */
- private int emitLocalStartsAtAddress(int curls,
- ArrayList<LocalList.Entry> sortedLocalsStart)
- throws IOException {
-
- int szl = sortedLocalsStart.size();
-
- while (curls < szl
- && sortedLocalsStart.get(curls).getStart() == address) {
- LocalList.Entry lle = sortedLocalsStart.get(curls++);
- int reg = lle.getRegister();
- LocalList.Entry prevlle = lastEntryForReg[reg];
-
- if (lle == prevlle) {
- /*
- * Here we ignore locals entries for parameters,
- * which have already been represented and placed in the
- * lastEntryForReg array.
- */
- continue;
- }
-
- // At this point we have a new live entry one way or another.
- lastEntryForReg[reg] = lle;
-
- if ((prevlle != null) && lle.matches(prevlle)) {
- if (prevlle.getEnd() == lle.getStart()) {
- /*
- * There is nothing more to do in this case: It's
- * an adjacent range with the same register. The
- * previous emitLocalEndsAtAddress() call skipped
- * this local end, so we'll skip this local start
- * as well.
- */
- } else {
- emitLocalRestart(lle);
- }
- } else {
- emitLocalStart(lle);
- }
- }
- return curls;
- }
-
- /**
- * Emits all positions that occur at the current <code>address</code>
- *
- * @param curp Current index in sortedPositions
- * @param sortedPositions positions, sorted by ascending address
- * @return new value for <code>curp</code>
- * @throws IOException
- */
- private int emitPositionsAtAddress(int curp,
- ArrayList<PositionList.Entry> sortedPositions)
- throws IOException {
-
- int szp = sortedPositions.size();
- while (curp < szp
- && sortedPositions.get(curp).getAddress() == address) {
- emitPosition(sortedPositions.get(curp++));
- }
- return curp;
- }
-
- /**
- * Emits the header sequence, which consists of LEB128-encoded initial
- * line number and string indicies for names of all non-"this" arguments.
- *
- * @param sortedPositions positions, sorted by ascending address
- * @param methodArgs local list entries for method argumens arguments,
- * in left-to-right order omitting "this"
- * @throws IOException
- */
- private void emitHeader(ArrayList<PositionList.Entry> sortedPositions,
- ArrayList<LocalList.Entry> methodArgs) throws IOException {
- boolean annotate = (annotateTo != null) || (debugPrint != null);
- int mark = output.getCursor();
-
- // Start by initializing the line number register.
- if (sortedPositions.size() > 0) {
- PositionList.Entry entry = sortedPositions.get(0);
- line = entry.getPosition().getLine();
- }
- output.writeUnsignedLeb128(line);
-
- if (annotate) {
- annotate(output.getCursor() - mark, "line_start: " + line);
- }
-
- int curParam = getParamBase();
- // paramTypes will not include 'this'
- StdTypeList paramTypes = desc.getParameterTypes();
- int szParamTypes = paramTypes.size();
-
- /*
- * Initialize lastEntryForReg to have an initial
- * entry for the 'this' pointer.
- */
- if (!isStatic) {
- for (LocalList.Entry arg: methodArgs) {
- if (curParam == arg.getRegister()) {
- lastEntryForReg[curParam] = arg;
- break;
- }
- }
- curParam++;
- }
-
- // Write out the number of parameter entries that will follow.
- mark = output.getCursor();
- output.writeUnsignedLeb128(szParamTypes);
-
- if (annotate) {
- annotate(output.getCursor() - mark,
- String.format("parameters_size: %04x", szParamTypes));
- }
-
- /*
- * Then emit the string indicies of all the method parameters.
- * Note that 'this', if applicable, is excluded.
- */
- for (int i = 0; i < szParamTypes; i++) {
- Type pt = paramTypes.get(i);
- LocalList.Entry found = null;
-
- mark = output.getCursor();
-
- for (LocalList.Entry arg: methodArgs) {
- if (curParam == arg.getRegister()) {
- found = arg;
-
- if (arg.getSignature() != null) {
- /*
- * Parameters with signatures will be re-emitted
- * in complete as LOCAL_START_EXTENDED's below.
- */
- emitStringIndex(null);
- } else {
- emitStringIndex(arg.getName());
- }
- lastEntryForReg[curParam] = arg;
-
- break;
- }
- }
-
- if (found == null) {
- /*
- * Emit a null symbol for "unnamed." This is common
- * for, e.g., synthesized methods and inner-class
- * this$0 arguments.
- */
- emitStringIndex(null);
- }
-
- if (annotate) {
- String parameterName
- = (found == null || found.getSignature() != null)
- ? "<unnamed>" : found.getName().toHuman();
- annotate(output.getCursor() - mark,
- "parameter " + parameterName + " "
- + RegisterSpec.PREFIX + curParam);
- }
-
- curParam += pt.getCategory();
- }
-
- /*
- * If anything emitted above has a type signature, emit it again as
- * a LOCAL_RESTART_EXTENDED
- */
-
- for (LocalList.Entry arg: lastEntryForReg) {
- if (arg == null) {
- continue;
- }
-
- CstUtf8 signature = arg.getSignature();
-
- if (signature != null) {
- emitLocalStartExtended(arg);
- }
- }
- }
-
- /**
- * Builds a list of position entries, sorted by ascending address.
- *
- * @return A sorted positions list
- */
- private ArrayList<PositionList.Entry> buildSortedPositions() {
- int sz = (positionlist == null) ? 0 : positionlist.size();
- ArrayList<PositionList.Entry> result = new ArrayList(sz);
-
- for (int i = 0; i < sz; i++) {
- result.add(positionlist.get(i));
- }
-
- // Sort ascending by address.
- Collections.sort (result, new Comparator<PositionList.Entry>() {
- public int compare (PositionList.Entry a, PositionList.Entry b) {
- return a.getAddress() - b.getAddress();
- }
-
- public boolean equals (Object obj) {
- return obj == this;
- }
- });
- return result;
- }
-
- /**
- * Builds a list of locals entries sorted by ascending start address.
- *
- * @return A sorted locals list list
- */
- private ArrayList<LocalList.Entry> buildLocalsStart() {
- int sz = (locallist == null) ? 0 : locallist.size();
- ArrayList<LocalList.Entry> result = new ArrayList(sz);
-
- // Add all the entries
- for (int i = 0; i < sz; i++) {
- LocalList.Entry e = locallist.get(i);
- result.add(locallist.get(i));
- }
-
- // Sort ascending by start address.
- Collections.sort (result, new Comparator<LocalList.Entry>() {
- public int compare (LocalList.Entry a, LocalList.Entry b) {
- return a.getStart() - b.getStart();
- }
-
- public boolean equals (Object obj) {
- return obj == this;
- }
- });
- return result;
- }
-
- /**
- * Builds a list of locals entries sorted by ascending end address.
- *
- * @param list locals list in any order
- * @return a sorted locals list
- */
- private ArrayList<LocalList.Entry> buildLocalsEnd(
- ArrayList<LocalList.Entry> list) {
-
- ArrayList<LocalList.Entry> sortedLocalsEnd = new ArrayList(list);
-
- // Sort ascending by end address.
- Collections.sort (sortedLocalsEnd, new Comparator<LocalList.Entry>() {
- public int compare (LocalList.Entry a, LocalList.Entry b) {
- return a.getEnd() - b.getEnd();
- }
-
- public boolean equals (Object obj) {
- return obj == this;
- }
- });
- return sortedLocalsEnd;
- }
-
- /**
- * Gets the register that begins the method's parameter range (including
- * the 'this' parameter for non-static methods). The range continues until
- * <code>regSize</code>
- *
- * @return register as noted above
- */
- private int getParamBase() {
- return regSize
- - desc.getParameterTypes().getWordCount() - (isStatic? 0 : 1);
- }
-
- /**
- * Extracts method arguments from a locals list. These will be collected
- * from the input list and sorted by ascending register in the
- * returned list.
- *
- * @param sortedLocals locals list, sorted by ascending start address,
- * to process; left unmodified
- * @return list of non-<code>this</code> method argument locals,
- * sorted by ascending register
- */
- private ArrayList<LocalList.Entry> extractMethodArguments (
- ArrayList<LocalList.Entry> sortedLocals) {
-
- ArrayList<LocalList.Entry> result
- = new ArrayList(desc.getParameterTypes().size());
-
- int argBase = getParamBase();
-
- BitSet seen = new BitSet(regSize - argBase);
-
- int sz = sortedLocals.size();
- for (int i = 0; i < sz; i++) {
- LocalList.Entry e = sortedLocals.get(i);
- int reg = e.getRegister();
-
- if (reg < argBase) {
- continue;
- }
-
- // only the lowest-start-address entry is included.
- if (seen.get(reg - argBase)) {
- continue;
- }
-
- seen.set(reg - argBase);
- result.add(e);
- }
-
- // Sort by ascending register.
- Collections.sort (result, new Comparator<LocalList.Entry>() {
- public int compare (LocalList.Entry a, LocalList.Entry b) {
- return a.getRegister() - b.getRegister();
- }
-
- public boolean equals (Object obj) {
- return obj == this;
- }
- });
-
- return result;
- }
-
- /**
- * Returns a string representation of this LocalList entry that is
- * appropriate for emitting as an annotation.
- *
- * @param e non-null; entry
- * @return non-null; annotation string
- */
- private String entryAnnotationString(LocalList.Entry e) {
- StringBuilder sb = new StringBuilder();
-
- sb.append(RegisterSpec.PREFIX);
- sb.append(e.getRegister());
- sb.append(' ');
-
- CstUtf8 name = e.getName();
- if (name == null) {
- sb.append("null");
- } else {
- sb.append(name.toHuman());
- }
- sb.append(' ');
-
- CstType type = e.getType();
- if (type == null) {
- sb.append("null");
- } else {
- sb.append(type.toHuman());
- }
-
- CstUtf8 signature = e.getSignature();
-
- if (signature != null) {
- sb.append(' ');
- sb.append(signature.toHuman());
- }
-
- return sb.toString();
- }
-
- /**
- * Emits a {@link DebugInfoConstants#DBG_RESTART_LOCAL DBG_RESTART_LOCAL}
- * sequence.
- *
- * @param entry entry associated with this restart
- * @throws IOException
- */
- private void emitLocalRestart(LocalList.Entry entry)
- throws IOException {
-
- int mark = output.getCursor();
-
- output.writeByte(DBG_RESTART_LOCAL);
- emitUnsignedLeb128(entry.getRegister());
-
- if (annotateTo != null || debugPrint != null) {
- annotate(output.getCursor() - mark,
- String.format("%04x: +local restart %s",
- address, entryAnnotationString(entry)));
- }
-
- if (DEBUG) {
- System.err.println("emit local restart");
- }
- }
-
- /**
- * Emits a string index as an unsigned LEB128. The actual value written
- * is shifted by 1, so that the '0' value is reserved for "null". The
- * null symbol is used in some cases by the parameter name list
- * at the beginning of the sequence.
- *
- * @param string null-ok; string to emit
- * @throws IOException
- */
- private void emitStringIndex(CstUtf8 string) throws IOException {
- if ((string == null) || (file == null)) {
- output.writeUnsignedLeb128(0);
- } else {
- output.writeUnsignedLeb128(
- 1 + file.getStringIds().indexOf(string));
- }
-
- if (DEBUG) {
- System.err.printf("Emit string %s\n",
- string == null ? "<null>" : string.toQuoted());
- }
- }
-
- /**
- * Emits a type index as an unsigned LEB128. The actual value written
- * is shifted by 1, so that the '0' value is reserved for "null".
- *
- * @param type null-ok; type to emit
- * @throws IOException
- */
- private void emitTypeIndex(CstType type) throws IOException {
- if ((type == null) || (file == null)) {
- output.writeUnsignedLeb128(0);
- } else {
- output.writeUnsignedLeb128(
- 1 + file.getTypeIds().indexOf(type));
- }
-
- if (DEBUG) {
- System.err.printf("Emit type %s\n",
- type == null ? "<null>" : type.toHuman());
- }
- }
-
- /**
- * Emits a {@link DebugInfoConstants#DBG_START_LOCAL DBG_START_LOCAL} or
- * {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED
- * DBG_START_LOCAL_EXTENDED} sequence.
- *
- * @param entry entry to emit
- * @throws IOException
- */
- private void emitLocalStart(LocalList.Entry entry)
- throws IOException {
-
- if (entry.getSignature() != null) {
- emitLocalStartExtended(entry);
- return;
- }
-
- int mark = output.getCursor();
-
- output.writeByte(DBG_START_LOCAL);
-
- emitUnsignedLeb128(entry.getRegister());
- emitStringIndex(entry.getName());
- emitTypeIndex(entry.getType());
-
- if (annotateTo != null || debugPrint != null) {
- annotate(output.getCursor() - mark,
- String.format("%04x: +local %s", address,
- entryAnnotationString(entry)));
- }
-
- if (DEBUG) {
- System.err.println("emit local start");
- }
- }
-
- /**
- * Emits a {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED
- * DBG_START_LOCAL_EXTENDED} sequence.
- *
- * @param entry entry to emit
- * @throws IOException
- */
- private void emitLocalStartExtended(LocalList.Entry entry)
- throws IOException {
-
- int mark = output.getCursor();
-
- output.writeByte(DBG_START_LOCAL_EXTENDED);
-
- emitUnsignedLeb128(entry.getRegister());
- emitStringIndex(entry.getName());
- emitTypeIndex(entry.getType());
- emitStringIndex(entry.getSignature());
-
- if (annotateTo != null || debugPrint != null) {
- annotate(output.getCursor() - mark,
- String.format("%04x: +localx %s", address,
- entryAnnotationString(entry)));
- }
-
- if (DEBUG) {
- System.err.println("emit local start");
- }
- }
-
- /**
- * Emits a {@link DebugInfoConstants#DBG_END_LOCAL DBG_END_LOCAL} sequence.
- *
- * @param entry entry non-null; entry associated with end.
- * @throws IOException
- */
- private void emitLocalEnd(LocalList.Entry entry)
- throws IOException {
-
- int mark = output.getCursor();
-
- output.writeByte(DBG_END_LOCAL);
- output.writeUnsignedLeb128(entry.getRegister());
-
- if (annotateTo != null || debugPrint != null) {
- annotate(output.getCursor() - mark,
- String.format("%04x: -local %s", address,
- entryAnnotationString(entry)));
- }
-
- if (DEBUG) {
- System.err.println("emit local end");
- }
- }
-
- /**
- * Emits the necessary byte sequences to emit the given position table
- * entry. This will typically be a single special opcode, although
- * it may also require DBG_ADVANCE_PC or DBG_ADVANCE_LINE.
- *
- * @param entry position entry to emit.
- * @throws IOException
- */
- private void emitPosition(PositionList.Entry entry)
- throws IOException {
-
- SourcePosition pos = entry.getPosition();
- int newLine = pos.getLine();
- int newAddress = entry.getAddress();
-
- int opcode;
-
- int deltaLines = newLine - line;
- int deltaAddress = newAddress - address;
-
- if (deltaAddress < 0) {
- throw new RuntimeException(
- "Position entries must be in ascending address order");
- }
-
- if ((deltaLines < DBG_LINE_BASE)
- || (deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1))) {
- emitAdvanceLine(deltaLines);
- deltaLines = 0;
- }
-
- opcode = computeOpcode (deltaLines, deltaAddress);
-
- if ((opcode & ~0xff) > 0) {
- emitAdvancePc(deltaAddress);
- deltaAddress = 0;
- opcode = computeOpcode (deltaLines, deltaAddress);
-
- if ((opcode & ~0xff) > 0) {
- emitAdvanceLine(deltaLines);
- deltaLines = 0;
- opcode = computeOpcode (deltaLines, deltaAddress);
- }
- }
-
- output.writeByte(opcode);
-
- line += deltaLines;
- address += deltaAddress;
-
- if (annotateTo != null || debugPrint != null) {
- annotate(1,
- String.format("%04x: line %d", address, line));
- }
- }
-
- /**
- * Computes a special opcode that will encode the given position change.
- * If the return value is > 0xff, then the request cannot be fulfilled.
- * Essentially the same as described in "DWARF Debugging Format Version 3"
- * section 6.2.5.1.
- *
- * @param deltaLines &gt;= DBG_LINE_BASE and &lt;= DBG_LINE_BASE +
- * DBG_LINE_RANGE, the line change to encode
- * @param deltaAddress &gt;= 0; the address change to encode
- * @return &lt;= 0xff if in range, otherwise parameters are out of range
- */
- private static int computeOpcode(int deltaLines, int deltaAddress) {
- if (deltaLines < DBG_LINE_BASE
- || deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1)) {
-
- throw new RuntimeException("Parameter out of range");
- }
-
- return (deltaLines - DBG_LINE_BASE)
- + (DBG_LINE_RANGE * deltaAddress) + DBG_FIRST_SPECIAL;
- }
-
- /**
- * Emits an {@link DebugInfoConstants#DBG_ADVANCE_LINE DBG_ADVANCE_LINE}
- * sequence.
- *
- * @param deltaLines amount to change line number register by
- * @throws IOException
- */
- private void emitAdvanceLine(int deltaLines) throws IOException {
- int mark = output.getCursor();
-
- output.writeByte(DBG_ADVANCE_LINE);
- output.writeSignedLeb128(deltaLines);
- line += deltaLines;
-
- if (annotateTo != null || debugPrint != null) {
- annotate(output.getCursor() - mark,
- String.format("line = %d", line));
- }
-
- if (DEBUG) {
- System.err.printf("Emitting advance_line for %d\n", deltaLines);
- }
- }
-
- /**
- * Emits an {@link DebugInfoConstants#DBG_ADVANCE_PC DBG_ADVANCE_PC}
- * sequence.
- *
- * @param deltaAddress &gt;= 0 amount to change program counter by
- * @throws IOException
- */
- private void emitAdvancePc(int deltaAddress) throws IOException {
- int mark = output.getCursor();
-
- output.writeByte(DBG_ADVANCE_PC);
- output.writeUnsignedLeb128(deltaAddress);
- address += deltaAddress;
-
- if (annotateTo != null || debugPrint != null) {
- annotate(output.getCursor() - mark,
- String.format("%04x: advance pc", address));
- }
-
- if (DEBUG) {
- System.err.printf("Emitting advance_pc for %d\n", deltaAddress);
- }
- }
-
- /**
- * Emits an unsigned LEB128 value.
- *
- * @param n &gt= 0 vallue to emit. Note that, although this can represent
- * integers larger than Integer.MAX_VALUE, we currently don't allow that.
- * @throws IOException
- */
- private void emitUnsignedLeb128(int n) throws IOException {
- // We'll never need the top end of the unsigned range anyway.
- if (n < 0) {
- throw new RuntimeException(
- "Signed value where unsigned required: " + n);
- }
-
- output.writeSignedLeb128(n);
- }
-
- /**
- * Emits the {@link DebugInfoConstants#DBG_END_SEQUENCE DBG_END_SEQUENCE}
- * bytecode.
- */
- private void emitEndSequence() {
- output.writeByte(DBG_END_SEQUENCE);
-
- if (annotateTo != null || debugPrint != null) {
- annotate(1, "end sequence");
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoItem.java b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
deleted file mode 100644
index b0745935d..000000000
--- a/dx/src/com/android/dx/dex/file/DebugInfoItem.java
+++ /dev/null
@@ -1,170 +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.dx.dex.file;
-
-import com.android.dx.dex.code.DalvCode;
-import com.android.dx.dex.code.DalvInsnList;
-import com.android.dx.dex.code.LocalList;
-import com.android.dx.dex.code.PositionList;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ExceptionWithContext;
-
-import java.io.PrintWriter;
-
-public class DebugInfoItem extends OffsettedItem {
- /** the required alignment for instances of this class */
- private static final int ALIGNMENT = 1;
-
- private static final boolean ENABLE_ENCODER_SELF_CHECK = false;
-
- /** non-null; the code this item represents */
- private final DalvCode code;
-
- private byte[] encoded;
-
- private final boolean isStatic;
- private final CstMethodRef ref;
-
- public DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref) {
- // We don't know the write size yet.
- super (ALIGNMENT, -1);
-
- if (code == null) {
- throw new NullPointerException("code == null");
- }
-
- this.code = code;
- this.isStatic = isStatic;
- this.ref = ref;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_DEBUG_INFO_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- // No contents to add.
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- // Encode the data and note the size.
-
- try {
- encoded = encode(addedTo.getFile(), null, null, null, false);
- setWriteSize(encoded.length);
- } catch (RuntimeException ex) {
- throw ExceptionWithContext.withContext(ex,
- "...while placing debug info for " + ref.toHuman());
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- throw new RuntimeException("unsupported");
- }
-
- /**
- * Writes annotations for the elements of this list, as
- * zero-length. This is meant to be used for dumping this instance
- * directly after a code dump (with the real local list actually
- * existing elsewhere in the output).
- *
- * @param file non-null; the file to use for referencing other sections
- * @param out non-null; where to annotate to
- * @param prefix null-ok; prefix to attach to each line of output
- */
- public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) {
- encode(file, prefix, null, out, false);
- }
-
- /**
- * Does a human-friendly dump of this instance.
- *
- * @param out non-null; where to dump
- * @param prefix non-null; prefix to attach to each line of output
- */
- public void debugPrint(PrintWriter out, String prefix) {
- encode(null, prefix, out, null, false);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- if (out.annotates()) {
- /*
- * Re-run the encoder to generate the annotations,
- * but write the bits from the original encode
- */
-
- out.annotate(offsetString() + " debug info");
- encode(file, null, null, out, true);
- }
-
- out.write(encoded);
- }
-
- /**
- * Performs debug info encoding.
- *
- * @param file null-ok; file to refer to during encoding
- * @param prefix null-ok; prefix to attach to each line of output
- * @param debugPrint null-ok; if specified, an alternate output for
- * annotations
- * @param out null-ok; if specified, where annotations should go
- * @param consume whether to claim to have consumed output for
- * <code>out</code>
- * @return non-null; the encoded array
- */
- private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
- AnnotatedOutput out, boolean consume) {
- PositionList positions = code.getPositions();
- LocalList locals = code.getLocals();
- DalvInsnList insns = code.getInsns();
- int codeSize = insns.codeSize();
- int regSize = insns.getRegistersSize();
-
- DebugInfoEncoder encoder =
- new DebugInfoEncoder(positions, locals,
- file, codeSize, regSize, isStatic, ref);
-
- byte[] result;
-
- if ((debugPrint == null) && (out == null)) {
- result = encoder.convert();
- } else {
- result = encoder.convertAndAnnotate(
- prefix, debugPrint, out, consume);
- }
-
- if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
- DebugInfoDecoder.validateEncode(encoded, codeSize,
- regSize, positions, locals, isStatic, ref, file);
- }
-
- return result;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/DexFile.java b/dx/src/com/android/dx/dex/file/DexFile.java
deleted file mode 100644
index 8a4075d67..000000000
--- a/dx/src/com/android/dx/dex/file/DexFile.java
+++ /dev/null
@@ -1,647 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstBaseMethodRef;
-import com.android.dx.rop.cst.CstEnumRef;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.Type;
-import com.android.dx.util.ByteArrayAnnotatedOutput;
-import com.android.dx.util.ExceptionWithContext;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.security.DigestException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.zip.Adler32;
-
-import static com.android.dx.dex.file.MixedItemSection.SortType;
-
-/**
- * Representation of an entire <code>.dex</code> (Dalvik EXecutable)
- * file, which itself consists of a set of Dalvik classes.
- */
-public final class DexFile {
- /** non-null; word data section */
- private final MixedItemSection wordData;
-
- /**
- * non-null; type lists section. This is word data, but separating
- * it from {@link #wordData} helps break what would otherwise be a
- * circular dependency between the that and {@link #protoIds}.
- */
- private final MixedItemSection typeLists;
-
- /**
- * non-null; map section. The map needs to be in a section by itself
- * for the self-reference mechanics to work in a reasonably
- * straightforward way. See {@link MapItem#addMap} for more detail.
- */
- private final MixedItemSection map;
-
- /** non-null; string data section */
- private final MixedItemSection stringData;
-
- /** non-null; string identifiers section */
- private final StringIdsSection stringIds;
-
- /** non-null; type identifiers section */
- private final TypeIdsSection typeIds;
-
- /** non-null; prototype identifiers section */
- private final ProtoIdsSection protoIds;
-
- /** non-null; field identifiers section */
- private final FieldIdsSection fieldIds;
-
- /** non-null; method identifiers section */
- private final MethodIdsSection methodIds;
-
- /** non-null; class definitions section */
- private final ClassDefsSection classDefs;
-
- /** non-null; class data section */
- private final MixedItemSection classData;
-
- /** non-null; byte data section */
- private final MixedItemSection byteData;
-
- /** non-null; file header */
- private final HeaderSection header;
-
- /**
- * non-null; array of sections in the order they will appear in the
- * final output file
- */
- private final Section[] sections;
-
- /** &gt;= -1; total file size or <code>-1</code> if unknown */
- private int fileSize;
-
- /** &gt;= 40; maximum width of the file dump */
- private int dumpWidth;
-
- /**
- * Constructs an instance. It is initially empty.
- */
- public DexFile() {
- header = new HeaderSection(this);
- typeLists = new MixedItemSection(null, this, 4, SortType.NONE);
- wordData = new MixedItemSection("word_data", this, 4, SortType.TYPE);
- stringData =
- new MixedItemSection("string_data", this, 1, SortType.INSTANCE);
- classData = new MixedItemSection(null, this, 1, SortType.NONE);
- byteData = new MixedItemSection("byte_data", this, 1, SortType.TYPE);
- stringIds = new StringIdsSection(this);
- typeIds = new TypeIdsSection(this);
- protoIds = new ProtoIdsSection(this);
- fieldIds = new FieldIdsSection(this);
- methodIds = new MethodIdsSection(this);
- classDefs = new ClassDefsSection(this);
- map = new MixedItemSection("map", this, 4, SortType.NONE);
-
- /*
- * This is the list of sections in the order they appear in
- * the final output.
- */
- sections = new Section[] {
- header, stringIds, typeIds, protoIds, fieldIds, methodIds,
- classDefs, wordData, typeLists, stringData, byteData,
- classData, map };
-
- fileSize = -1;
- dumpWidth = 79;
- }
-
- /**
- * Adds a class to this instance. It is illegal to attempt to add more
- * than one class with the same name.
- *
- * @param clazz non-null; the class to add
- */
- public void add(ClassDefItem clazz) {
- classDefs.add(clazz);
- }
-
- /**
- * Gets the class definition with the given name, if any.
- *
- * @param name non-null; the class name to look for
- * @return null-ok; the class with the given name, or <code>null</code>
- * if there is no such class
- */
- public ClassDefItem getClassOrNull(String name) {
- try {
- Type type = Type.internClassName(name);
- return (ClassDefItem) classDefs.get(new CstType(type));
- } catch (IllegalArgumentException ex) {
- // Translate exception, per contract.
- return null;
- }
- }
-
- /**
- * Writes the contents of this instance as either a binary or a
- * human-readable form, or both.
- *
- * @param out null-ok; where to write to
- * @param humanOut null-ok; where to write human-oriented output to
- * @param verbose whether to be verbose when writing human-oriented output
- */
- public void writeTo(OutputStream out, Writer humanOut, boolean verbose)
- throws IOException {
- boolean annotate = (humanOut != null);
- ByteArrayAnnotatedOutput result = toDex0(annotate, verbose);
-
- if (out != null) {
- out.write(result.getArray());
- }
-
- if (annotate) {
- result.writeAnnotationsTo(humanOut);
- }
- }
-
- /**
- * Returns the contents of this instance as a <code>.dex</code> file,
- * in <code>byte[]</code> form.
- *
- * @param humanOut null-ok; where to write human-oriented output to
- * @param verbose whether to be verbose when writing human-oriented output
- * @return non-null; a <code>.dex</code> file for this instance
- */
- public byte[] toDex(Writer humanOut, boolean verbose)
- throws IOException {
- boolean annotate = (humanOut != null);
- ByteArrayAnnotatedOutput result = toDex0(annotate, verbose);
-
- if (annotate) {
- result.writeAnnotationsTo(humanOut);
- }
-
- return result.getArray();
- }
-
- /**
- * Sets the maximum width of the human-oriented dump of the instance.
- *
- * @param dumpWidth &gt;= 40; the width
- */
- public void setDumpWidth(int dumpWidth) {
- if (dumpWidth < 40) {
- throw new IllegalArgumentException("dumpWidth < 40");
- }
-
- this.dumpWidth = dumpWidth;
- }
-
- /**
- * Gets the total file size, if known.
- *
- * <p>This is package-scope in order to allow
- * the {@link HeaderSection} to set itself up properly.</p>
- *
- * @return &gt;= 0; the total file size
- * @throws RuntimeException thrown if the file size is not yet known
- */
- /*package*/ int getFileSize() {
- if (fileSize < 0) {
- throw new RuntimeException("file size not yet known");
- }
-
- return fileSize;
- }
-
- /**
- * Gets the string data section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the string data section
- */
- /*package*/ MixedItemSection getStringData() {
- return stringData;
- }
-
- /**
- * Gets the word data section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the word data section
- */
- /*package*/ MixedItemSection getWordData() {
- return wordData;
- }
-
- /**
- * Gets the type lists section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the word data section
- */
- /*package*/ MixedItemSection getTypeLists() {
- return typeLists;
- }
-
- /**
- * Gets the map section.
- *
- * <p>This is package-scope in order to allow the header section
- * to query it.</p>
- *
- * @return non-null; the map section
- */
- /*package*/ MixedItemSection getMap() {
- return map;
- }
-
- /**
- * Gets the string identifiers section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the string identifiers section
- */
- /*package*/ StringIdsSection getStringIds() {
- return stringIds;
- }
-
- /**
- * Gets the class definitions section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the class definitions section
- */
- /*package*/ ClassDefsSection getClassDefs() {
- return classDefs;
- }
-
- /**
- * Gets the class data section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the class data section
- */
- /*package*/ MixedItemSection getClassData() {
- return classData;
- }
-
- /**
- * Gets the type identifiers section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the class identifiers section
- */
- /*package*/ TypeIdsSection getTypeIds() {
- return typeIds;
- }
-
- /**
- * Gets the prototype identifiers section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the prototype identifiers section
- */
- /*package*/ ProtoIdsSection getProtoIds() {
- return protoIds;
- }
-
- /**
- * Gets the field identifiers section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the field identifiers section
- */
- /*package*/ FieldIdsSection getFieldIds() {
- return fieldIds;
- }
-
- /**
- * Gets the method identifiers section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the method identifiers section
- */
- /*package*/ MethodIdsSection getMethodIds() {
- return methodIds;
- }
-
- /**
- * Gets the byte data section.
- *
- * <p>This is package-scope in order to allow
- * the various {@link Item} instances to add items to the
- * instance.</p>
- *
- * @return non-null; the byte data section
- */
- /*package*/ MixedItemSection getByteData() {
- return byteData;
- }
-
- /**
- * Gets the first section of the file that is to be considered
- * part of the data section.
- *
- * <p>This is package-scope in order to allow the header section
- * to query it.</p>
- *
- * @return non-null; the section
- */
- /*package*/ Section getFirstDataSection() {
- return wordData;
- }
-
- /**
- * Gets the last section of the file that is to be considered
- * part of the data section.
- *
- * <p>This is package-scope in order to allow the header section
- * to query it.</p>
- *
- * @return non-null; the section
- */
- /*package*/ Section getLastDataSection() {
- return map;
- }
-
- /**
- * Interns the given constant in the appropriate section of this
- * instance, or do nothing if the given constant isn't the sort
- * that should be interned.
- *
- * @param cst non-null; constant to possibly intern
- */
- /*package*/ void internIfAppropriate(Constant cst) {
- if (cst instanceof CstString) {
- stringIds.intern((CstString) cst);
- } else if (cst instanceof CstUtf8) {
- stringIds.intern((CstUtf8) cst);
- } else if (cst instanceof CstType) {
- typeIds.intern((CstType) cst);
- } else if (cst instanceof CstBaseMethodRef) {
- methodIds.intern((CstBaseMethodRef) cst);
- } else if (cst instanceof CstFieldRef) {
- fieldIds.intern((CstFieldRef) cst);
- } else if (cst instanceof CstEnumRef) {
- fieldIds.intern(((CstEnumRef) cst).getFieldRef());
- } else if (cst == null) {
- throw new NullPointerException("cst == null");
- }
- }
-
- /**
- * Gets the {@link IndexedItem} corresponding to the given constant,
- * if it is a constant that has such a correspondence, or return
- * <code>null</code> if it isn't such a constant. This will throw
- * an exception if the given constant <i>should</i> have been found
- * but wasn't.
- *
- * @param cst non-null; the constant to look up
- * @return null-ok; its corresponding item, if it has a corresponding
- * item, or <code>null</code> if it's not that sort of constant
- */
- /*package*/ IndexedItem findItemOrNull(Constant cst) {
- IndexedItem item;
-
- if (cst instanceof CstString) {
- return stringIds.get(cst);
- } else if (cst instanceof CstType) {
- return typeIds.get(cst);
- } else if (cst instanceof CstBaseMethodRef) {
- return methodIds.get(cst);
- } else if (cst instanceof CstFieldRef) {
- return fieldIds.get(cst);
- } else {
- return null;
- }
- }
-
- /**
- * Returns the contents of this instance as a <code>.dex</code> file,
- * in a {@link ByteArrayAnnotatedOutput} instance.
- *
- * @param annotate whether or not to keep annotations
- * @param verbose if annotating, whether to be verbose
- * @return non-null; a <code>.dex</code> file for this instance
- */
- private ByteArrayAnnotatedOutput toDex0(boolean annotate,
- boolean verbose) {
- /*
- * The following is ordered so that the prepare() calls which
- * add items happen before the calls to the sections that get
- * added to.
- */
-
- classDefs.prepare();
- classData.prepare();
- wordData.prepare();
- byteData.prepare();
- methodIds.prepare();
- fieldIds.prepare();
- protoIds.prepare();
- typeLists.prepare();
- typeIds.prepare();
- stringIds.prepare();
- stringData.prepare();
- header.prepare();
-
- // Place the sections within the file.
-
- int count = sections.length;
- int offset = 0;
-
- for (int i = 0; i < count; i++) {
- Section one = sections[i];
- int placedAt = one.setFileOffset(offset);
- if (placedAt < offset) {
- throw new RuntimeException("bogus placement for section " + i);
- }
-
- try {
- if (one == map) {
- /*
- * Inform the map of all the sections, and add it
- * to the file. This can only be done after all
- * the other items have been sorted and placed.
- */
- MapItem.addMap(sections, map);
- map.prepare();
- }
-
- if (one instanceof MixedItemSection) {
- /*
- * Place the items of a MixedItemSection that just
- * got placed.
- */
- ((MixedItemSection) one).placeItems();
- }
-
- offset = placedAt + one.writeSize();
- } catch (RuntimeException ex) {
- throw ExceptionWithContext.withContext(ex,
- "...while writing section " + i);
- }
- }
-
- // Write out all the sections.
-
- fileSize = offset;
- byte[] barr = new byte[fileSize];
- ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(barr);
-
- if (annotate) {
- out.enableAnnotations(dumpWidth, verbose);
- }
-
- for (int i = 0; i < count; i++) {
- try {
- Section one = sections[i];
- int zeroCount = one.getFileOffset() - out.getCursor();
- if (zeroCount < 0) {
- throw new ExceptionWithContext("excess write of " +
- (-zeroCount));
- }
- out.writeZeroes(one.getFileOffset() - out.getCursor());
- one.writeTo(out);
- } catch (RuntimeException ex) {
- ExceptionWithContext ec;
- if (ex instanceof ExceptionWithContext) {
- ec = (ExceptionWithContext) ex;
- } else {
- ec = new ExceptionWithContext(ex);
- }
- ec.addContext("...while writing section " + i);
- throw ec;
- }
- }
-
- if (out.getCursor() != fileSize) {
- throw new RuntimeException("foreshortened write");
- }
-
- // Perform final bookkeeping.
-
- calcSignature(barr);
- calcChecksum(barr);
-
- if (annotate) {
- wordData.writeIndexAnnotation(out, ItemType.TYPE_CODE_ITEM,
- "\nmethod code index:\n\n");
- getStatistics().writeAnnotation(out);
- out.finishAnnotating();
- }
-
- return out;
- }
-
- /**
- * Generates and returns statistics for all the items in the file.
- *
- * @return non-null; the statistics
- */
- public Statistics getStatistics() {
- Statistics stats = new Statistics();
-
- for (Section s : sections) {
- stats.addAll(s);
- }
-
- return stats;
- }
-
- /**
- * Calculates the signature for the <code>.dex</code> file in the
- * given array, and modify the array to contain it.
- *
- * @param bytes non-null; the bytes of the file
- */
- private static void calcSignature(byte[] bytes) {
- MessageDigest md;
-
- try {
- md = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException ex) {
- throw new RuntimeException(ex);
- }
-
- md.update(bytes, 32, bytes.length - 32);
-
- try {
- int amt = md.digest(bytes, 12, 20);
- if (amt != 20) {
- throw new RuntimeException("unexpected digest write: " + amt +
- " bytes");
- }
- } catch (DigestException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- /**
- * Calculates the checksum for the <code>.dex</code> file in the
- * given array, and modify the array to contain it.
- *
- * @param bytes non-null; the bytes of the file
- */
- private static void calcChecksum(byte[] bytes) {
- Adler32 a32 = new Adler32();
-
- a32.update(bytes, 12, bytes.length - 12);
-
- int sum = (int) a32.getValue();
-
- bytes[8] = (byte) sum;
- bytes[9] = (byte) (sum >> 8);
- bytes[10] = (byte) (sum >> 16);
- bytes[11] = (byte) (sum >> 24);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/EncodedArrayItem.java b/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
deleted file mode 100644
index 9ec72fa42..000000000
--- a/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
+++ /dev/null
@@ -1,131 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.rop.annotation.AnnotationVisibility;
-import com.android.dx.rop.annotation.NameValuePair;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.ByteArrayAnnotatedOutput;
-import com.android.dx.util.AnnotatedOutput;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-/**
- * Encoded array of constant values.
- */
-public final class EncodedArrayItem extends OffsettedItem {
- /** the required alignment for instances of this class */
- private static final int ALIGNMENT = 1;
-
- /** non-null; the array to represent */
- private final CstArray array;
-
- /**
- * null-ok; encoded form, ready for writing to a file; set during
- * {@link #place0}
- */
- private byte[] encodedForm;
-
- /**
- * Constructs an instance.
- *
- * @param array non-null; array to represent
- */
- public EncodedArrayItem(CstArray array) {
- /*
- * The write size isn't known up-front because (the variable-lengthed)
- * leb128 type is used to represent some things.
- */
- super(ALIGNMENT, -1);
-
- if (array == null) {
- throw new NullPointerException("array == null");
- }
-
- this.array = array;
- this.encodedForm = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_ENCODED_ARRAY_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return array.hashCode();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int compareTo0(OffsettedItem other) {
- EncodedArrayItem otherArray = (EncodedArrayItem) other;
-
- return array.compareTo(otherArray.array);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return array.toHuman();
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- ValueEncoder.addContents(file, array);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- // Encode the data and note the size.
-
- ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
- ValueEncoder encoder = new ValueEncoder(addedTo.getFile(), out);
-
- encoder.writeArray(array, false);
- encodedForm = out.toByteArray();
- setWriteSize(encodedForm.length);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- boolean annotates = out.annotates();
-
- if (annotates) {
- out.annotate(0, offsetString() + " encoded array");
-
- /*
- * The output is to be annotated, so redo the work previously
- * done by place0(), except this time annotations will actually
- * get emitted.
- */
- ValueEncoder encoder = new ValueEncoder(file, out);
- encoder.writeArray(array, true);
- } else {
- out.write(encodedForm);
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/EncodedField.java b/dx/src/com/android/dx/dex/file/EncodedField.java
deleted file mode 100644
index 62a5789d4..000000000
--- a/dx/src/com/android/dx/dex/file/EncodedField.java
+++ /dev/null
@@ -1,154 +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.dx.dex.file;
-
-import com.android.dx.rop.code.AccessFlags;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.Leb128Utils;
-
-import java.io.PrintWriter;
-
-/**
- * Representation of a field of a class, of any sort.
- */
-public final class EncodedField extends EncodedMember
- implements Comparable<EncodedField> {
- /** non-null; constant for the field */
- private final CstFieldRef field;
-
- /**
- * Constructs an instance.
- *
- * @param field non-null; constant for the field
- * @param accessFlags access flags
- */
- public EncodedField(CstFieldRef field, int accessFlags) {
- super(accessFlags);
-
- if (field == null) {
- throw new NullPointerException("field == null");
- }
-
- /*
- * TODO: Maybe check accessFlags, at least for
- * easily-checked stuff?
- */
-
- this.field = field;
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return field.hashCode();
- }
-
- /** {@inheritDoc} */
- public boolean equals(Object other) {
- if (! (other instanceof EncodedField)) {
- return false;
- }
-
- return compareTo((EncodedField) other) == 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * <p><b>Note:</b> This compares the method constants only,
- * ignoring any associated code, because it should never be the
- * case that two different items with the same method constant
- * ever appear in the same list (or same file, even).</p>
- */
- public int compareTo(EncodedField other) {
- return field.compareTo(other.field);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer(100);
-
- sb.append(getClass().getName());
- sb.append('{');
- sb.append(Hex.u2(getAccessFlags()));
- sb.append(' ');
- sb.append(field);
- sb.append('}');
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- FieldIdsSection fieldIds = file.getFieldIds();
- fieldIds.intern(field);
- }
-
- /** {@inheritDoc} */
- @Override
- public CstUtf8 getName() {
- return field.getNat().getName();
- }
-
- /** {@inheritDoc} */
- public String toHuman() {
- return field.toHuman();
- }
-
- /** {@inheritDoc} */
- @Override
- public void debugPrint(PrintWriter out, boolean verbose) {
- // TODO: Maybe put something better here?
- out.println(toString());
- }
-
- /**
- * Gets the constant for the field.
- *
- * @return non-null; the constant
- */
- public CstFieldRef getRef() {
- return field;
- }
-
- /** {@inheritDoc} */
- @Override
- public int encode(DexFile file, AnnotatedOutput out,
- int lastIndex, int dumpSeq) {
- int fieldIdx = file.getFieldIds().indexOf(field);
- int diff = fieldIdx - lastIndex;
- int accessFlags = getAccessFlags();
-
- if (out.annotates()) {
- out.annotate(0, String.format(" [%x] %s", dumpSeq,
- field.toHuman()));
- out.annotate(Leb128Utils.unsignedLeb128Size(diff),
- " field_idx: " + Hex.u4(fieldIdx));
- out.annotate(Leb128Utils.unsignedLeb128Size(accessFlags),
- " access_flags: " +
- AccessFlags.fieldString(accessFlags));
- }
-
- out.writeUnsignedLeb128(diff);
- out.writeUnsignedLeb128(accessFlags);
-
- return fieldIdx;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/EncodedMember.java b/dx/src/com/android/dx/dex/file/EncodedMember.java
deleted file mode 100644
index 3ae0d0902..000000000
--- a/dx/src/com/android/dx/dex/file/EncodedMember.java
+++ /dev/null
@@ -1,86 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ToHuman;
-
-import java.io.PrintWriter;
-
-/**
- * Representation of a member (field or method) of a class, for the
- * purposes of encoding it inside a {@link ClassDataItem}.
- */
-public abstract class EncodedMember implements ToHuman {
- /** access flags */
- private final int accessFlags;
-
- /**
- * Constructs an instance.
- *
- * @param accessFlags access flags for the member
- */
- public EncodedMember(int accessFlags) {
- this.accessFlags = accessFlags;
- }
-
- /**
- * Gets the access flags.
- *
- * @return the access flags
- */
- public final int getAccessFlags() {
- return accessFlags;
- }
-
- /**
- * Gets the name.
- *
- * @return non-null; the name
- */
- public abstract CstUtf8 getName();
-
- /**
- * Does a human-friendly dump of this instance.
- *
- * @param out non-null; where to dump
- * @param verbose whether to be verbose with the output
- */
- public abstract void debugPrint(PrintWriter out, boolean verbose);
-
- /**
- * Populates a {@link DexFile} with items from within this instance.
- *
- * @param file non-null; the file to populate
- */
- public abstract void addContents(DexFile file);
-
- /**
- * Encodes this instance to the given output.
- *
- * @param file non-null; file this instance is part of
- * @param out non-null; where to write to
- * @param lastIndex &gt;= 0; the previous member index value encoded, or
- * <code>0</code> if this is the first element to encode
- * @param dumpSeq &gt;= 0; sequence number of this instance for
- * annotation purposes
- * @return &gt;= 0; the member index value that was encoded
- */
- public abstract int encode(DexFile file, AnnotatedOutput out,
- int lastIndex, int dumpSeq);
-}
diff --git a/dx/src/com/android/dx/dex/file/EncodedMethod.java b/dx/src/com/android/dx/dex/file/EncodedMethod.java
deleted file mode 100644
index 319fbb72b..000000000
--- a/dx/src/com/android/dx/dex/file/EncodedMethod.java
+++ /dev/null
@@ -1,196 +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.dx.dex.file;
-
-import com.android.dx.dex.code.DalvCode;
-import com.android.dx.rop.code.AccessFlags;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.TypeList;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.Leb128Utils;
-
-import java.io.PrintWriter;
-
-/**
- * Class that representats a method of a class.
- */
-public final class EncodedMethod extends EncodedMember
- implements Comparable<EncodedMethod> {
- /** non-null; constant for the method */
- private final CstMethodRef method;
-
- /**
- * null-ok; code for the method, if the method is neither
- * <code>abstract</code> nor <code>native</code>
- */
- private final CodeItem code;
-
- /**
- * Constructs an instance.
- *
- * @param method non-null; constant for the method
- * @param accessFlags access flags
- * @param code null-ok; code for the method, if it is neither
- * <code>abstract</code> nor <code>native</code>
- * @param throwsList non-null; list of possibly-thrown exceptions,
- * just used in generating debugging output (listings)
- */
- public EncodedMethod(CstMethodRef method, int accessFlags,
- DalvCode code, TypeList throwsList) {
- super(accessFlags);
-
- if (method == null) {
- throw new NullPointerException("method == null");
- }
-
- this.method = method;
-
- if (code == null) {
- this.code = null;
- } else {
- boolean isStatic = (accessFlags & AccessFlags.ACC_STATIC) != 0;
- this.code = new CodeItem(method, code, isStatic, throwsList);
- }
- }
-
- /** {@inheritDoc} */
- public boolean equals(Object other) {
- if (! (other instanceof EncodedMethod)) {
- return false;
- }
-
- return compareTo((EncodedMethod) other) == 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * <p><b>Note:</b> This compares the method constants only,
- * ignoring any associated code, because it should never be the
- * case that two different items with the same method constant
- * ever appear in the same list (or same file, even).</p>
- */
- public int compareTo(EncodedMethod other) {
- return method.compareTo(other.method);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer(100);
-
- sb.append(getClass().getName());
- sb.append('{');
- sb.append(Hex.u2(getAccessFlags()));
- sb.append(' ');
- sb.append(method);
-
- if (code != null) {
- sb.append(' ');
- sb.append(code);
- }
-
- sb.append('}');
-
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- MethodIdsSection methodIds = file.getMethodIds();
- MixedItemSection wordData = file.getWordData();
-
- methodIds.intern(method);
-
- if (code != null) {
- wordData.add(code);
- }
- }
-
- /** {@inheritDoc} */
- public final String toHuman() {
- return method.toHuman();
- }
-
- /** {@inheritDoc} */
- @Override
- public final CstUtf8 getName() {
- return method.getNat().getName();
- }
-
- /** {@inheritDoc} */
- @Override
- public void debugPrint(PrintWriter out, boolean verbose) {
- if (code == null) {
- out.println(getRef().toHuman() + ": abstract or native");
- } else {
- code.debugPrint(out, " ", verbose);
- }
- }
-
- /**
- * Gets the constant for the method.
- *
- * @return non-null; the constant
- */
- public final CstMethodRef getRef() {
- return method;
- }
-
- /** {@inheritDoc} */
- @Override
- public int encode(DexFile file, AnnotatedOutput out,
- int lastIndex, int dumpSeq) {
- int methodIdx = file.getMethodIds().indexOf(method);
- int diff = methodIdx - lastIndex;
- int accessFlags = getAccessFlags();
- int codeOff = OffsettedItem.getAbsoluteOffsetOr0(code);
- boolean hasCode = (codeOff != 0);
- boolean shouldHaveCode = (accessFlags &
- (AccessFlags.ACC_ABSTRACT | AccessFlags.ACC_NATIVE)) == 0;
-
- /*
- * Verify that code appears if and only if a method is
- * declared to have it.
- */
- if (hasCode != shouldHaveCode) {
- throw new UnsupportedOperationException(
- "code vs. access_flags mismatch");
- }
-
- if (out.annotates()) {
- out.annotate(0, String.format(" [%x] %s", dumpSeq,
- method.toHuman()));
- out.annotate(Leb128Utils.unsignedLeb128Size(diff),
- " method_idx: " + Hex.u4(methodIdx));
- out.annotate(Leb128Utils.unsignedLeb128Size(accessFlags),
- " access_flags: " +
- AccessFlags.methodString(accessFlags));
- out.annotate(Leb128Utils.unsignedLeb128Size(codeOff),
- " code_off: " + Hex.u4(codeOff));
- }
-
- out.writeUnsignedLeb128(diff);
- out.writeUnsignedLeb128(accessFlags);
- out.writeUnsignedLeb128(codeOff);
-
- return methodIdx;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java b/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java
deleted file mode 100644
index e6169bd21..000000000
--- a/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java
+++ /dev/null
@@ -1,122 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotations;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.ToHuman;
-
-/**
- * Association of a field and its annotations.
- */
-public final class FieldAnnotationStruct
- implements ToHuman, Comparable<FieldAnnotationStruct> {
- /** non-null; the field in question */
- private final CstFieldRef field;
-
- /** non-null; the associated annotations */
- private AnnotationSetItem annotations;
-
- /**
- * Constructs an instance.
- *
- * @param field non-null; the field in question
- * @param annotations non-null; the associated annotations
- */
- public FieldAnnotationStruct(CstFieldRef field,
- AnnotationSetItem annotations) {
- if (field == null) {
- throw new NullPointerException("field == null");
- }
-
- if (annotations == null) {
- throw new NullPointerException("annotations == null");
- }
-
- this.field = field;
- this.annotations = annotations;
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return field.hashCode();
- }
-
- /** {@inheritDoc} */
- public boolean equals(Object other) {
- if (! (other instanceof FieldAnnotationStruct)) {
- return false;
- }
-
- return field.equals(((FieldAnnotationStruct) other).field);
- }
-
- /** {@inheritDoc} */
- public int compareTo(FieldAnnotationStruct other) {
- return field.compareTo(other.field);
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- FieldIdsSection fieldIds = file.getFieldIds();
- MixedItemSection wordData = file.getWordData();
-
- fieldIds.intern(field);
- annotations = wordData.intern(annotations);
- }
-
- /** {@inheritDoc} */
- public void writeTo(DexFile file, AnnotatedOutput out) {
- int fieldIdx = file.getFieldIds().indexOf(field);
- int annotationsOff = annotations.getAbsoluteOffset();
-
- if (out.annotates()) {
- out.annotate(0, " " + field.toHuman());
- out.annotate(4, " field_idx: " + Hex.u4(fieldIdx));
- out.annotate(4, " annotations_off: " +
- Hex.u4(annotationsOff));
- }
-
- out.writeInt(fieldIdx);
- out.writeInt(annotationsOff);
- }
-
- /** {@inheritDoc} */
- public String toHuman() {
- return field.toHuman() + ": " + annotations;
- }
-
- /**
- * Gets the field this item is for.
- *
- * @return non-null; the field
- */
- public CstFieldRef getField() {
- return field;
- }
-
- /**
- * Gets the associated annotations.
- *
- * @return non-null; the annotations
- */
- public Annotations getAnnotations() {
- return annotations.getAnnotations();
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/FieldIdItem.java b/dx/src/com/android/dx/dex/file/FieldIdItem.java
deleted file mode 100644
index d098d52ab..000000000
--- a/dx/src/com/android/dx/dex/file/FieldIdItem.java
+++ /dev/null
@@ -1,70 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstFieldRef;
-
-/**
- * Representation of a field reference inside a Dalvik file.
- */
-public final class FieldIdItem extends MemberIdItem {
- /**
- * Constructs an instance.
- *
- * @param field non-null; the constant for the field
- */
- public FieldIdItem(CstFieldRef field) {
- super(field);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_FIELD_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- super.addContents(file);
-
- TypeIdsSection typeIds = file.getTypeIds();
- typeIds.intern(getFieldRef().getType());
- }
-
- /**
- * Gets the field constant.
- *
- * @return non-null; the constant
- */
- public CstFieldRef getFieldRef() {
- return (CstFieldRef) getRef();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int getTypoidIdx(DexFile file) {
- TypeIdsSection typeIds = file.getTypeIds();
- return typeIds.indexOf(getFieldRef().getType());
- }
-
- /** {@inheritDoc} */
- @Override
- protected String getTypoidName() {
- return "type_idx";
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/FieldIdsSection.java b/dx/src/com/android/dx/dex/file/FieldIdsSection.java
deleted file mode 100644
index fddf55f47..000000000
--- a/dx/src/com/android/dx/dex/file/FieldIdsSection.java
+++ /dev/null
@@ -1,137 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-import java.util.TreeMap;
-
-/**
- * Field refs list section of a <code>.dex</code> file.
- */
-public final class FieldIdsSection extends MemberIdsSection {
- /**
- * non-null; map from field constants to {@link
- * FieldIdItem} instances
- */
- private final TreeMap<CstFieldRef, FieldIdItem> fieldIds;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public FieldIdsSection(DexFile file) {
- super("field_ids", file);
-
- fieldIds = new TreeMap<CstFieldRef, FieldIdItem>();
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return fieldIds.values();
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- if (cst == null) {
- throw new NullPointerException("cst == null");
- }
-
- throwIfNotPrepared();
-
- IndexedItem result = fieldIds.get((CstFieldRef) cst);
-
- if (result == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return result;
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- int sz = fieldIds.size();
- int offset = (sz == 0) ? 0 : getFileOffset();
-
- if (out.annotates()) {
- out.annotate(4, "field_ids_size: " + Hex.u4(sz));
- out.annotate(4, "field_ids_off: " + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param field non-null; the reference to intern
- * @return non-null; the interned reference
- */
- public FieldIdItem intern(CstFieldRef field) {
- if (field == null) {
- throw new NullPointerException("field == null");
- }
-
- throwIfPrepared();
-
- FieldIdItem result = fieldIds.get(field);
-
- if (result == null) {
- result = new FieldIdItem(field);
- fieldIds.put(field, result);
- }
-
- return result;
- }
-
- /**
- * Gets the index of the given reference, which must have been added
- * to this instance.
- *
- * @param ref non-null; the reference to look up
- * @return &gt;= 0; the reference's index
- */
- public int indexOf(CstFieldRef ref) {
- if (ref == null) {
- throw new NullPointerException("ref == null");
- }
-
- throwIfNotPrepared();
-
- FieldIdItem item = fieldIds.get(ref);
-
- if (item == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return item.getIndex();
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/HeaderItem.java b/dx/src/com/android/dx/dex/file/HeaderItem.java
deleted file mode 100644
index 55c1f1c5f..000000000
--- a/dx/src/com/android/dx/dex/file/HeaderItem.java
+++ /dev/null
@@ -1,123 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * File header section of a <code>.dex</code> file.
- */
-public final class HeaderItem extends IndexedItem {
- /**
- * non-null; the file format magic number, represented as the
- * low-order bytes of a string
- */
- private static final String MAGIC = "dex\n035\0";
-
- /** size of this section, in bytes */
- private static final int HEADER_SIZE = 0x70;
-
- /** the endianness tag */
- private static final int ENDIAN_TAG = 0x12345678;
-
- /**
- * Constructs an instance.
- */
- public HeaderItem() {
- // This space intentionally left blank.
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_HEADER_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- return HEADER_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- // Nothing to do here.
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo(DexFile file, AnnotatedOutput out) {
- int mapOff = file.getMap().getFileOffset();
- Section firstDataSection = file.getFirstDataSection();
- Section lastDataSection = file.getLastDataSection();
- int dataOff = firstDataSection.getFileOffset();
- int dataSize = lastDataSection.getFileOffset() +
- lastDataSection.writeSize() - dataOff;
-
- if (out.annotates()) {
- out.annotate(8, "magic: " + new CstUtf8(MAGIC).toQuoted());
- out.annotate(4, "checksum");
- out.annotate(20, "signature");
- out.annotate(4, "file_size: " +
- Hex.u4(file.getFileSize()));
- out.annotate(4, "header_size: " + Hex.u4(HEADER_SIZE));
- out.annotate(4, "endian_tag: " + Hex.u4(ENDIAN_TAG));
- out.annotate(4, "link_size: 0");
- out.annotate(4, "link_off: 0");
- out.annotate(4, "map_off: " + Hex.u4(mapOff));
- }
-
- // Write the magic number.
- for (int i = 0; i < 8; i++) {
- out.writeByte(MAGIC.charAt(i));
- }
-
- // Leave space for the checksum and signature.
- out.writeZeroes(24);
-
- out.writeInt(file.getFileSize());
- out.writeInt(HEADER_SIZE);
- out.writeInt(ENDIAN_TAG);
-
- /*
- * Write zeroes for the link size and data, as the output
- * isn't a staticly linked file.
- */
- out.writeZeroes(8);
-
- out.writeInt(mapOff);
-
- // Write out each section's respective header part.
- file.getStringIds().writeHeaderPart(out);
- file.getTypeIds().writeHeaderPart(out);
- file.getProtoIds().writeHeaderPart(out);
- file.getFieldIds().writeHeaderPart(out);
- file.getMethodIds().writeHeaderPart(out);
- file.getClassDefs().writeHeaderPart(out);
-
- if (out.annotates()) {
- out.annotate(4, "data_size: " + Hex.u4(dataSize));
- out.annotate(4, "data_off: " + Hex.u4(dataOff));
- }
-
- out.writeInt(dataSize);
- out.writeInt(dataOff);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/HeaderSection.java b/dx/src/com/android/dx/dex/file/HeaderSection.java
deleted file mode 100644
index 9022e0f2b..000000000
--- a/dx/src/com/android/dx/dex/file/HeaderSection.java
+++ /dev/null
@@ -1,63 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * File header section of a <code>.dex</code> file.
- */
-public final class HeaderSection extends UniformItemSection {
- /** non-null; the list of the one item in the section */
- private final List<HeaderItem> list;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public HeaderSection(DexFile file) {
- super(null, file, 4);
-
- HeaderItem item = new HeaderItem();
- item.setIndex(0);
-
- this.list = Collections.singletonList(item);
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return list;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void orderItems() {
- // Nothing to do here.
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/IdItem.java b/dx/src/com/android/dx/dex/file/IdItem.java
deleted file mode 100644
index 8342514be..000000000
--- a/dx/src/com/android/dx/dex/file/IdItem.java
+++ /dev/null
@@ -1,61 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstType;
-
-/**
- * Representation of a reference to an item inside a Dalvik file.
- */
-public abstract class IdItem extends IndexedItem {
- /**
- * non-null; the type constant for the defining class of
- * the reference
- */
- private final CstType type;
-
- /**
- * Constructs an instance.
- *
- * @param type non-null; the type constant for the defining
- * class of the reference
- */
- public IdItem(CstType type) {
- if (type == null) {
- throw new NullPointerException("type == null");
- }
-
- this.type = type;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- TypeIdsSection typeIds = file.getTypeIds();
- typeIds.intern(type);
- }
-
- /**
- * Gets the type constant for the defining class of the
- * reference.
- *
- * @return non-null; the type constant
- */
- public final CstType getDefiningClass() {
- return type;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/IndexedItem.java b/dx/src/com/android/dx/dex/file/IndexedItem.java
deleted file mode 100644
index 9bf7fd29a..000000000
--- a/dx/src/com/android/dx/dex/file/IndexedItem.java
+++ /dev/null
@@ -1,81 +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.dx.dex.file;
-
-/**
- * An item in a Dalvik file which is referenced by index.
- */
-public abstract class IndexedItem extends Item {
- /** &gt;= -1; assigned index of the item, or <code>-1</code> if not
- * yet assigned */
- private int index;
-
- /**
- * Constructs an instance. The index is initially unassigned.
- */
- public IndexedItem() {
- index = -1;
- }
-
- /**
- * Gets whether or not this instance has been assigned an index.
- *
- * @return <code>true</code> iff this instance has been assigned an index
- */
- public final boolean hasIndex() {
- return (index >= 0);
- }
-
- /**
- * Gets the item index.
- *
- * @return &gt;= 0; the index
- * @throws RuntimeException thrown if the item index is not yet assigned
- */
- public final int getIndex() {
- if (index < 0) {
- throw new RuntimeException("index not yet set");
- }
-
- return index;
- }
-
- /**
- * Sets the item index. This method may only ever be called once
- * per instance, and this will throw a <code>RuntimeException</code> if
- * called a second (or subsequent) time.
- *
- * @param index &gt;= 0; the item index
- */
- public final void setIndex(int index) {
- if (this.index != -1) {
- throw new RuntimeException("index already set");
- }
-
- this.index = index;
- }
-
- /**
- * Gets the index of this item as a string, suitable for including in
- * annotations.
- *
- * @return non-null; the index string
- */
- public final String indexString() {
- return '[' + Integer.toHexString(index) + ']';
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/Item.java b/dx/src/com/android/dx/dex/file/Item.java
deleted file mode 100644
index 3708d4561..000000000
--- a/dx/src/com/android/dx/dex/file/Item.java
+++ /dev/null
@@ -1,80 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-
-/**
- * Base class for any structurally-significant and (potentially)
- * repeated piece of a Dalvik file.
- */
-public abstract class Item {
- /**
- * Constructs an instance.
- */
- public Item() {
- // This space intentionally left blank.
- }
-
- /**
- * Returns the item type for this instance.
- *
- * @return non-null; the item type
- */
- public abstract ItemType itemType();
-
- /**
- * Returns the human name for the particular type of item this
- * instance is.
- *
- * @return non-null; the name
- */
- public final String typeName() {
- return itemType().toHuman();
- }
-
- /**
- * Gets the size of this instance when written, in bytes.
- *
- * @return &gt;= 0; the write size
- */
- public abstract int writeSize();
-
- /**
- * Populates a {@link DexFile} with items from within this instance.
- * This will <i>not</i> add an item to the file for this instance itself
- * (which should have been done by whatever refers to this instance).
- *
- * <p><b>Note:</b> Subclasses must override this to do something
- * appropriate.</p>
- *
- * @param file non-null; the file to populate
- */
- public abstract void addContents(DexFile file);
-
- /**
- * Writes the representation of this instance to the given data section,
- * using the given {@link DexFile} to look things up as needed.
- * If this instance keeps track of its offset, then this method will
- * note the written offset and will also throw an exception if this
- * instance has already been written.
- *
- * @param file non-null; the file to use for reference
- * @param out non-null; where to write to
- */
- public abstract void writeTo(DexFile file, AnnotatedOutput out);
-}
diff --git a/dx/src/com/android/dx/dex/file/ItemType.java b/dx/src/com/android/dx/dex/file/ItemType.java
deleted file mode 100644
index ffa65735f..000000000
--- a/dx/src/com/android/dx/dex/file/ItemType.java
+++ /dev/null
@@ -1,97 +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.dx.dex.file;
-
-import com.android.dx.util.ToHuman;
-
-/**
- * Enumeration of all the top-level item types.
- */
-public enum ItemType implements ToHuman {
- TYPE_HEADER_ITEM( 0x0000, "header_item"),
- TYPE_STRING_ID_ITEM( 0x0001, "string_id_item"),
- TYPE_TYPE_ID_ITEM( 0x0002, "type_id_item"),
- TYPE_PROTO_ID_ITEM( 0x0003, "proto_id_item"),
- TYPE_FIELD_ID_ITEM( 0x0004, "field_id_item"),
- TYPE_METHOD_ID_ITEM( 0x0005, "method_id_item"),
- TYPE_CLASS_DEF_ITEM( 0x0006, "class_def_item"),
- TYPE_MAP_LIST( 0x1000, "map_list"),
- TYPE_TYPE_LIST( 0x1001, "type_list"),
- TYPE_ANNOTATION_SET_REF_LIST( 0x1002, "annotation_set_ref_list"),
- TYPE_ANNOTATION_SET_ITEM( 0x1003, "annotation_set_item"),
- TYPE_CLASS_DATA_ITEM( 0x2000, "class_data_item"),
- TYPE_CODE_ITEM( 0x2001, "code_item"),
- TYPE_STRING_DATA_ITEM( 0x2002, "string_data_item"),
- TYPE_DEBUG_INFO_ITEM( 0x2003, "debug_info_item"),
- TYPE_ANNOTATION_ITEM( 0x2004, "annotation_item"),
- TYPE_ENCODED_ARRAY_ITEM( 0x2005, "encoded_array_item"),
- TYPE_ANNOTATIONS_DIRECTORY_ITEM(0x2006, "annotations_directory_item"),
- TYPE_MAP_ITEM( -1, "map_item"),
- TYPE_TYPE_ITEM( -1, "type_item"),
- TYPE_EXCEPTION_HANDLER_ITEM( -1, "exception_handler_item"),
- TYPE_ANNOTATION_SET_REF_ITEM( -1, "annotation_set_ref_item");
-
- /** value when represented in a {@link MapItem} */
- private final int mapValue;
-
- /** non-null; name of the type */
- private final String typeName;
-
- /** non-null; the short human name */
- private final String humanName;
-
- /**
- * Constructs an instance.
- *
- * @param mapValue value when represented in a {@link MapItem}
- * @param typeName non-null; name of the type
- */
- private ItemType(int mapValue, String typeName) {
- this.mapValue = mapValue;
- this.typeName = typeName;
-
- // Make the human name.
- String human = typeName;
- if (human.endsWith("_item")) {
- human = human.substring(0, human.length() - 5);
- }
- this.humanName = human.replace('_', ' ');
- }
-
- /**
- * Gets the map value.
- *
- * @return the map value
- */
- public int getMapValue() {
- return mapValue;
- }
-
- /**
- * Gets the type name.
- *
- * @return non-null; the type name
- */
- public String getTypeName() {
- return typeName;
- }
-
- /** {@inheritDoc} */
- public String toHuman() {
- return humanName;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MapItem.java b/dx/src/com/android/dx/dex/file/MapItem.java
deleted file mode 100644
index 5e7465ce0..000000000
--- a/dx/src/com/android/dx/dex/file/MapItem.java
+++ /dev/null
@@ -1,235 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.ArrayList;
-
-/**
- * Class that represents a map item.
- */
-public final class MapItem extends OffsettedItem {
- /** file alignment of this class, in bytes */
- private static final int ALIGNMENT = 4;
-
- /** write size of this class, in bytes: three <code>uint</code>s */
- private static final int WRITE_SIZE = (4 * 3);
-
- /** non-null; item type this instance covers */
- private final ItemType type;
-
- /** non-null; section this instance covers */
- private final Section section;
-
- /**
- * null-ok; first item covered or <code>null</code> if this is
- * a self-reference
- */
- private final Item firstItem;
-
- /**
- * null-ok; last item covered or <code>null</code> if this is
- * a self-reference
- */
- private final Item lastItem;
-
- /**
- * &gt; 0; count of items covered; <code>1</code> if this
- * is a self-reference
- */
- private final int itemCount;
-
- /**
- * Constructs a list item with instances of this class representing
- * the contents of the given array of sections, adding it to the
- * given map section.
- *
- * @param sections non-null; the sections
- * @param mapSection non-null; the section that the resulting map
- * should be added to; it should be empty on entry to this method
- */
- public static void addMap(Section[] sections,
- MixedItemSection mapSection) {
- if (sections == null) {
- throw new NullPointerException("sections == null");
- }
-
- if (mapSection.items().size() != 0) {
- throw new IllegalArgumentException(
- "mapSection.items().size() != 0");
- }
-
- ArrayList<MapItem> items = new ArrayList<MapItem>(50);
-
- for (Section section : sections) {
- ItemType currentType = null;
- Item firstItem = null;
- Item lastItem = null;
- int count = 0;
-
- for (Item item : section.items()) {
- ItemType type = item.itemType();
- if (type != currentType) {
- if (count != 0) {
- items.add(new MapItem(currentType, section,
- firstItem, lastItem, count));
- }
- currentType = type;
- firstItem = item;
- count = 0;
- }
- lastItem = item;
- count++;
- }
-
- if (count != 0) {
- // Add a MapItem for the final items in the section.
- items.add(new MapItem(currentType, section,
- firstItem, lastItem, count));
- } else if (section == mapSection) {
- // Add a MapItem for the self-referential section.
- items.add(new MapItem(mapSection));
- }
- }
-
- mapSection.add(
- new UniformListItem<MapItem>(ItemType.TYPE_MAP_LIST, items));
- }
-
- /**
- * Constructs an instance.
- *
- * @param type non-null; item type this instance covers
- * @param section non-null; section this instance covers
- * @param firstItem non-null; first item covered
- * @param lastItem non-null; last item covered
- * @param itemCount &gt; 0; count of items covered
- */
- private MapItem(ItemType type, Section section, Item firstItem,
- Item lastItem, int itemCount) {
- super(ALIGNMENT, WRITE_SIZE);
-
- if (type == null) {
- throw new NullPointerException("type == null");
- }
-
- if (section == null) {
- throw new NullPointerException("section == null");
- }
-
- if (firstItem == null) {
- throw new NullPointerException("firstItem == null");
- }
-
- if (lastItem == null) {
- throw new NullPointerException("lastItem == null");
- }
-
- if (itemCount <= 0) {
- throw new IllegalArgumentException("itemCount <= 0");
- }
-
- this.type = type;
- this.section = section;
- this.firstItem = firstItem;
- this.lastItem = lastItem;
- this.itemCount = itemCount;
- }
-
- /**
- * Constructs a self-referential instance. This instance is meant to
- * represent the section containing the <code>map_list</code>.
- *
- * @param section non-null; section this instance covers
- */
- private MapItem(Section section) {
- super(ALIGNMENT, WRITE_SIZE);
-
- if (section == null) {
- throw new NullPointerException("section == null");
- }
-
- this.type = ItemType.TYPE_MAP_LIST;
- this.section = section;
- this.firstItem = null;
- this.lastItem = null;
- this.itemCount = 1;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_MAP_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer(100);
-
- sb.append(getClass().getName());
- sb.append('{');
- sb.append(section.toString());
- sb.append(' ');
- sb.append(type.toHuman());
- sb.append('}');
-
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- // We have nothing to add.
- }
-
- /** {@inheritDoc} */
- @Override
- public final String toHuman() {
- return toString();
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- int value = type.getMapValue();
- int offset;
-
- if (firstItem == null) {
- offset = section.getFileOffset();
- } else {
- offset = section.getAbsoluteItemOffset(firstItem);
- }
-
- if (out.annotates()) {
- out.annotate(0, offsetString() + ' ' + type.getTypeName() +
- " map");
- out.annotate(2, " type: " + Hex.u2(value) + " // " +
- type.toString());
- out.annotate(2, " unused: 0");
- out.annotate(4, " size: " + Hex.u4(itemCount));
- out.annotate(4, " offset: " + Hex.u4(offset));
- }
-
- out.writeShort(value);
- out.writeShort(0); // unused
- out.writeInt(itemCount);
- out.writeInt(offset);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MemberIdItem.java b/dx/src/com/android/dx/dex/file/MemberIdItem.java
deleted file mode 100644
index d43715259..000000000
--- a/dx/src/com/android/dx/dex/file/MemberIdItem.java
+++ /dev/null
@@ -1,111 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstMemberRef;
-import com.android.dx.rop.cst.CstNat;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Representation of a member (field or method) reference inside a
- * Dalvik file.
- */
-public abstract class MemberIdItem extends IdItem {
- /** size of instances when written out to a file, in bytes */
- public static final int WRITE_SIZE = 8;
-
- /** non-null; the constant for the member */
- private final CstMemberRef cst;
-
- /**
- * Constructs an instance.
- *
- * @param cst non-null; the constant for the member
- */
- public MemberIdItem(CstMemberRef cst) {
- super(cst.getDefiningClass());
-
- this.cst = cst;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- return WRITE_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- super.addContents(file);
-
- StringIdsSection stringIds = file.getStringIds();
- stringIds.intern(getRef().getNat().getName());
- }
-
- /** {@inheritDoc} */
- @Override
- public final void writeTo(DexFile file, AnnotatedOutput out) {
- TypeIdsSection typeIds = file.getTypeIds();
- StringIdsSection stringIds = file.getStringIds();
- CstNat nat = cst.getNat();
- int classIdx = typeIds.indexOf(getDefiningClass());
- int nameIdx = stringIds.indexOf(nat.getName());
- int typoidIdx = getTypoidIdx(file);
-
- if (out.annotates()) {
- out.annotate(0, indexString() + ' ' + cst.toHuman());
- out.annotate(2, " class_idx: " + Hex.u2(classIdx));
- out.annotate(2, String.format(" %-10s %s", getTypoidName() + ':',
- Hex.u2(typoidIdx)));
- out.annotate(4, " name_idx: " + Hex.u4(nameIdx));
- }
-
- out.writeShort(classIdx);
- out.writeShort(typoidIdx);
- out.writeInt(nameIdx);
- }
-
- /**
- * Returns the index of the type-like thing associated with
- * this item, in order that it may be written out. Subclasses must
- * override this to get whatever it is they need to store.
- *
- * @param file non-null; the file being written
- * @return the index in question
- */
- protected abstract int getTypoidIdx(DexFile file);
-
- /**
- * Returns the field name of the type-like thing associated with
- * this item, for listing-generating purposes. Subclasses must override
- * this.
- *
- * @return non-null; the name in question
- */
- protected abstract String getTypoidName();
-
- /**
- * Gets the member constant.
- *
- * @return non-null; the constant
- */
- public final CstMemberRef getRef() {
- return cst;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MemberIdsSection.java b/dx/src/com/android/dx/dex/file/MemberIdsSection.java
deleted file mode 100644
index 885b5590a..000000000
--- a/dx/src/com/android/dx/dex/file/MemberIdsSection.java
+++ /dev/null
@@ -1,44 +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.dx.dex.file;
-
-/**
- * Member (field or method) refs list section of a <code>.dex</code> file.
- */
-public abstract class MemberIdsSection extends UniformItemSection {
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param name null-ok; the name of this instance, for annotation
- * purposes
- * @param file non-null; file that this instance is part of
- */
- public MemberIdsSection(String name, DexFile file) {
- super(name, file, 4);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void orderItems() {
- int idx = 0;
-
- for (Object i : items()) {
- ((MemberIdItem) i).setIndex(idx);
- idx++;
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java b/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java
deleted file mode 100644
index 175c1d29d..000000000
--- a/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java
+++ /dev/null
@@ -1,122 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotations;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.ToHuman;
-
-/**
- * Association of a method and its annotations.
- */
-public final class MethodAnnotationStruct
- implements ToHuman, Comparable<MethodAnnotationStruct> {
- /** non-null; the method in question */
- private final CstMethodRef method;
-
- /** non-null; the associated annotations */
- private AnnotationSetItem annotations;
-
- /**
- * Constructs an instance.
- *
- * @param method non-null; the method in question
- * @param annotations non-null; the associated annotations
- */
- public MethodAnnotationStruct(CstMethodRef method,
- AnnotationSetItem annotations) {
- if (method == null) {
- throw new NullPointerException("method == null");
- }
-
- if (annotations == null) {
- throw new NullPointerException("annotations == null");
- }
-
- this.method = method;
- this.annotations = annotations;
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return method.hashCode();
- }
-
- /** {@inheritDoc} */
- public boolean equals(Object other) {
- if (! (other instanceof MethodAnnotationStruct)) {
- return false;
- }
-
- return method.equals(((MethodAnnotationStruct) other).method);
- }
-
- /** {@inheritDoc} */
- public int compareTo(MethodAnnotationStruct other) {
- return method.compareTo(other.method);
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- MethodIdsSection methodIds = file.getMethodIds();
- MixedItemSection wordData = file.getWordData();
-
- methodIds.intern(method);
- annotations = wordData.intern(annotations);
- }
-
- /** {@inheritDoc} */
- public void writeTo(DexFile file, AnnotatedOutput out) {
- int methodIdx = file.getMethodIds().indexOf(method);
- int annotationsOff = annotations.getAbsoluteOffset();
-
- if (out.annotates()) {
- out.annotate(0, " " + method.toHuman());
- out.annotate(4, " method_idx: " + Hex.u4(methodIdx));
- out.annotate(4, " annotations_off: " +
- Hex.u4(annotationsOff));
- }
-
- out.writeInt(methodIdx);
- out.writeInt(annotationsOff);
- }
-
- /** {@inheritDoc} */
- public String toHuman() {
- return method.toHuman() + ": " + annotations;
- }
-
- /**
- * Gets the method this item is for.
- *
- * @return non-null; the method
- */
- public CstMethodRef getMethod() {
- return method;
- }
-
- /**
- * Gets the associated annotations.
- *
- * @return non-null; the annotations
- */
- public Annotations getAnnotations() {
- return annotations.getAnnotations();
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MethodIdItem.java b/dx/src/com/android/dx/dex/file/MethodIdItem.java
deleted file mode 100644
index 5d78e961c..000000000
--- a/dx/src/com/android/dx/dex/file/MethodIdItem.java
+++ /dev/null
@@ -1,70 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstBaseMethodRef;
-
-/**
- * Representation of a method reference inside a Dalvik file.
- */
-public final class MethodIdItem extends MemberIdItem {
- /**
- * Constructs an instance.
- *
- * @param method non-null; the constant for the method
- */
- public MethodIdItem(CstBaseMethodRef method) {
- super(method);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_METHOD_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- super.addContents(file);
-
- ProtoIdsSection protoIds = file.getProtoIds();
- protoIds.intern(getMethodRef().getPrototype());
- }
-
- /**
- * Gets the method constant.
- *
- * @return non-null; the constant
- */
- public CstBaseMethodRef getMethodRef() {
- return (CstBaseMethodRef) getRef();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int getTypoidIdx(DexFile file) {
- ProtoIdsSection protoIds = file.getProtoIds();
- return protoIds.indexOf(getMethodRef().getPrototype());
- }
-
- /** {@inheritDoc} */
- @Override
- protected String getTypoidName() {
- return "proto_idx";
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MethodIdsSection.java b/dx/src/com/android/dx/dex/file/MethodIdsSection.java
deleted file mode 100644
index 6ba7cac95..000000000
--- a/dx/src/com/android/dx/dex/file/MethodIdsSection.java
+++ /dev/null
@@ -1,137 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstBaseMethodRef;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-import java.util.TreeMap;
-
-/**
- * Method refs list section of a <code>.dex</code> file.
- */
-public final class MethodIdsSection extends MemberIdsSection {
- /**
- * non-null; map from method constants to {@link
- * MethodIdItem} instances
- */
- private final TreeMap<CstBaseMethodRef, MethodIdItem> methodIds;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public MethodIdsSection(DexFile file) {
- super("method_ids", file);
-
- methodIds = new TreeMap<CstBaseMethodRef, MethodIdItem>();
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return methodIds.values();
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- if (cst == null) {
- throw new NullPointerException("cst == null");
- }
-
- throwIfNotPrepared();
-
- IndexedItem result = methodIds.get((CstBaseMethodRef) cst);
-
- if (result == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return result;
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- int sz = methodIds.size();
- int offset = (sz == 0) ? 0 : getFileOffset();
-
- if (out.annotates()) {
- out.annotate(4, "method_ids_size: " + Hex.u4(sz));
- out.annotate(4, "method_ids_off: " + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param method non-null; the reference to intern
- * @return non-null; the interned reference
- */
- public MethodIdItem intern(CstBaseMethodRef method) {
- if (method == null) {
- throw new NullPointerException("method == null");
- }
-
- throwIfPrepared();
-
- MethodIdItem result = methodIds.get(method);
-
- if (result == null) {
- result = new MethodIdItem(method);
- methodIds.put(method, result);
- }
-
- return result;
- }
-
- /**
- * Gets the index of the given reference, which must have been added
- * to this instance.
- *
- * @param ref non-null; the reference to look up
- * @return &gt;= 0; the reference's index
- */
- public int indexOf(CstBaseMethodRef ref) {
- if (ref == null) {
- throw new NullPointerException("ref == null");
- }
-
- throwIfNotPrepared();
-
- MethodIdItem item = methodIds.get(ref);
-
- if (item == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return item.getIndex();
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/MixedItemSection.java b/dx/src/com/android/dx/dex/file/MixedItemSection.java
deleted file mode 100644
index f03a9a387..000000000
--- a/dx/src/com/android/dx/dex/file/MixedItemSection.java
+++ /dev/null
@@ -1,362 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ExceptionWithContext;
-import com.android.dx.util.Hex;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.TreeMap;
-
-/**
- * A section of a <code>.dex</code> file which consists of a sequence of
- * {@link OffsettedItem} objects, which may each be of a different concrete
- * class and/or size.
- *
- * <b>Note:</b> It is invalid for an item in an instance of this class to
- * have a larger alignment requirement than the alignment of this instance.
- */
-public final class MixedItemSection extends Section {
- static enum SortType {
- /** no sorting */
- NONE,
-
- /** sort by type only */
- TYPE,
-
- /** sort in class-major order, with instances sorted per-class */
- INSTANCE;
- };
-
- /** non-null; sorter which sorts instances by type */
- private static final Comparator<OffsettedItem> TYPE_SORTER =
- new Comparator<OffsettedItem>() {
- public int compare(OffsettedItem item1, OffsettedItem item2) {
- ItemType type1 = item1.itemType();
- ItemType type2 = item2.itemType();
- return type1.compareTo(type2);
- }
- };
-
- /** non-null; the items in this part */
- private final ArrayList<OffsettedItem> items;
-
- /** non-null; items that have been explicitly interned */
- private final HashMap<OffsettedItem, OffsettedItem> interns;
-
- /** non-null; how to sort the items */
- private final SortType sort;
-
- /**
- * &gt;= -1; the current size of this part, in bytes, or <code>-1</code>
- * if not yet calculated
- */
- private int writeSize;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param name null-ok; the name of this instance, for annotation
- * purposes
- * @param file non-null; file that this instance is part of
- * @param alignment &gt; 0; alignment requirement for the final output;
- * must be a power of 2
- * @param sort how the items should be sorted in the final output
- */
- public MixedItemSection(String name, DexFile file, int alignment,
- SortType sort) {
- super(name, file, alignment);
-
- this.items = new ArrayList<OffsettedItem>(100);
- this.interns = new HashMap<OffsettedItem, OffsettedItem>(100);
- this.sort = sort;
- this.writeSize = -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return items;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- throwIfNotPrepared();
- return writeSize;
- }
-
- /** {@inheritDoc} */
- @Override
- public int getAbsoluteItemOffset(Item item) {
- OffsettedItem oi = (OffsettedItem) item;
- return oi.getAbsoluteOffset();
- }
-
- /**
- * Gets the size of this instance, in items.
- *
- * @return &gt;= 0; the size
- */
- public int size() {
- return items.size();
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- if (writeSize == -1) {
- throw new RuntimeException("write size not yet set");
- }
-
- int sz = writeSize;
- int offset = (sz == 0) ? 0 : getFileOffset();
- String name = getName();
-
- if (name == null) {
- name = "<unnamed>";
- }
-
- int spaceCount = 15 - name.length();
- char[] spaceArr = new char[spaceCount];
- Arrays.fill(spaceArr, ' ');
- String spaces = new String(spaceArr);
-
- if (out.annotates()) {
- out.annotate(4, name + "_size:" + spaces + Hex.u4(sz));
- out.annotate(4, name + "_off: " + spaces + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Adds an item to this instance. This will in turn tell the given item
- * that it has been added to this instance. It is invalid to add the
- * same item to more than one instance, nor to add the same items
- * multiple times to a single instance.
- *
- * @param item non-null; the item to add
- */
- public void add(OffsettedItem item) {
- throwIfPrepared();
-
- try {
- if (item.getAlignment() > getAlignment()) {
- throw new IllegalArgumentException(
- "incompatible item alignment");
- }
- } catch (NullPointerException ex) {
- // Elucidate the exception.
- throw new NullPointerException("item == null");
- }
-
- items.add(item);
- }
-
- /**
- * Interns an item in this instance, returning the interned instance
- * (which may not be the one passed in). This will add the item if no
- * equal item has been added.
- *
- * @param item non-null; the item to intern
- * @return non-null; the equivalent interned instance
- */
- public <T extends OffsettedItem> T intern(T item) {
- throwIfPrepared();
-
- OffsettedItem result = interns.get(item);
-
- if (result != null) {
- return (T) result;
- }
-
- add(item);
- interns.put(item, item);
- return item;
- }
-
- /**
- * Gets an item which was previously interned.
- *
- * @param item non-null; the item to look for
- * @return non-null; the equivalent already-interned instance
- */
- public <T extends OffsettedItem> T get(T item) {
- throwIfNotPrepared();
-
- OffsettedItem result = interns.get(item);
-
- if (result != null) {
- return (T) result;
- }
-
- throw new NoSuchElementException(item.toString());
- }
-
- /**
- * Writes an index of contents of the items in this instance of the
- * given type. If there are none, this writes nothing. If there are any,
- * then the index is preceded by the given intro string.
- *
- * @param out non-null; where to write to
- * @param itemType non-null; the item type of interest
- * @param intro non-null; the introductory string for non-empty indices
- */
- public void writeIndexAnnotation(AnnotatedOutput out, ItemType itemType,
- String intro) {
- throwIfNotPrepared();
-
- TreeMap<String, OffsettedItem> index =
- new TreeMap<String, OffsettedItem>();
-
- for (OffsettedItem item : items) {
- if (item.itemType() == itemType) {
- String label = item.toHuman();
- index.put(label, item);
- }
- }
-
- if (index.size() == 0) {
- return;
- }
-
- out.annotate(0, intro);
-
- for (Map.Entry<String, OffsettedItem> entry : index.entrySet()) {
- String label = entry.getKey();
- OffsettedItem item = entry.getValue();
- out.annotate(0, item.offsetString() + ' ' + label + '\n');
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void prepare0() {
- DexFile file = getFile();
-
- /*
- * It's okay for new items to be added as a result of an
- * addContents() call; we just have to deal with the possibility.
- */
-
- int i = 0;
- for (;;) {
- int sz = items.size();
- if (i >= sz) {
- break;
- }
-
- for (/*i*/; i < sz; i++) {
- OffsettedItem one = items.get(i);
- one.addContents(file);
- }
- }
- }
-
- /**
- * Places all the items in this instance at particular offsets. This
- * will call {@link OffsettedItem#place} on each item. If an item
- * does not know its write size before the call to <code>place</code>,
- * it is that call which is responsible for setting the write size.
- * This method may only be called once per instance; subsequent calls
- * will throw an exception.
- */
- public void placeItems() {
- throwIfNotPrepared();
-
- switch (sort) {
- case INSTANCE: {
- Collections.sort(items);
- break;
- }
- case TYPE: {
- Collections.sort(items, TYPE_SORTER);
- break;
- }
- }
-
- int sz = items.size();
- int outAt = 0;
- for (int i = 0; i < sz; i++) {
- OffsettedItem one = items.get(i);
- try {
- int placedAt = one.place(this, outAt);
-
- if (placedAt < outAt) {
- throw new RuntimeException("bogus place() result for " +
- one);
- }
-
- outAt = placedAt + one.writeSize();
- } catch (RuntimeException ex) {
- throw ExceptionWithContext.withContext(ex,
- "...while placing " + one);
- }
- }
-
- writeSize = outAt;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(AnnotatedOutput out) {
- boolean annotates = out.annotates();
- boolean first = true;
- DexFile file = getFile();
- int at = 0;
-
- for (OffsettedItem one : items) {
- if (annotates) {
- if (first) {
- first = false;
- } else {
- out.annotate(0, "\n");
- }
- }
-
- int alignMask = one.getAlignment() - 1;
- int writeAt = (at + alignMask) & ~alignMask;
-
- if (at != writeAt) {
- out.writeZeroes(writeAt - at);
- at = writeAt;
- }
-
- one.writeTo(file, out);
- at += one.writeSize();
- }
-
- if (at != writeSize) {
- throw new RuntimeException("output size mismatch");
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/OffsettedItem.java b/dx/src/com/android/dx/dex/file/OffsettedItem.java
deleted file mode 100644
index 030c37089..000000000
--- a/dx/src/com/android/dx/dex/file/OffsettedItem.java
+++ /dev/null
@@ -1,313 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ExceptionWithContext;
-
-/**
- * An item in a Dalvik file which is referenced by absolute offset.
- */
-public abstract class OffsettedItem extends Item
- implements Comparable<OffsettedItem> {
- /** &gt; 0; alignment requirement */
- private final int alignment;
-
- /** &gt;= -1; the size of this instance when written, in bytes, or
- * <code>-1</code> if not yet known */
- private int writeSize;
-
- /**
- * null-ok; section the item was added to, or <code>null</code> if
- * not yet added
- */
- private Section addedTo;
-
- /**
- * &gt;= -1; assigned offset of the item from the start of its section,
- * or <code>-1</code> if not yet assigned
- */
- private int offset;
-
- /**
- * Gets the absolute offset of the given item, returning <code>0</code>
- * if handed <code>null</code>.
- *
- * @param item null-ok; the item in question
- * @return &gt;= 0; the item's absolute offset, or <code>0</code>
- * if <code>item == null</code>
- */
- public static int getAbsoluteOffsetOr0(OffsettedItem item) {
- if (item == null) {
- return 0;
- }
-
- return item.getAbsoluteOffset();
- }
-
- /**
- * Constructs an instance. The offset is initially unassigned.
- *
- * @param alignment &gt; 0; output alignment requirement; must be a
- * power of 2
- * @param writeSize &gt;= -1; the size of this instance when written,
- * in bytes, or <code>-1</code> if not immediately known
- */
- public OffsettedItem(int alignment, int writeSize) {
- Section.validateAlignment(alignment);
-
- if (writeSize < -1) {
- throw new IllegalArgumentException("writeSize < -1");
- }
-
- this.alignment = alignment;
- this.writeSize = writeSize;
- this.addedTo = null;
- this.offset = -1;
- }
-
- /**
- * {@inheritDoc}
- *
- * Comparisons for this class are defined to be type-major (if the
- * types don't match then the objects are not equal), with
- * {@link #compareTo0} deciding same-type comparisons.
- */
- @Override
- public final boolean equals(Object other) {
- if (this == other) {
- return true;
- }
-
- OffsettedItem otherItem = (OffsettedItem) other;
- ItemType thisType = itemType();
- ItemType otherType = otherItem.itemType();
-
- if (thisType != otherType) {
- return false;
- }
-
- return (compareTo0(otherItem) == 0);
- }
-
- /**
- * {@inheritDoc}
- *
- * Comparisons for this class are defined to be class-major (if the
- * classes don't match then the objects are not equal), with
- * {@link #compareTo0} deciding same-class comparisons.
- */
- public final int compareTo(OffsettedItem other) {
- if (this == other) {
- return 0;
- }
-
- ItemType thisType = itemType();
- ItemType otherType = other.itemType();
-
- if (thisType != otherType) {
- return thisType.compareTo(otherType);
- }
-
- return compareTo0(other);
- }
-
- /**
- * Sets the write size of this item. This may only be called once
- * per instance, and only if the size was unknown upon instance
- * creation.
- *
- * @param writeSize &gt; 0; the write size, in bytes
- */
- public final void setWriteSize(int writeSize) {
- if (writeSize < 0) {
- throw new IllegalArgumentException("writeSize < 0");
- }
-
- if (this.writeSize >= 0) {
- throw new UnsupportedOperationException("writeSize already set");
- }
-
- this.writeSize = writeSize;
- }
-
- /** {@inheritDoc}
- *
- * @throws UnsupportedOperationException thrown if the write size
- * is not yet known
- */
- @Override
- public final int writeSize() {
- if (writeSize < 0) {
- throw new UnsupportedOperationException("writeSize is unknown");
- }
-
- return writeSize;
- }
-
- /** {@inheritDoc} */
- @Override
- public final void writeTo(DexFile file, AnnotatedOutput out) {
- out.alignTo(alignment);
-
- try {
- if (writeSize < 0) {
- throw new UnsupportedOperationException(
- "writeSize is unknown");
- }
- out.assertCursor(getAbsoluteOffset());
- } catch (RuntimeException ex) {
- throw ExceptionWithContext.withContext(ex,
- "...while writing " + this);
- }
-
- writeTo0(file, out);
- }
-
- /**
- * Gets the relative item offset. The offset is from the start of
- * the section which the instance was written to.
- *
- * @return &gt;= 0; the offset
- * @throws RuntimeException thrown if the offset is not yet known
- */
- public final int getRelativeOffset() {
- if (offset < 0) {
- throw new RuntimeException("offset not yet known");
- }
-
- return offset;
- }
-
- /**
- * Gets the absolute item offset. The offset is from the start of
- * the file which the instance was written to.
- *
- * @return &gt;= 0; the offset
- * @throws RuntimeException thrown if the offset is not yet known
- */
- public final int getAbsoluteOffset() {
- if (offset < 0) {
- throw new RuntimeException("offset not yet known");
- }
-
- return addedTo.getAbsoluteOffset(offset);
- }
-
- /**
- * Indicates that this item has been added to the given section at
- * the given offset. It is only valid to call this method once per
- * instance.
- *
- * @param addedTo non-null; the section this instance has been added to
- * @param offset &gt;= 0; the desired offset from the start of the
- * section where this instance was placed
- * @return &gt;= 0; the offset that this instance should be placed at
- * in order to meet its alignment constraint
- */
- public final int place(Section addedTo, int offset) {
- if (addedTo == null) {
- throw new NullPointerException("addedTo == null");
- }
-
- if (offset < 0) {
- throw new IllegalArgumentException("offset < 0");
- }
-
- if (this.addedTo != null) {
- throw new RuntimeException("already written");
- }
-
- int mask = alignment - 1;
- offset = (offset + mask) & ~mask;
-
- this.addedTo = addedTo;
- this.offset = offset;
-
- place0(addedTo, offset);
-
- return offset;
- }
-
- /**
- * Gets the alignment requirement of this instance. An instance should
- * only be written when so aligned.
- *
- * @return &gt; 0; the alignment requirement; must be a power of 2
- */
- public final int getAlignment() {
- return alignment;
- }
-
- /**
- * Gets the absolute offset of this item as a string, suitable for
- * including in annotations.
- *
- * @return non-null; the offset string
- */
- public final String offsetString() {
- return '[' + Integer.toHexString(getAbsoluteOffset()) + ']';
- }
-
- /**
- * Gets a short human-readable string representing this instance.
- *
- * @return non-null; the human form
- */
- public abstract String toHuman();
-
- /**
- * Compares this instance to another which is guaranteed to be of
- * the same class. The default implementation of this method is to
- * throw an exception (unsupported operation). If a particular
- * class needs to actually sort, then it should override this
- * method.
- *
- * @param other non-null; instance to compare to
- * @return <code>-1</code>, <code>0</code>, or <code>1</code>, depending
- * on the sort order of this instance and the other
- */
- protected int compareTo0(OffsettedItem other) {
- throw new UnsupportedOperationException("unsupported");
- }
-
- /**
- * Does additional work required when placing an instance. The
- * default implementation of this method is a no-op. If a
- * particular class needs to do something special, then it should
- * override this method. In particular, if this instance did not
- * know its write size up-front, then this method is responsible
- * for setting it.
- *
- * @param addedTo non-null; the section this instance has been added to
- * @param offset &gt;= 0; the offset from the start of the
- * section where this instance was placed
- */
- protected void place0(Section addedTo, int offset) {
- // This space intentionally left blank.
- }
-
- /**
- * Performs the actual write of the contents of this instance to
- * the given data section. This is called by {@link #writeTo},
- * which will have taken care of ensuring alignment.
- *
- * @param file non-null; the file to use for reference
- * @param out non-null; where to write to
- */
- protected abstract void writeTo0(DexFile file, AnnotatedOutput out);
-}
diff --git a/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java b/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java
deleted file mode 100644
index 0c2d28692..000000000
--- a/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotations;
-import com.android.dx.rop.annotation.AnnotationsList;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-import com.android.dx.util.ToHuman;
-
-import java.util.ArrayList;
-
-/**
- * Association of a method and its parameter annotations.
- */
-public final class ParameterAnnotationStruct
- implements ToHuman, Comparable<ParameterAnnotationStruct> {
- /** non-null; the method in question */
- private final CstMethodRef method;
-
- /** non-null; the associated annotations list */
- private final AnnotationsList annotationsList;
-
- /** non-null; the associated annotations list, as an item */
- private final UniformListItem<AnnotationSetRefItem> annotationsItem;
-
- /**
- * Constructs an instance.
- *
- * @param method non-null; the method in question
- * @param annotationsList non-null; the associated annotations list
- */
- public ParameterAnnotationStruct(CstMethodRef method,
- AnnotationsList annotationsList) {
- if (method == null) {
- throw new NullPointerException("method == null");
- }
-
- if (annotationsList == null) {
- throw new NullPointerException("annotationsList == null");
- }
-
- this.method = method;
- this.annotationsList = annotationsList;
-
- /*
- * Construct an item for the annotations list. TODO: This
- * requires way too much copying; fix it.
- */
-
- int size = annotationsList.size();
- ArrayList<AnnotationSetRefItem> arrayList = new
- ArrayList<AnnotationSetRefItem>(size);
-
- for (int i = 0; i < size; i++) {
- Annotations annotations = annotationsList.get(i);
- AnnotationSetItem item = new AnnotationSetItem(annotations);
- arrayList.add(new AnnotationSetRefItem(item));
- }
-
- this.annotationsItem = new UniformListItem<AnnotationSetRefItem>(
- ItemType.TYPE_ANNOTATION_SET_REF_LIST, arrayList);
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return method.hashCode();
- }
-
- /** {@inheritDoc} */
- public boolean equals(Object other) {
- if (! (other instanceof ParameterAnnotationStruct)) {
- return false;
- }
-
- return method.equals(((ParameterAnnotationStruct) other).method);
- }
-
- /** {@inheritDoc} */
- public int compareTo(ParameterAnnotationStruct other) {
- return method.compareTo(other.method);
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- MethodIdsSection methodIds = file.getMethodIds();
- MixedItemSection wordData = file.getWordData();
-
- methodIds.intern(method);
- wordData.add(annotationsItem);
- }
-
- /** {@inheritDoc} */
- public void writeTo(DexFile file, AnnotatedOutput out) {
- int methodIdx = file.getMethodIds().indexOf(method);
- int annotationsOff = annotationsItem.getAbsoluteOffset();
-
- if (out.annotates()) {
- out.annotate(0, " " + method.toHuman());
- out.annotate(4, " method_idx: " + Hex.u4(methodIdx));
- out.annotate(4, " annotations_off: " +
- Hex.u4(annotationsOff));
- }
-
- out.writeInt(methodIdx);
- out.writeInt(annotationsOff);
- }
-
- /** {@inheritDoc} */
- public String toHuman() {
- StringBuilder sb = new StringBuilder();
-
- sb.append(method.toHuman());
- sb.append(": ");
-
- boolean first = true;
- for (AnnotationSetRefItem item : annotationsItem.getItems()) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(item.toHuman());
- }
-
- return sb.toString();
- }
-
- /**
- * Gets the method this item is for.
- *
- * @return non-null; the method
- */
- public CstMethodRef getMethod() {
- return method;
- }
-
- /**
- * Gets the associated annotations list.
- *
- * @return non-null; the annotations list
- */
- public AnnotationsList getAnnotationsList() {
- return annotationsList;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/ProtoIdItem.java b/dx/src/com/android/dx/dex/file/ProtoIdItem.java
deleted file mode 100644
index a144c304e..000000000
--- a/dx/src/com/android/dx/dex/file/ProtoIdItem.java
+++ /dev/null
@@ -1,162 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.rop.type.Prototype;
-import com.android.dx.rop.type.StdTypeList;
-import com.android.dx.rop.type.Type;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Representation of a method prototype reference inside a Dalvik file.
- */
-public final class ProtoIdItem extends IndexedItem {
- /** size of instances when written out to a file, in bytes */
- public static final int WRITE_SIZE = 12;
-
- /** non-null; the wrapped prototype */
- private final Prototype prototype;
-
- /** non-null; the short-form of the prototype */
- private final CstUtf8 shortForm;
-
- /**
- * null-ok; the list of parameter types or <code>null</code> if this
- * prototype has no parameters
- */
- private TypeListItem parameterTypes;
-
- /**
- * Constructs an instance.
- *
- * @param prototype non-null; the constant for the prototype
- */
- public ProtoIdItem(Prototype prototype) {
- if (prototype == null) {
- throw new NullPointerException("prototype == null");
- }
-
- this.prototype = prototype;
- this.shortForm = makeShortForm(prototype);
-
- StdTypeList parameters = prototype.getParameterTypes();
- this.parameterTypes = (parameters.size() == 0) ? null
- : new TypeListItem(parameters);
- }
-
- /**
- * Creates the short-form of the given prototype.
- *
- * @param prototype non-null; the prototype
- * @return non-null; the short form
- */
- private static CstUtf8 makeShortForm(Prototype prototype) {
- StdTypeList parameters = prototype.getParameterTypes();
- int size = parameters.size();
- StringBuilder sb = new StringBuilder(size + 1);
-
- sb.append(shortFormCharFor(prototype.getReturnType()));
-
- for (int i = 0; i < size; i++) {
- sb.append(shortFormCharFor(parameters.getType(i)));
- }
-
- return new CstUtf8(sb.toString());
- }
-
- /**
- * Gets the short-form character for the given type.
- *
- * @param type non-null; the type
- * @return the corresponding short-form character
- */
- private static char shortFormCharFor(Type type) {
- char descriptorChar = type.getDescriptor().charAt(0);
-
- if (descriptorChar == '[') {
- return 'L';
- }
-
- return descriptorChar;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_PROTO_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- return WRITE_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- StringIdsSection stringIds = file.getStringIds();
- TypeIdsSection typeIds = file.getTypeIds();
- MixedItemSection typeLists = file.getTypeLists();
-
- typeIds.intern(prototype.getReturnType());
- stringIds.intern(shortForm);
-
- if (parameterTypes != null) {
- parameterTypes = typeLists.intern(parameterTypes);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo(DexFile file, AnnotatedOutput out) {
- int shortyIdx = file.getStringIds().indexOf(shortForm);
- int returnIdx = file.getTypeIds().indexOf(prototype.getReturnType());
- int paramsOff = OffsettedItem.getAbsoluteOffsetOr0(parameterTypes);
-
- if (out.annotates()) {
- StringBuilder sb = new StringBuilder();
- sb.append(prototype.getReturnType().toHuman());
- sb.append(" proto(");
-
- StdTypeList params = prototype.getParameterTypes();
- int size = params.size();
-
- for (int i = 0; i < size; i++) {
- if (i != 0) {
- sb.append(", ");
- }
- sb.append(params.getType(i).toHuman());
- }
-
- sb.append(")");
- out.annotate(0, indexString() + ' ' + sb.toString());
- out.annotate(4, " shorty_idx: " + Hex.u4(shortyIdx) +
- " // " + shortForm.toQuoted());
- out.annotate(4, " return_type_idx: " + Hex.u4(returnIdx) +
- " // " + prototype.getReturnType().toHuman());
- out.annotate(4, " parameters_off: " + Hex.u4(paramsOff));
- }
-
- out.writeInt(shortyIdx);
- out.writeInt(returnIdx);
- out.writeInt(paramsOff);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/ProtoIdsSection.java b/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
deleted file mode 100644
index 852ab9d5f..000000000
--- a/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
+++ /dev/null
@@ -1,140 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.type.Prototype;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-import java.util.TreeMap;
-
-/**
- * Proto (method prototype) identifiers list section of a
- * <code>.dex</code> file.
- */
-public final class ProtoIdsSection extends UniformItemSection {
- /**
- * non-null; map from method prototypes to {@link ProtoIdItem} instances
- */
- private final TreeMap<Prototype, ProtoIdItem> protoIds;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public ProtoIdsSection(DexFile file) {
- super("proto_ids", file, 4);
-
- protoIds = new TreeMap<Prototype, ProtoIdItem>();
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return protoIds.values();
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- throw new UnsupportedOperationException("unsupported");
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- int sz = protoIds.size();
- int offset = (sz == 0) ? 0 : getFileOffset();
-
- if (sz > 65536) {
- throw new UnsupportedOperationException("too many proto ids");
- }
-
- if (out.annotates()) {
- out.annotate(4, "proto_ids_size: " + Hex.u4(sz));
- out.annotate(4, "proto_ids_off: " + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param prototype non-null; the prototype to intern
- * @return non-null; the interned reference
- */
- public ProtoIdItem intern(Prototype prototype) {
- if (prototype == null) {
- throw new NullPointerException("prototype == null");
- }
-
- throwIfPrepared();
-
- ProtoIdItem result = protoIds.get(prototype);
-
- if (result == null) {
- result = new ProtoIdItem(prototype);
- protoIds.put(prototype, result);
- }
-
- return result;
- }
-
- /**
- * Gets the index of the given prototype, which must have
- * been added to this instance.
- *
- * @param prototype non-null; the prototype to look up
- * @return &gt;= 0; the reference's index
- */
- public int indexOf(Prototype prototype) {
- if (prototype == null) {
- throw new NullPointerException("prototype == null");
- }
-
- throwIfNotPrepared();
-
- ProtoIdItem item = protoIds.get(prototype);
-
- if (item == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return item.getIndex();
- }
-
- /** {@inheritDoc} */
- @Override
- protected void orderItems() {
- int idx = 0;
-
- for (Object i : items()) {
- ((ProtoIdItem) i).setIndex(idx);
- idx++;
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/Section.java b/dx/src/com/android/dx/dex/file/Section.java
deleted file mode 100644
index 9f7657c6c..000000000
--- a/dx/src/com/android/dx/dex/file/Section.java
+++ /dev/null
@@ -1,287 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-
-import java.util.Collection;
-
-/**
- * A section of a <code>.dex</code> file. Each section consists of a list
- * of items of some sort or other.
- */
-public abstract class Section {
- /** null-ok; name of this part, for annotation purposes */
- private final String name;
-
- /** non-null; file that this instance is part of */
- private final DexFile file;
-
- /** &gt; 0; alignment requirement for the final output;
- * must be a power of 2 */
- private final int alignment;
-
- /** &gt;= -1; offset from the start of the file to this part, or
- * <code>-1</code> if not yet known */
- private int fileOffset;
-
- /** whether {@link #prepare} has been called successfully on this
- * instance */
- private boolean prepared;
-
- /**
- * Validates an alignment.
- *
- * @param alignment the alignment
- * @throws IllegalArgumentException thrown if <code>alignment</code>
- * isn't a positive power of 2
- */
- public static void validateAlignment(int alignment) {
- if ((alignment <= 0) ||
- (alignment & (alignment - 1)) != 0) {
- throw new IllegalArgumentException("invalid alignment");
- }
- }
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param name null-ok; the name of this instance, for annotation
- * purposes
- * @param file non-null; file that this instance is part of
- * @param alignment &gt; 0; alignment requirement for the final output;
- * must be a power of 2
- */
- public Section(String name, DexFile file, int alignment) {
- if (file == null) {
- throw new NullPointerException("file == null");
- }
-
- validateAlignment(alignment);
-
- this.name = name;
- this.file = file;
- this.alignment = alignment;
- this.fileOffset = -1;
- this.prepared = false;
- }
-
- /**
- * Gets the file that this instance is part of.
- *
- * @return non-null; the file
- */
- public final DexFile getFile() {
- return file;
- }
-
- /**
- * Gets the alignment for this instance's final output.
- *
- * @return &gt; 0; the alignment
- */
- public final int getAlignment() {
- return alignment;
- }
-
- /**
- * Gets the offset from the start of the file to this part. This
- * throws an exception if the offset has not yet been set.
- *
- * @return &gt;= 0; the file offset
- */
- public final int getFileOffset() {
- if (fileOffset < 0) {
- throw new RuntimeException("fileOffset not set");
- }
-
- return fileOffset;
- }
-
- /**
- * Sets the file offset. It is only valid to call this method once
- * once per instance.
- *
- * @param fileOffset &gt;= 0; the desired offset from the start of the
- * file where this for this instance
- * @return &gt;= 0; the offset that this instance should be placed at
- * in order to meet its alignment constraint
- */
- public final int setFileOffset(int fileOffset) {
- if (fileOffset < 0) {
- throw new IllegalArgumentException("fileOffset < 0");
- }
-
- if (this.fileOffset >= 0) {
- throw new RuntimeException("fileOffset already set");
- }
-
- int mask = alignment - 1;
- fileOffset = (fileOffset + mask) & ~mask;
-
- this.fileOffset = fileOffset;
-
- return fileOffset;
- }
-
- /**
- * Writes this instance to the given raw data object.
- *
- * @param out non-null; where to write to
- */
- public final void writeTo(AnnotatedOutput out) {
- throwIfNotPrepared();
- align(out);
-
- int cursor = out.getCursor();
-
- if (fileOffset < 0) {
- fileOffset = cursor;
- } else if (fileOffset != cursor) {
- throw new RuntimeException("alignment mismatch: for " + this +
- ", at " + cursor +
- ", but expected " + fileOffset);
- }
-
- if (out.annotates()) {
- if (name != null) {
- out.annotate(0, "\n" + name + ":");
- } else if (cursor != 0) {
- out.annotate(0, "\n");
- }
- }
-
- writeTo0(out);
- }
-
- /**
- * Returns the absolute file offset, given an offset from the
- * start of this instance's output. This is only valid to call
- * once this instance has been assigned a file offset (via {@link
- * #setFileOffset}).
- *
- * @param relative &gt;= 0; the relative offset
- * @return &gt;= 0; the corresponding absolute file offset
- */
- public final int getAbsoluteOffset(int relative) {
- if (relative < 0) {
- throw new IllegalArgumentException("relative < 0");
- }
-
- if (fileOffset < 0) {
- throw new RuntimeException("fileOffset not yet set");
- }
-
- return fileOffset + relative;
- }
-
- /**
- * Returns the absolute file offset of the given item which must
- * be contained in this section. This is only valid to call
- * once this instance has been assigned a file offset (via {@link
- * #setFileOffset}).
- *
- * <p><b>Note:</b> Subclasses must implement this as appropriate for
- * their contents.</p>
- *
- * @param item non-null; the item in question
- * @return &gt;= 0; the item's absolute file offset
- */
- public abstract int getAbsoluteItemOffset(Item item);
-
- /**
- * Prepares this instance for writing. This performs any necessary
- * prerequisites, including particularly adding stuff to other
- * sections. This method may only be called once per instance;
- * subsequent calls will throw an exception.
- */
- public final void prepare() {
- throwIfPrepared();
- prepare0();
- prepared = true;
- }
-
- /**
- * Gets the collection of all the items in this section.
- * It is not valid to attempt to change the returned list.
- *
- * @return non-null; the items
- */
- public abstract Collection<? extends Item> items();
-
- /**
- * Does the main work of {@link #prepare}.
- */
- protected abstract void prepare0();
-
- /**
- * Gets the size of this instance when output, in bytes.
- *
- * @return &gt;= 0; the size of this instance, in bytes
- */
- public abstract int writeSize();
-
- /**
- * Throws an exception if {@link #prepare} has not been
- * called on this instance.
- */
- protected final void throwIfNotPrepared() {
- if (!prepared) {
- throw new RuntimeException("not prepared");
- }
- }
-
- /**
- * Throws an exception if {@link #prepare} has already been called
- * on this instance.
- */
- protected final void throwIfPrepared() {
- if (prepared) {
- throw new RuntimeException("already prepared");
- }
- }
-
- /**
- * Aligns the output of the given data to the alignment of this instance.
- *
- * @param out non-null; the output to align
- */
- protected final void align(AnnotatedOutput out) {
- out.alignTo(alignment);
- }
-
- /**
- * Writes this instance to the given raw data object. This gets
- * called by {@link #writeTo} after aligning the cursor of
- * <code>out</code> and verifying that either the assigned file
- * offset matches the actual cursor <code>out</code> or that the
- * file offset was not previously assigned, in which case it gets
- * assigned to <code>out</code>'s cursor.
- *
- * @param out non-null; where to write to
- */
- protected abstract void writeTo0(AnnotatedOutput out);
-
- /**
- * Returns the name of this section, for annotation purposes.
- *
- * @return null-ok; name of this part, for annotation purposes
- */
- protected final String getName() {
- return name;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/Statistics.java b/dx/src/com/android/dx/dex/file/Statistics.java
deleted file mode 100644
index b11ab6eb1..000000000
--- a/dx/src/com/android/dx/dex/file/Statistics.java
+++ /dev/null
@@ -1,195 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.TreeMap;
-
-/**
- * Statistics about the contents of a file.
- */
-public final class Statistics {
- /** non-null; data about each type of item */
- private final HashMap<String, Data> dataMap;
-
- /**
- * Constructs an instance.
- */
- public Statistics() {
- dataMap = new HashMap<String, Data>(50);
- }
-
- /**
- * Adds the given item to the statistics.
- *
- * @param item non-null; the item to add
- */
- public void add(Item item) {
- String typeName = item.typeName();
- Data data = dataMap.get(typeName);
-
- if (data == null) {
- dataMap.put(typeName, new Data(item, typeName));
- } else {
- data.add(item);
- }
- }
-
- /**
- * Adds the given list of items to the statistics.
- *
- * @param list non-null; the list of items to add
- */
- public void addAll(Section list) {
- Collection<? extends Item> items = list.items();
- for (Item item : items) {
- add(item);
- }
- }
-
- /**
- * Writes the statistics as an annotation.
- *
- * @param out non-null; where to write to
- */
- public final void writeAnnotation(AnnotatedOutput out) {
- if (dataMap.size() == 0) {
- return;
- }
-
- out.annotate(0, "\nstatistics:\n");
-
- TreeMap<String, Data> sortedData = new TreeMap<String, Data>();
-
- for (Data data : dataMap.values()) {
- sortedData.put(data.name, data);
- }
-
- for (Data data : sortedData.values()) {
- data.writeAnnotation(out);
- }
- }
-
- public String toHuman() {
- StringBuilder sb = new StringBuilder();
-
- sb.append("Statistics:\n");
-
- TreeMap<String, Data> sortedData = new TreeMap<String, Data>();
-
- for (Data data : dataMap.values()) {
- sortedData.put(data.name, data);
- }
-
- for (Data data : sortedData.values()) {
- sb.append(data.toHuman());
- }
-
- return sb.toString();
- }
-
- /**
- * Statistical data about a particular class.
- */
- private static class Data {
- /** non-null; name to use as a label */
- private final String name;
-
- /** &gt;= 0; number of instances */
- private int count;
-
- /** &gt;= 0; total size of instances in bytes */
- private int totalSize;
-
- /** &gt;= 0; largest size of any individual item */
- private int largestSize;
-
- /** &gt;= 0; smallest size of any individual item */
- private int smallestSize;
-
- /**
- * Constructs an instance for the given item.
- *
- * @param item non-null; item in question
- * @param name non-null; type name to use
- */
- public Data(Item item, String name) {
- int size = item.writeSize();
-
- this.name = name;
- this.count = 1;
- this.totalSize = size;
- this.largestSize = size;
- this.smallestSize = size;
- }
-
- /**
- * Incorporates a new item. This assumes the type name matches.
- *
- * @param item non-null; item to incorporate
- */
- public void add(Item item) {
- int size = item.writeSize();
-
- count++;
- totalSize += size;
-
- if (size > largestSize) {
- largestSize = size;
- }
-
- if (size < smallestSize) {
- smallestSize = size;
- }
- }
-
- /**
- * Writes this instance as an annotation.
- *
- * @param out non-null; where to write to
- */
- public void writeAnnotation(AnnotatedOutput out) {
- out.annotate(toHuman());
- }
-
- /**
- * Generates a human-readable string for this data item.
- *
- * @return string for human consumption.
- */
- public String toHuman() {
- StringBuilder sb = new StringBuilder();
-
- sb.append(" " + name + ": " +
- count + " item" + (count == 1 ? "" : "s") + "; " +
- totalSize + " bytes total\n");
-
- if (smallestSize == largestSize) {
- sb.append(" " + smallestSize + " bytes/item\n");
- } else {
- int average = totalSize / count;
- sb.append(" " + smallestSize + ".." + largestSize +
- " bytes/item; average " + average + "\n");
- }
-
- return sb.toString();
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/StringDataItem.java b/dx/src/com/android/dx/dex/file/StringDataItem.java
deleted file mode 100644
index 49eea5757..000000000
--- a/dx/src/com/android/dx/dex/file/StringDataItem.java
+++ /dev/null
@@ -1,99 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.ByteArray;
-import com.android.dx.util.Hex;
-import com.android.dx.util.Leb128Utils;
-
-/**
- * Representation of string data for a particular string, in a Dalvik file.
- */
-public final class StringDataItem extends OffsettedItem {
- /** non-null; the string value */
- private final CstUtf8 value;
-
- /**
- * Constructs an instance.
- *
- * @param value non-null; the string value
- */
- public StringDataItem(CstUtf8 value) {
- super(1, writeSize(value));
-
- this.value = value;
- }
-
- /**
- * Gets the write size for a given value.
- *
- * @param value non-null; the string value
- * @return &gt;= 2 the write size, in bytes
- */
- private static int writeSize(CstUtf8 value) {
- int utf16Size = value.getUtf16Size();
-
- // The +1 is for the '\0' termination byte.
- return Leb128Utils.unsignedLeb128Size(utf16Size)
- + value.getUtf8Size() + 1;
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_STRING_DATA_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- // Nothing to do here.
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo0(DexFile file, AnnotatedOutput out) {
- ByteArray bytes = value.getBytes();
- int utf16Size = value.getUtf16Size();
-
- if (out.annotates()) {
- out.annotate(Leb128Utils.unsignedLeb128Size(utf16Size),
- "utf16_size: " + Hex.u4(utf16Size));
- out.annotate(bytes.size() + 1, value.toQuoted());
- }
-
- out.writeUnsignedLeb128(utf16Size);
- out.write(bytes);
- out.writeByte(0);
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- return value.toQuoted();
- }
-
- /** {@inheritDoc} */
- @Override
- protected int compareTo0(OffsettedItem other) {
- StringDataItem otherData = (StringDataItem) other;
-
- return value.compareTo(otherData.value);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/StringIdItem.java b/dx/src/com/android/dx/dex/file/StringIdItem.java
deleted file mode 100644
index e80a7f877..000000000
--- a/dx/src/com/android/dx/dex/file/StringIdItem.java
+++ /dev/null
@@ -1,128 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Representation of a string inside a Dalvik file.
- */
-public final class StringIdItem
- extends IndexedItem implements Comparable {
- /** size of instances when written out to a file, in bytes */
- public static final int WRITE_SIZE = 4;
-
- /** non-null; the string value */
- private final CstUtf8 value;
-
- /** null-ok; associated string data object, if known */
- private StringDataItem data;
-
- /**
- * Constructs an instance.
- *
- * @param value non-null; the string value
- */
- public StringIdItem(CstUtf8 value) {
- if (value == null) {
- throw new NullPointerException("value == null");
- }
-
- this.value = value;
- this.data = null;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof StringIdItem)) {
- return false;
- }
-
- StringIdItem otherString = (StringIdItem) other;
- return value.equals(otherString.value);
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
- /** {@inheritDoc} */
- public int compareTo(Object other) {
- StringIdItem otherString = (StringIdItem) other;
- return value.compareTo(otherString.value);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_STRING_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- return WRITE_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- if (data == null) {
- // The string data hasn't yet been added, so add it.
- MixedItemSection stringData = file.getStringData();
- data = new StringDataItem(value);
- stringData.add(data);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo(DexFile file, AnnotatedOutput out) {
- int dataOff = data.getAbsoluteOffset();
-
- if (out.annotates()) {
- out.annotate(0, indexString() + ' ' + value.toQuoted(100));
- out.annotate(4, " string_data_off: " + Hex.u4(dataOff));
- }
-
- out.writeInt(dataOff);
- }
-
- /**
- * Gets the string value.
- *
- * @return non-null; the value
- */
- public CstUtf8 getValue() {
- return value;
- }
-
- /**
- * Gets the associated data object for this instance, if known.
- *
- * @return null-ok; the associated data object or <code>null</code>
- * if not yet known
- */
- public StringDataItem getData() {
- return data;
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/StringIdsSection.java b/dx/src/com/android/dx/dex/file/StringIdsSection.java
deleted file mode 100644
index 17fbb578b..000000000
--- a/dx/src/com/android/dx/dex/file/StringIdsSection.java
+++ /dev/null
@@ -1,210 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstNat;
-import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-import java.util.TreeMap;
-
-/**
- * Strings list section of a <code>.dex</code> file.
- */
-public final class StringIdsSection
- extends UniformItemSection {
- /**
- * non-null; map from string constants to {@link
- * StringIdItem} instances
- */
- private final TreeMap<CstUtf8, StringIdItem> strings;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public StringIdsSection(DexFile file) {
- super("string_ids", file, 4);
-
- strings = new TreeMap<CstUtf8, StringIdItem>();
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return strings.values();
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- if (cst == null) {
- throw new NullPointerException("cst == null");
- }
-
- throwIfNotPrepared();
-
- if (cst instanceof CstString) {
- cst = ((CstString) cst).getString();
- }
-
- IndexedItem result = strings.get((CstUtf8) cst);
-
- if (result == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return result;
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- int sz = strings.size();
- int offset = (sz == 0) ? 0 : getFileOffset();
-
- if (out.annotates()) {
- out.annotate(4, "string_ids_size: " + Hex.u4(sz));
- out.annotate(4, "string_ids_off: " + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param string non-null; the string to intern, as a regular Java
- * <code>String</code>
- * @return non-null; the interned string
- */
- public StringIdItem intern(String string) {
- CstUtf8 utf8 = new CstUtf8(string);
- return intern(new StringIdItem(utf8));
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param string non-null; the string to intern, as a {@link CstString}
- * @return non-null; the interned string
- */
- public StringIdItem intern(CstString string) {
- CstUtf8 utf8 = string.getString();
- return intern(new StringIdItem(utf8));
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param string non-null; the string to intern, as a constant
- * @return non-null; the interned string
- */
- public StringIdItem intern(CstUtf8 string) {
- return intern(new StringIdItem(string));
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param string non-null; the string to intern
- * @return non-null; the interned string
- */
- public StringIdItem intern(StringIdItem string) {
- if (string == null) {
- throw new NullPointerException("string == null");
- }
-
- throwIfPrepared();
-
- CstUtf8 value = string.getValue();
- StringIdItem already = strings.get(value);
-
- if (already != null) {
- return already;
- }
-
- strings.put(value, string);
- return string;
- }
-
- /**
- * Interns the components of a name-and-type into this instance.
- *
- * @param nat non-null; the name-and-type
- */
- public void intern(CstNat nat) {
- intern(nat.getName());
- intern(nat.getDescriptor());
- }
-
- /**
- * Gets the index of the given string, which must have been added
- * to this instance.
- *
- * @param string non-null; the string to look up
- * @return &gt;= 0; the string's index
- */
- public int indexOf(CstUtf8 string) {
- if (string == null) {
- throw new NullPointerException("string == null");
- }
-
- throwIfNotPrepared();
-
- StringIdItem s = strings.get(string);
-
- if (s == null) {
- throw new IllegalArgumentException("not found");
- }
-
- return s.getIndex();
- }
-
- /**
- * Gets the index of the given string, which must have been added
- * to this instance.
- *
- * @param string non-null; the string to look up
- * @return &gt;= 0; the string's index
- */
- public int indexOf(CstString string) {
- return indexOf(string.getString());
- }
-
- /** {@inheritDoc} */
- @Override
- protected void orderItems() {
- int idx = 0;
-
- for (StringIdItem s : strings.values()) {
- s.setIndex(idx);
- idx++;
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/TypeIdItem.java b/dx/src/com/android/dx/dex/file/TypeIdItem.java
deleted file mode 100644
index f3402e643..000000000
--- a/dx/src/com/android/dx/dex/file/TypeIdItem.java
+++ /dev/null
@@ -1,72 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Representation of a type reference inside a Dalvik file.
- */
-public final class TypeIdItem extends IdItem {
- /** size of instances when written out to a file, in bytes */
- public static final int WRITE_SIZE = 4;
-
- /**
- * Constructs an instance.
- *
- * @param type non-null; the constant for the type
- */
- public TypeIdItem(CstType type) {
- super(type);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_TYPE_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- @Override
- public int writeSize() {
- return WRITE_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- file.getStringIds().intern(getDefiningClass().getDescriptor());
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeTo(DexFile file, AnnotatedOutput out) {
- CstType type = getDefiningClass();
- CstUtf8 descriptor = type.getDescriptor();
- int idx = file.getStringIds().indexOf(descriptor);
-
- if (out.annotates()) {
- out.annotate(0, indexString() + ' ' + descriptor.toHuman());
- out.annotate(4, " descriptor_idx: " + Hex.u4(idx));
- }
-
- out.writeInt(idx);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/TypeIdsSection.java b/dx/src/com/android/dx/dex/file/TypeIdsSection.java
deleted file mode 100644
index 296263f09..000000000
--- a/dx/src/com/android/dx/dex/file/TypeIdsSection.java
+++ /dev/null
@@ -1,192 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.type.Type;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-import java.util.TreeMap;
-
-/**
- * Type identifiers list section of a <code>.dex</code> file.
- */
-public final class TypeIdsSection extends UniformItemSection {
- /**
- * non-null; map from types to {@link TypeIdItem} instances
- */
- private final TreeMap<Type, TypeIdItem> typeIds;
-
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param file non-null; file that this instance is part of
- */
- public TypeIdsSection(DexFile file) {
- super("type_ids", file, 4);
-
- typeIds = new TreeMap<Type, TypeIdItem>();
- }
-
- /** {@inheritDoc} */
- @Override
- public Collection<? extends Item> items() {
- return typeIds.values();
- }
-
- /** {@inheritDoc} */
- @Override
- public IndexedItem get(Constant cst) {
- if (cst == null) {
- throw new NullPointerException("cst == null");
- }
-
- throwIfNotPrepared();
-
- Type type = ((CstType) cst).getClassType();
- IndexedItem result = typeIds.get(type);
-
- if (result == null) {
- throw new IllegalArgumentException("not found: " + cst);
- }
-
- return result;
- }
-
- /**
- * Writes the portion of the file header that refers to this instance.
- *
- * @param out non-null; where to write
- */
- public void writeHeaderPart(AnnotatedOutput out) {
- throwIfNotPrepared();
-
- int sz = typeIds.size();
- int offset = (sz == 0) ? 0 : getFileOffset();
-
- if (sz > 65536) {
- throw new UnsupportedOperationException("too many type ids");
- }
-
- if (out.annotates()) {
- out.annotate(4, "type_ids_size: " + Hex.u4(sz));
- out.annotate(4, "type_ids_off: " + Hex.u4(offset));
- }
-
- out.writeInt(sz);
- out.writeInt(offset);
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param type non-null; the type to intern
- * @return non-null; the interned reference
- */
- public TypeIdItem intern(Type type) {
- if (type == null) {
- throw new NullPointerException("type == null");
- }
-
- throwIfPrepared();
-
- TypeIdItem result = typeIds.get(type);
-
- if (result == null) {
- result = new TypeIdItem(new CstType(type));
- typeIds.put(type, result);
- }
-
- return result;
- }
-
- /**
- * Interns an element into this instance.
- *
- * @param type non-null; the type to intern
- * @return non-null; the interned reference
- */
- public TypeIdItem intern(CstType type) {
- if (type == null) {
- throw new NullPointerException("type == null");
- }
-
- throwIfPrepared();
-
- Type typePerSe = type.getClassType();
- TypeIdItem result = typeIds.get(typePerSe);
-
- if (result == null) {
- result = new TypeIdItem(type);
- typeIds.put(typePerSe, result);
- }
-
- return result;
- }
-
- /**
- * Gets the index of the given type, which must have
- * been added to this instance.
- *
- * @param type non-null; the type to look up
- * @return &gt;= 0; the reference's index
- */
- public int indexOf(Type type) {
- if (type == null) {
- throw new NullPointerException("type == null");
- }
-
- throwIfNotPrepared();
-
- TypeIdItem item = typeIds.get(type);
-
- if (item == null) {
- throw new IllegalArgumentException("not found: " + type);
- }
-
- return item.getIndex();
- }
-
- /**
- * Gets the index of the given type, which must have
- * been added to this instance.
- *
- * @param type non-null; the type to look up
- * @return &gt;= 0; the reference's index
- */
- public int indexOf(CstType type) {
- if (type == null) {
- throw new NullPointerException("type == null");
- }
-
- return indexOf(type.getClassType());
- }
-
- /** {@inheritDoc} */
- @Override
- protected void orderItems() {
- int idx = 0;
-
- for (Object i : items()) {
- ((TypeIdItem) i).setIndex(idx);
- idx++;
- }
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/TypeListItem.java b/dx/src/com/android/dx/dex/file/TypeListItem.java
deleted file mode 100644
index 6557ca415..000000000
--- a/dx/src/com/android/dx/dex/file/TypeListItem.java
+++ /dev/null
@@ -1,122 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.type.StdTypeList;
-import com.android.dx.rop.type.Type;
-import com.android.dx.rop.type.TypeList;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-/**
- * Representation of a list of class references.
- */
-public final class TypeListItem extends OffsettedItem {
- /** alignment requirement */
- private static final int ALIGNMENT = 4;
-
- /** element size in bytes */
- private static final int ELEMENT_SIZE = 2;
-
- /** header size in bytes */
- private static final int HEADER_SIZE = 4;
-
- /** non-null; the actual list */
- private final TypeList list;
-
- /**
- * Constructs an instance.
- *
- * @param list non-null; the actual list
- */
- public TypeListItem(TypeList list) {
- super(ALIGNMENT, (list.size() * ELEMENT_SIZE) + HEADER_SIZE);
-
- this.list = list;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return StdTypeList.hashContents(list);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return ItemType.TYPE_TYPE_LIST;
- }
-
- /** {@inheritDoc} */
- public void addContents(DexFile file) {
- TypeIdsSection typeIds = file.getTypeIds();
- int sz = list.size();
-
- for (int i = 0; i < sz; i++) {
- typeIds.intern(list.getType(i));
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public String toHuman() {
- throw new RuntimeException("unsupported");
- }
-
- /**
- * Gets the underlying list.
- *
- * @return non-null; the list
- */
- public TypeList getList() {
- return list;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- TypeIdsSection typeIds = file.getTypeIds();
- int sz = list.size();
-
- if (out.annotates()) {
- out.annotate(0, offsetString() + " type_list");
- out.annotate(HEADER_SIZE, " size: " + Hex.u4(sz));
- for (int i = 0; i < sz; i++) {
- Type one = list.getType(i);
- int idx = typeIds.indexOf(one);
- out.annotate(ELEMENT_SIZE,
- " " + Hex.u2(idx) + " // " + one.toHuman());
- }
- }
-
- out.writeInt(sz);
-
- for (int i = 0; i < sz; i++) {
- out.writeShort(typeIds.indexOf(list.getType(i)));
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected int compareTo0(OffsettedItem other) {
- TypeList thisList = this.list;
- TypeList otherList = ((TypeListItem) other).list;
-
- return StdTypeList.compareContents(thisList, otherList);
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/UniformItemSection.java b/dx/src/com/android/dx/dex/file/UniformItemSection.java
deleted file mode 100644
index 602bc2dcb..000000000
--- a/dx/src/com/android/dx/dex/file/UniformItemSection.java
+++ /dev/null
@@ -1,112 +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.dx.dex.file;
-
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.util.AnnotatedOutput;
-
-import java.util.Collection;
-
-/**
- * A section of a <code>.dex</code> file which consists of a sequence of
- * {@link Item} objects. Each of the items must have the same size in
- * the output.
- */
-public abstract class UniformItemSection extends Section {
- /**
- * Constructs an instance. The file offset is initially unknown.
- *
- * @param name null-ok; the name of this instance, for annotation
- * purposes
- * @param file non-null; file that this instance is part of
- * @param alignment &gt; 0; alignment requirement for the final output;
- * must be a power of 2
- */
- public UniformItemSection(String name, DexFile file, int alignment) {
- super(name, file, alignment);
- }
-
- /** {@inheritDoc} */
- @Override
- public final int writeSize() {
- Collection<? extends Item> items = items();
- int sz = items.size();
-
- if (sz == 0) {
- return 0;
- }
-
- // Since each item has to be the same size, we can pick any.
- return sz * items.iterator().next().writeSize();
- }
-
- /**
- * Gets the item corresponding to the given {@link Constant}. This
- * will throw an exception if the constant is not found, including
- * if this instance isn't the sort that maps constants to {@link
- * IndexedItem} instances.
- *
- * @param cst non-null; constant to look for
- * @return non-null; the corresponding item found in this instance
- */
- public abstract IndexedItem get(Constant cst);
-
- /** {@inheritDoc} */
- @Override
- protected final void prepare0() {
- DexFile file = getFile();
-
- orderItems();
-
- for (Item one : items()) {
- one.addContents(file);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected final void writeTo0(AnnotatedOutput out) {
- DexFile file = getFile();
- int alignment = getAlignment();
-
- for (Item one : items()) {
- one.writeTo(file, out);
- out.alignTo(alignment);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public final int getAbsoluteItemOffset(Item item) {
- /*
- * Since all items must be the same size, we can use the size
- * of the one we're given to calculate its offset.
- */
- IndexedItem ii = (IndexedItem) item;
- int relativeOffset = ii.getIndex() * ii.writeSize();
-
- return getAbsoluteOffset(relativeOffset);
- }
-
- /**
- * Alters or picks the order for items in this instance if desired,
- * so that subsequent calls to {@link #items} will yield a
- * so-ordered collection. If the items in this instance are indexed,
- * then this method should also assign indices.
- */
- protected abstract void orderItems();
-}
diff --git a/dx/src/com/android/dx/dex/file/UniformListItem.java b/dx/src/com/android/dx/dex/file/UniformListItem.java
deleted file mode 100644
index 3af39428a..000000000
--- a/dx/src/com/android/dx/dex/file/UniformListItem.java
+++ /dev/null
@@ -1,216 +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.dx.dex.file;
-
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Class that represents a contiguous list of uniform items. Each
- * item in the list, in particular, must have the same write size and
- * alignment.
- *
- * <p>This class inherits its alignment from its items, bumped up to
- * <code>4</code> if the items have a looser alignment requirement. If
- * it is more than <code>4</code>, then there will be a gap after the
- * output list size (which is four bytes) and before the first item.</p>
- *
- * @param <T> type of element contained in an instance
- */
-public final class UniformListItem<T extends OffsettedItem>
- extends OffsettedItem {
- /** the size of the list header */
- private static final int HEADER_SIZE = 4;
-
- /** non-null; the item type */
- private final ItemType itemType;
-
- /** non-null; the contents */
- private final List<T> items;
-
- /**
- * Constructs an instance. It is illegal to modify the given list once
- * it is used to construct an instance of this class.
- *
- * @param itemType non-null; the type of the item
- * @param items non-null and non-empty; list of items to represent
- */
- public UniformListItem(ItemType itemType, List<T> items) {
- super(getAlignment(items), writeSize(items));
-
- if (itemType == null) {
- throw new NullPointerException("itemType == null");
- }
-
- this.items = items;
- this.itemType = itemType;
- }
-
- /**
- * Helper for {@link #UniformListItem}, which returns the alignment
- * requirement implied by the given list. See the header comment for
- * more details.
- *
- * @param items non-null; list of items being represented
- * @return &gt;= 4; the alignment requirement
- */
- private static int getAlignment(List<? extends OffsettedItem> items) {
- try {
- // Since they all must have the same alignment, any one will do.
- return Math.max(HEADER_SIZE, items.get(0).getAlignment());
- } catch (IndexOutOfBoundsException ex) {
- // Translate the exception.
- throw new IllegalArgumentException("items.size() == 0");
- } catch (NullPointerException ex) {
- // Translate the exception.
- throw new NullPointerException("items == null");
- }
- }
-
- /**
- * Calculates the write size for the given list.
- *
- * @param items non-null; the list in question
- * @return &gt;= 0; the write size
- */
- private static int writeSize(List<? extends OffsettedItem> items) {
- /*
- * This class assumes all included items are the same size,
- * an assumption which is verified in place0().
- */
- OffsettedItem first = items.get(0);
- return (items.size() * first.writeSize()) + getAlignment(items);
- }
-
- /** {@inheritDoc} */
- @Override
- public ItemType itemType() {
- return itemType;
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer(100);
-
- sb.append(getClass().getName());
- sb.append(items);
-
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- @Override
- public void addContents(DexFile file) {
- for (OffsettedItem i : items) {
- i.addContents(file);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public final String toHuman() {
- StringBuffer sb = new StringBuffer(100);
- boolean first = true;
-
- sb.append("{");
-
- for (OffsettedItem i : items) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(i.toHuman());
- }
-
- sb.append("}");
- return sb.toString();
- }
-
- /**
- * Gets the underlying list of items.
- *
- * @return non-null; the list
- */
- public final List<T> getItems() {
- return items;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void place0(Section addedTo, int offset) {
- offset += headerSize();
-
- boolean first = true;
- int theSize = -1;
- int theAlignment = -1;
-
- for (OffsettedItem i : items) {
- int size = i.writeSize();
- if (first) {
- theSize = size;
- theAlignment = i.getAlignment();
- first = false;
- } else {
- if (size != theSize) {
- throw new UnsupportedOperationException(
- "item size mismatch");
- }
- if (i.getAlignment() != theAlignment) {
- throw new UnsupportedOperationException(
- "item alignment mismatch");
- }
- }
-
- offset = i.place(addedTo, offset) + size;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void writeTo0(DexFile file, AnnotatedOutput out) {
- int size = items.size();
-
- if (out.annotates()) {
- out.annotate(0, offsetString() + " " + typeName());
- out.annotate(4, " size: " + Hex.u4(size));
- }
-
- out.writeInt(size);
-
- for (OffsettedItem i : items) {
- i.writeTo(file, out);
- }
- }
-
- /**
- * Get the size of the header of this list.
- *
- * @return &gt;= 0; the header size
- */
- private int headerSize() {
- /*
- * Because of how this instance was set up, this is the same
- * as the alignment.
- */
- return getAlignment();
- }
-}
diff --git a/dx/src/com/android/dx/dex/file/ValueEncoder.java b/dx/src/com/android/dx/dex/file/ValueEncoder.java
deleted file mode 100644
index 02a34194f..000000000
--- a/dx/src/com/android/dx/dex/file/ValueEncoder.java
+++ /dev/null
@@ -1,532 +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.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.rop.annotation.NameValuePair;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstBoolean;
-import com.android.dx.rop.cst.CstByte;
-import com.android.dx.rop.cst.CstChar;
-import com.android.dx.rop.cst.CstDouble;
-import com.android.dx.rop.cst.CstEnumRef;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstFloat;
-import com.android.dx.rop.cst.CstInteger;
-import com.android.dx.rop.cst.CstKnownNull;
-import com.android.dx.rop.cst.CstLiteralBits;
-import com.android.dx.rop.cst.CstLong;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstShort;
-import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-
-/**
- * Handler for writing out <code>encoded_values</code> and parts
- * thereof.
- */
-public final class ValueEncoder {
- /** annotation value type constant: <code>byte</code> */
- private static final int VALUE_BYTE = 0x00;
-
- /** annotation value type constant: <code>short</code> */
- private static final int VALUE_SHORT = 0x02;
-
- /** annotation value type constant: <code>char</code> */
- private static final int VALUE_CHAR = 0x03;
-
- /** annotation value type constant: <code>int</code> */
- private static final int VALUE_INT = 0x04;
-
- /** annotation value type constant: <code>long</code> */
- private static final int VALUE_LONG = 0x06;
-
- /** annotation value type constant: <code>float</code> */
- private static final int VALUE_FLOAT = 0x10;
-
- /** annotation value type constant: <code>double</code> */
- private static final int VALUE_DOUBLE = 0x11;
-
- /** annotation value type constant: <code>string</code> */
- private static final int VALUE_STRING = 0x17;
-
- /** annotation value type constant: <code>type</code> */
- private static final int VALUE_TYPE = 0x18;
-
- /** annotation value type constant: <code>field</code> */
- private static final int VALUE_FIELD = 0x19;
-
- /** annotation value type constant: <code>method</code> */
- private static final int VALUE_METHOD = 0x1a;
-
- /** annotation value type constant: <code>enum</code> */
- private static final int VALUE_ENUM = 0x1b;
-
- /** annotation value type constant: <code>array</code> */
- private static final int VALUE_ARRAY = 0x1c;
-
- /** annotation value type constant: <code>annotation</code> */
- private static final int VALUE_ANNOTATION = 0x1d;
-
- /** annotation value type constant: <code>null</code> */
- private static final int VALUE_NULL = 0x1e;
-
- /** annotation value type constant: <code>boolean</code> */
- private static final int VALUE_BOOLEAN = 0x1f;
-
- /** non-null; file being written */
- private final DexFile file;
-
- /** non-null; output stream to write to */
- private final AnnotatedOutput out;
-
- /**
- * Construct an instance.
- *
- * @param file non-null; file being written
- * @param out non-null; output stream to write to
- */
- public ValueEncoder(DexFile file, AnnotatedOutput out) {
- if (file == null) {
- throw new NullPointerException("file == null");
- }
-
- if (out == null) {
- throw new NullPointerException("out == null");
- }
-
- this.file = file;
- this.out = out;
- }
-
- /**
- * Writes out the encoded form of the given constant.
- *
- * @param cst non-null; the constant to write
- */
- public void writeConstant(Constant cst) {
- int type = constantToValueType(cst);
- int arg;
-
- switch (type) {
- case VALUE_BYTE:
- case VALUE_SHORT:
- case VALUE_INT:
- case VALUE_LONG: {
- long value = ((CstLiteralBits) cst).getLongBits();
- writeSignedIntegralValue(type, value);
- break;
- }
- case VALUE_CHAR: {
- long value = ((CstLiteralBits) cst).getLongBits();
- writeUnsignedIntegralValue(type, value);
- break;
- }
- case VALUE_FLOAT: {
- // Shift value left 32 so that right-zero-extension works.
- long value = ((CstFloat) cst).getLongBits() << 32;
- writeRightZeroExtendedValue(type, value);
- break;
- }
- case VALUE_DOUBLE: {
- long value = ((CstDouble) cst).getLongBits();
- writeRightZeroExtendedValue(type, value);
- break;
- }
- case VALUE_STRING: {
- int index = file.getStringIds().indexOf((CstString) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_TYPE: {
- int index = file.getTypeIds().indexOf((CstType) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_FIELD: {
- int index = file.getFieldIds().indexOf((CstFieldRef) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_METHOD: {
- int index = file.getMethodIds().indexOf((CstMethodRef) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_ENUM: {
- CstFieldRef fieldRef = ((CstEnumRef) cst).getFieldRef();
- int index = file.getFieldIds().indexOf(fieldRef);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_ARRAY: {
- out.writeByte(type);
- writeArray((CstArray) cst, false);
- break;
- }
- case VALUE_ANNOTATION: {
- out.writeByte(type);
- writeAnnotation(((CstAnnotation) cst).getAnnotation(),
- false);
- break;
- }
- case VALUE_NULL: {
- out.writeByte(type);
- break;
- }
- case VALUE_BOOLEAN: {
- int value = ((CstBoolean) cst).getIntBits();
- out.writeByte(type | (value << 5));
- break;
- }
- default: {
- throw new RuntimeException("Shouldn't happen");
- }
- }
- }
-
- /**
- * Gets the value type for the given constant.
- *
- * @param cst non-null; the constant
- * @return the value type; one of the <code>VALUE_*</code> constants
- * defined by this class
- */
- private static int constantToValueType(Constant cst) {
- /*
- * TODO: Constant should probable have an associated enum, so this
- * can be a switch().
- */
- if (cst instanceof CstByte) {
- return VALUE_BYTE;
- } else if (cst instanceof CstShort) {
- return VALUE_SHORT;
- } else if (cst instanceof CstChar) {
- return VALUE_CHAR;
- } else if (cst instanceof CstInteger) {
- return VALUE_INT;
- } else if (cst instanceof CstLong) {
- return VALUE_LONG;
- } else if (cst instanceof CstFloat) {
- return VALUE_FLOAT;
- } else if (cst instanceof CstDouble) {
- return VALUE_DOUBLE;
- } else if (cst instanceof CstString) {
- return VALUE_STRING;
- } else if (cst instanceof CstType) {
- return VALUE_TYPE;
- } else if (cst instanceof CstFieldRef) {
- return VALUE_FIELD;
- } else if (cst instanceof CstMethodRef) {
- return VALUE_METHOD;
- } else if (cst instanceof CstEnumRef) {
- return VALUE_ENUM;
- } else if (cst instanceof CstArray) {
- return VALUE_ARRAY;
- } else if (cst instanceof CstAnnotation) {
- return VALUE_ANNOTATION;
- } else if (cst instanceof CstKnownNull) {
- return VALUE_NULL;
- } else if (cst instanceof CstBoolean) {
- return VALUE_BOOLEAN;
- } else {
- throw new RuntimeException("Shouldn't happen");
- }
- }
-
- /**
- * Writes out the encoded form of the given array, that is, as
- * an <code>encoded_array</code> and not including a
- * <code>value_type</code> prefix. If the output stream keeps
- * (debugging) annotations and <code>topLevel</code> is
- * <code>true</code>, then this method will write (debugging)
- * annotations.
- *
- * @param array non-null; array instance to write
- * @param topLevel <code>true</code> iff the given annotation is the
- * top-level annotation or <code>false</code> if it is a sub-annotation
- * of some other annotation
- */
- public void writeArray(CstArray array, boolean topLevel) {
- boolean annotates = topLevel && out.annotates();
- CstArray.List list = ((CstArray) array).getList();
- int size = list.size();
-
- if (annotates) {
- out.annotate(" size: " + Hex.u4(size));
- }
-
- out.writeUnsignedLeb128(size);
-
- for (int i = 0; i < size; i++) {
- Constant cst = list.get(i);
- if (annotates) {
- out.annotate(" [" + Integer.toHexString(i) + "] " +
- constantToHuman(cst));
- }
- writeConstant(cst);
- }
-
- if (annotates) {
- out.endAnnotation();
- }
- }
-
- /**
- * Writes out the encoded form of the given annotation, that is,
- * as an <code>encoded_annotation</code> and not including a
- * <code>value_type</code> prefix. If the output stream keeps
- * (debugging) annotations and <code>topLevel</code> is
- * <code>true</code>, then this method will write (debugging)
- * annotations.
- *
- * @param annotation non-null; annotation instance to write
- * @param topLevel <code>true</code> iff the given annotation is the
- * top-level annotation or <code>false</code> if it is a sub-annotation
- * of some other annotation
- */
- public void writeAnnotation(Annotation annotation, boolean topLevel) {
- boolean annotates = topLevel && out.annotates();
- StringIdsSection stringIds = file.getStringIds();
- TypeIdsSection typeIds = file.getTypeIds();
-
- CstType type = annotation.getType();
- int typeIdx = typeIds.indexOf(type);
-
- if (annotates) {
- out.annotate(" type_idx: " + Hex.u4(typeIdx) + " // " +
- type.toHuman());
- }
-
- out.writeUnsignedLeb128(typeIds.indexOf(annotation.getType()));
-
- Collection<NameValuePair> pairs = annotation.getNameValuePairs();
- int size = pairs.size();
-
- if (annotates) {
- out.annotate(" size: " + Hex.u4(size));
- }
-
- out.writeUnsignedLeb128(size);
-
- int at = 0;
- for (NameValuePair pair : pairs) {
- CstUtf8 name = pair.getName();
- int nameIdx = stringIds.indexOf(name);
- Constant value = pair.getValue();
-
- if (annotates) {
- out.annotate(0, " elements[" + at + "]:");
- at++;
- out.annotate(" name_idx: " + Hex.u4(nameIdx) + " // " +
- name.toHuman());
- }
-
- out.writeUnsignedLeb128(nameIdx);
-
- if (annotates) {
- out.annotate(" value: " + constantToHuman(value));
- }
-
- writeConstant(value);
- }
-
- if (annotates) {
- out.endAnnotation();
- }
- }
-
- /**
- * Gets the colloquial type name and human form of the type of the
- * given constant, when used as an encoded value.
- *
- * @param cst non-null; the constant
- * @return non-null; its type name and human form
- */
- public static String constantToHuman(Constant cst) {
- int type = constantToValueType(cst);
-
- if (type == VALUE_NULL) {
- return "null";
- }
-
- StringBuilder sb = new StringBuilder();
-
- sb.append(cst.typeName());
- sb.append(' ');
- sb.append(cst.toHuman());
-
- return sb.toString();
- }
-
- /**
- * Helper for {@link #writeConstant}, which writes out the value
- * for any signed integral type.
- *
- * @param type the type constant
- * @param value <code>long</code> bits of the value
- */
- private void writeSignedIntegralValue(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--;
- }
- }
-
- /**
- * Helper for {@link #writeConstant}, which writes out the value
- * for any unsigned integral type.
- *
- * @param type the type constant
- * @param value <code>long</code> bits of the value
- */
- private void writeUnsignedIntegralValue(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--;
- }
- }
-
- /**
- * Helper for {@link #writeConstant}, which writes out a
- * right-zero-extended value.
- *
- * @param type the type constant
- * @param value <code>long</code> bits of the value
- */
- private void writeRightZeroExtendedValue(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--;
- }
- }
-
-
- /**
- * Helper for <code>addContents()</code> methods, which adds
- * contents for a particular {@link Annotation}, calling itself
- * recursively should it encounter a nested annotation.
- *
- * @param file non-null; the file to add to
- * @param annotation non-null; the annotation to add contents for
- */
- public static void addContents(DexFile file, Annotation annotation) {
- TypeIdsSection typeIds = file.getTypeIds();
- StringIdsSection stringIds = file.getStringIds();
-
- typeIds.intern(annotation.getType());
-
- for (NameValuePair pair : annotation.getNameValuePairs()) {
- stringIds.intern(pair.getName());
- addContents(file, pair.getValue());
- }
- }
-
- /**
- * Helper for <code>addContents()</code> methods, which adds
- * contents for a particular constant, calling itself recursively
- * should it encounter a {@link CstArray} and calling {@link
- * #addContents(DexFile,Annotation)} recursively should it
- * encounter a {@link CstAnnotation}.
- *
- * @param file non-null; the file to add to
- * @param cst non-null; the constant to add contents for
- */
- public static void addContents(DexFile file, Constant cst) {
- TypeIdsSection typeIds = file.getTypeIds();
- StringIdsSection stringIds = file.getStringIds();
-
- if (cst instanceof CstAnnotation) {
- addContents(file, ((CstAnnotation) cst).getAnnotation());
- } else if (cst instanceof CstArray) {
- CstArray.List list = ((CstArray) cst).getList();
- int size = list.size();
- for (int i = 0; i < size; i++) {
- addContents(file, list.get(i));
- }
- } else {
- file.internIfAppropriate(cst);
- }
- }
-}