From 4d68e05fb5e3262c58bc9896befe910698daa6a8 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Fri, 21 Aug 2009 02:50:07 +0000 Subject: [PATCH] Changes to dump annotation format git-svn-id: https://smali.googlecode.com/svn/trunk@398 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- .../jf/dexlib/AnnotationDirectoryItem.java | 44 +++- .../java/org/jf/dexlib/AnnotationItem.java | 3 +- .../java/org/jf/dexlib/AnnotationSetItem.java | 7 +- .../org/jf/dexlib/AnnotationSetRefList.java | 5 +- .../java/org/jf/dexlib/ClassDataItem.java | 45 +++- .../main/java/org/jf/dexlib/ClassDefItem.java | 21 +- .../src/main/java/org/jf/dexlib/CodeItem.java | 101 ++++++--- .../Debug/DebugInstructionIterator.java | 18 +- .../java/org/jf/dexlib/Debug/DebugOpcode.java | 2 +- .../java/org/jf/dexlib/DebugInfoItem.java | 211 +++++++++++++++++- .../src/main/java/org/jf/dexlib/DexFile.java | 8 + .../java/org/jf/dexlib/EncodedArrayItem.java | 3 - .../AnnotationEncodedSubValue.java | 9 + .../EncodedValue/AnnotationEncodedValue.java | 3 + .../EncodedValue/ArrayEncodedSubValue.java | 19 +- .../EncodedValue/ArrayEncodedValue.java | 3 + .../EncodedValue/BooleanEncodedValue.java | 3 + .../dexlib/EncodedValue/ByteEncodedValue.java | 6 +- .../dexlib/EncodedValue/CharEncodedValue.java | 8 + .../EncodedValue/DoubleEncodedValue.java | 6 + .../dexlib/EncodedValue/EnumEncodedValue.java | 6 + .../EncodedValue/FieldEncodedValue.java | 6 + .../EncodedValue/FloatEncodedValue.java | 6 + .../dexlib/EncodedValue/IntEncodedValue.java | 6 + .../dexlib/EncodedValue/LongEncodedValue.java | 6 + .../EncodedValue/MethodEncodedValue.java | 6 + .../dexlib/EncodedValue/NullEncodedValue.java | 3 + .../EncodedValue/ShortEncodedValue.java | 6 + .../EncodedValue/StringEncodedValue.java | 7 + .../dexlib/EncodedValue/TypeEncodedValue.java | 6 + .../main/java/org/jf/dexlib/FieldIdItem.java | 27 ++- .../src/main/java/org/jf/dexlib/MapItem.java | 16 +- .../main/java/org/jf/dexlib/MethodIdItem.java | 19 +- .../main/java/org/jf/dexlib/ProtoIdItem.java | 4 +- .../java/org/jf/dexlib/StringDataItem.java | 13 +- .../main/java/org/jf/dexlib/TypeListItem.java | 52 ++--- .../java/org/jf/dexlib/Util/AccessFlags.java | 70 +++++- .../org/jf/dexlib/Util/ReadOnlyArrayList.java | 48 ++++ 38 files changed, 697 insertions(+), 135 deletions(-) create mode 100644 dexlib/src/main/java/org/jf/dexlib/Util/ReadOnlyArrayList.java diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java index fa40c6a2..f57d107a 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java @@ -177,25 +177,49 @@ public class AnnotationDirectoryItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(4, "class_annotations_off"); - out.annotate(4, "annotated_fields_size"); - out.annotate(4, "annotated_methods_size"); - out.annotate(4, "annotated_parameters_size"); + if (!isInternable() && parent != null) { + out.annotate(0, parent.getClassType().getTypeDescriptor()); + } + if (classAnnotations != null) { + out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset())); + } else { + out.annotate(4, "class_annotations_off:"); + } + + out.annotate(4, "annotated_fields_size: 0x" + Integer.toHexString(fieldAnnotations.length) + " (" + + fieldAnnotations.length + ")"); + out.annotate(4, "annotated_methods_size: 0x" + Integer.toHexString(methodAnnotations.length) + " (" + + methodAnnotations.length + ")"); + out.annotate(4, "annotated_parameters_size: 0x" + Integer.toHexString(parameterAnnotations.length) + " (" + + parameterAnnotations.length + ")"); + int index = 0; for (int i=0; i { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate("visibility"); + out.annotate("visibility: " + visibility.name()); out.writeByte(visibility.value); - out.annotate("annotation"); annotationValue.writeValue(out); }else { out.writeByte(visibility.value); diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java index 33a17a99..6bb94538 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java @@ -84,9 +84,10 @@ public class AnnotationSetItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(4, "size"); - for (int i=0; i { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(4, "size"); + out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length + + ")"); for (AnnotationSetItem annotationSetItem: annotationSets) { - out.annotate(4, "annotation_set_off"); + out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset())); } } out.writeInt(annotationSets.length); diff --git a/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java b/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java index 0d4b521c..b7ee53b1 100644 --- a/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java @@ -147,36 +147,56 @@ public class ClassDataItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate("static_fields_size"); + out.annotate("static_fields_size: 0x" + Integer.toHexString(staticFields.length) + " (" + + staticFields.length + ")"); out.writeUnsignedLeb128(staticFields.length); - out.annotate("instance_fields_size"); + out.annotate("instance_fields_size: 0x" + Integer.toHexString(instanceFields.length) + " (" + + instanceFields.length + ")"); out.writeUnsignedLeb128(instanceFields.length); - out.annotate("direct_methods_size"); + out.annotate("direct_methods_size: 0x" + Integer.toHexString(directMethods.length) + " (" + + directMethods.length + ")"); out.writeUnsignedLeb128(directMethods.length); - out.annotate("virtual_methods_size"); + out.annotate("virtual_methods_size: 0x" + Integer.toHexString(virtualMethods.length) + " (" + + virtualMethods.length + ")"); out.writeUnsignedLeb128(virtualMethods.length); + int index = 0; EncodedField previousEncodedField = null; for (EncodedField encodedField: staticFields) { + out.annotate("[" + index++ + "] static_field"); + out.indent(); encodedField.writeTo(out, previousEncodedField); + out.deindent(); previousEncodedField = encodedField; } + index = 0; previousEncodedField = null; for (EncodedField encodedField: instanceFields) { + out.annotate("[" + index++ + "] instance_field"); + out.indent(); encodedField.writeTo(out, previousEncodedField); + out.deindent(); previousEncodedField = encodedField; } + index = 0; EncodedMethod previousEncodedMethod = null; for (EncodedMethod encodedMethod: directMethods) { + out.annotate("[" + index++ + "] direct_method"); + out.indent(); encodedMethod.writeTo(out, previousEncodedMethod); + out.deindent(); previousEncodedMethod = encodedMethod; } + index = 0; previousEncodedMethod = null; for (EncodedMethod encodedMethod: virtualMethods) { + out.annotate("[" + index++ + "] virtual_method"); + out.indent(); encodedMethod.writeTo(out, previousEncodedMethod); + out.deindent(); previousEncodedMethod = encodedMethod; } } else { @@ -315,9 +335,9 @@ public class ClassDataItem extends Item { int previousIndex = previousEncodedField==null?0:previousEncodedField.field.getIndex(); if (out.annotates()) { - out.annotate("field_idx_diff"); + out.annotate("field: " + field.getFieldString()); out.writeUnsignedLeb128(field.getIndex() - previousIndex); - out.annotate("access_flags"); + out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForField(accessFlags)); out.writeUnsignedLeb128(accessFlags); }else { out.writeUnsignedLeb128(field.getIndex() - previousIndex); @@ -422,12 +442,17 @@ public class ClassDataItem extends Item { int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex(); if (out.annotates()) { - out.annotate("method_idx_diff"); + out.annotate("method: " + method.getMethodString()); out.writeUnsignedLeb128(method.getIndex() - previousIndex); - out.annotate("access_flags"); + out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForMethod(accessFlags)); out.writeUnsignedLeb128(accessFlags); - out.annotate("code_off"); - out.writeUnsignedLeb128(codeItem==null?0:codeItem.getOffset()); + if (codeItem != null) { + out.annotate("code_off: 0x" + codeItem.getOffset()); + out.writeUnsignedLeb128(codeItem.getOffset()); + } else { + out.annotate("code_off: 0x0"); + out.writeUnsignedLeb128(0); + } }else { out.writeUnsignedLeb128(method.getIndex() - previousIndex); out.writeUnsignedLeb128(accessFlags); diff --git a/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java b/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java index 77930bb4..4423a864 100644 --- a/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java @@ -30,6 +30,7 @@ package org.jf.dexlib; import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.AnnotatedOutput; +import org.jf.dexlib.Util.AccessFlags; import java.util.*; @@ -139,14 +140,18 @@ public class ClassDefItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(4, "class_idx"); - out.annotate(4, "access_flags"); - out.annotate(4, "superclass_idx"); - out.annotate(4, "interfaces_off"); - out.annotate(4, "source_file_idx"); - out.annotate(4, "annotations_off"); - out.annotate(4, "class_data_off"); - out.annotate(4, "static_values_off"); + out.annotate(4, "class_type: " + classType.getTypeDescriptor()); + out.annotate(4, "access_flags: " + AccessFlags.formatAccessFlagsForClass(accessFlags)); + out.annotate(4, "superclass_type: " + (superType==null?"":superType.getTypeDescriptor())); + out.annotate(4, "interfaces: " + + (implementedInterfaces==null?"":implementedInterfaces.getTypeListString(" "))); + out.annotate(4, "source_file: " + (sourceFile==null?"":sourceFile.getStringValue())); + out.annotate(4, "annotations_off: " + + (annotations==null?"":"0x"+Integer.toHexString(annotations.getOffset()))); + out.annotate(4, "class_data_off:" + + (classData==null?"":"0x"+Integer.toHexString(classData.getOffset()))); + out.annotate(4, "static_values_off: " + + (staticFieldInitializers==null?"":"0x"+Integer.toHexString(staticFieldInitializers.getOffset()))); } out.writeInt(classType.getIndex()); out.writeInt(accessFlags); diff --git a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java index 9ad1e218..c0b6d0c1 100644 --- a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java @@ -186,33 +186,46 @@ public class CodeItem extends Item { /** {@inheritDoc} */ protected void writeItem(final AnnotatedOutput out) { if (out.annotates()) { - out.annotate(2, "registers_size"); - out.annotate(2, "ins_size"); - out.annotate(2, "outs_size"); - out.annotate(2, "tries_size"); - out.annotate(4, "debug_info_off"); - out.annotate(4, "insns_size"); + out.annotate(0, parent.method.getMethodString()); + out.annotate(2, "registers_size: 0x" + Integer.toHexString(registerCount) + " (" + registerCount + ")"); + out.annotate(2, "ins_size: 0x" + Integer.toHexString(inWords) + " (" + inWords + ")"); + out.annotate(2, "outs_size: 0x" + Integer.toHexString(outWords) + " (" + outWords + ")"); + int triesLength = tries==null?0:tries.length; + out.annotate(2, "tries_size: 0x" + Integer.toHexString(triesLength) + " (" + triesLength + ")"); + if (debugInfo == null) { + out.annotate(4, "debug_info_off:"); + } else { + out.annotate(4, "debug_info_off: 0x" + debugInfo.getOffset()); + } + out.annotate(4, "insns_size: 0x" + Integer.toHexString(encodedInstructions.length / 2) + " (" + + (encodedInstructions.length / 2) + ")"); InstructionIterator.IterateInstructions(encodedInstructions, new InstructionIterator.ProcessRawInstructionDelegate() { public void ProcessNormalInstruction(Opcode opcode, int index) { - out.annotate(opcode.format.size, opcode.name + " instruction"); + out.annotate(opcode.format.size, "[0x" + Integer.toHexString(index/2) + "] " + opcode.name + + " instruction"); } public void ProcessReferenceInstruction(Opcode opcode, int index) { - out.annotate(opcode.format.size, opcode.name + " instruction"); + out.annotate(opcode.format.size, "[0x" + Integer.toHexString(index/2) + "] " + opcode.name + + " instruction"); } public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength) { - out.annotate(instructionLength, "packed_switch instruction"); + out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " + + "packed_switch instruction"); } public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength) { - out.annotate(instructionLength, "sparse_switch instruction"); + out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " + + "sparse_switch instruction"); } - public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount, int instructionLength) { - out.annotate(instructionLength, "fill_array_data instruction"); + public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount, + int instructionLength) { + out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " + + "fill_array_data instruction"); } }); if (tries != null && (tries.length % 2 == 1)) { @@ -237,18 +250,45 @@ public class CodeItem extends Item { InstructionWriter.writeInstructions(encodedInstructions, referencedItems, out); if (tries != null && tries.length > 0) { - if ((encodedInstructions.length % 4) != 0) { - out.writeShort(0); - } + if (out.annotates()) { + if ((encodedInstructions.length % 4) != 0) { + out.annotate("padding"); + out.writeShort(0); + } - for (TryItem tryItem: tries) { - tryItem.writeTo(out); - } + int index = 0; + for (TryItem tryItem: tries) { + out.annotate(0, "[0x" + Integer.toHexString(index++) + "] try_item"); + out.indent(); + tryItem.writeTo(out); + out.deindent(); + } - out.writeUnsignedLeb128(encodedCatchHandlers.length); + out.annotate("handler_count: 0x" + Integer.toHexString(encodedCatchHandlers.length) + "(" + + encodedCatchHandlers.length + ")"); + out.writeUnsignedLeb128(encodedCatchHandlers.length); - for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) { - encodedCatchHandler.writeTo(out); + index = 0; + for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) { + out.annotate(0, "[" + Integer.toHexString(index++) + "] encoded_catch_handler"); + out.indent(); + encodedCatchHandler.writeTo(out); + out.deindent(); + } + } else { + if ((encodedInstructions.length % 4) != 0) { + out.writeShort(0); + } + + for (TryItem tryItem: tries) { + tryItem.writeTo(out); + } + + out.writeUnsignedLeb128(encodedCatchHandlers.length); + + for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) { + encodedCatchHandler.writeTo(out); + } } } } @@ -373,9 +413,10 @@ public class CodeItem extends Item { */ private void writeTo(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(4, "start_addr"); - out.annotate(2, "insn_count"); - out.annotate(2, "handler_off"); + out.annotate(4, "start_addr: 0x" + Integer.toHexString(startAddress)); + out.annotate(2, "insn_count: 0x" + Integer.toHexString(instructionCount) + " (" + instructionCount + + ")"); + out.annotate(2, "handler_off: 0x" + Integer.toHexString(encodedCatchHandler.getOffsetInList())); } out.writeInt(startAddress); @@ -476,7 +517,7 @@ public class CodeItem extends Item { */ private void writeTo(AnnotatedOutput out) { if (out.annotates()) { - out.annotate("size"); + out.annotate("size: 0x" + Integer.toHexString(handlers.length) + " (" + handlers.length + ")"); int size = handlers.length; if (catchAllHandlerAddress < 0) { @@ -484,12 +525,16 @@ public class CodeItem extends Item { } out.writeSignedLeb128(size); + int index = 0; for (EncodedTypeAddrPair handler: handlers) { + out.annotate(0, "[" + index++ + "] encoded_type_addr_pair"); + out.indent(); handler.writeTo(out); + out.deindent(); } if (catchAllHandlerAddress > -1) { - out.annotate("catch_all_addr"); + out.annotate("catch_all_addr: 0x" + Integer.toHexString(catchAllHandlerAddress)); out.writeUnsignedLeb128(catchAllHandlerAddress); } } else { @@ -556,10 +601,10 @@ public class CodeItem extends Item { */ private void writeTo(AnnotatedOutput out) { if (out.annotates()) { - out.annotate("type_idx"); + out.annotate("exception_type: " + exceptionType.getTypeDescriptor()); out.writeUnsignedLeb128(exceptionType.getIndex()); - out.annotate("addr"); + out.annotate("handler_addr: 0x" + Integer.toHexString(handlerAddress)); out.writeUnsignedLeb128(handlerAddress); } else { out.writeUnsignedLeb128(exceptionType.getIndex()); diff --git a/dexlib/src/main/java/org/jf/dexlib/Debug/DebugInstructionIterator.java b/dexlib/src/main/java/org/jf/dexlib/Debug/DebugInstructionIterator.java index a9085dfc..c401ce3d 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Debug/DebugInstructionIterator.java +++ b/dexlib/src/main/java/org/jf/dexlib/Debug/DebugInstructionIterator.java @@ -266,15 +266,15 @@ public class DebugInstructionIterator { { //TODO: add javadocs public void ProcessEndSequence(int startOffset) { - ProcessStaticOpcode(startOffset, 1); + ProcessStaticOpcode(DebugOpcode.DBG_END_SEQUENCE, startOffset, 1); } public void ProcessAdvancePC(int startOffset, int length, int addressDiff) { - ProcessStaticOpcode(startOffset, length); + ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_PC, startOffset, length); } public void ProcessAdvanceLine(int startOffset, int length, int lineDiff) { - ProcessStaticOpcode(startOffset, length); + ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_LINE, startOffset, length); } public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex, int typeIndex, @@ -286,29 +286,29 @@ public class DebugInstructionIterator { } public void ProcessEndLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) { - ProcessStaticOpcode(startOffset, length); + ProcessStaticOpcode(DebugOpcode.DBG_END_LOCAL, startOffset, length); } public void ProcessRestartLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) { - ProcessStaticOpcode(startOffset, length); + ProcessStaticOpcode(DebugOpcode.DBG_RESTART_LOCAL, startOffset, length); } public void ProcessSetPrologueEnd(int startOffset) { - ProcessStaticOpcode(startOffset, 1); + ProcessStaticOpcode(DebugOpcode.DBG_SET_PROLOGUE_END, startOffset, 1); } public void ProcessSetEpilogueBegin(int startOffset) { - ProcessStaticOpcode(startOffset, 1); + ProcessStaticOpcode(DebugOpcode.DBG_SET_EPILOGUE_BEGIN, startOffset, 1); } public void ProcessSetFile(int startOffset, int length, int nameIndex) { } public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDiff, int addressDiff) { - ProcessStaticOpcode(startOffset, 1); + ProcessStaticOpcode(DebugOpcode.DBG_SPECIAL_OPCODE, startOffset, 1); } - public void ProcessStaticOpcode(int startOffset, int length) { + public void ProcessStaticOpcode(DebugOpcode debugOpcode, int startOffset, int length) { } } diff --git a/dexlib/src/main/java/org/jf/dexlib/Debug/DebugOpcode.java b/dexlib/src/main/java/org/jf/dexlib/Debug/DebugOpcode.java index c11e7f9b..5f41eea9 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Debug/DebugOpcode.java +++ b/dexlib/src/main/java/org/jf/dexlib/Debug/DebugOpcode.java @@ -37,7 +37,7 @@ public enum DebugOpcode { DBG_END_LOCAL((byte)0x05), DBG_RESTART_LOCAL((byte)0x06), DBG_SET_PROLOGUE_END((byte)0x07), - DBG_SET_EPILOGUE_END((byte)0x08), + DBG_SET_EPILOGUE_BEGIN((byte)0x08), DBG_SET_FILE((byte)0x09), DBG_SPECIAL_OPCODE((byte)0x0A); diff --git a/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java b/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java index 967955f0..4e28277f 100644 --- a/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java @@ -187,7 +187,7 @@ public class DebugInfoItem extends Item { private int referencedItemsPosition = 0; @Override - public void ProcessStaticOpcode(int startOffset, int length) { + public void ProcessStaticOpcode(DebugOpcode opcode, int startOffset, int length) { this.length+=length; } @@ -261,6 +261,19 @@ public class DebugInfoItem extends Item { /** {@inheritDoc} */ protected void writeItem(final AnnotatedOutput out) { + + if (out.annotates()) { + writeItemWithAnnotations(out); + } else { + writeItemWithNoAnnotations(out); + } + } + + /** + * Helper method that writes the item, without writing annotations + * @param out the AnnotatedOutput object + */ + private void writeItemWithNoAnnotations(final AnnotatedOutput out) { out.writeUnsignedLeb128(lineStart); out.writeUnsignedLeb128(parameterNames.length); for (StringIdItem parameterName: parameterNames) { @@ -278,7 +291,7 @@ public class DebugInfoItem extends Item { private int referencedItemsPosition = 0; @Override - public void ProcessStaticOpcode(int startOffset, int length) { + public void ProcessStaticOpcode(DebugOpcode opcode, int startOffset, int length) { out.write(encodedDebugInfo, startOffset, length); } @@ -342,6 +355,200 @@ public class DebugInfoItem extends Item { }); } + /** + * Helper method that writes and annotates the item + * @param out the AnnotatedOutput object + */ + private void writeItemWithAnnotations(final AnnotatedOutput out) { + out.annotate(0, parent.getParent().method.getMethodString()); + out.annotate("line_start: 0x" + Integer.toHexString(lineStart) + " (" + lineStart + ")"); + out.writeUnsignedLeb128(lineStart); + out.annotate("parameters_size: 0x" + Integer.toHexString(parameterNames.length) + " (" + parameterNames.length + + ")"); + out.writeUnsignedLeb128(parameterNames.length); + int index = 0; + for (StringIdItem parameterName: parameterNames) { + int indexp1; + if (parameterName == null) { + out.annotate("[" + index++ +"] parameterName: "); + indexp1 = 0; + } else { + out.annotate("[" + index++ +"] parameterName: " + parameterName.getStringValue()); + indexp1 = parameterName.getIndex() + 1; + } + out.writeUnsignedLeb128(indexp1); + } + + DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo), + new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() { + private int referencedItemsPosition = 0; + + @Override + public void ProcessEndSequence(int startOffset) { + out.annotate("DBG_END_SEQUENCE"); + out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value); + } + + @Override + public void ProcessAdvancePC(int startOffset, int length, int addressDiff) { + out.annotate("DBG_ADVANCE_PC"); + out.writeByte(DebugOpcode.DBG_ADVANCE_PC.value); + out.indent(); + out.annotate("addr_diff: 0x" + Integer.toHexString(addressDiff) + " (" + addressDiff + ")"); + out.writeUnsignedLeb128(addressDiff); + out.deindent(); + } + + @Override + public void ProcessAdvanceLine(int startOffset, int length, int lineDiff) { + out.annotate("DBG_ADVANCE_LINE"); + out.writeByte(DebugOpcode.DBG_ADVANCE_LINE.value); + out.indent(); + out.annotate("line_diff: 0x" + Integer.toHexString(lineDiff) + " (" + lineDiff + ")"); + out.writeSignedLeb128(lineDiff); + out.deindent(); + } + + @Override + public void ProcessStartLocal(int startOffset, int length, int registerNum, int nameIndex, + int typeIndex, boolean registerIsSigned) { + out.annotate("DBG_START_LOCAL"); + out.writeByte(DebugOpcode.DBG_START_LOCAL.value); + out.indent(); + out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); + if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { + out.writeSignedLeb128(registerNum); + } else { + out.writeUnsignedLeb128(registerNum); + } + if (nameIndex != -1) { + Item nameItem = referencedItems[referencedItemsPosition++]; + assert nameItem instanceof StringIdItem; + out.annotate("name: " + ((StringIdItem)nameItem).getStringValue()); + out.writeUnsignedLeb128(nameItem.getIndex() + 1); + } else { + out.annotate("name: "); + out.writeByte(0); + } + if (typeIndex != -1) { + Item typeItem = referencedItems[referencedItemsPosition++]; + assert typeItem instanceof TypeIdItem; + out.annotate("type: " + ((TypeIdItem)typeItem).getTypeDescriptor()); + out.writeUnsignedLeb128(typeItem.getIndex() + 1); + } else { + out.annotate("type: "); + out.writeByte(0); + } + out.deindent(); + } + + @Override + public void ProcessStartLocalExtended(int startOffset, int length, int registerNum, int nameIndex, + int typeIndex, int signatureIndex, + boolean registerIsSigned) { + out.annotate("DBG_START_LOCAL_EXTENDED"); + out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value); + out.indent(); + out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); + if (dexFile.getPreserveSignedRegisters() && registerIsSigned) { + out.writeSignedLeb128(registerNum); + } else { + out.writeUnsignedLeb128(registerNum); + } + if (nameIndex != -1) { + Item nameItem = referencedItems[referencedItemsPosition++]; + assert nameItem instanceof StringIdItem; + out.annotate("name: " + ((StringIdItem)nameItem).getStringValue()); + out.writeUnsignedLeb128(nameItem.getIndex() + 1); + } else { + out.annotate("name: "); + out.writeByte(0); + } + if (typeIndex != -1) { + Item typeItem = referencedItems[referencedItemsPosition++]; + assert typeItem instanceof TypeIdItem; + out.annotate("type: " + ((TypeIdItem)typeItem).getTypeDescriptor()); + out.writeUnsignedLeb128(typeItem.getIndex() + 1); + } else { + out.annotate("type: "); + out.writeByte(0); + } + if (signatureIndex != -1) { + Item signatureItem = referencedItems[referencedItemsPosition++]; + assert signatureItem instanceof StringIdItem; + out.annotate("signature: " + ((StringIdItem)signatureItem).getStringValue()); + out.writeUnsignedLeb128(signatureItem.getIndex() + 1); + } else { + out.annotate("signature: "); + out.writeByte(0); + } + out.deindent(); + } + + @Override + public void ProcessEndLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) { + out.annotate("DBG_END_LOCAL"); + out.writeByte(DebugOpcode.DBG_END_LOCAL.value); + out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); + if (registerIsSigned) { + out.writeSignedLeb128(registerNum); + } else { + out.writeUnsignedLeb128(registerNum); + } + } + + @Override + public void ProcessRestartLocal(int startOffset, int length, int registerNum, boolean registerIsSigned) { + out.annotate("DBG_RESTART_LOCAL"); + out.writeByte(DebugOpcode.DBG_RESTART_LOCAL.value); + out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")"); + if (registerIsSigned) { + out.writeSignedLeb128(registerNum); + } else { + out.writeUnsignedLeb128(registerNum); + } + } + + @Override + public void ProcessSetPrologueEnd(int startOffset) { + out.annotate("DBG_SET_PROLOGUE_END"); + out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value); + } + + @Override + public void ProcessSetEpilogueBegin(int startOffset) { + out.annotate("DBG_SET_EPILOGUE_BEGIN"); + out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value); + } + + @Override + public void ProcessSetFile(int startOffset, int length, int nameIndex) { + out.annotate("DBG_SET_FILE"); + out.writeByte(DebugOpcode.DBG_SET_FILE.value); + if (nameIndex != -1) { + Item sourceItem = referencedItems[referencedItemsPosition++]; + assert sourceItem instanceof StringIdItem; + out.annotate("source_file: \"" + ((StringIdItem)sourceItem).getStringValue() + "\""); + out.writeUnsignedLeb128(sourceItem.getIndex() + 1); + } else { + out.annotate("source_file: "); + out.writeByte(0); + } + } + + @Override + public void ProcessSpecialOpcode(int startOffset, int debugOpcode, int lineDiff, int addressDiff) { + out.annotate("DBG_SPECIAL_OPCODE: line_diff=0x" + Integer.toHexString(lineDiff) + "(" + + lineDiff +"),addressDiff=0x" + Integer.toHexString(addressDiff) + "(" + addressDiff + + ")"); + out.writeByte(debugOpcode); + } + }); + } + + + + /** {@inheritDoc} */ public ItemType getItemType() { return ItemType.TYPE_DEBUG_INFO_ITEM; diff --git a/dexlib/src/main/java/org/jf/dexlib/DexFile.java b/dexlib/src/main/java/org/jf/dexlib/DexFile.java index ad44cd73..d7a73fd7 100644 --- a/dexlib/src/main/java/org/jf/dexlib/DexFile.java +++ b/dexlib/src/main/java/org/jf/dexlib/DexFile.java @@ -526,6 +526,8 @@ public class DexFile out.annotate(0, " "); HeaderItem.writeTo(out); + out.annotate(0, " "); + int sectionsPosition = 0; Section[] sections; if (this.inplace) { @@ -542,6 +544,12 @@ public class DexFile } out.alignTo(MapItem.getItemType().ItemAlignment); + + out.annotate(0, " "); + out.annotate(0, "-----------------------------"); + out.annotate(0, "map item"); + out.annotate(0, "-----------------------------"); + out.annotate(0, " "); MapItem.writeTo(out); } diff --git a/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java b/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java index e17c29b1..845b2494 100644 --- a/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java @@ -79,9 +79,6 @@ public class EncodedArrayItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { - if (out.annotates()) { - out.annotate("encoded_array"); - } encodedArray.writeValue(out); } diff --git a/dexlib/src/main/java/org/jf/dexlib/EncodedValue/AnnotationEncodedSubValue.java b/dexlib/src/main/java/org/jf/dexlib/EncodedValue/AnnotationEncodedSubValue.java index 2dd2133c..f35ff493 100644 --- a/dexlib/src/main/java/org/jf/dexlib/EncodedValue/AnnotationEncodedSubValue.java +++ b/dexlib/src/main/java/org/jf/dexlib/EncodedValue/AnnotationEncodedSubValue.java @@ -81,12 +81,21 @@ public class AnnotationEncodedSubValue extends EncodedValue { /** {@inheritDoc} */ public void writeValue(AnnotatedOutput out) { + out.annotate("annotation_type: " + annotationType.getTypeDescriptor()); out.writeUnsignedLeb128(annotationType.getIndex()); + out.annotate("element_count: 0x" + Integer.toHexString(names.length) + " (" + names.length + ")"); out.writeUnsignedLeb128(names.length); for (int i=0; i { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(2, classType.getConciseIdentity()); - out.annotate(2, fieldType.getConciseIdentity()); - out.annotate(4, fieldName.getConciseIdentity()); + out.annotate(2, "class_type: " + classType.getTypeDescriptor()); + out.annotate(2, "field_type: " + fieldType.getTypeDescriptor()); + out.annotate(4, "field_name: " + fieldName.getStringValue()); } out.writeShort(classType.getIndex()); @@ -157,6 +157,27 @@ public class FieldIdItem extends Item { return fieldName; } + String cachedFieldString = null; + /** + * @return a string formatted like LclassName;->fieldName:fieldType + */ + public String getFieldString() { + if (cachedFieldString == null) { + String typeDescriptor = classType.getTypeDescriptor(); + String fieldName = this.fieldName.getStringValue(); + String fieldType = this.fieldType.getTypeDescriptor(); + + StringBuffer sb = new StringBuffer(typeDescriptor.length() + fieldName.length() + fieldType.length() + 3); + sb.append(typeDescriptor); + sb.append("->"); + sb.append(fieldName); + sb.append(":"); + sb.append(fieldType); + cachedFieldString = sb.toString(); + } + return cachedFieldString; + } + /** * calculate and cache the hashcode */ diff --git a/dexlib/src/main/java/org/jf/dexlib/MapItem.java b/dexlib/src/main/java/org/jf/dexlib/MapItem.java index 7265f24c..32919bc2 100644 --- a/dexlib/src/main/java/org/jf/dexlib/MapItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/MapItem.java @@ -86,21 +86,31 @@ public class MapItem extends Item { protected void writeItem(AnnotatedOutput out) { Assert.assertTrue(getOffset() > 0); + int index = 0; + out.annotate(0, "[" + index++ + "]"); + out.indent(); writeSectionInfo(out, ItemType.TYPE_HEADER_ITEM, 1, 0); + out.deindent(); for (Section section: dexFile.getOrderedSections()) { + out.annotate(0, "[" + index++ + "]"); + out.indent(); writeSectionInfo(out, section.ItemType, section.getItems().size(), section.getOffset()); + out.deindent(); } + out.annotate(0, "[" + index++ + "]"); + out.indent(); writeSectionInfo(out, ItemType.TYPE_MAP_LIST, 1, dexFile.MapItem.getOffset()); + out.deindent(); } private void writeSectionInfo(AnnotatedOutput out, ItemType itemType, int sectionSize, int sectionOffset) { if (out.annotates()) { - out.annotate(2, "ItemType: " + itemType); + out.annotate(2, "item_type: " + itemType); out.annotate(2, "unused"); - out.annotate(4, "Section Size: " + sectionSize); - out.annotate(4, "Section Offset: " + Hex.u4(sectionOffset)); + out.annotate(4, "section_size: 0x" + Integer.toHexString(sectionSize) + " (" + sectionSize + ")"); + out.annotate(4, "section_off: 0x" + Integer.toHexString(sectionOffset)); } out.writeShort(itemType.MapValue); diff --git a/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java b/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java index 3da44067..8e934b5f 100644 --- a/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java @@ -91,9 +91,9 @@ public class MethodIdItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - out.annotate(2, classType.getConciseIdentity()); - out.annotate(2, methodPrototype.getConciseIdentity()); - out.annotate(4, methodName.getConciseIdentity()); + out.annotate(2, "class_type: " + classType.getTypeDescriptor()); + out.annotate(2, "method_prototype: " + methodPrototype.getPrototypeString()); + out.annotate(4, "method_name: " + methodName.getStringValue()); } out.writeShort(classType.getIndex()); @@ -132,8 +132,17 @@ public class MethodIdItem extends Item { */ public String getMethodString() { if (cachedMethodString == null) { - cachedMethodString = classType.getTypeDescriptor() + "->" + methodName.getStringValue() + - methodPrototype.getPrototypeString(); + String classType = this.classType.getTypeDescriptor(); + String methodName = this.methodName.getStringValue(); + String prototypeString = methodPrototype.getPrototypeString(); + + StringBuilder sb = new StringBuilder(classType.length() + methodName.length() + prototypeString.length() + + 2); + sb.append(classType); + sb.append("->"); + sb.append(methodName); + sb.append(prototypeString); + cachedMethodString = sb.toString(); } return cachedMethodString; } diff --git a/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java b/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java index fece37c3..6289dae6 100644 --- a/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java @@ -99,7 +99,7 @@ public class ProtoIdItem extends Item { if (parameters == null) { out.annotate(4, "parameters:"); } else { - out.annotate(4, "parameters: " + parameters.getTypeListString()); + out.annotate(4, "parameters: " + parameters.getTypeListString("")); } } @@ -145,7 +145,7 @@ public class ProtoIdItem extends Item { if (cachedPrototypeString == null) { StringBuilder sb = new StringBuilder("("); if (parameters != null) { - sb.append(parameters.getTypeListString()); + sb.append(parameters.getTypeListString("")); } sb.append(")"); sb.append(returnType.getTypeDescriptor()); diff --git a/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java b/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java index 032cdb30..5d794101 100644 --- a/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java @@ -83,11 +83,14 @@ public class StringDataItem extends Item { protected void writeItem(AnnotatedOutput out) { byte[] encodedValue = Utf8Utils.stringToUtf8Bytes(stringValue); if (out.annotates()) { - out.annotate(stringValue.length(), "string_size"); - out.annotate(encodedValue.length + 1, "string_data (" + Utf8Utils.escapeString(stringValue) + ")"); - } + out.annotate("string_size: 0x" + Integer.toHexString(stringValue.length()) + " (" + stringValue.length() + + ")"); + out.writeUnsignedLeb128(stringValue.length()); - out.writeUnsignedLeb128(stringValue.length()); + out.annotate(encodedValue.length + 1, "string_data: \"" + Utf8Utils.escapeString(stringValue) + "\""); + } else { + out.writeUnsignedLeb128(stringValue.length()); + } out.write(encodedValue); out.writeByte(0); } @@ -99,7 +102,7 @@ public class StringDataItem extends Item { /** {@inheritDoc} */ public String getConciseIdentity() { - return "string_data_item: " + Utf8Utils.escapeString(getStringValue()); + return "string_data_item: \"" + Utf8Utils.escapeString(getStringValue()) + "\""; } /** {@inheritDoc} */ diff --git a/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java b/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java index 9ded7807..b1f4db1a 100644 --- a/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java @@ -30,6 +30,7 @@ package org.jf.dexlib; import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.AnnotatedOutput; +import org.jf.dexlib.Util.ReadOnlyArrayList; import java.util.List; @@ -91,19 +92,15 @@ public class TypeListItem extends Item { //yes, the code to write the item is duplicated. This eliminates the need to iterate over the list twice if (out.annotates()) { - out.annotate(4, "size: " + typeList.length); - out.writeInt(typeList.length); + out.annotate(4, "size: 0x" + Integer.toHexString(typeList.length) + " (" + typeList.length +")"); for (TypeIdItem typeIdItem: typeList) { - out.annotate(2, typeIdItem.getConciseIdentity()); - out.writeShort(typeIdItem.getIndex()); + out.annotate(2, "type_id_item: " + typeIdItem.getTypeDescriptor()); } - } else { - - out.writeInt(typeList.length); - for (TypeIdItem typeIdItem: typeList) { - out.writeShort(typeIdItem.getIndex()); - } + } + out.writeInt(typeList.length); + for (TypeIdItem typeIdItem: typeList) { + out.writeShort(typeIdItem.getIndex()); } } @@ -114,7 +111,7 @@ public class TypeListItem extends Item { /** {@inheritDoc} */ public String getConciseIdentity() { - return "type_list: " + getTypeListString(); + return "type_list: " + getTypeListString(""); } /** {@inheritDoc} */ @@ -154,22 +151,27 @@ public class TypeListItem extends Item { return wordCount; } - private String cachedTypeListString = null; /** * @return a string consisting of the type descriptors in this TypeListItem - * that are directly concatenated together + * that are separated by the given separator + * @param separator the separator between each type */ - public String getTypeListString() { - - if (cachedTypeListString == null) { - StringBuilder sb = new StringBuilder(); - - for (TypeIdItem typeIdItem: typeList) { - sb.append(typeIdItem.getTypeDescriptor()); - } - cachedTypeListString = sb.toString(); + public String getTypeListString(String separator) { + int size = 0; + for (TypeIdItem typeIdItem: typeList) { + size += typeIdItem.getTypeDescriptor().length(); + size += separator.length(); } - return cachedTypeListString; + + StringBuilder sb = new StringBuilder(size); + for (TypeIdItem typeIdItem: typeList) { + sb.append(typeIdItem.getTypeDescriptor()); + sb.append(separator); + } + if (typeList.length > 0) { + sb.delete(sb.length() - separator.length(), sb.length()); + } + return sb.toString(); } /** @@ -202,8 +204,8 @@ public class TypeListItem extends Item { /** * @return an array of the TypeIdItems in this TypeListItem */ - public TypeIdItem[] getTypes() { - return typeList.clone(); + public List getTypes() { + return new ReadOnlyArrayList(typeList); } /** diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/AccessFlags.java b/dexlib/src/main/java/org/jf/dexlib/Util/AccessFlags.java index 5557497d..ab97a9a7 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Util/AccessFlags.java +++ b/dexlib/src/main/java/org/jf/dexlib/Util/AccessFlags.java @@ -78,39 +78,89 @@ public enum AccessFlags this.validForField = validForField; } - public static List getAccessFlagsForClass(int accessFlagValue) { - ArrayList accessFlags = new ArrayList(); - + public static AccessFlags[] getAccessFlagsForClass(int accessFlagValue) { + int size = 0; for (AccessFlags accessFlag: AccessFlags.values()) { if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) { - accessFlags.add(accessFlag); + size++; + } + } + + AccessFlags[] accessFlags = new AccessFlags[size]; + int accessFlagsPosition = 0; + for (AccessFlags accessFlag: AccessFlags.values()) { + if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) { + accessFlags[accessFlagsPosition++] = accessFlag; } } return accessFlags; } - public static List getAccessFlagsForMethod(int accessFlagValue) { - ArrayList accessFlags = new ArrayList(); + private static String formatAccessFlags(AccessFlags[] accessFlags) { + int size = 0; + for (AccessFlags accessFlag: accessFlags) { + size += accessFlag.toString().length() + 1; + } + StringBuilder sb = new StringBuilder(size); + for (AccessFlags accessFlag: accessFlags) { + sb.append(accessFlag.toString()); + sb.append(" "); + } + if (accessFlags.length > 0) { + sb.delete(sb.length() - 1, sb.length()); + } + return sb.toString(); + } + + public static String formatAccessFlagsForClass(int accessFlagValue) { + return formatAccessFlags(getAccessFlagsForClass(accessFlagValue)); + } + + public static AccessFlags[] getAccessFlagsForMethod(int accessFlagValue) { + int size = 0; for (AccessFlags accessFlag: AccessFlags.values()) { if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) { - accessFlags.add(accessFlag); + size++; + } + } + + AccessFlags[] accessFlags = new AccessFlags[size]; + int accessFlagsPosition = 0; + for (AccessFlags accessFlag: AccessFlags.values()) { + if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) { + accessFlags[accessFlagsPosition++] = accessFlag; } } return accessFlags; } - public static List getAccessFlagsForField(int accessFlagValue) { - ArrayList accessFlags = new ArrayList(); + public static String formatAccessFlagsForMethod(int accessFlagValue) { + return formatAccessFlags(getAccessFlagsForMethod(accessFlagValue)); + } + public static AccessFlags[] getAccessFlagsForField(int accessFlagValue) { + int size = 0; for (AccessFlags accessFlag: AccessFlags.values()) { if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) { - accessFlags.add(accessFlag); + size++; + } + } + + AccessFlags[] accessFlags = new AccessFlags[size]; + int accessFlagsPosition = 0; + for (AccessFlags accessFlag: AccessFlags.values()) { + if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) { + accessFlags[accessFlagsPosition++] = accessFlag; } } return accessFlags; } + public static String formatAccessFlagsForField(int accessFlagValue) { + return formatAccessFlags(getAccessFlagsForField(accessFlagValue)); + } + public static AccessFlags getAccessFlag(String accessFlag) { return accessFlagsByName.get(accessFlag); } diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/ReadOnlyArrayList.java b/dexlib/src/main/java/org/jf/dexlib/Util/ReadOnlyArrayList.java new file mode 100644 index 00000000..4df4e6ef --- /dev/null +++ b/dexlib/src/main/java/org/jf/dexlib/Util/ReadOnlyArrayList.java @@ -0,0 +1,48 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2009 Ben Gruver + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib.Util; + +import java.util.AbstractList; +import java.util.RandomAccess; + +public class ReadOnlyArrayList extends AbstractList implements RandomAccess { + private final T[] arr; + + public ReadOnlyArrayList(T[] arr) { + this.arr = arr; + } + + public int size() { + return arr.length; + } + + public T get(int i) { + return arr[i]; + } +}