From 689e0e59a69e08362a5b1373495e389496e12e57 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Mon, 8 Oct 2012 18:50:34 -0500 Subject: [PATCH] updating JesusFreke's smali/baksmali. Fixed SmaliMod to handle removal of smaliLexer. --- .../jf/baksmali/Adaptors/ClassDefinition.java | 2 +- .../Format/InstructionMethodItemFactory.java | 12 +- .../OffsetInstructionFormatMethodItem.java | 6 +- .../jf/dexlib/AnnotationDirectoryItem.java | 114 +- .../java/org/jf/dexlib/ClassDataItem.java | 57 +- .../main/java/org/jf/dexlib/ClassDefItem.java | 17 +- .../jf/dexlib/Code/Analysis/ClassPath.java | 8 +- .../jf/dexlib/Code/Format/Instruction10t.java | 2 +- .../jf/dexlib/Code/Format/Instruction20t.java | 2 +- .../jf/dexlib/Code/Format/Instruction21t.java | 2 +- .../jf/dexlib/Code/Format/Instruction22t.java | 2 +- .../jf/dexlib/Code/Format/Instruction30t.java | 2 +- .../jf/dexlib/Code/Format/Instruction31t.java | 2 +- .../org/jf/dexlib/Code/OffsetInstruction.java | 10 +- .../smali/src/main/antlr3/smaliLexer.g | 791 ------ .../smali/src/main/antlr3/smaliParser.g | 1677 ++++++------ .../smali/src/main/antlr3/smaliTreeWalker.g | 2304 ++++++++--------- .../main/java/org/jf/smali/InvalidToken.java | 5 +- .../main/java/org/jf/smali/LiteralTools.java | 39 + .../src/main/java/org/jf/smali/main.java | 35 +- .../smali/src/main/jflex/smaliLexer.flex | 6 +- .../smali/src/test/java/LexerTest.java | 4 +- .../LexerTest/ByteLiteralTest.tokens | 70 +- .../resources/LexerTest/CommentTest.tokens | 2 +- .../LexerTest/FloatLiteralTest.tokens | 2 +- .../LexerTest/IntegerLiteralTest.tokens | 90 +- .../LexerTest/LongLiteralTest.tokens | 60 +- .../test/resources/LexerTest/MiscTest.tokens | 2 +- .../LexerTest/RealSmaliFileTest.tokens | 80 +- .../LexerTest/ShortLiteralTest.tokens | 70 +- .../src/main/java/ds/tree/RadixTreeNode.java | 10 +- .../src/main/java/ds/tree/VisitorImpl.java | 20 +- .../org/jf/util/ClassFileNameHandler.java | 2 +- .../src/main/java/brut/androlib/Androlib.java | 1 + .../main/java/brut/androlib/mod/SmaliMod.java | 17 +- 35 files changed, 2446 insertions(+), 3079 deletions(-) delete mode 100644 brut.apktool.smali/smali/src/main/antlr3/smaliLexer.g diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java index 781e70b1..816b1ae3 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java @@ -262,7 +262,7 @@ public class ClassDefinition { classDefItem.getClassType().getTypeDescriptor(), field.field.getShortFieldString())); } - FieldDefinition.writeTo(fieldWriter, field, null, fieldAnnotations, false); + FieldDefinition.writeTo(fieldWriter, field, null, fieldAnnotations, false); } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java index c38b524a..772d7311 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java @@ -38,13 +38,11 @@ public class InstructionMethodItemFactory { private InstructionMethodItemFactory() { } - public static InstructionMethodItem makeInstructionFormatMethodItem(MethodDefinition methodDefinition, - CodeItem codeItem, - int codeAddress, - Instruction instruction) { + public static InstructionMethodItem makeInstructionFormatMethodItem( + MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, Instruction instruction) { if (instruction instanceof OffsetInstruction) { - return new OffsetInstructionFormatMethodItem(methodDefinition.getLabelCache(), codeItem, codeAddress, - instruction); + return new OffsetInstructionFormatMethodItem(methodDefinition.getLabelCache(), codeItem, + codeAddress, (OffsetInstruction)instruction); } switch (instruction.getFormat()) { @@ -61,7 +59,7 @@ public class InstructionMethodItemFactory { return new UnresolvedOdexInstructionMethodItem(codeItem, codeAddress, (UnresolvedOdexInstruction)instruction); default: - return new InstructionMethodItem(codeItem, codeAddress, instruction); + return new InstructionMethodItem(codeItem, codeAddress, instruction); } } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java index d63e43bf..d4edf3d0 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java @@ -31,19 +31,17 @@ package org.jf.baksmali.Adaptors.Format; import org.jf.baksmali.Adaptors.LabelMethodItem; import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.util.IndentingWriter; -import org.jf.dexlib.Code.Instruction; import org.jf.dexlib.Code.OffsetInstruction; import org.jf.dexlib.Code.Opcode; import org.jf.dexlib.CodeItem; import java.io.IOException; -public class OffsetInstructionFormatMethodItem - extends InstructionMethodItem { +public class OffsetInstructionFormatMethodItem extends InstructionMethodItem { protected LabelMethodItem label; public OffsetInstructionFormatMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress, - T instruction) { + OffsetInstruction instruction) { super(codeItem, codeAddress, instruction); label = new LabelMethodItem(codeAddress + instruction.getTargetAddressOffset(), getLabelPrefix()); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java index 3942ce52..3882b25d 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java @@ -48,16 +48,6 @@ public class AnnotationDirectoryItem extends Item { @Nullable private ParameterAnnotation[] parameterAnnotations; - /** - * typically each AnnotationDirectoryItem will have a distinct parent. The only case that isn't true is when - * the AnnotationDirectoryItem *only* contains class annotations, with no other type of annotation. In that - * case, the same AnnotationDirectoryItem could be referenced from multiple classes. - * This isn't a problem though, because this field is only used in compareTo to determine the sort order, which - * which knows it should handle a null value as a special case - */ - @Nullable - private ClassDefItem parent = null; - /** * Creates a new uninitialized AnnotationDirectoryItem * @param dexFile The DexFile that this item belongs to @@ -211,8 +201,9 @@ public class AnnotationDirectoryItem extends Item { /** {@inheritDoc} */ protected void writeItem(AnnotatedOutput out) { if (out.annotates()) { - if (!isInternable() && parent != null) { - out.annotate(0, parent.getClassType().getTypeDescriptor()); + TypeIdItem parentType = getParentType(); + if (parentType != null) { + out.annotate(0, parentType.getTypeDescriptor()); } if (classAnnotations != null) { out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset())); @@ -303,29 +294,60 @@ public class AnnotationDirectoryItem extends Item { /** {@inheritDoc} */ public String getConciseIdentity() { - if (parent == null) { + TypeIdItem parentType = getParentType(); + if (parentType == null) { return "annotation_directory_item @0x" + Integer.toHexString(getOffset()); } - return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() + ")"; + return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) + + " (" + parentType.getTypeDescriptor() + ")"; } /** {@inheritDoc} */ public int compareTo(AnnotationDirectoryItem o) { Preconditions.checkNotNull(o); - if (!isInternable()) { - if (!o.isInternable()) { - Preconditions.checkState(parent != null && o.parent != null, - "Must call setParent before comparing AnnotationDirectoryItem instances"); - return parent.compareTo(o.parent); + + TypeIdItem parentType = getParentType(); + TypeIdItem otherParentType = o.getParentType(); + if (parentType != null) { + if (otherParentType != null) { + return parentType.compareTo(otherParentType); } + return 1; + } + if (otherParentType != null) { return -1; } - if (!o.isInternable()) { + if (classAnnotations != null) { + if (o.classAnnotations != null) { + return classAnnotations.compareTo(o.classAnnotations); + } return 1; } + return -1; + } - return classAnnotations.compareTo(o.classAnnotations); + /** + * Returns the parent type for an AnnotationDirectoryItem that is guaranteed to have a single parent, or null + * for one that may be referenced by multiple classes. + * + * Specifically, the AnnotationDirectoryItem may be referenced by multiple classes if it has only class annotations, + * but not field/method/parameter annotations. + * + * @return The parent type for this AnnotationDirectoryItem, or null if it may have multiple parents + */ + @Nullable + public TypeIdItem getParentType() { + if (fieldAnnotations != null && fieldAnnotations.length > 0) { + return fieldAnnotations[0].field.getContainingClass(); + } + if (methodAnnotations != null && methodAnnotations.length > 0) { + return methodAnnotations[0].method.getContainingClass(); + } + if (parameterAnnotations != null && parameterAnnotations.length > 0) { + return parameterAnnotations[0].method.getContainingClass(); + } + return null; } /** @@ -425,6 +447,17 @@ public class AnnotationDirectoryItem extends Item { return parameterAnnotations[index].annotationSet; } + /** + * + */ + public int getClassAnnotationCount() { + if (classAnnotations == null) { + return 0; + } + AnnotationItem[] annotations = classAnnotations.getAnnotations(); + return annotations.length; + } + /** * @return The number of field annotations in this AnnotationDirectoryItem */ @@ -455,40 +488,17 @@ public class AnnotationDirectoryItem extends Item { return parameterAnnotations.length; } - /** - * @return true if this AnnotationDirectoryItem is internable. It is only internable if it has - * only class annotations, but no field, method or parameter annotations - */ - private boolean isInternable() { - return classAnnotations != null && - (fieldAnnotations == null || fieldAnnotations.length == 0) && - (methodAnnotations == null || methodAnnotations.length == 0) && - (parameterAnnotations == null || parameterAnnotations.length == 0); - } - - /** - * Sets the ClassDefItem that this AnnotationDirectoryItem is associated with. - * - * @param classDefItem the ClassDefItem that this AnnotationDirectoryItem is associated - * with. - */ - protected void setParent(ClassDefItem classDefItem) { - // If this AnnotationDirectoryItem is internable, then setParent may be called multiple times, because it is - // reused for multiple classes. In this case, the parent field isn't used, so it doesn't matter if we overwrite - // it. - // If, on the other hand, it is not internable, we want to make sure that only a single parent is set. parent - // should either be null, or be equal to the new parent - Preconditions.checkState(this.isInternable() || (parent == null || parent.equals(classDefItem))); - this.parent = classDefItem; - } - @Override public int hashCode() { - // An instance is internable only if it has only class annotations, but no other type of annotation - if (!isInternable()) { - return super.hashCode(); + // If the item has a single parent, we can use the re-use the identity (hash) of that parent + TypeIdItem parentType = getParentType(); + if (parentType != null) { + return parentType.hashCode(); } - return classAnnotations.hashCode(); + if (classAnnotations != null) { + return classAnnotations.hashCode(); + } + return 0; } @Override diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java index 33710710..9fe605e5 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java @@ -45,9 +45,6 @@ public class ClassDataItem extends Item { @Nullable private EncodedMethod[] virtualMethods = null; - @Nullable - private ClassDefItem parent = null; - /** * Creates a new uninitialized ClassDataItem * @param dexFile The DexFile that this item belongs to @@ -384,14 +381,17 @@ public class ClassDataItem extends Item { /** {@inheritDoc} */ public String getConciseIdentity() { - if (parent == null) { + TypeIdItem parentType = getParentType(); + if (parentType == null) { return "class_data_item @0x" + Integer.toHexString(getOffset()); } - return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() +")"; + return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parentType.getTypeDescriptor() +")"; } /** {@inheritDoc} */ public int compareTo(ClassDataItem other) { + Preconditions.checkNotNull(other); + // An empty CodeDataItem may be shared by multiple ClassDefItems, so we can't use parent in this case if (isEmpty()) { if (other.isEmpty()) { @@ -403,25 +403,54 @@ public class ClassDataItem extends Item { return 1; } - if (parent == null) { - if (other.parent == null) { + TypeIdItem parentType = getParentType(); + TypeIdItem otherParentType= other.getParentType(); + if (parentType == null) { + if (otherParentType == null) { return 0; } return -1; } - if (other.parent == null) { + if (otherParentType == null) { return 1; } - return parent.compareTo(other.parent); + return parentType.compareTo(otherParentType); + } + + @Override + public int hashCode() { + // If the item has a single parent, we can use the re-use the identity (hash) of that parent + TypeIdItem parentType = getParentType(); + if (parentType != null) { + return parentType.hashCode(); + } + return 0; } /** - * Sets the ClassDefItem that this ClassDataItem is associated with - * @param classDefItem the ClassDefItem that this ClassDataItem is associated with + * Returns the parent type for a non-empty ClassDataItem, or null for an empty one (which could be referenced by + * multiple ClassDefItem parents) + * + * Specifically, the AnnotationDirectoryItem may be referenced by multiple classes if it has only class annotations, + * but not field/method/parameter annotations. + * + * @return The parent type for this AnnotationDirectoryItem, or null if it may have multiple parents */ - protected void setParent(ClassDefItem classDefItem) { - Preconditions.checkState(parent == null || parent.compareTo(classDefItem) == 0 || isEmpty()); - parent = classDefItem; + @Nullable + public TypeIdItem getParentType() { + if (staticFields != null && staticFields.length > 0) { + return staticFields[0].field.getContainingClass(); + } + if (instanceFields != null && instanceFields.length > 0) { + return instanceFields[0].field.getContainingClass(); + } + if (directMethods != null && directMethods.length > 0) { + return directMethods[0].method.getContainingClass(); + } + if (virtualMethods != null && virtualMethods.length > 0) { + return virtualMethods[0].method.getContainingClass(); + } + return null; } /** diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java index 3737adbc..9664b997 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java @@ -28,7 +28,6 @@ package org.jf.dexlib; -import com.google.common.base.Preconditions; import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue; import org.jf.dexlib.EncodedValue.EncodedValue; import org.jf.dexlib.Util.AccessFlags; @@ -88,13 +87,6 @@ public class ClassDefItem extends Item { this.annotations = annotations; this.classData = classData; this.staticFieldInitializers = staticFieldInitializers; - - if (classData != null) { - classData.setParent(this); - } - if (annotations != null) { - annotations.setParent(this); - } } /** @@ -145,13 +137,6 @@ public class ClassDefItem extends Item { classData = (ClassDataItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt()); staticFieldInitializers = (EncodedArrayItem)readContext.getOptionalOffsettedItemByOffset( ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt()); - - if (classData != null) { - classData.setParent(this); - } - if (annotations != null) { - annotations.setParent(this); - } } /** {@inheritDoc} */ @@ -344,7 +329,7 @@ public class ClassDefItem extends Item { */ private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile, @Nonnull List staticFieldInitializers) { - if (staticFieldInitializers == null || staticFieldInitializers.size() == 0) { + if (staticFieldInitializers.size() == 0) { return null; } diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java index ac1da808..db1a27e5 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java @@ -408,7 +408,13 @@ public class ClassPath { //if the two arrays have the same number of dimensions, then we should return an array class with the //same number of dimensions, for the common superclass of the 2 element classes if (class1.arrayDimensions == class2.arrayDimensions) { - ClassDef commonElementClass = getCommonSuperclass(class1.elementClass, class2.elementClass); + ClassDef commonElementClass; + if (class1.elementClass instanceof UnresolvedClassDef || + class2.elementClass instanceof UnresolvedClassDef) { + commonElementClass = ClassPath.getUnresolvedObjectClassDef(); + } else { + commonElementClass = getCommonSuperclass(class1.elementClass, class2.elementClass); + } return getArrayClassDefByElementClassAndDimension(commonElementClass, class1.arrayDimensions); } diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction10t.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction10t.java index 9947a109..4b7f872e 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction10t.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction10t.java @@ -34,7 +34,7 @@ import org.jf.dexlib.Code.Opcode; import org.jf.dexlib.DexFile; import org.jf.dexlib.Util.AnnotatedOutput; -public class Instruction10t extends Instruction implements OffsetInstruction { +public class Instruction10t extends OffsetInstruction { public static final InstructionFactory Factory = new Factory(); private int targetAddressOffset; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java index a92e1a8b..f970cfb5 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java @@ -35,7 +35,7 @@ import org.jf.dexlib.DexFile; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction20t extends Instruction implements OffsetInstruction { +public class Instruction20t extends OffsetInstruction { public static final InstructionFactory Factory = new Factory(); private int targetAddressOffset; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java index 4a839d5a..f1cd7d27 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java @@ -36,7 +36,7 @@ import org.jf.dexlib.DexFile; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction21t extends Instruction implements OffsetInstruction, SingleRegisterInstruction { +public class Instruction21t extends OffsetInstruction implements SingleRegisterInstruction { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regA; private short targetAddressOffset; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java index d5b3a734..56b8298a 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java @@ -36,7 +36,7 @@ import org.jf.dexlib.DexFile; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction22t extends Instruction implements OffsetInstruction, TwoRegisterInstruction { +public class Instruction22t extends OffsetInstruction implements TwoRegisterInstruction { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regA; private byte regB; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java index 7a97903f..fc83b222 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java @@ -35,7 +35,7 @@ import org.jf.dexlib.DexFile; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction30t extends Instruction implements OffsetInstruction { +public class Instruction30t extends OffsetInstruction { public static final InstructionFactory Factory = new Factory(); private int targetAddressOffset; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java index 52d6ce66..55bcc6bf 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java @@ -36,7 +36,7 @@ import org.jf.dexlib.DexFile; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction31t extends Instruction implements OffsetInstruction, SingleRegisterInstruction { +public class Instruction31t extends OffsetInstruction implements SingleRegisterInstruction { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regA; private int targetAddressOffset; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/OffsetInstruction.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/OffsetInstruction.java index 7ab366ab..d0589c73 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/OffsetInstruction.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/OffsetInstruction.java @@ -28,7 +28,11 @@ package org.jf.dexlib.Code; -public interface OffsetInstruction { - public int getTargetAddressOffset(); - public void updateTargetAddressOffset(int targetAddressOffset); +public abstract class OffsetInstruction extends Instruction { + protected OffsetInstruction(Opcode opcode) { + super(opcode); + } + + public abstract int getTargetAddressOffset(); + public abstract void updateTargetAddressOffset(int targetAddressOffset); } diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliLexer.g b/brut.apktool.smali/smali/src/main/antlr3/smaliLexer.g deleted file mode 100644 index 872e1065..00000000 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliLexer.g +++ /dev/null @@ -1,791 +0,0 @@ -/* - * The comment, number, string and character constant lexical rules are - * derived from rules from the Java 1.6 grammar which can be found here: - * http://openjdk.java.net/projects/compiler-grammar/antlrworks/Java.g - * - * Specifically, these rules: - * - * BASE_INTEGER, DECIMAL_EXPONENT, BINARY_EXPONENT, HEX_PREFIX, HEX_DIGIT, - * BASE_FLOAT_OR_ID, BASE_FLOAT, ESCAPE_SEQUENCE, POSITIVE_INTEGER_LITERAL, - * NEGATIVE_INTEGER_LITERAL, LONG_LITERAL, SHORT_LITERAL, BYTE_LITERAL, - * FLOAT_LITERAL_OR_ID, DOUBLE_LITERAL_OR_ID, FLOAT_LITERAL, DOUBLE_LITERAL, - * BOOL_LITERAL, STRING_LITERAL, BASE_STRING_LITERAL, CHAR_LITERAL, - * BASE_CHAR_LITERAL - * - * These rules were originally copyrighted by Terence Parr, and are used here in - * accordance with the following license - * - * [The "BSD licence"] - * Copyright (c) 2007-2008 Terence Parr - * 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. - * - * - * The remainder of this grammar is released by me (Ben Gruver) under the - * following license: - * - * [The "BSD licence"] - * Copyright (c) 2010 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. - */ - -lexer grammar smaliLexer; - -options { - superClass=ANTLRLexerWithErrorInterface; -} - -@lexer::header { - package org.jf.smali; - - import static org.jf.smali.LexerErrorInterface.ANTLRLexerWithErrorInterface; -} - -@lexer::members { - public static final int ERROR_CHANNEL = 100; - public String getErrorHeader(RecognitionException e) { - return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; - } -} - -/********************************************************** -* DIRECTIVES -**********************************************************/ - -CLASS_DIRECTIVE - : '.class'; - -SUPER_DIRECTIVE - : '.super'; - -IMPLEMENTS_DIRECTIVE - : '.implements'; - -SOURCE_DIRECTIVE - : '.source'; - -FIELD_DIRECTIVE - : '.field'; - -END_FIELD_DIRECTIVE - : '.end field'; - -SUBANNOTATION_DIRECTIVE - : '.subannotation'; - -END_SUBANNOTATION_DIRECTIVE - : '.end subannotation'; - -ANNOTATION_DIRECTIVE - : '.annotation'; - -END_ANNOTATION_DIRECTIVE - : '.end annotation'; - -ENUM_DIRECTIVE - : '.enum'; - -METHOD_DIRECTIVE - : '.method'; - -END_METHOD_DIRECTIVE - : '.end method'; - -REGISTERS_DIRECTIVE - : '.registers'; - -LOCALS_DIRECTIVE - : '.locals'; - -ARRAY_DATA_DIRECTIVE - : '.array-data'; - -END_ARRAY_DATA_DIRECTIVE - : '.end array-data'; - -PACKED_SWITCH_DIRECTIVE - : '.packed-switch'; - -END_PACKED_SWITCH_DIRECTIVE - : '.end packed-switch'; - -SPARSE_SWITCH_DIRECTIVE - : '.sparse-switch'; - -END_SPARSE_SWITCH_DIRECTIVE - : '.end sparse-switch'; - -CATCH_DIRECTIVE - : '.catch'; - -CATCHALL_DIRECTIVE - : '.catchall'; - -LINE_DIRECTIVE - : '.line'; - -PARAMETER_DIRECTIVE - : '.parameter'; - -END_PARAMETER_DIRECTIVE - : '.end parameter'; - -LOCAL_DIRECTIVE - : '.local'; - -END_LOCAL_DIRECTIVE - : '.end local'; - -RESTART_LOCAL_DIRECTIVE - : '.restart local'; - -PROLOGUE_DIRECTIVE - : '.prologue'; - -EPILOGUE_DIRECTIVE - : '.epilogue'; - -/********************************************************** -* LITERALS -**********************************************************/ -fragment BASE_INTEGER - : '0' - | ('1'..'9') ('0'..'9')* - | '0' ('0'..'7')+ - | HEX_PREFIX HEX_DIGIT+; - -fragment DECIMAL_EXPONENT - : ('e'|'E') '-'? ('0'..'9')+; - -fragment BINARY_EXPONENT - : ('p'|'P') '-'? ('0'..'9')+; - -fragment HEX_PREFIX - : '0x'|'0X'; - -fragment HEX_DIGIT - : ('0'..'9')|('A'..'F')|('a'..'f'); - -fragment HEX_DIGITS - : HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT; - -/*This can either be floating point numbers, or identifier*/ -fragment BASE_FLOAT_OR_ID - : '-'? ('0'..'9')+ DECIMAL_EXPONENT - | HEX_PREFIX HEX_DIGIT+ BINARY_EXPONENT - | '-'? ('i' | 'I') ('n' | 'N') ('f' | 'F') ('i' | 'I') ('n' | 'N') ('i' | 'I') ('t' | 'T') ('y' | 'Y') - | ('n' | 'N') ('a' | 'A') ('n' | 'N'); - -/*These can't be identifiers, due to the decimal point*/ -fragment BASE_FLOAT - : '-'? ('0'..'9')+ '.' ('0'..'9')* DECIMAL_EXPONENT? - | '-'? '.' ('0'..'9')+ DECIMAL_EXPONENT? - | '-'? HEX_PREFIX HEX_DIGIT+ '.' HEX_DIGIT* BINARY_EXPONENT - | '-'? HEX_PREFIX '.' HEX_DIGIT+ BINARY_EXPONENT; - -fragment ESCAPE_SEQUENCE[StringBuilder sb] - : '\\' - ( - 'b' {sb.append("\b");} - | 't' {sb.append("\t");} - | 'n' {sb.append("\n");} - | 'f' {sb.append("\f");} - | 'r' {sb.append("\r");} - | '\"' {sb.append("\"");} - | '\'' {sb.append("'");} - | '\\' {sb.append("\\");} - | 'u' HEX_DIGITS {sb.append((char)Integer.parseInt($HEX_DIGITS.text, 16));} - ); - -POSITIVE_INTEGER_LITERAL - : BASE_INTEGER; - -NEGATIVE_INTEGER_LITERAL - : '-' BASE_INTEGER; - -LONG_LITERAL - : '-'? BASE_INTEGER ('l'|'L'); - -SHORT_LITERAL - : '-'? BASE_INTEGER ('s'|'S'); - -BYTE_LITERAL - : '-'? BASE_INTEGER ('t'|'T'); - -FLOAT_LITERAL_OR_ID - : BASE_FLOAT_OR_ID ('f'|'F') - | '-'? ('0'..'9')+ ('f'|'F'); - -DOUBLE_LITERAL_OR_ID - : BASE_FLOAT_OR_ID ('d'|'D')? - | '-'? ('0'..'9')+ ('d'|'D'); - -FLOAT_LITERAL - : BASE_FLOAT ('f'|'F'); - -DOUBLE_LITERAL - : BASE_FLOAT ('d'|'D')?; - -BOOL_LITERAL - : 'true' - | 'false'; - -NULL_LITERAL - : 'null'; - -STRING_LITERAL - @init {StringBuilder sb = new StringBuilder();} - : BASE_STRING_LITERAL[sb] {setText(sb.toString());}; - -fragment BASE_STRING_LITERAL[StringBuilder sb] - : '"' {sb.append('"');} - ( ESCAPE_SEQUENCE[sb] - | ~( '\\' | '"' | '\r' | '\n' ) {sb.append((char)input.LA(-1));} - )* - '"' {sb.append('"');}; - -CHAR_LITERAL - @init {StringBuilder sb = new StringBuilder();} - : BASE_CHAR_LITERAL[sb] {setText(sb.toString());}; - -fragment BASE_CHAR_LITERAL[StringBuilder sb] - : '\'' {sb.append('\'');} - ( ESCAPE_SEQUENCE[sb] - | ~( '\\' | '\'' | '\r' | '\n' ) {sb.append((char)input.LA(-1));} - ) - '\'' { sb.append('\''); }; - - -/********************************************************** -* MISC -**********************************************************/ -REGISTER - : ('v'|'p') ('0'..'9')+; - -ANNOTATION_VISIBILITY - : 'build' - | 'runtime' - | 'system'; - -ACCESS_SPEC - : 'public' - | 'private' - | 'protected' - | 'static' - | 'final' - | 'synchronized' - | 'bridge' - | 'varargs' - | 'native' - | 'abstract' - | 'strictfp' - | 'synthetic' - | 'constructor' - | 'declared-synchronized' - | 'interface' - | 'enum' - | 'annotation' - | 'volatile' - | 'transient'; - -VERIFICATION_ERROR_TYPE - : 'no-error' - | 'generic-error' - | 'no-such-class' - | 'no-such-field' - | 'no-such-method' - | 'illegal-class-access' - | 'illegal-field-access' - | 'illegal-method-access' - | 'class-change-error' - | 'instantiation-error'; - -INLINE_INDEX - : 'inline@0x' HEX_DIGIT+; - -VTABLE_INDEX - : 'vtable@0x' HEX_DIGIT+; - -FIELD_OFFSET - : 'field@0x' HEX_DIGIT+; - -OFFSET - : '+' BASE_INTEGER; - -LINE_COMMENT - : '#' - ( - ~('\n'|'\r')* ('\r\n' | '\r' | '\n') - | ~('\n'|'\r')* - ) - {$channel = HIDDEN;}; - -/********************************************************** -* Instructions -**********************************************************/ -INSTRUCTION_FORMAT10t - : 'goto'; - -INSTRUCTION_FORMAT10x - : 'return-void' - | 'nop'; - -INSTRUCTION_FORMAT10x_ODEX - : 'return-void-barrier'; - -INSTRUCTION_FORMAT11n - : 'const/4'; - -INSTRUCTION_FORMAT11x - : 'move-result' - | 'move-result-wide' - | 'move-result-object' - | 'move-exception' - | 'return' - | 'return-wide' - | 'return-object' - | 'monitor-enter' - | 'monitor-exit' - | 'throw'; - -INSTRUCTION_FORMAT12x_OR_ID - : 'move' - | 'move-wide' - | 'move-object' - | 'array-length' - | 'neg-int' - | 'not-int' - | 'neg-long' - | 'not-long' - | 'neg-float' - | 'neg-double' - | 'int-to-long' - | 'int-to-float' - | 'int-to-double' - | 'long-to-int' - | 'long-to-float' - | 'long-to-double' - | 'float-to-int' - | 'float-to-long' - | 'float-to-double' - | 'double-to-int' - | 'double-to-long' - | 'double-to-float' - | 'int-to-byte' - | 'int-to-char' - | 'int-to-short'; - -INSTRUCTION_FORMAT12x - : 'add-int/2addr' - | 'sub-int/2addr' - | 'mul-int/2addr' - | 'div-int/2addr' - | 'rem-int/2addr' - | 'and-int/2addr' - | 'or-int/2addr' - | 'xor-int/2addr' - | 'shl-int/2addr' - | 'shr-int/2addr' - | 'ushr-int/2addr' - | 'add-long/2addr' - | 'sub-long/2addr' - | 'mul-long/2addr' - | 'div-long/2addr' - | 'rem-long/2addr' - | 'and-long/2addr' - | 'or-long/2addr' - | 'xor-long/2addr' - | 'shl-long/2addr' - | 'shr-long/2addr' - | 'ushr-long/2addr' - | 'add-float/2addr' - | 'sub-float/2addr' - | 'mul-float/2addr' - | 'div-float/2addr' - | 'rem-float/2addr' - | 'add-double/2addr' - | 'sub-double/2addr' - | 'mul-double/2addr' - | 'div-double/2addr' - | 'rem-double/2addr'; - -INSTRUCTION_FORMAT20bc - : 'throw-verification-error'; - -INSTRUCTION_FORMAT20t - : 'goto/16'; - -INSTRUCTION_FORMAT21c_FIELD - : 'sget' - | 'sget-wide' - | 'sget-object' - | 'sget-boolean' - | 'sget-byte' - | 'sget-char' - | 'sget-short' - | 'sput' - | 'sput-wide' - | 'sput-object' - | 'sput-boolean' - | 'sput-byte' - | 'sput-char' - | 'sput-short'; - -INSTRUCTION_FORMAT21c_FIELD_ODEX - : 'sget-volatile' - | 'sget-wide-volatile' - | 'sget-object-volatile' - | 'sput-volatile' - | 'sput-wide-volatile' - | 'sput-object-volatile'; - -INSTRUCTION_FORMAT21c_STRING - : 'const-string'; - -INSTRUCTION_FORMAT21c_TYPE - : 'check-cast' - | 'new-instance' - | 'const-class'; - -INSTRUCTION_FORMAT21h - : 'const/high16' - | 'const-wide/high16'; - -INSTRUCTION_FORMAT21s - : 'const/16' - | 'const-wide/16'; - -INSTRUCTION_FORMAT21t - : 'if-eqz' - | 'if-nez' - | 'if-ltz' - | 'if-gez' - | 'if-gtz' - | 'if-lez'; - -INSTRUCTION_FORMAT22b - : 'add-int/lit8' - | 'rsub-int/lit8' - | 'mul-int/lit8' - | 'div-int/lit8' - | 'rem-int/lit8' - | 'and-int/lit8' - | 'or-int/lit8' - | 'xor-int/lit8' - | 'shl-int/lit8' - | 'shr-int/lit8' - | 'ushr-int/lit8'; - -INSTRUCTION_FORMAT22c_FIELD - : 'iget' - | 'iget-wide' - | 'iget-object' - | 'iget-boolean' - | 'iget-byte' - | 'iget-char' - | 'iget-short' - | 'iput' - | 'iput-wide' - | 'iput-object' - | 'iput-boolean' - | 'iput-byte' - | 'iput-char' - | 'iput-short'; - -INSTRUCTION_FORMAT22c_FIELD_ODEX - : 'iget-volatile' - | 'iget-wide-volatile' - | 'iget-object-volatile' - | 'iput-volatile' - | 'iput-wide-volatile' - | 'iput-object-volatile'; - -INSTRUCTION_FORMAT22c_TYPE - : 'instance-of' - | 'new-array'; - - -INSTRUCTION_FORMAT22cs_FIELD - : 'iget-quick' - | 'iget-wide-quick' - | 'iget-object-quick' - | 'iput-quick' - | 'iput-wide-quick' - | 'iput-object-quick'; - -INSTRUCTION_FORMAT22s_OR_ID - : 'rsub-int'; - -INSTRUCTION_FORMAT22s - : 'add-int/lit16' - | 'mul-int/lit16' - | 'div-int/lit16' - | 'rem-int/lit16' - | 'and-int/lit16' - | 'or-int/lit16' - | 'xor-int/lit16'; - -INSTRUCTION_FORMAT22t - : 'if-eq' - | 'if-ne' - | 'if-lt' - | 'if-ge' - | 'if-gt' - | 'if-le'; - -INSTRUCTION_FORMAT22x - : 'move/from16' - | 'move-wide/from16' - | 'move-object/from16'; - -INSTRUCTION_FORMAT23x - : 'cmpl-float' - | 'cmpg-float' - | 'cmpl-double' - | 'cmpg-double' - | 'cmp-long' - | 'aget' - | 'aget-wide' - | 'aget-object' - | 'aget-boolean' - | 'aget-byte' - | 'aget-char' - | 'aget-short' - | 'aput' - | 'aput-wide' - | 'aput-object' - | 'aput-boolean' - | 'aput-byte' - | 'aput-char' - | 'aput-short' - | 'add-int' - | 'sub-int' - | 'mul-int' - | 'div-int' - | 'rem-int' - | 'and-int' - | 'or-int' - | 'xor-int' - | 'shl-int' - | 'shr-int' - | 'ushr-int' - | 'add-long' - | 'sub-long' - | 'mul-long' - | 'div-long' - | 'rem-long' - | 'and-long' - | 'or-long' - | 'xor-long' - | 'shl-long' - | 'shr-long' - | 'ushr-long' - | 'add-float' - | 'sub-float' - | 'mul-float' - | 'div-float' - | 'rem-float' - | 'add-double' - | 'sub-double' - | 'mul-double' - | 'div-double' - | 'rem-double'; - -INSTRUCTION_FORMAT30t - : 'goto/32'; - -INSTRUCTION_FORMAT31c - : 'const-string/jumbo'; - -INSTRUCTION_FORMAT31i_OR_ID - : 'const'; - -INSTRUCTION_FORMAT31i - : 'const-wide/32'; - -INSTRUCTION_FORMAT31t - : 'fill-array-data' - | 'packed-switch' - | 'sparse-switch'; - -INSTRUCTION_FORMAT32x - : 'move/16' - | 'move-wide/16' - | 'move-object/16'; - -INSTRUCTION_FORMAT35c_METHOD - : 'invoke-virtual' - | 'invoke-super' - | 'invoke-direct' - | 'invoke-static' - | 'invoke-interface'; - -INSTRUCTION_FORMAT35c_METHOD_ODEX - : 'invoke-direct-empty'; - -INSTRUCTION_FORMAT35c_TYPE - : 'filled-new-array'; - -INSTRUCTION_FORMAT35mi_METHOD - : 'execute-inline'; - -INSTRUCTION_FORMAT35ms_METHOD - : 'invoke-virtual-quick' - | 'invoke-super-quick'; - -INSTRUCTION_FORMAT3rc_METHOD - : 'invoke-virtual/range' - | 'invoke-super/range' - | 'invoke-direct/range' - | 'invoke-static/range' - | 'invoke-interface/range'; - -INSTRUCTION_FORMAT3rc_METHOD_ODEX - : 'invoke-object-init/range'; - -INSTRUCTION_FORMAT3rc_TYPE - : 'filled-new-array/range'; - -INSTRUCTION_FORMAT3rmi_METHOD - : 'execute-inline/range'; - -INSTRUCTION_FORMAT3rms_METHOD - : 'invoke-virtual-quick/range' - | 'invoke-super-quick/range'; - -INSTRUCTION_FORMAT51l - : 'const-wide'; - -/********************************************************** -* Types -**********************************************************/ -fragment BASE_SIMPLE_NAME: - ( 'A'..'Z' - | 'a'..'z' - | '0'..'9' - | '$' - | '-' - | '_' - | '\u00a1'..'\u1fff' - | '\u2010'..'\u2027' - | '\u2030'..'\ud7ff' - | '\ue000'..'\uffef' - )+; - -fragment BASE_PRIMITIVE_TYPE - : 'Z'|'B'|'S'|'C'|'I'|'J'|'F'|'D'; - - -fragment BASE_CLASS_DESCRIPTOR - : 'L' (BASE_SIMPLE_NAME '/')* BASE_SIMPLE_NAME ';'; - -fragment BASE_ARRAY_DESCRIPTOR - : '['+ (BASE_PRIMITIVE_TYPE | BASE_CLASS_DESCRIPTOR); - -fragment BASE_TYPE - : BASE_PRIMITIVE_TYPE - | BASE_CLASS_DESCRIPTOR - | BASE_ARRAY_DESCRIPTOR; - -PRIMITIVE_TYPE - : BASE_PRIMITIVE_TYPE; - -VOID_TYPE - : 'V'; - -CLASS_DESCRIPTOR - : BASE_CLASS_DESCRIPTOR; - -ARRAY_DESCRIPTOR - : BASE_ARRAY_DESCRIPTOR; - -PARAM_LIST_OR_ID - : BASE_PRIMITIVE_TYPE BASE_PRIMITIVE_TYPE+; - -PARAM_LIST - : BASE_TYPE BASE_TYPE+; - -SIMPLE_NAME - : BASE_SIMPLE_NAME; - -METHOD_NAME - : '' - | ''; - - -/********************************************************** -* Symbols -**********************************************************/ - -DOTDOT - : '..'; - -ARROW - : '->'; - -EQUAL - : '='; - -COLON - : ':'; - -COMMA - : ','; - -OPEN_BRACE - : '{'; - -CLOSE_BRACE - : '}'; - -OPEN_PAREN - : '('; - -CLOSE_PAREN - : ')'; - -WHITE_SPACE - : (' '|'\t'|'\n'|'\r')+ {$channel = HIDDEN;}; diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g b/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g index 3d272b0e..d9c987fb 100644 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g +++ b/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g @@ -29,104 +29,236 @@ parser grammar smaliParser; options { - tokenVocab=smaliLexer; - output=AST; - ASTLabelType=CommonTree; + output=AST; + ASTLabelType=CommonTree; } tokens { - //I_* tokens are imaginary tokens used as parent AST nodes - I_CLASS_DEF; - I_SUPER; - I_IMPLEMENTS; - I_SOURCE; - I_ACCESS_LIST; - I_METHODS; - I_FIELDS; - I_FIELD; - I_FIELD_TYPE; - I_FIELD_INITIAL_VALUE; - I_METHOD; - I_METHOD_PROTOTYPE; - I_METHOD_RETURN_TYPE; - I_REGISTERS; - I_LOCALS; - I_LABELS; - I_LABEL; - I_ANNOTATIONS; - I_ANNOTATION; - I_ANNOTATION_ELEMENT; - I_SUBANNOTATION; - I_ENCODED_FIELD; - I_ENCODED_METHOD; - I_ENCODED_ENUM; - I_ENCODED_ARRAY; - I_ARRAY_ELEMENT_SIZE; - I_ARRAY_ELEMENTS; - I_PACKED_SWITCH_START_KEY; - I_PACKED_SWITCH_TARGET_COUNT; - I_PACKED_SWITCH_TARGETS; - I_PACKED_SWITCH_DECLARATION; - I_PACKED_SWITCH_DECLARATIONS; - I_SPARSE_SWITCH_KEYS; - I_SPARSE_SWITCH_TARGET_COUNT; - I_SPARSE_SWITCH_TARGETS; - I_SPARSE_SWITCH_DECLARATION; - I_SPARSE_SWITCH_DECLARATIONS; - I_ADDRESS; - I_CATCH; - I_CATCHALL; - I_CATCHES; - I_PARAMETER; - I_PARAMETERS; - I_PARAMETER_NOT_SPECIFIED; - I_ORDERED_DEBUG_DIRECTIVES; - I_LINE; - I_LOCAL; - I_END_LOCAL; - I_RESTART_LOCAL; - I_PROLOGUE; - I_EPILOGUE; - I_STATEMENTS; - I_STATEMENT_FORMAT10t; - I_STATEMENT_FORMAT10x; - I_STATEMENT_FORMAT11n; - I_STATEMENT_FORMAT11x; - I_STATEMENT_FORMAT12x; - I_STATEMENT_FORMAT20bc; - I_STATEMENT_FORMAT20t; - I_STATEMENT_FORMAT21c_TYPE; - I_STATEMENT_FORMAT21c_FIELD; - I_STATEMENT_FORMAT21c_STRING; - I_STATEMENT_FORMAT21h; - I_STATEMENT_FORMAT21s; - I_STATEMENT_FORMAT21t; - I_STATEMENT_FORMAT22b; - I_STATEMENT_FORMAT22c_FIELD; - I_STATEMENT_FORMAT22c_TYPE; - I_STATEMENT_FORMAT22s; - I_STATEMENT_FORMAT22t; - I_STATEMENT_FORMAT22x; - I_STATEMENT_FORMAT23x; - I_STATEMENT_FORMAT30t; - I_STATEMENT_FORMAT31c; - I_STATEMENT_FORMAT31i; - I_STATEMENT_FORMAT31t; - I_STATEMENT_FORMAT32x; - I_STATEMENT_FORMAT35c_METHOD; - I_STATEMENT_FORMAT35c_TYPE; - I_STATEMENT_FORMAT3rc_METHOD; - I_STATEMENT_FORMAT3rc_TYPE; - I_STATEMENT_FORMAT51l; - I_STATEMENT_ARRAY_DATA; - I_STATEMENT_PACKED_SWITCH; - I_STATEMENT_SPARSE_SWITCH; - I_REGISTER_RANGE; - I_REGISTER_LIST; + //Lexer tokens + ACCESS_SPEC; + ANNOTATION_DIRECTIVE; + ANNOTATION_VISIBILITY; + ARRAY_DATA_DIRECTIVE; + ARRAY_DESCRIPTOR; + ARROW; + BASE_ARRAY_DESCRIPTOR; + BASE_CHAR_LITERAL; + BASE_CLASS_DESCRIPTOR; + BASE_FLOAT; + BASE_FLOAT_OR_ID; + BASE_INTEGER; + BASE_PRIMITIVE_TYPE; + BASE_SIMPLE_NAME; + BASE_STRING_LITERAL; + BASE_TYPE; + BINARY_EXPONENT; + BOOL_LITERAL; + BYTE_LITERAL; + CATCH_DIRECTIVE; + CATCHALL_DIRECTIVE; + CHAR_LITERAL; + CLASS_DESCRIPTOR; + CLASS_DIRECTIVE; + CLOSE_BRACE; + CLOSE_PAREN; + COLON; + COMMA; + DECIMAL_EXPONENT; + DOTDOT; + DOUBLE_LITERAL; + DOUBLE_LITERAL_OR_ID; + END_ANNOTATION_DIRECTIVE; + END_ARRAY_DATA_DIRECTIVE; + END_FIELD_DIRECTIVE; + END_LOCAL_DIRECTIVE; + END_METHOD_DIRECTIVE; + END_PACKED_SWITCH_DIRECTIVE; + END_PARAMETER_DIRECTIVE; + END_SPARSE_SWITCH_DIRECTIVE; + END_SUBANNOTATION_DIRECTIVE; + ENUM_DIRECTIVE; + EPILOGUE_DIRECTIVE; + EQUAL; + ESCAPE_SEQUENCE; + FIELD_DIRECTIVE; + FIELD_OFFSET; + FLOAT_LITERAL; + FLOAT_LITERAL_OR_ID; + HEX_DIGIT; + HEX_DIGITS; + HEX_PREFIX; + IMPLEMENTS_DIRECTIVE; + INLINE_INDEX; + INSTRUCTION_FORMAT10t; + INSTRUCTION_FORMAT10x; + INSTRUCTION_FORMAT10x_ODEX; + INSTRUCTION_FORMAT11n; + INSTRUCTION_FORMAT11x; + INSTRUCTION_FORMAT12x; + INSTRUCTION_FORMAT12x_OR_ID; + INSTRUCTION_FORMAT20bc; + INSTRUCTION_FORMAT20t; + INSTRUCTION_FORMAT21c_FIELD; + INSTRUCTION_FORMAT21c_FIELD_ODEX; + INSTRUCTION_FORMAT21c_STRING; + INSTRUCTION_FORMAT21c_TYPE; + INSTRUCTION_FORMAT21h; + INSTRUCTION_FORMAT21s; + INSTRUCTION_FORMAT21t; + INSTRUCTION_FORMAT22b; + INSTRUCTION_FORMAT22c_FIELD; + INSTRUCTION_FORMAT22c_FIELD_ODEX; + INSTRUCTION_FORMAT22c_TYPE; + INSTRUCTION_FORMAT22cs_FIELD; + INSTRUCTION_FORMAT22s; + INSTRUCTION_FORMAT22s_OR_ID; + INSTRUCTION_FORMAT22t; + INSTRUCTION_FORMAT22x; + INSTRUCTION_FORMAT23x; + INSTRUCTION_FORMAT30t; + INSTRUCTION_FORMAT31c; + INSTRUCTION_FORMAT31i; + INSTRUCTION_FORMAT31i_OR_ID; + INSTRUCTION_FORMAT31t; + INSTRUCTION_FORMAT32x; + INSTRUCTION_FORMAT35c_METHOD; + INSTRUCTION_FORMAT35c_METHOD_ODEX; + INSTRUCTION_FORMAT35c_TYPE; + INSTRUCTION_FORMAT35mi_METHOD; + INSTRUCTION_FORMAT35ms_METHOD; + INSTRUCTION_FORMAT3rc_METHOD; + INSTRUCTION_FORMAT3rc_METHOD_ODEX; + INSTRUCTION_FORMAT3rc_TYPE; + INSTRUCTION_FORMAT3rmi_METHOD; + INSTRUCTION_FORMAT3rms_METHOD; + INSTRUCTION_FORMAT51l; + INVALID_TOKEN; + LINE_COMMENT; + LINE_DIRECTIVE; + LOCAL_DIRECTIVE; + LOCALS_DIRECTIVE; + LONG_LITERAL; + METHOD_DIRECTIVE; + METHOD_NAME; + NEGATIVE_INTEGER_LITERAL; + NULL_LITERAL; + OFFSET; + OPEN_BRACE; + OPEN_PAREN; + PACKED_SWITCH_DIRECTIVE; + PARAM_LIST; + PARAM_LIST_OR_ID; + PARAMETER_DIRECTIVE; + POSITIVE_INTEGER_LITERAL; + PRIMITIVE_TYPE; + PROLOGUE_DIRECTIVE; + REGISTER; + REGISTERS_DIRECTIVE; + RESTART_LOCAL_DIRECTIVE; + SHORT_LITERAL; + SIMPLE_NAME; + SOURCE_DIRECTIVE; + SPARSE_SWITCH_DIRECTIVE; + STRING_LITERAL; + SUBANNOTATION_DIRECTIVE; + SUPER_DIRECTIVE; + VERIFICATION_ERROR_TYPE; + VOID_TYPE; + VTABLE_INDEX; + WHITE_SPACE; - LABEL; - INTEGER_LITERAL; - INVALID_TOKEN; + //A couple of generated types that we remap other tokens to, to simplify the generated AST + LABEL; + INTEGER_LITERAL; + + //I_* tokens are imaginary tokens used as parent AST nodes + I_CLASS_DEF; + I_SUPER; + I_IMPLEMENTS; + I_SOURCE; + I_ACCESS_LIST; + I_METHODS; + I_FIELDS; + I_FIELD; + I_FIELD_TYPE; + I_FIELD_INITIAL_VALUE; + I_METHOD; + I_METHOD_PROTOTYPE; + I_METHOD_RETURN_TYPE; + I_REGISTERS; + I_LOCALS; + I_LABELS; + I_LABEL; + I_ANNOTATIONS; + I_ANNOTATION; + I_ANNOTATION_ELEMENT; + I_SUBANNOTATION; + I_ENCODED_FIELD; + I_ENCODED_METHOD; + I_ENCODED_ENUM; + I_ENCODED_ARRAY; + I_ARRAY_ELEMENT_SIZE; + I_ARRAY_ELEMENTS; + I_PACKED_SWITCH_START_KEY; + I_PACKED_SWITCH_TARGET_COUNT; + I_PACKED_SWITCH_TARGETS; + I_PACKED_SWITCH_DECLARATION; + I_PACKED_SWITCH_DECLARATIONS; + I_SPARSE_SWITCH_KEYS; + I_SPARSE_SWITCH_TARGET_COUNT; + I_SPARSE_SWITCH_TARGETS; + I_SPARSE_SWITCH_DECLARATION; + I_SPARSE_SWITCH_DECLARATIONS; + I_ADDRESS; + I_CATCH; + I_CATCHALL; + I_CATCHES; + I_PARAMETER; + I_PARAMETERS; + I_PARAMETER_NOT_SPECIFIED; + I_ORDERED_DEBUG_DIRECTIVES; + I_LINE; + I_LOCAL; + I_END_LOCAL; + I_RESTART_LOCAL; + I_PROLOGUE; + I_EPILOGUE; + I_STATEMENTS; + I_STATEMENT_FORMAT10t; + I_STATEMENT_FORMAT10x; + I_STATEMENT_FORMAT11n; + I_STATEMENT_FORMAT11x; + I_STATEMENT_FORMAT12x; + I_STATEMENT_FORMAT20bc; + I_STATEMENT_FORMAT20t; + I_STATEMENT_FORMAT21c_TYPE; + I_STATEMENT_FORMAT21c_FIELD; + I_STATEMENT_FORMAT21c_STRING; + I_STATEMENT_FORMAT21h; + I_STATEMENT_FORMAT21s; + I_STATEMENT_FORMAT21t; + I_STATEMENT_FORMAT22b; + I_STATEMENT_FORMAT22c_FIELD; + I_STATEMENT_FORMAT22c_TYPE; + I_STATEMENT_FORMAT22s; + I_STATEMENT_FORMAT22t; + I_STATEMENT_FORMAT22x; + I_STATEMENT_FORMAT23x; + I_STATEMENT_FORMAT30t; + I_STATEMENT_FORMAT31c; + I_STATEMENT_FORMAT31i; + I_STATEMENT_FORMAT31t; + I_STATEMENT_FORMAT32x; + I_STATEMENT_FORMAT35c_METHOD; + I_STATEMENT_FORMAT35c_TYPE; + I_STATEMENT_FORMAT3rc_METHOD; + I_STATEMENT_FORMAT3rc_TYPE; + I_STATEMENT_FORMAT51l; + I_STATEMENT_ARRAY_DATA; + I_STATEMENT_PACKED_SWITCH; + I_STATEMENT_SPARSE_SWITCH; + I_REGISTER_RANGE; + I_REGISTER_LIST; } @header { @@ -138,224 +270,226 @@ import org.jf.dexlib.Code.Opcode; @members { - private boolean verboseErrors = false; - private boolean allowOdex = false; - private int apiLevel; + public static final int ERROR_CHANNEL = 100; - public void setVerboseErrors(boolean verboseErrors) { - this.verboseErrors = verboseErrors; - } + private boolean verboseErrors = false; + private boolean allowOdex = false; + private int apiLevel; - public void setAllowOdex(boolean allowOdex) { - this.allowOdex = allowOdex; - } + public void setVerboseErrors(boolean verboseErrors) { + this.verboseErrors = verboseErrors; + } - public void setApiLevel(int apiLevel) { - this.apiLevel = apiLevel; - } + public void setAllowOdex(boolean allowOdex) { + this.allowOdex = allowOdex; + } - public String getErrorMessage(RecognitionException e, - String[] tokenNames) { + public void setApiLevel(int apiLevel) { + this.apiLevel = apiLevel; + } - if (verboseErrors) { - List stack = getRuleInvocationStack(e, this.getClass().getName()); - String msg = null; + public String getErrorMessage(RecognitionException e, + String[] tokenNames) { - if (e instanceof NoViableAltException) { - NoViableAltException nvae = (NoViableAltException)e; - msg = " no viable alt; token="+getTokenErrorDisplay(e.token)+ - " (decision="+nvae.decisionNumber+ - " state "+nvae.stateNumber+")"+ - " decision=<<"+nvae.grammarDecisionDescription+">>"; - } else { - msg = super.getErrorMessage(e, tokenNames); - } + if (verboseErrors) { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = null; - return stack + " " + msg; - } else { - return super.getErrorMessage(e, tokenNames); - } - } + if (e instanceof NoViableAltException) { + NoViableAltException nvae = (NoViableAltException)e; + msg = " no viable alt; token="+getTokenErrorDisplay(e.token)+ + " (decision="+nvae.decisionNumber+ + " state "+nvae.stateNumber+")"+ + " decision=<<"+nvae.grammarDecisionDescription+">>"; + } else { + msg = super.getErrorMessage(e, tokenNames); + } - public String getTokenErrorDisplay(Token t) { - if (!verboseErrors) { - String s = t.getText(); - if ( s==null ) { - if ( t.getType()==Token.EOF ) { - s = ""; - } - else { - s = "<"+tokenNames[t.getType()]+">"; - } - } - s = s.replaceAll("\n","\\\\n"); - s = s.replaceAll("\r","\\\\r"); - s = s.replaceAll("\t","\\\\t"); - return "'"+s+"'"; - } + return stack + " " + msg; + } else { + return super.getErrorMessage(e, tokenNames); + } + } - CommonToken ct = (CommonToken)t; + public String getTokenErrorDisplay(Token t) { + if (!verboseErrors) { + String s = t.getText(); + if ( s==null ) { + if ( t.getType()==Token.EOF ) { + s = ""; + } + else { + s = "<"+tokenNames[t.getType()]+">"; + } + } + s = s.replaceAll("\n","\\\\n"); + s = s.replaceAll("\r","\\\\r"); + s = s.replaceAll("\t","\\\\t"); + return "'"+s+"'"; + } - String channelStr = ""; - if (t.getChannel()>0) { - channelStr=",channel="+t.getChannel(); - } - String txt = t.getText(); - if ( txt!=null ) { - txt = txt.replaceAll("\n","\\\\n"); - txt = txt.replaceAll("\r","\\\\r"); - txt = txt.replaceAll("\t","\\\\t"); - } - else { - txt = ""; - } - return "[@"+t.getTokenIndex()+","+ct.getStartIndex()+":"+ct.getStopIndex()+"='"+txt+"',<"+tokenNames[t.getType()]+">"+channelStr+","+t.getLine()+":"+t.getCharPositionInLine()+"]"; - } + CommonToken ct = (CommonToken)t; - public String getErrorHeader(RecognitionException e) { - return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; - } + String channelStr = ""; + if (t.getChannel()>0) { + channelStr=",channel="+t.getChannel(); + } + String txt = t.getText(); + if ( txt!=null ) { + txt = txt.replaceAll("\n","\\\\n"); + txt = txt.replaceAll("\r","\\\\r"); + txt = txt.replaceAll("\t","\\\\t"); + } + else { + txt = ""; + } + return "[@"+t.getTokenIndex()+","+ct.getStartIndex()+":"+ct.getStopIndex()+"='"+txt+"',<"+tokenNames[t.getType()]+">"+channelStr+","+t.getLine()+":"+t.getCharPositionInLine()+"]"; + } - private CommonTree buildTree(int type, String text, List children) { - CommonTree root = new CommonTree(new CommonToken(type, text)); - for (CommonTree child: children) { - root.addChild(child); - } - return root; - } + public String getErrorHeader(RecognitionException e) { + return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; + } - private CommonToken getParamListSubToken(CommonToken baseToken, String str, int typeStartIndex) { - CommonToken token = new CommonToken(baseToken); - token.setStartIndex(baseToken.getStartIndex() + typeStartIndex); + private CommonTree buildTree(int type, String text, List children) { + CommonTree root = new CommonTree(new CommonToken(type, text)); + for (CommonTree child: children) { + root.addChild(child); + } + return root; + } - switch (str.charAt(typeStartIndex)) { - case 'Z': - case 'B': - case 'S': - case 'C': - case 'I': - case 'J': - case 'F': - case 'D': - { - token.setType(PRIMITIVE_TYPE); - token.setText(str.substring(typeStartIndex, typeStartIndex+1)); - token.setStopIndex(baseToken.getStartIndex() + typeStartIndex); - break; - } - case 'L': - { - int i = typeStartIndex; - while (str.charAt(++i) != ';'); + private CommonToken getParamListSubToken(CommonToken baseToken, String str, int typeStartIndex) { + CommonToken token = new CommonToken(baseToken); + token.setStartIndex(baseToken.getStartIndex() + typeStartIndex); - token.setType(CLASS_DESCRIPTOR); - token.setText(str.substring(typeStartIndex, i + 1)); - token.setStopIndex(baseToken.getStartIndex() + i); - break; - } - case '[': - { - int i = typeStartIndex; - while (str.charAt(++i) == '['); + switch (str.charAt(typeStartIndex)) { + case 'Z': + case 'B': + case 'S': + case 'C': + case 'I': + case 'J': + case 'F': + case 'D': + { + token.setType(PRIMITIVE_TYPE); + token.setText(str.substring(typeStartIndex, typeStartIndex+1)); + token.setStopIndex(baseToken.getStartIndex() + typeStartIndex); + break; + } + case 'L': + { + int i = typeStartIndex; + while (str.charAt(++i) != ';'); - if (str.charAt(i++) == 'L') { - while (str.charAt(i++) != ';'); - } + token.setType(CLASS_DESCRIPTOR); + token.setText(str.substring(typeStartIndex, i + 1)); + token.setStopIndex(baseToken.getStartIndex() + i); + break; + } + case '[': + { + int i = typeStartIndex; + while (str.charAt(++i) == '['); - token.setType(ARRAY_DESCRIPTOR); - token.setText(str.substring(typeStartIndex, i)); - token.setStopIndex(baseToken.getStartIndex() + i - 1); - break; - } - default: - throw new RuntimeException(String.format("Invalid character '\%c' in param list \"\%s\" at position \%d", str.charAt(typeStartIndex), str, typeStartIndex)); - } + if (str.charAt(i++) == 'L') { + while (str.charAt(i++) != ';'); + } - return token; - } + token.setType(ARRAY_DESCRIPTOR); + token.setText(str.substring(typeStartIndex, i)); + token.setStopIndex(baseToken.getStartIndex() + i - 1); + break; + } + default: + throw new RuntimeException(String.format("Invalid character '\%c' in param list \"\%s\" at position \%d", str.charAt(typeStartIndex), str, typeStartIndex)); + } - private CommonTree parseParamList(CommonToken paramListToken) { - String paramList = paramListToken.getText(); - CommonTree root = new CommonTree(); + return token; + } - int startIndex = paramListToken.getStartIndex(); + private CommonTree parseParamList(CommonToken paramListToken) { + String paramList = paramListToken.getText(); + CommonTree root = new CommonTree(); - int i=0; - while (i classAnnotations; - } - @init - { $smali_file::hasClassSpec = $smali_file::hasSuperSpec = $smali_file::hasSourceSpec = false; - $smali_file::classAnnotations = new ArrayList(); - } - : - ( {!$smali_file::hasClassSpec}?=> class_spec {$smali_file::hasClassSpec = true;} - | {!$smali_file::hasSuperSpec}?=> super_spec {$smali_file::hasSuperSpec = true;} - | implements_spec - | {!$smali_file::hasSourceSpec}?=> source_spec {$smali_file::hasSourceSpec = true;} - | method - | field - | annotation {$smali_file::classAnnotations.add($annotation.tree);} - )+ - EOF - { - if (!$smali_file::hasClassSpec) { - throw new SemanticException(input, "The file must contain a .class directive"); - } + scope + { + boolean hasClassSpec; + boolean hasSuperSpec; + boolean hasSourceSpec; + List classAnnotations; + } + @init + { $smali_file::hasClassSpec = $smali_file::hasSuperSpec = $smali_file::hasSourceSpec = false; + $smali_file::classAnnotations = new ArrayList(); + } + : + ( {!$smali_file::hasClassSpec}?=> class_spec {$smali_file::hasClassSpec = true;} + | {!$smali_file::hasSuperSpec}?=> super_spec {$smali_file::hasSuperSpec = true;} + | implements_spec + | {!$smali_file::hasSourceSpec}?=> source_spec {$smali_file::hasSourceSpec = true;} + | method + | field + | annotation {$smali_file::classAnnotations.add($annotation.tree);} + )+ + EOF + { + if (!$smali_file::hasClassSpec) { + throw new SemanticException(input, "The file must contain a .class directive"); + } - if (!$smali_file::hasSuperSpec) { - if (!$class_spec.className.equals("Ljava/lang/Object;")) { - throw new SemanticException(input, "The file must contain a .super directive"); - } - } - } - -> ^(I_CLASS_DEF - class_spec - super_spec? - implements_spec* - source_spec? - ^(I_METHODS method*) ^(I_FIELDS field*) {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $smali_file::classAnnotations)}); + if (!$smali_file::hasSuperSpec) { + if (!$class_spec.className.equals("Ljava/lang/Object;")) { + throw new SemanticException(input, "The file must contain a .super directive"); + } + } + } + -> ^(I_CLASS_DEF + class_spec + super_spec? + implements_spec* + source_spec? + ^(I_METHODS method*) ^(I_FIELDS field*) {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $smali_file::classAnnotations)}); class_spec returns[String className] - : CLASS_DIRECTIVE access_list CLASS_DESCRIPTOR {$className = $CLASS_DESCRIPTOR.text;} -> CLASS_DESCRIPTOR access_list; + : CLASS_DIRECTIVE access_list CLASS_DESCRIPTOR {$className = $CLASS_DESCRIPTOR.text;} -> CLASS_DESCRIPTOR access_list; super_spec - : SUPER_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_SUPER[$start, "I_SUPER"] CLASS_DESCRIPTOR); + : SUPER_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_SUPER[$start, "I_SUPER"] CLASS_DESCRIPTOR); implements_spec - : IMPLEMENTS_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_IMPLEMENTS[$start, "I_IMPLEMENTS"] CLASS_DESCRIPTOR); + : IMPLEMENTS_DIRECTIVE CLASS_DESCRIPTOR -> ^(I_IMPLEMENTS[$start, "I_IMPLEMENTS"] CLASS_DESCRIPTOR); source_spec - : SOURCE_DIRECTIVE STRING_LITERAL -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL); + : SOURCE_DIRECTIVE STRING_LITERAL -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL); access_list - : ACCESS_SPEC* -> ^(I_ACCESS_LIST[$start,"I_ACCESS_LIST"] ACCESS_SPEC*); + : ACCESS_SPEC* -> ^(I_ACCESS_LIST[$start,"I_ACCESS_LIST"] ACCESS_SPEC*); /*When there are annotations immediately after a field definition, we don't know whether they are field annotations @@ -363,699 +497,702 @@ or class annotations until we determine if there is an .end field directive. In the annotations. If it turns out that they are field annotations, we include them in the I_FIELD AST. Otherwise, we add them to the $smali_file::classAnnotations list*/ field - @init {List annotations = new ArrayList();} - : FIELD_DIRECTIVE access_list simple_name COLON nonvoid_type_descriptor (EQUAL literal)? - ( ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* - ( END_FIELD_DIRECTIVE - -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*)) - | /*epsilon*/ {$smali_file::classAnnotations.addAll(annotations);} - -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS)) - ) - ); + @init {List annotations = new ArrayList();} + : FIELD_DIRECTIVE access_list simple_name COLON nonvoid_type_descriptor (EQUAL literal)? + ( ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* + ( END_FIELD_DIRECTIVE + -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*)) + | /*epsilon*/ {$smali_file::classAnnotations.addAll(annotations);} + -> ^(I_FIELD[$start, "I_FIELD"] simple_name access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS)) + ) + ); method - scope {int currentAddress;} - : {$method::currentAddress = 0;} - METHOD_DIRECTIVE access_list method_name method_prototype statements_and_directives - END_METHOD_DIRECTIVE - -> ^(I_METHOD[$start, "I_METHOD"] method_name method_prototype access_list statements_and_directives); + scope {int currentAddress;} + : {$method::currentAddress = 0;} + METHOD_DIRECTIVE access_list method_name method_prototype statements_and_directives + END_METHOD_DIRECTIVE + -> ^(I_METHOD[$start, "I_METHOD"] method_name method_prototype access_list statements_and_directives); statements_and_directives - scope - { - boolean hasRegistersDirective; - List packedSwitchDeclarations; - List sparseSwitchDeclarations; - List methodAnnotations; - } - : { - $method::currentAddress = 0; - $statements_and_directives::hasRegistersDirective = false; - $statements_and_directives::packedSwitchDeclarations = new ArrayList(); - $statements_and_directives::sparseSwitchDeclarations = new ArrayList(); - $statements_and_directives::methodAnnotations = new ArrayList(); - } - ( instruction {$method::currentAddress += $instruction.size/2;} - | registers_directive - | label - | catch_directive - | catchall_directive - | parameter_directive - | ordered_debug_directive - | annotation {$statements_and_directives::methodAnnotations.add($annotation.tree);} - )* - -> registers_directive? - ^(I_LABELS label*) - {buildTree(I_PACKED_SWITCH_DECLARATIONS, "I_PACKED_SWITCH_DECLARATIONS", $statements_and_directives::packedSwitchDeclarations)} - {buildTree(I_SPARSE_SWITCH_DECLARATIONS, "I_SPARSE_SWITCH_DECLARATIONS", $statements_and_directives::sparseSwitchDeclarations)} - ^(I_STATEMENTS instruction*) - ^(I_CATCHES catch_directive* catchall_directive*) - ^(I_PARAMETERS parameter_directive*) - ^(I_ORDERED_DEBUG_DIRECTIVES ordered_debug_directive*) - {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $statements_and_directives::methodAnnotations)}; + scope + { + boolean hasRegistersDirective; + List packedSwitchDeclarations; + List sparseSwitchDeclarations; + List methodAnnotations; + } + : { + $method::currentAddress = 0; + $statements_and_directives::hasRegistersDirective = false; + $statements_and_directives::packedSwitchDeclarations = new ArrayList(); + $statements_and_directives::sparseSwitchDeclarations = new ArrayList(); + $statements_and_directives::methodAnnotations = new ArrayList(); + } + ( instruction {$method::currentAddress += $instruction.size/2;} + | registers_directive + | label + | catch_directive + | catchall_directive + | parameter_directive + | ordered_debug_directive + | annotation {$statements_and_directives::methodAnnotations.add($annotation.tree);} + )* + -> registers_directive? + ^(I_LABELS label*) + {buildTree(I_PACKED_SWITCH_DECLARATIONS, "I_PACKED_SWITCH_DECLARATIONS", $statements_and_directives::packedSwitchDeclarations)} + {buildTree(I_SPARSE_SWITCH_DECLARATIONS, "I_SPARSE_SWITCH_DECLARATIONS", $statements_and_directives::sparseSwitchDeclarations)} + ^(I_STATEMENTS instruction*) + ^(I_CATCHES catch_directive* catchall_directive*) + ^(I_PARAMETERS parameter_directive*) + ^(I_ORDERED_DEBUG_DIRECTIVES ordered_debug_directive*) + {buildTree(I_ANNOTATIONS, "I_ANNOTATIONS", $statements_and_directives::methodAnnotations)}; registers_directive - : ( - directive=REGISTERS_DIRECTIVE regCount=integral_literal -> ^(I_REGISTERS[$REGISTERS_DIRECTIVE, "I_REGISTERS"] $regCount) - | directive=LOCALS_DIRECTIVE regCount2=integral_literal -> ^(I_LOCALS[$LOCALS_DIRECTIVE, "I_LOCALS"] $regCount2) - ) - { - if ($statements_and_directives::hasRegistersDirective) { - throw new SemanticException(input, $directive, "There can only be a single .registers or .locals directive in a method"); - } - $statements_and_directives::hasRegistersDirective=true; - }; + : ( + directive=REGISTERS_DIRECTIVE regCount=integral_literal -> ^(I_REGISTERS[$REGISTERS_DIRECTIVE, "I_REGISTERS"] $regCount) + | directive=LOCALS_DIRECTIVE regCount2=integral_literal -> ^(I_LOCALS[$LOCALS_DIRECTIVE, "I_LOCALS"] $regCount2) + ) + { + if ($statements_and_directives::hasRegistersDirective) { + throw new SemanticException(input, $directive, "There can only be a single .registers or .locals directive in a method"); + } + $statements_and_directives::hasRegistersDirective=true; + }; /*identifiers are much more general than most languages. Any of the below can either be the indicated type OR an identifier, depending on the context*/ simple_name - : SIMPLE_NAME - | ACCESS_SPEC -> SIMPLE_NAME[$ACCESS_SPEC] - | VERIFICATION_ERROR_TYPE -> SIMPLE_NAME[$VERIFICATION_ERROR_TYPE] - | POSITIVE_INTEGER_LITERAL -> SIMPLE_NAME[$POSITIVE_INTEGER_LITERAL] - | NEGATIVE_INTEGER_LITERAL -> SIMPLE_NAME[$NEGATIVE_INTEGER_LITERAL] - | INTEGER_LITERAL -> SIMPLE_NAME[$INTEGER_LITERAL] - | FLOAT_LITERAL_OR_ID -> SIMPLE_NAME[$FLOAT_LITERAL_OR_ID] - | DOUBLE_LITERAL_OR_ID -> SIMPLE_NAME[$DOUBLE_LITERAL_OR_ID] - | BOOL_LITERAL -> SIMPLE_NAME[$BOOL_LITERAL] - | NULL_LITERAL -> SIMPLE_NAME[$NULL_LITERAL] - | REGISTER -> SIMPLE_NAME[$REGISTER] - | PARAM_LIST_OR_ID -> SIMPLE_NAME[$PARAM_LIST_OR_ID] - | PRIMITIVE_TYPE -> SIMPLE_NAME[$PRIMITIVE_TYPE] - | VOID_TYPE -> SIMPLE_NAME[$VOID_TYPE] - | ANNOTATION_VISIBILITY -> SIMPLE_NAME[$ANNOTATION_VISIBILITY] - | INSTRUCTION_FORMAT10t -> SIMPLE_NAME[$INSTRUCTION_FORMAT10t] - | INSTRUCTION_FORMAT10x -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x] - | INSTRUCTION_FORMAT10x_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x_ODEX] - | INSTRUCTION_FORMAT11x -> SIMPLE_NAME[$INSTRUCTION_FORMAT11x] - | INSTRUCTION_FORMAT12x_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT12x_OR_ID] - | INSTRUCTION_FORMAT21c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD] - | INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX] - | INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING] - | INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE] - | INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t] - | INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD] - | INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX] - | INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE] - | INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD] - | INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID] - | INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t] - | INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x] - | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID] - | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t] - | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] - | INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX] - | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] - | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] - | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] - | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l]; + : SIMPLE_NAME + | ACCESS_SPEC -> SIMPLE_NAME[$ACCESS_SPEC] + | VERIFICATION_ERROR_TYPE -> SIMPLE_NAME[$VERIFICATION_ERROR_TYPE] + | POSITIVE_INTEGER_LITERAL -> SIMPLE_NAME[$POSITIVE_INTEGER_LITERAL] + | NEGATIVE_INTEGER_LITERAL -> SIMPLE_NAME[$NEGATIVE_INTEGER_LITERAL] + | FLOAT_LITERAL_OR_ID -> SIMPLE_NAME[$FLOAT_LITERAL_OR_ID] + | DOUBLE_LITERAL_OR_ID -> SIMPLE_NAME[$DOUBLE_LITERAL_OR_ID] + | BOOL_LITERAL -> SIMPLE_NAME[$BOOL_LITERAL] + | NULL_LITERAL -> SIMPLE_NAME[$NULL_LITERAL] + | REGISTER -> SIMPLE_NAME[$REGISTER] + | PARAM_LIST_OR_ID -> SIMPLE_NAME[$PARAM_LIST_OR_ID] + | PRIMITIVE_TYPE -> SIMPLE_NAME[$PRIMITIVE_TYPE] + | VOID_TYPE -> SIMPLE_NAME[$VOID_TYPE] + | ANNOTATION_VISIBILITY -> SIMPLE_NAME[$ANNOTATION_VISIBILITY] + | INSTRUCTION_FORMAT10t -> SIMPLE_NAME[$INSTRUCTION_FORMAT10t] + | INSTRUCTION_FORMAT10x -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x] + | INSTRUCTION_FORMAT10x_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT10x_ODEX] + | INSTRUCTION_FORMAT11x -> SIMPLE_NAME[$INSTRUCTION_FORMAT11x] + | INSTRUCTION_FORMAT12x_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT12x_OR_ID] + | INSTRUCTION_FORMAT21c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD] + | INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX] + | INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING] + | INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE] + | INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t] + | INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD] + | INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX] + | INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE] + | INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD] + | INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID] + | INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t] + | INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x] + | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID] + | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t] + | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] + | INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX] + | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] + | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] + | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] + | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l]; method_name - : simple_name - | METHOD_NAME -> SIMPLE_NAME[$METHOD_NAME]; + : simple_name + | METHOD_NAME -> SIMPLE_NAME[$METHOD_NAME]; method_prototype - : OPEN_PAREN param_list CLOSE_PAREN type_descriptor - -> ^(I_METHOD_PROTOTYPE[$start, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) param_list?); + : OPEN_PAREN param_list CLOSE_PAREN type_descriptor + -> ^(I_METHOD_PROTOTYPE[$start, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) param_list?); param_list - : PARAM_LIST -> { parseParamList((CommonToken)$PARAM_LIST) } - | PARAM_LIST_OR_ID -> { parseParamList((CommonToken)$PARAM_LIST_OR_ID) } - | nonvoid_type_descriptor*; + : PARAM_LIST -> { parseParamList((CommonToken)$PARAM_LIST) } + | PARAM_LIST_OR_ID -> { parseParamList((CommonToken)$PARAM_LIST_OR_ID) } + | nonvoid_type_descriptor*; type_descriptor - : VOID_TYPE - | PRIMITIVE_TYPE - | CLASS_DESCRIPTOR - | ARRAY_DESCRIPTOR; + : VOID_TYPE + | PRIMITIVE_TYPE + | CLASS_DESCRIPTOR + | ARRAY_DESCRIPTOR; nonvoid_type_descriptor - : PRIMITIVE_TYPE - | CLASS_DESCRIPTOR - | ARRAY_DESCRIPTOR; + : PRIMITIVE_TYPE + | CLASS_DESCRIPTOR + | ARRAY_DESCRIPTOR; reference_type_descriptor - : CLASS_DESCRIPTOR - | ARRAY_DESCRIPTOR; + : CLASS_DESCRIPTOR + | ARRAY_DESCRIPTOR; integer_literal - : POSITIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$POSITIVE_INTEGER_LITERAL] - | NEGATIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$NEGATIVE_INTEGER_LITERAL] - | INTEGER_LITERAL; + : POSITIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$POSITIVE_INTEGER_LITERAL] + | NEGATIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$NEGATIVE_INTEGER_LITERAL]; float_literal - : FLOAT_LITERAL_OR_ID -> FLOAT_LITERAL[$FLOAT_LITERAL_OR_ID] - | FLOAT_LITERAL; + : FLOAT_LITERAL_OR_ID -> FLOAT_LITERAL[$FLOAT_LITERAL_OR_ID] + | FLOAT_LITERAL; double_literal - : DOUBLE_LITERAL_OR_ID -> DOUBLE_LITERAL[$DOUBLE_LITERAL_OR_ID] - | DOUBLE_LITERAL; + : DOUBLE_LITERAL_OR_ID -> DOUBLE_LITERAL[$DOUBLE_LITERAL_OR_ID] + | DOUBLE_LITERAL; literal - : LONG_LITERAL - | integer_literal - | SHORT_LITERAL - | BYTE_LITERAL - | float_literal - | double_literal - | CHAR_LITERAL - | STRING_LITERAL - | BOOL_LITERAL - | NULL_LITERAL - | array_literal - | subannotation - | type_field_method_literal - | enum_literal; + : LONG_LITERAL + | integer_literal + | SHORT_LITERAL + | BYTE_LITERAL + | float_literal + | double_literal + | CHAR_LITERAL + | STRING_LITERAL + | BOOL_LITERAL + | NULL_LITERAL + | array_literal + | subannotation + | type_field_method_literal + | enum_literal; integral_literal - : LONG_LITERAL - | integer_literal - | SHORT_LITERAL - | CHAR_LITERAL - | BYTE_LITERAL; + : LONG_LITERAL + | integer_literal + | SHORT_LITERAL + | CHAR_LITERAL + | BYTE_LITERAL; fixed_32bit_literal - : LONG_LITERAL - | integer_literal - | SHORT_LITERAL - | BYTE_LITERAL - | float_literal - | CHAR_LITERAL - | BOOL_LITERAL; + : LONG_LITERAL + | integer_literal + | SHORT_LITERAL + | BYTE_LITERAL + | float_literal + | CHAR_LITERAL + | BOOL_LITERAL; fixed_literal returns[int size] - : integer_literal {$size = 4;} - | LONG_LITERAL {$size = 8;} - | SHORT_LITERAL {$size = 2;} - | BYTE_LITERAL {$size = 1;} - | float_literal {$size = 4;} - | double_literal {$size = 8;} - | CHAR_LITERAL {$size = 2;} - | BOOL_LITERAL {$size = 1;}; + : integer_literal {$size = 4;} + | LONG_LITERAL {$size = 8;} + | SHORT_LITERAL {$size = 2;} + | BYTE_LITERAL {$size = 1;} + | float_literal {$size = 4;} + | double_literal {$size = 8;} + | CHAR_LITERAL {$size = 2;} + | BOOL_LITERAL {$size = 1;}; array_literal - : OPEN_BRACE (literal (COMMA literal)* | ) CLOSE_BRACE - -> ^(I_ENCODED_ARRAY[$start, "I_ENCODED_ARRAY"] literal*); + : OPEN_BRACE (literal (COMMA literal)* | ) CLOSE_BRACE + -> ^(I_ENCODED_ARRAY[$start, "I_ENCODED_ARRAY"] literal*); annotation_element - : simple_name EQUAL literal - -> ^(I_ANNOTATION_ELEMENT[$start, "I_ANNOTATION_ELEMENT"] simple_name literal); + : simple_name EQUAL literal + -> ^(I_ANNOTATION_ELEMENT[$start, "I_ANNOTATION_ELEMENT"] simple_name literal); annotation - : ANNOTATION_DIRECTIVE ANNOTATION_VISIBILITY CLASS_DESCRIPTOR - annotation_element* END_ANNOTATION_DIRECTIVE - -> ^(I_ANNOTATION[$start, "I_ANNOTATION"] ANNOTATION_VISIBILITY ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*)); + : ANNOTATION_DIRECTIVE ANNOTATION_VISIBILITY CLASS_DESCRIPTOR + annotation_element* END_ANNOTATION_DIRECTIVE + -> ^(I_ANNOTATION[$start, "I_ANNOTATION"] ANNOTATION_VISIBILITY ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*)); subannotation - : SUBANNOTATION_DIRECTIVE CLASS_DESCRIPTOR annotation_element* END_SUBANNOTATION_DIRECTIVE - -> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*); + : SUBANNOTATION_DIRECTIVE CLASS_DESCRIPTOR annotation_element* END_SUBANNOTATION_DIRECTIVE + -> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*); enum_literal - : ENUM_DIRECTIVE reference_type_descriptor ARROW simple_name COLON reference_type_descriptor - -> ^(I_ENCODED_ENUM reference_type_descriptor simple_name reference_type_descriptor); + : ENUM_DIRECTIVE reference_type_descriptor ARROW simple_name COLON reference_type_descriptor + -> ^(I_ENCODED_ENUM reference_type_descriptor simple_name reference_type_descriptor); type_field_method_literal - : reference_type_descriptor - ( ARROW - ( simple_name COLON nonvoid_type_descriptor -> ^(I_ENCODED_FIELD reference_type_descriptor simple_name nonvoid_type_descriptor) - | method_name method_prototype -> ^(I_ENCODED_METHOD reference_type_descriptor method_name method_prototype) - ) - | -> reference_type_descriptor - ) - | PRIMITIVE_TYPE - | VOID_TYPE; + : reference_type_descriptor + ( ARROW + ( simple_name COLON nonvoid_type_descriptor -> ^(I_ENCODED_FIELD reference_type_descriptor simple_name nonvoid_type_descriptor) + | method_name method_prototype -> ^(I_ENCODED_METHOD reference_type_descriptor method_name method_prototype) + ) + | -> reference_type_descriptor + ) + | PRIMITIVE_TYPE + | VOID_TYPE; fully_qualified_method - : reference_type_descriptor ARROW method_name method_prototype - -> reference_type_descriptor method_name method_prototype; + : reference_type_descriptor ARROW method_name method_prototype + -> reference_type_descriptor method_name method_prototype; fully_qualified_field - : reference_type_descriptor ARROW simple_name COLON nonvoid_type_descriptor - -> reference_type_descriptor simple_name nonvoid_type_descriptor; + : reference_type_descriptor ARROW simple_name COLON nonvoid_type_descriptor + -> reference_type_descriptor simple_name nonvoid_type_descriptor; label - : COLON simple_name -> ^(I_LABEL[$COLON, "I_LABEL"] simple_name I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : COLON simple_name -> ^(I_LABEL[$COLON, "I_LABEL"] simple_name I_ADDRESS[$start, Integer.toString($method::currentAddress)]); label_ref_or_offset - : COLON simple_name -> simple_name - | OFFSET - | NEGATIVE_INTEGER_LITERAL -> OFFSET[$NEGATIVE_INTEGER_LITERAL]; + : COLON simple_name -> simple_name + | OFFSET + | NEGATIVE_INTEGER_LITERAL -> OFFSET[$NEGATIVE_INTEGER_LITERAL]; register_list - : REGISTER (COMMA REGISTER)* -> ^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"] REGISTER*) - | ->^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"]); + : REGISTER (COMMA REGISTER)* -> ^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"] REGISTER*) + | ->^(I_REGISTER_LIST[$start, "I_REGISTER_LIST"]); register_range - : (startreg=REGISTER (DOTDOT endreg=REGISTER)?)? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] $startreg? $endreg?); + : (startreg=REGISTER (DOTDOT endreg=REGISTER)?)? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] $startreg? $endreg?); verification_error_reference - : CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method; + : CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method; catch_directive - : CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset - -> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using); + : CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset + -> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using); catchall_directive - : CATCHALL_DIRECTIVE OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset - -> ^(I_CATCHALL[$start, "I_CATCHALL"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] $from $to $using); + : CATCHALL_DIRECTIVE OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset + -> ^(I_CATCHALL[$start, "I_CATCHALL"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] $from $to $using); /*When there are annotations immediately after a parameter definition, we don't know whether they are parameter annotations or method annotations until we determine if there is an .end parameter directive. In either case, we still "consume" and parse the annotations. If it turns out that they are parameter annotations, we include them in the I_PARAMETER AST. Otherwise, we add them to the $statements_and_directives::methodAnnotations list*/ parameter_directive - @init {List annotations = new ArrayList();} - : PARAMETER_DIRECTIVE - STRING_LITERAL? - ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* + @init {List annotations = new ArrayList();} + : PARAMETER_DIRECTIVE + STRING_LITERAL? + ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* - ( END_PARAMETER_DIRECTIVE - -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS annotation*)) - | /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);} - -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS)) - ); + ( END_PARAMETER_DIRECTIVE + -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS annotation*)) + | /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);} + -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS)) + ); ordered_debug_directive - : line_directive - | local_directive - | end_local_directive - | restart_local_directive - | prologue_directive - | epilogue_directive - | source_directive; + : line_directive + | local_directive + | end_local_directive + | restart_local_directive + | prologue_directive + | epilogue_directive + | source_directive; line_directive - : LINE_DIRECTIVE integral_literal - -> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : LINE_DIRECTIVE integral_literal + -> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]); local_directive - : LOCAL_DIRECTIVE REGISTER COMMA simple_name COLON nonvoid_type_descriptor (COMMA STRING_LITERAL)? - -> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER simple_name nonvoid_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : LOCAL_DIRECTIVE REGISTER COMMA simple_name COLON nonvoid_type_descriptor (COMMA STRING_LITERAL)? + -> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER simple_name nonvoid_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]); end_local_directive - : END_LOCAL_DIRECTIVE REGISTER - -> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : END_LOCAL_DIRECTIVE REGISTER + -> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]); restart_local_directive - : RESTART_LOCAL_DIRECTIVE REGISTER - -> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : RESTART_LOCAL_DIRECTIVE REGISTER + -> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]); prologue_directive - : PROLOGUE_DIRECTIVE - -> ^(I_PROLOGUE[$start, "I_PROLOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : PROLOGUE_DIRECTIVE + -> ^(I_PROLOGUE[$start, "I_PROLOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); epilogue_directive - : EPILOGUE_DIRECTIVE - -> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : EPILOGUE_DIRECTIVE + -> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); source_directive - : SOURCE_DIRECTIVE STRING_LITERAL - -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : SOURCE_DIRECTIVE STRING_LITERAL + -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL I_ADDRESS[$start, Integer.toString($method::currentAddress)]); instruction_format12x - : INSTRUCTION_FORMAT12x - | INSTRUCTION_FORMAT12x_OR_ID -> INSTRUCTION_FORMAT12x[$INSTRUCTION_FORMAT12x_OR_ID]; + : INSTRUCTION_FORMAT12x + | INSTRUCTION_FORMAT12x_OR_ID -> INSTRUCTION_FORMAT12x[$INSTRUCTION_FORMAT12x_OR_ID]; instruction_format22s - : INSTRUCTION_FORMAT22s - | INSTRUCTION_FORMAT22s_OR_ID -> INSTRUCTION_FORMAT22s[$INSTRUCTION_FORMAT22s_OR_ID]; + : INSTRUCTION_FORMAT22s + | INSTRUCTION_FORMAT22s_OR_ID -> INSTRUCTION_FORMAT22s[$INSTRUCTION_FORMAT22s_OR_ID]; instruction_format31i - : INSTRUCTION_FORMAT31i - | INSTRUCTION_FORMAT31i_OR_ID -> INSTRUCTION_FORMAT31i[$INSTRUCTION_FORMAT31i_OR_ID]; + : INSTRUCTION_FORMAT31i + | INSTRUCTION_FORMAT31i_OR_ID -> INSTRUCTION_FORMAT31i[$INSTRUCTION_FORMAT31i_OR_ID]; instruction returns [int size] - : insn_format10t { $size = $insn_format10t.size; } - | insn_format10x { $size = $insn_format10x.size; } - | insn_format10x_odex { $size = $insn_format10x_odex.size; } - | insn_format11n { $size = $insn_format11n.size; } - | insn_format11x { $size = $insn_format11x.size; } - | insn_format12x { $size = $insn_format12x.size; } - | insn_format20bc { $size = $insn_format20bc.size; } - | insn_format20t { $size = $insn_format20t.size; } - | insn_format21c_field { $size = $insn_format21c_field.size; } - | insn_format21c_field_odex { $size = $insn_format21c_field_odex.size; } - | insn_format21c_string { $size = $insn_format21c_string.size; } - | insn_format21c_type { $size = $insn_format21c_type.size; } - | insn_format21h { $size = $insn_format21h.size; } - | insn_format21s { $size = $insn_format21s.size; } - | insn_format21t { $size = $insn_format21t.size; } - | insn_format22b { $size = $insn_format22b.size; } - | insn_format22c_field { $size = $insn_format22c_field.size; } - | insn_format22c_field_odex { $size = $insn_format22c_field_odex.size; } - | insn_format22c_type { $size = $insn_format22c_type.size; } - | insn_format22cs_field { $size = $insn_format22cs_field.size; } - | insn_format22s { $size = $insn_format22s.size; } - | insn_format22t { $size = $insn_format22t.size; } - | insn_format22x { $size = $insn_format22x.size; } - | insn_format23x { $size = $insn_format23x.size; } - | insn_format30t { $size = $insn_format30t.size; } - | insn_format31c { $size = $insn_format31c.size; } - | insn_format31i { $size = $insn_format31i.size; } - | insn_format31t { $size = $insn_format31t.size; } - | insn_format32x { $size = $insn_format32x.size; } - | insn_format35c_method { $size = $insn_format35c_method.size; } - | insn_format35c_type { $size = $insn_format35c_type.size; } - | insn_format35c_method_odex { $size = $insn_format35c_method_odex.size; } - | insn_format35mi_method { $size = $insn_format35mi_method.size; } - | insn_format35ms_method { $size = $insn_format35ms_method.size; } - | insn_format3rc_method { $size = $insn_format3rc_method.size; } - | insn_format3rc_method_odex { $size = $insn_format3rc_method_odex.size; } - | insn_format3rc_type { $size = $insn_format3rc_type.size; } - | insn_format3rmi_method { $size = $insn_format3rmi_method.size; } - | insn_format3rms_method { $size = $insn_format3rms_method.size; } - | insn_format51l { $size = $insn_format51l.size; } - | insn_array_data_directive { $size = $insn_array_data_directive.size; } - | insn_packed_switch_directive { $size = $insn_packed_switch_directive.size; } - | insn_sparse_switch_directive { $size = $insn_sparse_switch_directive.size; }; + : insn_format10t { $size = $insn_format10t.size; } + | insn_format10x { $size = $insn_format10x.size; } + | insn_format10x_odex { $size = $insn_format10x_odex.size; } + | insn_format11n { $size = $insn_format11n.size; } + | insn_format11x { $size = $insn_format11x.size; } + | insn_format12x { $size = $insn_format12x.size; } + | insn_format20bc { $size = $insn_format20bc.size; } + | insn_format20t { $size = $insn_format20t.size; } + | insn_format21c_field { $size = $insn_format21c_field.size; } + | insn_format21c_field_odex { $size = $insn_format21c_field_odex.size; } + | insn_format21c_string { $size = $insn_format21c_string.size; } + | insn_format21c_type { $size = $insn_format21c_type.size; } + | insn_format21h { $size = $insn_format21h.size; } + | insn_format21s { $size = $insn_format21s.size; } + | insn_format21t { $size = $insn_format21t.size; } + | insn_format22b { $size = $insn_format22b.size; } + | insn_format22c_field { $size = $insn_format22c_field.size; } + | insn_format22c_field_odex { $size = $insn_format22c_field_odex.size; } + | insn_format22c_type { $size = $insn_format22c_type.size; } + | insn_format22cs_field { $size = $insn_format22cs_field.size; } + | insn_format22s { $size = $insn_format22s.size; } + | insn_format22t { $size = $insn_format22t.size; } + | insn_format22x { $size = $insn_format22x.size; } + | insn_format23x { $size = $insn_format23x.size; } + | insn_format30t { $size = $insn_format30t.size; } + | insn_format31c { $size = $insn_format31c.size; } + | insn_format31i { $size = $insn_format31i.size; } + | insn_format31t { $size = $insn_format31t.size; } + | insn_format32x { $size = $insn_format32x.size; } + | insn_format35c_method { $size = $insn_format35c_method.size; } + | insn_format35c_type { $size = $insn_format35c_type.size; } + | insn_format35c_method_odex { $size = $insn_format35c_method_odex.size; } + | insn_format35mi_method { $size = $insn_format35mi_method.size; } + | insn_format35ms_method { $size = $insn_format35ms_method.size; } + | insn_format3rc_method { $size = $insn_format3rc_method.size; } + | insn_format3rc_method_odex { $size = $insn_format3rc_method_odex.size; } + | insn_format3rc_type { $size = $insn_format3rc_type.size; } + | insn_format3rmi_method { $size = $insn_format3rmi_method.size; } + | insn_format3rms_method { $size = $insn_format3rms_method.size; } + | insn_format51l { $size = $insn_format51l.size; } + | insn_array_data_directive { $size = $insn_array_data_directive.size; } + | insn_packed_switch_directive { $size = $insn_packed_switch_directive.size; } + | insn_sparse_switch_directive { $size = $insn_sparse_switch_directive.size; }; insn_format10t returns [int size] - : //e.g. goto endloop: - //e.g. goto +3 - INSTRUCTION_FORMAT10t label_ref_or_offset {$size = Format.Format10t.size;} - -> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t label_ref_or_offset); + : //e.g. goto endloop: + //e.g. goto +3 + INSTRUCTION_FORMAT10t label_ref_or_offset {$size = Format.Format10t.size;} + -> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t label_ref_or_offset); insn_format10x returns [int size] - : //e.g. return-void - INSTRUCTION_FORMAT10x {$size = Format.Format10x.size;} - -> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x); + : //e.g. return-void + INSTRUCTION_FORMAT10x {$size = Format.Format10x.size;} + -> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x); insn_format10x_odex returns [int size] - : //e.g. return-void-barrier - INSTRUCTION_FORMAT10x_ODEX {$size = Format.Format10x.size;} - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT10x_ODEX.text); - }; + : //e.g. return-void-barrier + INSTRUCTION_FORMAT10x_ODEX {$size = Format.Format10x.size;} + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT10x_ODEX.text); + }; insn_format11n returns [int size] - : //e.g. const/4 v0, 5 - INSTRUCTION_FORMAT11n REGISTER COMMA integral_literal {$size = Format.Format11n.size;} - -> ^(I_STATEMENT_FORMAT11n[$start, "I_STATEMENT_FORMAT11n"] INSTRUCTION_FORMAT11n REGISTER integral_literal); + : //e.g. const/4 v0, 5 + INSTRUCTION_FORMAT11n REGISTER COMMA integral_literal {$size = Format.Format11n.size;} + -> ^(I_STATEMENT_FORMAT11n[$start, "I_STATEMENT_FORMAT11n"] INSTRUCTION_FORMAT11n REGISTER integral_literal); insn_format11x returns [int size] - : //e.g. move-result-object v1 - INSTRUCTION_FORMAT11x REGISTER {$size = Format.Format11x.size;} - -> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_FORMAT11x REGISTER); + : //e.g. move-result-object v1 + INSTRUCTION_FORMAT11x REGISTER {$size = Format.Format11x.size;} + -> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_FORMAT11x REGISTER); insn_format12x returns [int size] - : //e.g. move v1 v2 - instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;} - -> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER); + : //e.g. move v1 v2 + instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;} + -> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER); insn_format20bc returns [int size] - : //e.g. throw-verification-error generic-error, Lsome/class; - INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;} - { - if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text); - } - } - -> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference); - //TODO: check if dalvik has a jumbo version of throw-verification-error + : //e.g. throw-verification-error generic-error, Lsome/class; + INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;} + { + if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text); + } + } + -> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference); + //TODO: check if dalvik has a jumbo version of throw-verification-error insn_format20t returns [int size] - : //e.g. goto/16 endloop: - INSTRUCTION_FORMAT20t label_ref_or_offset {$size = Format.Format20t.size;} - -> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref_or_offset); + : //e.g. goto/16 endloop: + INSTRUCTION_FORMAT20t label_ref_or_offset {$size = Format.Format20t.size;} + -> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref_or_offset); insn_format21c_field returns [int size] - : //e.g. sget-object v0, java/lang/System/out LJava/io/PrintStream; - INSTRUCTION_FORMAT21c_FIELD REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} - -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field); + : //e.g. sget-object v0, java/lang/System/out LJava/io/PrintStream; + INSTRUCTION_FORMAT21c_FIELD REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} + -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field); insn_format21c_field_odex returns [int size] - : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream; - INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} - { - if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT21c_FIELD_ODEX.text); - } - } - -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER fully_qualified_field); + : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream; + INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} + { + if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT21c_FIELD_ODEX.text); + } + } + -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER fully_qualified_field); insn_format21c_string returns [int size] - : //e.g. const-string v1, "Hello World!" - INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;} - -> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL); + : //e.g. const-string v1, "Hello World!" + INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;} + -> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL); insn_format21c_type returns [int size] - : //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2; - INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;} - -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor); + : //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2; + INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;} + -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor); insn_format21h returns [int size] - : //e.g. const/high16 v1, 1234 - INSTRUCTION_FORMAT21h REGISTER COMMA integral_literal {$size = Format.Format21h.size;} - -> ^(I_STATEMENT_FORMAT21h[$start, "I_STATEMENT_FORMAT21h"] INSTRUCTION_FORMAT21h REGISTER integral_literal); + : //e.g. const/high16 v1, 1234 + INSTRUCTION_FORMAT21h REGISTER COMMA integral_literal {$size = Format.Format21h.size;} + -> ^(I_STATEMENT_FORMAT21h[$start, "I_STATEMENT_FORMAT21h"] INSTRUCTION_FORMAT21h REGISTER integral_literal); insn_format21s returns [int size] - : //e.g. const/16 v1, 1234 - INSTRUCTION_FORMAT21s REGISTER COMMA integral_literal {$size = Format.Format21s.size;} - -> ^(I_STATEMENT_FORMAT21s[$start, "I_STATEMENT_FORMAT21s"] INSTRUCTION_FORMAT21s REGISTER integral_literal); + : //e.g. const/16 v1, 1234 + INSTRUCTION_FORMAT21s REGISTER COMMA integral_literal {$size = Format.Format21s.size;} + -> ^(I_STATEMENT_FORMAT21s[$start, "I_STATEMENT_FORMAT21s"] INSTRUCTION_FORMAT21s REGISTER integral_literal); insn_format21t returns [int size] - : //e.g. if-eqz v0, endloop: - INSTRUCTION_FORMAT21t REGISTER COMMA (label_ref_or_offset) {$size = Format.Format21t.size;} - -> ^(I_STATEMENT_FORMAT21t[$start, "I_STATEMENT_FORMAT21t"] INSTRUCTION_FORMAT21t REGISTER label_ref_or_offset); + : //e.g. if-eqz v0, endloop: + INSTRUCTION_FORMAT21t REGISTER COMMA (label_ref_or_offset) {$size = Format.Format21t.size;} + -> ^(I_STATEMENT_FORMAT21t[$start, "I_STATEMENT_FORMAT21t"] INSTRUCTION_FORMAT21t REGISTER label_ref_or_offset); insn_format22b returns [int size] - : //e.g. add-int v0, v1, 123 - INSTRUCTION_FORMAT22b REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22b.size;} - -> ^(I_STATEMENT_FORMAT22b[$start, "I_STATEMENT_FORMAT22b"] INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal); + : //e.g. add-int v0, v1, 123 + INSTRUCTION_FORMAT22b REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22b.size;} + -> ^(I_STATEMENT_FORMAT22b[$start, "I_STATEMENT_FORMAT22b"] INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal); insn_format22c_field returns [int size] - : //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; - INSTRUCTION_FORMAT22c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} - -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field); + : //e.g. iput-object v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; + INSTRUCTION_FORMAT22c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} + -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field); insn_format22c_field_odex returns [int size] - : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; - INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} - { - if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22c_FIELD_ODEX.text); - } - } - -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER REGISTER fully_qualified_field); + : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; + INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} + { + if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22c_FIELD_ODEX.text); + } + } + -> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER REGISTER fully_qualified_field); insn_format22c_type returns [int size] - : //e.g. instance-of v0, v1, Ljava/lang/String; - INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format22c.size;} - -> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor); + : //e.g. instance-of v0, v1, Ljava/lang/String; + INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format22c.size;} + -> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor); insn_format22cs_field returns [int size] - : //e.g. iget-quick v0, v1, field@0xc - INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22cs_FIELD.text); - }; + : //e.g. iget-quick v0, v1, field@0xc + INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22cs_FIELD.text); + }; insn_format22s returns [int size] - : //e.g. add-int/lit16 v0, v1, 12345 - instruction_format22s REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22s.size;} - -> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] instruction_format22s REGISTER REGISTER integral_literal); + : //e.g. add-int/lit16 v0, v1, 12345 + instruction_format22s REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22s.size;} + -> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] instruction_format22s REGISTER REGISTER integral_literal); insn_format22t returns [int size] - : //e.g. if-eq v0, v1, endloop: - INSTRUCTION_FORMAT22t REGISTER COMMA REGISTER COMMA label_ref_or_offset {$size = Format.Format22t.size;} - -> ^(I_STATEMENT_FORMAT22t[$start, "I_STATEMENT_FFORMAT22t"] INSTRUCTION_FORMAT22t REGISTER REGISTER label_ref_or_offset); + : //e.g. if-eq v0, v1, endloop: + INSTRUCTION_FORMAT22t REGISTER COMMA REGISTER COMMA label_ref_or_offset {$size = Format.Format22t.size;} + -> ^(I_STATEMENT_FORMAT22t[$start, "I_STATEMENT_FFORMAT22t"] INSTRUCTION_FORMAT22t REGISTER REGISTER label_ref_or_offset); insn_format22x returns [int size] - : //e.g. move/from16 v1, v1234 - INSTRUCTION_FORMAT22x REGISTER COMMA REGISTER {$size = Format.Format22x.size;} - -> ^(I_STATEMENT_FORMAT22x[$start, "I_STATEMENT_FORMAT22x"] INSTRUCTION_FORMAT22x REGISTER REGISTER); + : //e.g. move/from16 v1, v1234 + INSTRUCTION_FORMAT22x REGISTER COMMA REGISTER {$size = Format.Format22x.size;} + -> ^(I_STATEMENT_FORMAT22x[$start, "I_STATEMENT_FORMAT22x"] INSTRUCTION_FORMAT22x REGISTER REGISTER); insn_format23x returns [int size] - : //e.g. add-int v1, v2, v3 - INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER {$size = Format.Format23x.size;} - -> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER); + : //e.g. add-int v1, v2, v3 + INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER {$size = Format.Format23x.size;} + -> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER); insn_format30t returns [int size] - : //e.g. goto/32 endloop: - INSTRUCTION_FORMAT30t label_ref_or_offset {$size = Format.Format30t.size;} - -> ^(I_STATEMENT_FORMAT30t[$start, "I_STATEMENT_FORMAT30t"] INSTRUCTION_FORMAT30t label_ref_or_offset); + : //e.g. goto/32 endloop: + INSTRUCTION_FORMAT30t label_ref_or_offset {$size = Format.Format30t.size;} + -> ^(I_STATEMENT_FORMAT30t[$start, "I_STATEMENT_FORMAT30t"] INSTRUCTION_FORMAT30t label_ref_or_offset); insn_format31c returns [int size] - : //e.g. const-string/jumbo v1 "Hello World!" - INSTRUCTION_FORMAT31c REGISTER COMMA STRING_LITERAL {$size = Format.Format31c.size;} - ->^(I_STATEMENT_FORMAT31c[$start, "I_STATEMENT_FORMAT31c"] INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL); + : //e.g. const-string/jumbo v1 "Hello World!" + INSTRUCTION_FORMAT31c REGISTER COMMA STRING_LITERAL {$size = Format.Format31c.size;} + ->^(I_STATEMENT_FORMAT31c[$start, "I_STATEMENT_FORMAT31c"] INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL); insn_format31i returns [int size] - : //e.g. const v0, 123456 - instruction_format31i REGISTER COMMA fixed_32bit_literal {$size = Format.Format31i.size;} - -> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] instruction_format31i REGISTER fixed_32bit_literal); + : //e.g. const v0, 123456 + instruction_format31i REGISTER COMMA fixed_32bit_literal {$size = Format.Format31i.size;} + -> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] instruction_format31i REGISTER fixed_32bit_literal); insn_format31t returns [int size] - : //e.g. fill-array-data v0, ArrayData: - INSTRUCTION_FORMAT31t REGISTER COMMA label_ref_or_offset {$size = Format.Format31t.size;} - { - if ($INSTRUCTION_FORMAT31t.text.equals("packed-switch")) { - CommonTree root = new CommonTree(new CommonToken(I_PACKED_SWITCH_DECLARATION, "I_PACKED_SWITCH_DECLARATION")); - CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress))); - root.addChild(address); - root.addChild($label_ref_or_offset.tree.dupNode()); - $statements_and_directives::packedSwitchDeclarations.add(root); - } else if ($INSTRUCTION_FORMAT31t.text.equals("sparse-switch")) { - CommonTree root = new CommonTree(new CommonToken(I_SPARSE_SWITCH_DECLARATION, "I_SPARSE_SWITCH_DECLARATION")); - CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress))); - root.addChild(address); - root.addChild($label_ref_or_offset.tree.dupNode()); - $statements_and_directives::sparseSwitchDeclarations.add(root); - } - } - -> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER label_ref_or_offset); + : //e.g. fill-array-data v0, ArrayData: + INSTRUCTION_FORMAT31t REGISTER COMMA label_ref_or_offset {$size = Format.Format31t.size;} + { + if ($INSTRUCTION_FORMAT31t.text.equals("packed-switch")) { + CommonTree root = new CommonTree(new CommonToken(I_PACKED_SWITCH_DECLARATION, "I_PACKED_SWITCH_DECLARATION")); + CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress))); + root.addChild(address); + root.addChild($label_ref_or_offset.tree.dupNode()); + $statements_and_directives::packedSwitchDeclarations.add(root); + } else if ($INSTRUCTION_FORMAT31t.text.equals("sparse-switch")) { + CommonTree root = new CommonTree(new CommonToken(I_SPARSE_SWITCH_DECLARATION, "I_SPARSE_SWITCH_DECLARATION")); + CommonTree address = new CommonTree(new CommonToken(I_ADDRESS, Integer.toString($method::currentAddress))); + root.addChild(address); + root.addChild($label_ref_or_offset.tree.dupNode()); + $statements_and_directives::sparseSwitchDeclarations.add(root); + } + } + -> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER label_ref_or_offset); insn_format32x returns [int size] - : //e.g. move/16 v4567, v1234 - INSTRUCTION_FORMAT32x REGISTER COMMA REGISTER {$size = Format.Format32x.size;} - -> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER); + : //e.g. move/16 v4567, v1234 + INSTRUCTION_FORMAT32x REGISTER COMMA REGISTER {$size = Format.Format32x.size;} + -> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER); insn_format35c_method returns [int size] - : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V - INSTRUCTION_FORMAT35c_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format35c.size;} - -> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method); + : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V + INSTRUCTION_FORMAT35c_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format35c.size;} + -> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method); insn_format35c_type returns [int size] - : //e.g. filled-new-array {v0,v1}, I - INSTRUCTION_FORMAT35c_TYPE OPEN_BRACE register_list CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format35c.size;} - -> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor); + : //e.g. filled-new-array {v0,v1}, I + INSTRUCTION_FORMAT35c_TYPE OPEN_BRACE register_list CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format35c.size;} + -> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor); insn_format35c_method_odex returns [int size] - : //e.g. invoke-direct {p0}, Ljava/lang/Object;->()V - INSTRUCTION_FORMAT35c_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35c_METHOD_ODEX.text); - }; + : //e.g. invoke-direct {p0}, Ljava/lang/Object;->()V + INSTRUCTION_FORMAT35c_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35c_METHOD_ODEX.text); + }; insn_format35mi_method returns [int size] - : //e.g. execute-inline {v0, v1}, inline@0x4 - INSTRUCTION_FORMAT35mi_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA INLINE_INDEX - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35mi_METHOD.text); - }; + : //e.g. execute-inline {v0, v1}, inline@0x4 + INSTRUCTION_FORMAT35mi_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA INLINE_INDEX + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35mi_METHOD.text); + }; insn_format35ms_method returns [int size] - : //e.g. invoke-virtual-quick {v0, v1}, vtable@0x4 - INSTRUCTION_FORMAT35ms_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA VTABLE_INDEX - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35ms_METHOD.text); - }; + : //e.g. invoke-virtual-quick {v0, v1}, vtable@0x4 + INSTRUCTION_FORMAT35ms_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA VTABLE_INDEX + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35ms_METHOD.text); + }; insn_format3rc_method returns [int size] - : //e.g. invoke-virtual/range {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; - INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format3rc.size;} - -> ^(I_STATEMENT_FORMAT3rc_METHOD[$start, "I_STATEMENT_FORMAT3rc_METHOD"] INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method); + : //e.g. invoke-virtual/range {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; + INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format3rc.size;} + -> ^(I_STATEMENT_FORMAT3rc_METHOD[$start, "I_STATEMENT_FORMAT3rc_METHOD"] INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method); insn_format3rc_method_odex returns [int size] - : //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;->()V - INSTRUCTION_FORMAT3rc_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rc_METHOD_ODEX.text); - }; + : //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;->()V + INSTRUCTION_FORMAT3rc_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rc_METHOD_ODEX.text); + }; insn_format3rc_type returns [int size] - : //e.g. filled-new-array/range {v0..v6}, I - INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format3rc.size;} - -> ^(I_STATEMENT_FORMAT3rc_TYPE[$start, "I_STATEMENT_FORMAT3rc_TYPE"] INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor); + : //e.g. filled-new-array/range {v0..v6}, I + INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format3rc.size;} + -> ^(I_STATEMENT_FORMAT3rc_TYPE[$start, "I_STATEMENT_FORMAT3rc_TYPE"] INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor); insn_format3rmi_method returns [int size] - : //e.g. execute-inline/range {v0 .. v10}, inline@0x14 - INSTRUCTION_FORMAT3rmi_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA INLINE_INDEX - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rmi_METHOD.text); - }; + : //e.g. execute-inline/range {v0 .. v10}, inline@0x14 + INSTRUCTION_FORMAT3rmi_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA INLINE_INDEX + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rmi_METHOD.text); + }; insn_format3rms_method returns [int size] - : //e.g. invoke-virtual-quick/range {v0 .. v10}, vtable@0x14 - INSTRUCTION_FORMAT3rms_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA VTABLE_INDEX - { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text); - }; + : //e.g. invoke-virtual-quick/range {v0 .. v10}, vtable@0x14 + INSTRUCTION_FORMAT3rms_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA VTABLE_INDEX + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text); + }; insn_format51l returns [int size] - : //e.g. const-wide v0, 5000000000L - INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;} - -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal); + : //e.g. const-wide v0, 5000000000L + INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;} + -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal); insn_array_data_directive returns [int size] @init {boolean needsNop = false;} - : ARRAY_DATA_DIRECTIVE - { - if (($method::currentAddress \% 2) != 0) { - needsNop = true; - $size = 2; - } else { - $size = 0; - } - } + : ARRAY_DATA_DIRECTIVE + { + if (($method::currentAddress \% 2) != 0) { + needsNop = true; + $size = 2; + } else { + $size = 0; + } + } - integral_literal (fixed_literal {$size+=$fixed_literal.size;})* END_ARRAY_DATA_DIRECTIVE - {$size = (($size + 1)/2)*2 + 8;} + integral_literal (fixed_literal {$size+=$fixed_literal.size;})* END_ARRAY_DATA_DIRECTIVE + {$size = (($size + 1)/2)*2 + 8;} - /*add a nop statement before this if needed to force the correct alignment*/ - -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) - ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*)) + /*add a nop statement before this if needed to force the correct alignment*/ + -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) + ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*)) - -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE integral_literal) - ^(I_ARRAY_ELEMENTS fixed_literal*)); + -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE integral_literal) + ^(I_ARRAY_ELEMENTS fixed_literal*)); insn_packed_switch_directive returns [int size] @init {boolean needsNop = false; int targetCount = 0;} : PACKED_SWITCH_DIRECTIVE - { - targetCount = 0; - if (($method::currentAddress \% 2) != 0) { - needsNop = true; - $size = 2; - } else { - $size = 0; - } - } + { + targetCount = 0; + if (($method::currentAddress \% 2) != 0) { + needsNop = true; + $size = 2; + } else { + $size = 0; + } + } - fixed_32bit_literal + fixed_32bit_literal - (switch_target += label_ref_or_offset {$size+=4; targetCount++;})* + (switch_target += label_ref_or_offset {$size+=4; targetCount++;})* - END_PACKED_SWITCH_DIRECTIVE {$size = $size + 8;} + END_PACKED_SWITCH_DIRECTIVE {$size = $size + 8;} - /*add a nop statement before this if needed to force the correct alignment*/ - -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) - ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] - ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) - ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*) - ) + /*add a nop statement before this if needed to force the correct alignment*/ + -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) + ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] + ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) + ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] + I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*) + ) - -> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] - ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) - ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*) - ); + -> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] + ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) + ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] + I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*) + ); insn_sparse_switch_directive returns [int size] @init {boolean needsNop = false; int targetCount = 0;} - : SPARSE_SWITCH_DIRECTIVE - { - targetCount = 0; - if (($method::currentAddress \% 2) != 0) { - needsNop = true; - $size = 2; - } else { - $size = 0; - } - } + : SPARSE_SWITCH_DIRECTIVE + { + targetCount = 0; + if (($method::currentAddress \% 2) != 0) { + needsNop = true; + $size = 2; + } else { + $size = 0; + } + } - (fixed_32bit_literal ARROW switch_target += label_ref_or_offset {$size += 8; targetCount++;})* + (fixed_32bit_literal ARROW switch_target += label_ref_or_offset {$size += 8; targetCount++;})* - END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;} + END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;} - /*add a nop statement before this if needed to force the correct alignment*/ - -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) - ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] - I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] - ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*) - ^(I_SPARSE_SWITCH_TARGETS $switch_target*)) - -> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] - I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] - ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*) - ^(I_SPARSE_SWITCH_TARGETS $switch_target*)); \ No newline at end of file + /*add a nop statement before this if needed to force the correct alignment*/ + -> {needsNop}? + ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) + ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] + I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] + ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*) + ^(I_SPARSE_SWITCH_TARGETS $switch_target*) + ) + + -> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] + I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] + ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*) + ^(I_SPARSE_SWITCH_TARGETS $switch_target*)); \ No newline at end of file diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g b/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g index 22338594..66110645 100644 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g +++ b/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g @@ -29,8 +29,8 @@ tree grammar smaliTreeWalker; options { - tokenVocab=smaliParser; - ASTLabelType=CommonTree; + tokenVocab=smaliParser; + ASTLabelType=CommonTree; } @header { @@ -50,857 +50,829 @@ import org.jf.dexlib.Code.Format.*; } @members { - public DexFile dexFile; - public TypeIdItem classType; + public DexFile dexFile; + public TypeIdItem classType; + private boolean verboseErrors = false; - private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters) - throws SemanticException { - //register should be in the format "v12" - int val = Byte.parseByte(register.substring(1)); - if (register.charAt(0) == 'p') { - val = totalMethodRegisters - methodParameterRegisters + val; - } - if (val >= 2<<4) { - throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15"); - } - //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0; - return (byte)val; - } + public void setVerboseErrors(boolean verboseErrors) { + this.verboseErrors = verboseErrors; + } - //return a short, because java's byte is signed - private short parseRegister_byte(String register, int totalMethodRegisters, int methodParameterRegisters) - throws SemanticException { - //register should be in the format "v123" - int val = Short.parseShort(register.substring(1)); - if (register.charAt(0) == 'p') { - val = totalMethodRegisters - methodParameterRegisters + val; - } - if (val >= 2<<8) { - throw new SemanticException(input, "The maximum allowed register in this context is v255"); - } - return (short)val; - } + private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters) + throws SemanticException { + //register should be in the format "v12" + int val = Byte.parseByte(register.substring(1)); + if (register.charAt(0) == 'p') { + val = totalMethodRegisters - methodParameterRegisters + val; + } + if (val >= 2<<4) { + throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15"); + } + //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0; + return (byte)val; + } - //return an int because java's short is signed - private int parseRegister_short(String register, int totalMethodRegisters, int methodParameterRegisters) - throws SemanticException { - //register should be in the format "v12345" - int val = Integer.parseInt(register.substring(1)); - if (register.charAt(0) == 'p') { - val = totalMethodRegisters - methodParameterRegisters + val; - } - if (val >= 2<<16) { - throw new SemanticException(input, "The maximum allowed register in this context is v65535"); - } - //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0; - return val; - } + //return a short, because java's byte is signed + private short parseRegister_byte(String register, int totalMethodRegisters, int methodParameterRegisters) + throws SemanticException { + //register should be in the format "v123" + int val = Short.parseShort(register.substring(1)); + if (register.charAt(0) == 'p') { + val = totalMethodRegisters - methodParameterRegisters + val; + } + if (val >= 2<<8) { + throw new SemanticException(input, "The maximum allowed register in this context is v255"); + } + return (short)val; + } - private static Pattern specialFloatRegex = Pattern.compile("((-)?infinityf)|(nanf)", Pattern.CASE_INSENSITIVE); - private float parseFloat(String floatString) { - Matcher m = specialFloatRegex.matcher(floatString); - if (m.matches()) { - //got an infinity - if (m.start(1) != -1) { - if (m.start(2) != -1) { - return Float.NEGATIVE_INFINITY; - } else { - return Float.POSITIVE_INFINITY; - } - } else { - return Float.NaN; - } - } - return Float.parseFloat(floatString); - } + //return an int because java's short is signed + private int parseRegister_short(String register, int totalMethodRegisters, int methodParameterRegisters) + throws SemanticException { + //register should be in the format "v12345" + int val = Integer.parseInt(register.substring(1)); + if (register.charAt(0) == 'p') { + val = totalMethodRegisters - methodParameterRegisters + val; + } + if (val >= 2<<16) { + throw new SemanticException(input, "The maximum allowed register in this context is v65535"); + } + //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0; + return val; + } - private static Pattern specialDoubleRegex = Pattern.compile("((-)?infinityd?)|(nand?)", Pattern.CASE_INSENSITIVE); - private double parseDouble(String doubleString) { - Matcher m = specialDoubleRegex.matcher(doubleString); - if (m.matches()) { - //got an infinity - if (m.start(1) != -1) { - if (m.start(2) != -1) { - return Double.NEGATIVE_INFINITY; - } else { - return Double.POSITIVE_INFINITY; - } - } else { - return Double.NaN; - } - } - return Double.parseDouble(doubleString); - } + public String getErrorMessage(RecognitionException e, String[] tokenNames) { + if ( e instanceof SemanticException ) { + return e.getMessage(); + } else { + return super.getErrorMessage(e, tokenNames); + } + } - public String getErrorMessage(RecognitionException e, String[] tokenNames) { - if ( e instanceof SemanticException ) { - return e.getMessage(); - } else { - return super.getErrorMessage(e, tokenNames); - } - } - - public String getErrorHeader(RecognitionException e) { - return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; - } + public String getErrorHeader(RecognitionException e) { + return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]"; + } } smali_file - : ^(I_CLASS_DEF header methods fields annotations) - { - AnnotationDirectoryItem annotationDirectoryItem = null; - ClassDefItem classDefItem = null; - ClassDataItem classDataItem = null; + : ^(I_CLASS_DEF header methods fields annotations) + { + AnnotationDirectoryItem annotationDirectoryItem = null; + ClassDefItem classDefItem = null; + ClassDataItem classDataItem = null; - if ( $methods.methodAnnotations != null || - $methods.parameterAnnotations != null || - $fields.fieldAnnotations != null || - $annotations.annotationSetItem != null) { - annotationDirectoryItem = AnnotationDirectoryItem.internAnnotationDirectoryItem( - dexFile, - $annotations.annotationSetItem, - $fields.fieldAnnotations, - $methods.methodAnnotations, - $methods.parameterAnnotations); - } + if ($methods.methodAnnotations != null || + $methods.parameterAnnotations != null || + $fields.fieldAnnotations != null || + $annotations.annotationSetItem != null) { + annotationDirectoryItem = AnnotationDirectoryItem.internAnnotationDirectoryItem( + dexFile, + $annotations.annotationSetItem, + $fields.fieldAnnotations, + $methods.methodAnnotations, + $methods.parameterAnnotations); + } - if ($fields.staticFields.size() != 0 || $fields.instanceFields.size() != 0 || - $methods.directMethods.size() != 0 || $methods.virtualMethods.size()!= 0) { - classDataItem = ClassDataItem.internClassDataItem(dexFile, $fields.staticFields, $fields.instanceFields, - $methods.directMethods, $methods.virtualMethods); - } + if ($fields.staticFields.size() != 0 || $fields.instanceFields.size() != 0 || + $methods.directMethods.size() != 0 || $methods.virtualMethods.size()!= 0) { + classDataItem = ClassDataItem.internClassDataItem(dexFile, $fields.staticFields, $fields.instanceFields, + $methods.directMethods, $methods.virtualMethods); + } - classDefItem = ClassDefItem.internClassDefItem(dexFile, $header.classType, $header.accessFlags, - $header.superType, $header.implementsList, $header.sourceSpec, annotationDirectoryItem, - classDataItem, $fields.staticFieldInitialValues); - }; - catch [Exception ex] { - reportError(new SemanticException(input, ex)); - } + classDefItem = ClassDefItem.internClassDefItem(dexFile, $header.classType, $header.accessFlags, + $header.superType, $header.implementsList, $header.sourceSpec, annotationDirectoryItem, + classDataItem, $fields.staticFieldInitialValues); + }; + catch [Exception ex] { + if (verboseErrors) { + ex.printStackTrace(System.err); + } + reportError(new SemanticException(input, ex)); + } - -header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec] -: class_spec super_spec? implements_list source_spec - { - classType = $class_spec.type; - $classType = classType; - $accessFlags = $class_spec.accessFlags; - $superType = $super_spec.type; - $implementsList = $implements_list.implementsList; - $sourceSpec = $source_spec.source; - }; +header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec] +: class_spec super_spec? implements_list source_spec + { + classType = $class_spec.type; + $classType = classType; + $accessFlags = $class_spec.accessFlags; + $superType = $super_spec.type; + $implementsList = $implements_list.implementsList; + $sourceSpec = $source_spec.source; + }; class_spec returns[TypeIdItem type, int accessFlags] - : class_type_descriptor access_list - { - $type = $class_type_descriptor.type; - $accessFlags = $access_list.value; - }; + : class_type_descriptor access_list + { + $type = $class_type_descriptor.type; + $accessFlags = $access_list.value; + }; super_spec returns[TypeIdItem type] - : ^(I_SUPER class_type_descriptor) - { - $type = $class_type_descriptor.type; - }; + : ^(I_SUPER class_type_descriptor) + { + $type = $class_type_descriptor.type; + }; implements_spec returns[TypeIdItem type] - : ^(I_IMPLEMENTS class_type_descriptor) - { - $type = $class_type_descriptor.type; - }; + : ^(I_IMPLEMENTS class_type_descriptor) + { + $type = $class_type_descriptor.type; + }; implements_list returns[TypeListItem implementsList] -@init { List typeList; } - : {typeList = new LinkedList();} - (implements_spec {typeList.add($implements_spec.type);} )* - { - if (typeList.size() > 0) { - $implementsList = TypeListItem.internTypeListItem(dexFile, typeList); - } else { - $implementsList = null; - } - }; +@init { List typeList; } + : {typeList = new LinkedList();} + (implements_spec {typeList.add($implements_spec.type);} )* + { + if (typeList.size() > 0) { + $implementsList = TypeListItem.internTypeListItem(dexFile, typeList); + } else { + $implementsList = null; + } + }; source_spec returns[StringIdItem source] - : {$source = null;} - ^(I_SOURCE string_literal {$source = StringIdItem.internStringIdItem(dexFile, $string_literal.value);}) - | ; + : {$source = null;} + ^(I_SOURCE string_literal {$source = StringIdItem.internStringIdItem(dexFile, $string_literal.value);}) + | /*epsilon*/; access_list returns [int value] - @init - { - $value = 0; - } - : ^(I_ACCESS_LIST - ( - ACCESS_SPEC - { - $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue(); - } - )*); + @init + { + $value = 0; + } + : ^(I_ACCESS_LIST + ( + ACCESS_SPEC + { + $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue(); + } + )*); fields returns[List staticFields, List instanceFields, - List staticFieldInitialValues, List fieldAnnotations] - @init - { - $staticFields = new LinkedList(); - $instanceFields = new LinkedList(); - $staticFieldInitialValues = new ArrayList(); - } - : ^(I_FIELDS - (field - { - if ($field.encodedField.isStatic()) { - $staticFields.add($field.encodedField); - $staticFieldInitialValues.add(new ClassDefItem.StaticFieldInitializer( - $field.encodedValue, $field.encodedField)); - } else { - $instanceFields.add($field.encodedField); - } - if ($field.fieldAnnotationSet != null) { - if ($fieldAnnotations == null) { - $fieldAnnotations = new LinkedList(); - } - AnnotationDirectoryItem.FieldAnnotation fieldAnnotation = new AnnotationDirectoryItem.FieldAnnotation( - $field.encodedField.field, $field.fieldAnnotationSet); - $fieldAnnotations.add(fieldAnnotation); - } - })*); + List staticFieldInitialValues, List fieldAnnotations] + @init + { + $staticFields = new LinkedList(); + $instanceFields = new LinkedList(); + $staticFieldInitialValues = new ArrayList(); + } + : ^(I_FIELDS + (field + { + if ($field.encodedField.isStatic()) { + $staticFields.add($field.encodedField); + $staticFieldInitialValues.add(new ClassDefItem.StaticFieldInitializer( + $field.encodedValue, $field.encodedField)); + } else { + $instanceFields.add($field.encodedField); + } + if ($field.fieldAnnotationSet != null) { + if ($fieldAnnotations == null) { + $fieldAnnotations = new LinkedList(); + } + AnnotationDirectoryItem.FieldAnnotation fieldAnnotation = new AnnotationDirectoryItem.FieldAnnotation( + $field.encodedField.field, $field.fieldAnnotationSet); + $fieldAnnotations.add(fieldAnnotation); + } + })*); methods returns[List directMethods, - List virtualMethods, - List methodAnnotations, - List parameterAnnotations] - @init - { - $directMethods = new LinkedList(); - $virtualMethods = new LinkedList(); - } - : ^(I_METHODS - (method - { - if ($method.encodedMethod.isDirect()) { - $directMethods.add($method.encodedMethod); - } else { - $virtualMethods.add($method.encodedMethod); - } - if ($method.methodAnnotationSet != null) { - if ($methodAnnotations == null) { - $methodAnnotations = new LinkedList(); - } - AnnotationDirectoryItem.MethodAnnotation methodAnnotation = - new AnnotationDirectoryItem.MethodAnnotation($method.encodedMethod.method, $method.methodAnnotationSet); - $methodAnnotations.add(methodAnnotation); - } - if ($method.parameterAnnotationSets != null) { - if ($parameterAnnotations == null) { - $parameterAnnotations = new LinkedList(); - } - AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation = - new AnnotationDirectoryItem.ParameterAnnotation($method.encodedMethod.method, - $method.parameterAnnotationSets); - $parameterAnnotations.add(parameterAnnotation); - } - })*); + List virtualMethods, + List methodAnnotations, + List parameterAnnotations] + @init + { + $directMethods = new LinkedList(); + $virtualMethods = new LinkedList(); + } + : ^(I_METHODS + (method + { + if ($method.encodedMethod.isDirect()) { + $directMethods.add($method.encodedMethod); + } else { + $virtualMethods.add($method.encodedMethod); + } + if ($method.methodAnnotationSet != null) { + if ($methodAnnotations == null) { + $methodAnnotations = new LinkedList(); + } + AnnotationDirectoryItem.MethodAnnotation methodAnnotation = + new AnnotationDirectoryItem.MethodAnnotation($method.encodedMethod.method, $method.methodAnnotationSet); + $methodAnnotations.add(methodAnnotation); + } + if ($method.parameterAnnotationSets != null) { + if ($parameterAnnotations == null) { + $parameterAnnotations = new LinkedList(); + } + AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation = + new AnnotationDirectoryItem.ParameterAnnotation($method.encodedMethod.method, + $method.parameterAnnotationSets); + $parameterAnnotations.add(parameterAnnotation); + } + })*); field returns [ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationSetItem fieldAnnotationSet] - :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?) - { - StringIdItem memberName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - TypeIdItem fieldType = $nonvoid_type_descriptor.type; + :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?) + { + StringIdItem memberName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); + TypeIdItem fieldType = $nonvoid_type_descriptor.type; - FieldIdItem fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, memberName); - $encodedField = new ClassDataItem.EncodedField(fieldIdItem, $access_list.value); + FieldIdItem fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, memberName); + $encodedField = new ClassDataItem.EncodedField(fieldIdItem, $access_list.value); - if ($field_initial_value.encodedValue != null) { - if (!$encodedField.isStatic()) { - throw new SemanticException(input, "Initial field values can only be specified for static fields."); - } + if ($field_initial_value.encodedValue != null) { + if (!$encodedField.isStatic()) { + throw new SemanticException(input, "Initial field values can only be specified for static fields."); + } - $encodedValue = $field_initial_value.encodedValue; - } else { - $encodedValue = null; - } + $encodedValue = $field_initial_value.encodedValue; + } else { + $encodedValue = null; + } - if ($annotations.annotationSetItem != null) { - $fieldAnnotationSet = $annotations.annotationSetItem; - } - }; + if ($annotations.annotationSetItem != null) { + $fieldAnnotationSet = $annotations.annotationSetItem; + } + }; field_initial_value returns[EncodedValue encodedValue] - : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;} - | ; + : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;} + | /*epsilon*/; literal returns[EncodedValue encodedValue] - : integer_literal { $encodedValue = new IntEncodedValue($integer_literal.value); } - | long_literal { $encodedValue = new LongEncodedValue($long_literal.value); } - | short_literal { $encodedValue = new ShortEncodedValue($short_literal.value); } - | byte_literal { $encodedValue = new ByteEncodedValue($byte_literal.value); } - | float_literal { $encodedValue = new FloatEncodedValue($float_literal.value); } - | double_literal { $encodedValue = new DoubleEncodedValue($double_literal.value); } - | char_literal { $encodedValue = new CharEncodedValue($char_literal.value); } - | string_literal { $encodedValue = new StringEncodedValue(StringIdItem.internStringIdItem(dexFile, $string_literal.value)); } - | bool_literal { $encodedValue = $bool_literal.value?BooleanEncodedValue.TrueValue:BooleanEncodedValue.FalseValue; } - | NULL_LITERAL { $encodedValue = NullEncodedValue.NullValue; } - | type_descriptor { $encodedValue = new TypeEncodedValue($type_descriptor.type); } - | array_literal { $encodedValue = new ArrayEncodedValue($array_literal.values); } - | subannotation { $encodedValue = new AnnotationEncodedValue($subannotation.annotationType, $subannotation.elementNames, $subannotation.elementValues); } - | field_literal { $encodedValue = new FieldEncodedValue($field_literal.value); } - | method_literal { $encodedValue = new MethodEncodedValue($method_literal.value); } - | enum_literal { $encodedValue = new EnumEncodedValue($enum_literal.value); }; + : integer_literal { $encodedValue = new IntEncodedValue($integer_literal.value); } + | long_literal { $encodedValue = new LongEncodedValue($long_literal.value); } + | short_literal { $encodedValue = new ShortEncodedValue($short_literal.value); } + | byte_literal { $encodedValue = new ByteEncodedValue($byte_literal.value); } + | float_literal { $encodedValue = new FloatEncodedValue($float_literal.value); } + | double_literal { $encodedValue = new DoubleEncodedValue($double_literal.value); } + | char_literal { $encodedValue = new CharEncodedValue($char_literal.value); } + | string_literal { $encodedValue = new StringEncodedValue(StringIdItem.internStringIdItem(dexFile, $string_literal.value)); } + | bool_literal { $encodedValue = $bool_literal.value?BooleanEncodedValue.TrueValue:BooleanEncodedValue.FalseValue; } + | NULL_LITERAL { $encodedValue = NullEncodedValue.NullValue; } + | type_descriptor { $encodedValue = new TypeEncodedValue($type_descriptor.type); } + | array_literal { $encodedValue = new ArrayEncodedValue($array_literal.values); } + | subannotation { $encodedValue = new AnnotationEncodedValue($subannotation.annotationType, $subannotation.elementNames, $subannotation.elementValues); } + | field_literal { $encodedValue = new FieldEncodedValue($field_literal.value); } + | method_literal { $encodedValue = new MethodEncodedValue($method_literal.value); } + | enum_literal { $encodedValue = new EnumEncodedValue($enum_literal.value); }; //everything but string fixed_size_literal returns[byte[\] value] - : integer_literal { $value = LiteralTools.intToBytes($integer_literal.value); } - | long_literal { $value = LiteralTools.longToBytes($long_literal.value); } - | short_literal { $value = LiteralTools.shortToBytes($short_literal.value); } - | byte_literal { $value = new byte[] { $byte_literal.value }; } - | float_literal { $value = LiteralTools.floatToBytes($float_literal.value); } - | double_literal { $value = LiteralTools.doubleToBytes($double_literal.value); } - | char_literal { $value = LiteralTools.charToBytes($char_literal.value); } - | bool_literal { $value = LiteralTools.boolToBytes($bool_literal.value); }; + : integer_literal { $value = LiteralTools.intToBytes($integer_literal.value); } + | long_literal { $value = LiteralTools.longToBytes($long_literal.value); } + | short_literal { $value = LiteralTools.shortToBytes($short_literal.value); } + | byte_literal { $value = new byte[] { $byte_literal.value }; } + | float_literal { $value = LiteralTools.floatToBytes($float_literal.value); } + | double_literal { $value = LiteralTools.doubleToBytes($double_literal.value); } + | char_literal { $value = LiteralTools.charToBytes($char_literal.value); } + | bool_literal { $value = LiteralTools.boolToBytes($bool_literal.value); }; //everything but string fixed_64bit_literal returns[long value] - : integer_literal { $value = $integer_literal.value; } - | long_literal { $value = $long_literal.value; } - | short_literal { $value = $short_literal.value; } - | byte_literal { $value = $byte_literal.value; } - | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } - | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } - | char_literal { $value = $char_literal.value; } - | bool_literal { $value = $bool_literal.value?1:0; }; + : integer_literal { $value = $integer_literal.value; } + | long_literal { $value = $long_literal.value; } + | short_literal { $value = $short_literal.value; } + | byte_literal { $value = $byte_literal.value; } + | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } + | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } + | char_literal { $value = $char_literal.value; } + | bool_literal { $value = $bool_literal.value?1:0; }; //everything but string and double //long is allowed, but it must fit into an int fixed_32bit_literal returns[int value] - : integer_literal { $value = $integer_literal.value; } - | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; } - | short_literal { $value = $short_literal.value; } - | byte_literal { $value = $byte_literal.value; } - | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } - | char_literal { $value = $char_literal.value; } - | bool_literal { $value = $bool_literal.value?1:0; }; + : integer_literal { $value = $integer_literal.value; } + | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; } + | short_literal { $value = $short_literal.value; } + | byte_literal { $value = $byte_literal.value; } + | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } + | char_literal { $value = $char_literal.value; } + | bool_literal { $value = $bool_literal.value?1:0; }; array_elements returns[List values] - : {$values = new ArrayList();} - ^(I_ARRAY_ELEMENTS - (fixed_size_literal - { - $values.add($fixed_size_literal.value); - })*); + : {$values = new ArrayList();} + ^(I_ARRAY_ELEMENTS + (fixed_size_literal + { + $values.add($fixed_size_literal.value); + })*); packed_switch_target_count returns[int targetCount] - : I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);}; + : I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);}; packed_switch_targets[int baseAddress] returns[int[\] targets] - : - ^(I_PACKED_SWITCH_TARGETS - packed_switch_target_count - { - int targetCount = $packed_switch_target_count.targetCount; - $targets = new int[targetCount]; - int targetsPosition = 0; - } + : + ^(I_PACKED_SWITCH_TARGETS + packed_switch_target_count + { + int targetCount = $packed_switch_target_count.targetCount; + $targets = new int[targetCount]; + int targetsPosition = 0; + } - (offset_or_label - { - $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; - })* - ); + (offset_or_label + { + $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; + })* + ); sparse_switch_target_count returns[int targetCount] - : I_SPARSE_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_SPARSE_SWITCH_TARGET_COUNT.text);}; + : I_SPARSE_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_SPARSE_SWITCH_TARGET_COUNT.text);}; sparse_switch_keys[int targetCount] returns[int[\] keys] - : { - $keys = new int[$targetCount]; - int keysPosition = 0; - } - ^(I_SPARSE_SWITCH_KEYS - (fixed_32bit_literal - { - $keys[keysPosition++] = $fixed_32bit_literal.value; - })* - ); + : { + $keys = new int[$targetCount]; + int keysPosition = 0; + } + ^(I_SPARSE_SWITCH_KEYS + (fixed_32bit_literal + { + $keys[keysPosition++] = $fixed_32bit_literal.value; + })* + ); sparse_switch_targets[int baseAddress, int targetCount] returns[int[\] targets] - : { - $targets = new int[$targetCount]; - int targetsPosition = 0; - } - ^(I_SPARSE_SWITCH_TARGETS - (offset_or_label - { - $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; - })* - ); + : { + $targets = new int[$targetCount]; + int targetsPosition = 0; + } + ^(I_SPARSE_SWITCH_TARGETS + (offset_or_label + { + $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; + })* + ); -method returns[ ClassDataItem.EncodedMethod encodedMethod, - AnnotationSetItem methodAnnotationSet, - AnnotationSetRefList parameterAnnotationSets] - scope - { - HashMap labels; - TryListBuilder tryList; - int currentAddress; - DebugInfoBuilder debugInfo; - HashMap packedSwitchDeclarations; - HashMap sparseSwitchDeclarations; - } - @init - { - MethodIdItem methodIdItem = null; - int totalMethodRegisters = 0; - int methodParameterRegisters = 0; - int accessFlags = 0; - boolean isStatic = false; - } - : { - $method::labels = new HashMap(); - $method::tryList = new TryListBuilder(); - $method::currentAddress = 0; - $method::debugInfo = new DebugInfoBuilder(); - $method::packedSwitchDeclarations = new HashMap(); - $method::sparseSwitchDeclarations = new HashMap(); - } - ^( I_METHOD - method_name_and_prototype - access_list - { - methodIdItem = $method_name_and_prototype.methodIdItem; - accessFlags = $access_list.value; - isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0; - methodParameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); - if (!isStatic) { - methodParameterRegisters++; - } - } - ( registers_directive - { - if ($registers_directive.isLocalsDirective) { - totalMethodRegisters = $registers_directive.registers + methodParameterRegisters; - } else { - totalMethodRegisters = $registers_directive.registers; - } - } - )? - labels - packed_switch_declarations - sparse_switch_declarations - statements[totalMethodRegisters, methodParameterRegisters] - catches - parameters - ordered_debug_directives[totalMethodRegisters, methodParameterRegisters] - annotations - ) - { - Pair, List> temp = $method::tryList.encodeTries(); - List tries = temp.first; - List handlers = temp.second; +method returns[ClassDataItem.EncodedMethod encodedMethod, + AnnotationSetItem methodAnnotationSet, + AnnotationSetRefList parameterAnnotationSets] + scope + { + HashMap labels; + TryListBuilder tryList; + int currentAddress; + DebugInfoBuilder debugInfo; + HashMap packedSwitchDeclarations; + HashMap sparseSwitchDeclarations; + } + @init + { + MethodIdItem methodIdItem = null; + int totalMethodRegisters = 0; + int methodParameterRegisters = 0; + int accessFlags = 0; + boolean isStatic = false; + } + : { + $method::labels = new HashMap(); + $method::tryList = new TryListBuilder(); + $method::currentAddress = 0; + $method::debugInfo = new DebugInfoBuilder(); + $method::packedSwitchDeclarations = new HashMap(); + $method::sparseSwitchDeclarations = new HashMap(); + } + ^(I_METHOD + method_name_and_prototype + access_list + { + methodIdItem = $method_name_and_prototype.methodIdItem; + accessFlags = $access_list.value; + isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0; + methodParameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); + if (!isStatic) { + methodParameterRegisters++; + } + } + (registers_directive + { + if ($registers_directive.isLocalsDirective) { + totalMethodRegisters = $registers_directive.registers + methodParameterRegisters; + } else { + totalMethodRegisters = $registers_directive.registers; + } + } + )? + labels + packed_switch_declarations + sparse_switch_declarations + statements[totalMethodRegisters, methodParameterRegisters] + catches + parameters + ordered_debug_directives[totalMethodRegisters, methodParameterRegisters] + annotations + ) + { + Pair, List> temp = $method::tryList.encodeTries(); + List tries = temp.first; + List handlers = temp.second; - DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile); + DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile); - CodeItem codeItem; + CodeItem codeItem; - boolean isAbstract = false; - boolean isNative = false; + boolean isAbstract = false; + boolean isNative = false; - if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) { - isAbstract = true; - } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) { - isNative = true; - } + if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) { + isAbstract = true; + } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) { + isNative = true; + } - if ($statements.instructions.size() == 0) { - if (!isAbstract && !isNative) { - throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction"); - } + if ($statements.instructions.size() == 0) { + if (!isAbstract && !isNative) { + throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction"); + } - String methodType; - if (isAbstract) { - methodType = "an abstract"; - } else { - methodType = "a native"; - } + String methodType; + if (isAbstract) { + methodType = "an abstract"; + } else { + methodType = "a native"; + } - if ($registers_directive.start != null) { - if ($registers_directive.isLocalsDirective) { - throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType); - } else { - throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType); - } - } + if ($registers_directive.start != null) { + if ($registers_directive.isLocalsDirective) { + throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType); + } else { + throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType); + } + } - if ($method::labels.size() > 0) { - throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType); - } + if ($method::labels.size() > 0) { + throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType); + } - if ((tries != null && tries.size() > 0) || (handlers != null && handlers.size() > 0)) { - throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType); - } + if ((tries != null && tries.size() > 0) || (handlers != null && handlers.size() > 0)) { + throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType); + } - if (debugInfoItem != null) { - throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType); - } + if (debugInfoItem != null) { + throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType); + } - codeItem = null; - } else { - if (isAbstract) { - throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions"); - } - if (isNative) { - throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions"); - } + codeItem = null; + } else { + if (isAbstract) { + throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions"); + } + if (isNative) { + throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions"); + } - if ($registers_directive.start == null) { - throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method"); - } + if ($registers_directive.start == null) { + throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method"); + } - if (totalMethodRegisters < methodParameterRegisters) { - throw new SemanticException(input, $registers_directive.start, "This method requires at least " + - Integer.toString(methodParameterRegisters) + - " registers, for the method parameters"); - } + if (totalMethodRegisters < methodParameterRegisters) { + throw new SemanticException(input, $registers_directive.start, "This method requires at least " + + Integer.toString(methodParameterRegisters) + + " registers, for the method parameters"); + } - int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount(); - if ($method::debugInfo.getParameterNameCount() > methodParameterCount) { - throw new SemanticException(input, $I_METHOD, "Too many parameter names specified. This method only has " + - Integer.toString(methodParameterCount) + - " parameters."); - } + int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount(); + if ($method::debugInfo.getParameterNameCount() > methodParameterCount) { + throw new SemanticException(input, $I_METHOD, "Too many parameter names specified. This method only has " + + Integer.toString(methodParameterCount) + + " parameters."); + } - codeItem = CodeItem.internCodeItem(dexFile, - totalMethodRegisters, - methodParameterRegisters, - $statements.maxOutRegisters, - debugInfoItem, - $statements.instructions, - tries, - handlers); - } + codeItem = CodeItem.internCodeItem(dexFile, + totalMethodRegisters, + methodParameterRegisters, + $statements.maxOutRegisters, + debugInfoItem, + $statements.instructions, + tries, + handlers); + } - $encodedMethod = new ClassDataItem.EncodedMethod(methodIdItem, accessFlags, codeItem); + $encodedMethod = new ClassDataItem.EncodedMethod(methodIdItem, accessFlags, codeItem); - if ($annotations.annotationSetItem != null) { - $methodAnnotationSet = $annotations.annotationSetItem; - } + if ($annotations.annotationSetItem != null) { + $methodAnnotationSet = $annotations.annotationSetItem; + } - if ($parameters.parameterAnnotations != null) { - $parameterAnnotationSets = $parameters.parameterAnnotations; - } - }; + if ($parameters.parameterAnnotations != null) { + $parameterAnnotationSets = $parameters.parameterAnnotations; + } + }; method_prototype returns[ProtoIdItem protoIdItem] - : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list) - { - TypeIdItem returnType = $type_descriptor.type; - List parameterTypes = $field_type_list.types; - TypeListItem parameterTypeListItem = null; - if (parameterTypes != null && parameterTypes.size() > 0) { - parameterTypeListItem = TypeListItem.internTypeListItem(dexFile, parameterTypes); - } + : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list) + { + TypeIdItem returnType = $type_descriptor.type; + List parameterTypes = $field_type_list.types; + TypeListItem parameterTypeListItem = null; + if (parameterTypes != null && parameterTypes.size() > 0) { + parameterTypeListItem = TypeListItem.internTypeListItem(dexFile, parameterTypes); + } - $protoIdItem = ProtoIdItem.internProtoIdItem(dexFile, returnType, parameterTypeListItem); - }; + $protoIdItem = ProtoIdItem.internProtoIdItem(dexFile, returnType, parameterTypeListItem); + }; method_name_and_prototype returns[MethodIdItem methodIdItem] - : SIMPLE_NAME method_prototype - { - String methodNameString = $SIMPLE_NAME.text; - StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, methodNameString); - ProtoIdItem protoIdItem = $method_prototype.protoIdItem; + : SIMPLE_NAME method_prototype + { + String methodNameString = $SIMPLE_NAME.text; + StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, methodNameString); + ProtoIdItem protoIdItem = $method_prototype.protoIdItem; - $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, protoIdItem, methodName); - }; + $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, protoIdItem, methodName); + }; field_type_list returns[List types] - @init - { - $types = new LinkedList(); - } - : ( - nonvoid_type_descriptor - { - $types.add($nonvoid_type_descriptor.type); - } - )*; + @init + { + $types = new LinkedList(); + } + : ( + nonvoid_type_descriptor + { + $types.add($nonvoid_type_descriptor.type); + } + )*; fully_qualified_method returns[MethodIdItem methodIdItem] - : reference_type_descriptor SIMPLE_NAME method_prototype - { - TypeIdItem classType = $reference_type_descriptor.type; - StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - ProtoIdItem prototype = $method_prototype.protoIdItem; - $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, prototype, methodName); - }; + : reference_type_descriptor SIMPLE_NAME method_prototype + { + TypeIdItem classType = $reference_type_descriptor.type; + StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); + ProtoIdItem prototype = $method_prototype.protoIdItem; + $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, prototype, methodName); + }; fully_qualified_field returns[FieldIdItem fieldIdItem] - : reference_type_descriptor SIMPLE_NAME nonvoid_type_descriptor - { - TypeIdItem classType = $reference_type_descriptor.type; - StringIdItem fieldName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - TypeIdItem fieldType = $nonvoid_type_descriptor.type; - $fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, fieldName); - }; + : reference_type_descriptor SIMPLE_NAME nonvoid_type_descriptor + { + TypeIdItem classType = $reference_type_descriptor.type; + StringIdItem fieldName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); + TypeIdItem fieldType = $nonvoid_type_descriptor.type; + $fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, fieldName); + }; registers_directive returns[boolean isLocalsDirective, int registers] - : {$registers = 0;} - ^( ( I_REGISTERS {$isLocalsDirective = false;} - | I_LOCALS {$isLocalsDirective = true;} - ) - short_integral_literal {$registers = $short_integral_literal.value;} - ); + : {$registers = 0;} + ^(( I_REGISTERS {$isLocalsDirective = false;} + | I_LOCALS {$isLocalsDirective = true;} + ) + short_integral_literal {$registers = $short_integral_literal.value;} + ); labels - : ^(I_LABELS label_def*); + : ^(I_LABELS label_def*); label_def - : ^(I_LABEL SIMPLE_NAME address) - { - if ($method::labels.containsKey($SIMPLE_NAME.text)) { - throw new SemanticException(input, $I_LABEL, "Label " + $SIMPLE_NAME.text + " has multiple defintions."); - } + : ^(I_LABEL SIMPLE_NAME address) + { + if ($method::labels.containsKey($SIMPLE_NAME.text)) { + throw new SemanticException(input, $I_LABEL, "Label " + $SIMPLE_NAME.text + " has multiple defintions."); + } - - $method::labels.put($SIMPLE_NAME.text, $address.address); - }; + $method::labels.put($SIMPLE_NAME.text, $address.address); + }; packed_switch_declarations - : ^(I_PACKED_SWITCH_DECLARATIONS packed_switch_declaration*); + : ^(I_PACKED_SWITCH_DECLARATIONS packed_switch_declaration*); packed_switch_declaration - : ^(I_PACKED_SWITCH_DECLARATION address offset_or_label_absolute[$address.address]) - { - int switchDataAddress = $offset_or_label_absolute.address; - if ((switchDataAddress \% 2) != 0) { - switchDataAddress++; - } - if (!$method::packedSwitchDeclarations.containsKey(switchDataAddress)) { - $method::packedSwitchDeclarations.put(switchDataAddress, $address.address); - } - }; + : ^(I_PACKED_SWITCH_DECLARATION address offset_or_label_absolute[$address.address]) + { + int switchDataAddress = $offset_or_label_absolute.address; + if ((switchDataAddress \% 2) != 0) { + switchDataAddress++; + } + if (!$method::packedSwitchDeclarations.containsKey(switchDataAddress)) { + $method::packedSwitchDeclarations.put(switchDataAddress, $address.address); + } + }; sparse_switch_declarations - : ^(I_SPARSE_SWITCH_DECLARATIONS sparse_switch_declaration*); + : ^(I_SPARSE_SWITCH_DECLARATIONS sparse_switch_declaration*); sparse_switch_declaration - : ^(I_SPARSE_SWITCH_DECLARATION address offset_or_label_absolute[$address.address]) - { - int switchDataAddress = $offset_or_label_absolute.address; - if ((switchDataAddress \% 2) != 0) { - switchDataAddress++; - } - if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) { - $method::sparseSwitchDeclarations.put(switchDataAddress, $address.address); - } + : ^(I_SPARSE_SWITCH_DECLARATION address offset_or_label_absolute[$address.address]) + { + int switchDataAddress = $offset_or_label_absolute.address; + if ((switchDataAddress \% 2) != 0) { + switchDataAddress++; + } + if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) { + $method::sparseSwitchDeclarations.put(switchDataAddress, $address.address); + } - }; + }; -catches : ^(I_CATCHES catch_directive* catchall_directive*); +catches : ^(I_CATCHES catch_directive* catchall_directive*); catch_directive - : ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] - using=offset_or_label_absolute[$address.address]) - { - TypeIdItem type = $nonvoid_type_descriptor.type; - int startAddress = $from.address; - int endAddress = $to.address; - int handlerAddress = $using.address; + : ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] + using=offset_or_label_absolute[$address.address]) + { + TypeIdItem type = $nonvoid_type_descriptor.type; + int startAddress = $from.address; + int endAddress = $to.address; + int handlerAddress = $using.address; - $method::tryList.addHandler(type, startAddress, endAddress, handlerAddress); - }; + $method::tryList.addHandler(type, startAddress, endAddress, handlerAddress); + }; catchall_directive - : ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] - using=offset_or_label_absolute[$address.address]) - { - int startAddress = $from.address; - int endAddress = $to.address; - int handlerAddress = $using.address; + : ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] + using=offset_or_label_absolute[$address.address]) + { + int startAddress = $from.address; + int endAddress = $to.address; + int handlerAddress = $using.address; - $method::tryList.addCatchAllHandler(startAddress, endAddress, handlerAddress); - }; + $method::tryList.addCatchAllHandler(startAddress, endAddress, handlerAddress); + }; address returns[int address] - : I_ADDRESS - { - $address = Integer.parseInt($I_ADDRESS.text); - }; + : I_ADDRESS + { + $address = Integer.parseInt($I_ADDRESS.text); + }; parameters returns[AnnotationSetRefList parameterAnnotations] - @init - { - int parameterCount = 0; - List annotationSetItems = new ArrayList(); - } - : ^(I_PARAMETERS (parameter - { - if ($parameter.parameterAnnotationSet != null) { - while (annotationSetItems.size() < parameterCount) { - annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); - } - annotationSetItems.add($parameter.parameterAnnotationSet); - } + @init + { + int parameterCount = 0; + List annotationSetItems = new ArrayList(); + } + : ^(I_PARAMETERS (parameter + { + if ($parameter.parameterAnnotationSet != null) { + while (annotationSetItems.size() < parameterCount) { + annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); + } + annotationSetItems.add($parameter.parameterAnnotationSet); + } - parameterCount++; - })* - ) - { - if (annotationSetItems.size() > 0) { - while (annotationSetItems.size() < parameterCount) { - annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); - } - $parameterAnnotations = AnnotationSetRefList.internAnnotationSetRefList(dexFile, annotationSetItems); - } - }; + parameterCount++; + })* + ) + { + if (annotationSetItems.size() > 0) { + while (annotationSetItems.size() < parameterCount) { + annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); + } + $parameterAnnotations = AnnotationSetRefList.internAnnotationSetRefList(dexFile, annotationSetItems); + } + }; parameter returns[AnnotationSetItem parameterAnnotationSet] - : ^(I_PARAMETER ( string_literal {$method::debugInfo.addParameterName($string_literal.value);} - | {$method::debugInfo.addParameterName(null);} - ) - annotations {$parameterAnnotationSet = $annotations.annotationSetItem;} - ); + : ^(I_PARAMETER (string_literal {$method::debugInfo.addParameterName($string_literal.value);} + | {$method::debugInfo.addParameterName(null);} + ) + annotations {$parameterAnnotationSet = $annotations.annotationSetItem;} + ); ordered_debug_directives[int totalMethodRegisters, int methodParameterRegisters] - : ^(I_ORDERED_DEBUG_DIRECTIVES ( line - | local[$totalMethodRegisters, $methodParameterRegisters] - | end_local[$totalMethodRegisters, $methodParameterRegisters] - | restart_local[$totalMethodRegisters, $methodParameterRegisters] - | prologue - | epilogue - | source - )*); + : ^(I_ORDERED_DEBUG_DIRECTIVES + ( line + | local[$totalMethodRegisters, $methodParameterRegisters] + | end_local[$totalMethodRegisters, $methodParameterRegisters] + | restart_local[$totalMethodRegisters, $methodParameterRegisters] + | prologue + | epilogue + | source + )* + ); line - : ^(I_LINE integral_literal address) - { - $method::debugInfo.addLine($address.address, $integral_literal.value); - }; + : ^(I_LINE integral_literal address) + { + $method::debugInfo.addLine($address.address, $integral_literal.value); + }; local[int totalMethodRegisters, int methodParameterRegisters] - : ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address) - { - int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address) + { + int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - if ($string_literal.value != null) { - $method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value); - } else { - $method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor()); - } - }; + if ($string_literal.value != null) { + $method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value); + } else { + $method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor()); + } + }; end_local[int totalMethodRegisters, int methodParameterRegisters] - : ^(I_END_LOCAL REGISTER address) - { - int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : ^(I_END_LOCAL REGISTER address) + { + int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - $method::debugInfo.addEndLocal($address.address, registerNumber); - }; + $method::debugInfo.addEndLocal($address.address, registerNumber); + }; restart_local[int totalMethodRegisters, int methodParameterRegisters] - : ^(I_RESTART_LOCAL REGISTER address) - { - int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : ^(I_RESTART_LOCAL REGISTER address) + { + int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - $method::debugInfo.addRestartLocal($address.address, registerNumber); - }; + $method::debugInfo.addRestartLocal($address.address, registerNumber); + }; prologue - : ^(I_PROLOGUE address) - { - $method::debugInfo.addPrologue($address.address); - }; + : ^(I_PROLOGUE address) + { + $method::debugInfo.addPrologue($address.address); + }; epilogue - : ^(I_EPILOGUE address) - { - $method::debugInfo.addEpilogue($address.address); - }; + : ^(I_EPILOGUE address) + { + $method::debugInfo.addEpilogue($address.address); + }; source - : ^(I_SOURCE string_literal address) - { - $method::debugInfo.addSetFile($address.address, $string_literal.value); - }; + : ^(I_SOURCE string_literal address) + { + $method::debugInfo.addSetFile($address.address, $string_literal.value); + }; statements[int totalMethodRegisters, int methodParameterRegisters] returns[List instructions, int maxOutRegisters] - @init - { - $instructions = new LinkedList(); - $maxOutRegisters = 0; - } - : ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters, $instructions] - { - $method::currentAddress += $instructions.get($instructions.size() - 1).getSize($method::currentAddress); - if ($maxOutRegisters < $instruction.outRegisters) { - $maxOutRegisters = $instruction.outRegisters; - } - })*); + @init + { + $instructions = new LinkedList(); + $maxOutRegisters = 0; + } + : ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters, $instructions] + { + $method::currentAddress += $instructions.get($instructions.size() - 1).getSize($method::currentAddress); + if ($maxOutRegisters < $instruction.outRegisters) { + $maxOutRegisters = $instruction.outRegisters; + } + })*); label_ref returns[int labelAddress] - : SIMPLE_NAME - { - Integer labelAdd = $method::labels.get($SIMPLE_NAME.text); + : SIMPLE_NAME + { + Integer labelAdd = $method::labels.get($SIMPLE_NAME.text); - if (labelAdd == null) { - throw new SemanticException(input, $SIMPLE_NAME, "Label \"" + $SIMPLE_NAME.text + "\" is not defined."); - } + if (labelAdd == null) { + throw new SemanticException(input, $SIMPLE_NAME, "Label \"" + $SIMPLE_NAME.text + "\" is not defined."); + } - $labelAddress = labelAdd; - }; + $labelAddress = labelAdd; + }; -offset returns[int offsetValue] - : OFFSET - { - String offsetText = $OFFSET.text; - if (offsetText.charAt(0) == '+') { - offsetText = offsetText.substring(1); - } - $offsetValue = LiteralTools.parseInt(offsetText); - }; +offset returns[int offsetValue] + : OFFSET + { + String offsetText = $OFFSET.text; + if (offsetText.charAt(0) == '+') { + offsetText = offsetText.substring(1); + } + $offsetValue = LiteralTools.parseInt(offsetText); + }; offset_or_label_absolute[int baseAddress] returns[int address] - : offset {$address = $offset.offsetValue + $baseAddress;} - | label_ref {$address = $label_ref.labelAddress;}; + : offset {$address = $offset.offsetValue + $baseAddress;} + | label_ref {$address = $label_ref.labelAddress;}; offset_or_label returns[int offsetValue] - : offset {$offsetValue = $offset.offsetValue;} - | label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;}; + : offset {$offsetValue = $offset.offsetValue;} + | label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;}; register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount] - @init - { - $registers = new byte[5]; - $registerCount = 0; - } - : ^(I_REGISTER_LIST - (REGISTER - { - if ($registerCount == 5) { - throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 registers. Use the /range alternate opcode instead."); - } - $registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - })*); + @init + { + $registers = new byte[5]; + $registerCount = 0; + } + : ^(I_REGISTER_LIST + (REGISTER + { + if ($registerCount == 5) { + throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 registers. Use the /range alternate opcode instead."); + } + $registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + })*); register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister] - : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) - { - if ($startReg == null) { - $startRegister = 0; - $endRegister = -1; - } else { + : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) + { + if ($startReg == null) { + $startRegister = 0; + $endRegister = -1; + } else { $startRegister = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters); if ($endReg == null) { $endRegister = $startRegister; @@ -913,539 +885,539 @@ register_range[int totalMethodRegisters, int methodParameterRegisters] returns[i throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first"); } } - } - ; + } + ; verification_error_reference returns[Item item] - : CLASS_DESCRIPTOR - { - $item = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); - } - | fully_qualified_field - { - $item = $fully_qualified_field.fieldIdItem; - } - | fully_qualified_method - { - $item = $fully_qualified_method.methodIdItem; - }; + : CLASS_DESCRIPTOR + { + $item = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + } + | fully_qualified_field + { + $item = $fully_qualified_field.fieldIdItem; + } + | fully_qualified_method + { + $item = $fully_qualified_method.methodIdItem; + }; verification_error_type returns[VerificationErrorType verificationErrorType] - : VERIFICATION_ERROR_TYPE - { - $verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text); - }; + : VERIFICATION_ERROR_TYPE + { + $verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text); + }; instruction[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : insn_format10t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10t.outRegisters; } - | insn_format10x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10x.outRegisters; } - | insn_format11n[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11n.outRegisters; } - | insn_format11x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11x.outRegisters; } - | insn_format12x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format12x.outRegisters; } - | insn_format20bc[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20bc.outRegisters; } - | insn_format20t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20t.outRegisters; } - | insn_format21c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_field.outRegisters; } - | insn_format21c_string[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_string.outRegisters; } - | insn_format21c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_type.outRegisters; } - | insn_format21h[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21h.outRegisters; } - | insn_format21s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21s.outRegisters; } - | insn_format21t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21t.outRegisters; } - | insn_format22b[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22b.outRegisters; } - | insn_format22c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_field.outRegisters; } - | insn_format22c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_type.outRegisters; } - | insn_format22s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22s.outRegisters; } - | insn_format22t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22t.outRegisters; } - | insn_format22x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22x.outRegisters; } - | insn_format23x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format23x.outRegisters; } - | insn_format30t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format30t.outRegisters; } - | insn_format31c[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31c.outRegisters; } - | insn_format31i[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31i.outRegisters; } - | insn_format31t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31t.outRegisters; } - | insn_format32x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format32x.outRegisters; } - | insn_format35c_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_method.outRegisters; } - | insn_format35c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_type.outRegisters; } - | insn_format3rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_method.outRegisters; } - | insn_format3rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_type.outRegisters; } - | insn_format51l_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format51l_type.outRegisters; } - | insn_array_data_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_array_data_directive.outRegisters; } - | insn_packed_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; } - | insn_sparse_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; }; + : insn_format10t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10t.outRegisters; } + | insn_format10x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10x.outRegisters; } + | insn_format11n[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11n.outRegisters; } + | insn_format11x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11x.outRegisters; } + | insn_format12x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format12x.outRegisters; } + | insn_format20bc[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20bc.outRegisters; } + | insn_format20t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20t.outRegisters; } + | insn_format21c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_field.outRegisters; } + | insn_format21c_string[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_string.outRegisters; } + | insn_format21c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_type.outRegisters; } + | insn_format21h[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21h.outRegisters; } + | insn_format21s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21s.outRegisters; } + | insn_format21t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21t.outRegisters; } + | insn_format22b[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22b.outRegisters; } + | insn_format22c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_field.outRegisters; } + | insn_format22c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_type.outRegisters; } + | insn_format22s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22s.outRegisters; } + | insn_format22t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22t.outRegisters; } + | insn_format22x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22x.outRegisters; } + | insn_format23x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format23x.outRegisters; } + | insn_format30t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format30t.outRegisters; } + | insn_format31c[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31c.outRegisters; } + | insn_format31i[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31i.outRegisters; } + | insn_format31t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31t.outRegisters; } + | insn_format32x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format32x.outRegisters; } + | insn_format35c_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_method.outRegisters; } + | insn_format35c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_type.outRegisters; } + | insn_format3rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_method.outRegisters; } + | insn_format3rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_type.outRegisters; } + | insn_format51l_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format51l_type.outRegisters; } + | insn_array_data_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_array_data_directive.outRegisters; } + | insn_packed_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; } + | insn_sparse_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; }; catch [Exception ex] { - reportError(new SemanticException(input, ex)); - recover(input, null); - } + reportError(new SemanticException(input, ex)); + recover(input, null); + } insn_format10t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. goto endloop: - {$outRegisters = 0;} - ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text); + : //e.g. goto endloop: + {$outRegisters = 0;} + ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text); - int addressOffset = $offset_or_label.offsetValue; + int addressOffset = $offset_or_label.offsetValue; - $instructions.add(new Instruction10t(opcode, addressOffset)); - }; + $instructions.add(new Instruction10t(opcode, addressOffset)); + }; insn_format10x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. return - ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text); - $instructions.add(new Instruction10x(opcode)); - }; + : //e.g. return + ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text); + $instructions.add(new Instruction10x(opcode)); + }; insn_format11n[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const/4 v0, 5 - ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text); - byte regA = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const/4 v0, 5 + ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text); + byte regA = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - short litB = $short_integral_literal.value; - LiteralTools.checkNibble(litB); + short litB = $short_integral_literal.value; + LiteralTools.checkNibble(litB); - $instructions.add(new Instruction11n(opcode, regA, (byte)litB)); - }; + $instructions.add(new Instruction11n(opcode, regA, (byte)litB)); + }; insn_format11x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. move-result-object v1 - ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. move-result-object v1 + ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - $instructions.add(new Instruction11x(opcode, regA)); - }; + $instructions.add(new Instruction11x(opcode, regA)); + }; insn_format12x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. move v1 v2 - ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. move v1 v2 + ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text); + byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - $instructions.add(new Instruction12x(opcode, regA, regB)); - }; + $instructions.add(new Instruction12x(opcode, regA, regB)); + }; insn_format20bc[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. throw-verification-error generic-error, Lsome/class; - ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text); + : //e.g. throw-verification-error generic-error, Lsome/class; + ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text); - VerificationErrorType verificationErrorType = $verification_error_type.verificationErrorType; - Item referencedItem = $verification_error_reference.item; + VerificationErrorType verificationErrorType = $verification_error_type.verificationErrorType; + Item referencedItem = $verification_error_reference.item; - $instructions.add(new Instruction20bc(opcode, verificationErrorType, referencedItem)); - }; + $instructions.add(new Instruction20bc(opcode, verificationErrorType, referencedItem)); + }; insn_format20t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. goto/16 endloop: - ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20t.text); + : //e.g. goto/16 endloop: + ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20t.text); - int addressOffset = $offset_or_label.offsetValue; + int addressOffset = $offset_or_label.offsetValue; - $instructions.add(new Instruction20t(opcode, addressOffset)); - }; + $instructions.add(new Instruction20t(opcode, addressOffset)); + }; insn_format21c_field[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream; - ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field) - { - Opcode opcode = Opcode.getOpcodeByName($inst.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream; + ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field) + { + Opcode opcode = Opcode.getOpcodeByName($inst.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; + FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; - $instructions.add(new Instruction21c(opcode, regA, fieldIdItem)); - }; + $instructions.add(new Instruction21c(opcode, regA, fieldIdItem)); + }; insn_format21c_string[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const-string v1, "Hello World!" - ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const-string v1, "Hello World!" + ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); + StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); - instructions.add(new Instruction21c(opcode, regA, stringIdItem)); - }; + instructions.add(new Instruction21c(opcode, regA, stringIdItem)); + }; insn_format21c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2 - ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2 + ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - TypeIdItem typeIdItem = $reference_type_descriptor.type; + TypeIdItem typeIdItem = $reference_type_descriptor.type; - $instructions.add(new Instruction21c(opcode, regA, typeIdItem)); - }; + $instructions.add(new Instruction21c(opcode, regA, typeIdItem)); + }; insn_format21h[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const/high16 v1, 1234 - ^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const/high16 v1, 1234 + ^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - short litB = $short_integral_literal.value; + short litB = $short_integral_literal.value; - instructions.add(new Instruction21h(opcode, regA, litB)); - }; + instructions.add(new Instruction21h(opcode, regA, litB)); + }; insn_format21s[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const/16 v1, 1234 - ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const/16 v1, 1234 + ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - short litB = $short_integral_literal.value; + short litB = $short_integral_literal.value; - $instructions.add(new Instruction21s(opcode, regA, litB)); - }; + $instructions.add(new Instruction21s(opcode, regA, litB)); + }; insn_format21t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. if-eqz v0, endloop: - ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. if-eqz v0, endloop: + ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - int addressOffset = $offset_or_label.offsetValue; + int addressOffset = $offset_or_label.offsetValue; - if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) { - throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767]."); - } + if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) { + throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767]."); + } - $instructions.add(new Instruction21t(opcode, regA, (short)addressOffset)); - }; + $instructions.add(new Instruction21t(opcode, regA, (short)addressOffset)); + }; insn_format22b[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. add-int v0, v1, 123 - ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text); - short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. add-int v0, v1, 123 + ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text); + short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - short litC = $short_integral_literal.value; - LiteralTools.checkByte(litC); + short litC = $short_integral_literal.value; + LiteralTools.checkByte(litC); - $instructions.add(new Instruction22b(opcode, regA, regB, (byte)litC)); - }; + $instructions.add(new Instruction22b(opcode, regA, regB, (byte)litC)); + }; insn_format22c_field[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; - ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field) - { - Opcode opcode = Opcode.getOpcodeByName($inst.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; + ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field) + { + Opcode opcode = Opcode.getOpcodeByName($inst.text); + byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; + FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; - $instructions.add(new Instruction22c(opcode, regA, regB, fieldIdItem)); - }; + $instructions.add(new Instruction22c(opcode, regA, regB, fieldIdItem)); + }; insn_format22c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. instance-of v0, v1, Ljava/lang/String; - ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. instance-of v0, v1, Ljava/lang/String; + ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); + byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; + TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; - $instructions.add(new Instruction22c(opcode, regA, regB, typeIdItem)); - }; + $instructions.add(new Instruction22c(opcode, regA, regB, typeIdItem)); + }; insn_format22s[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. add-int/lit16 v0, v1, 12345 - ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. add-int/lit16 v0, v1, 12345 + ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text); + byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - short litC = $short_integral_literal.value; + short litC = $short_integral_literal.value; - $instructions.add(new Instruction22s(opcode, regA, regB, litC)); - }; + $instructions.add(new Instruction22s(opcode, regA, regB, litC)); + }; insn_format22t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. if-eq v0, v1, endloop: - ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. if-eq v0, v1, endloop: + ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text); + byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - int addressOffset = $offset_or_label.offsetValue; + int addressOffset = $offset_or_label.offsetValue; - if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) { - throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767]."); - } + if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) { + throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767]."); + } - $instructions.add(new Instruction22t(opcode, regA, regB, (short)addressOffset)); - }; + $instructions.add(new Instruction22t(opcode, regA, regB, (short)addressOffset)); + }; insn_format22x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. move/from16 v1, v1234 - ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text); - short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. move/from16 v1, v1234 + ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text); + short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - $instructions.add(new Instruction22x(opcode, regA, regB)); - }; + $instructions.add(new Instruction22x(opcode, regA, regB)); + }; insn_format23x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. add-int v1, v2, v3 - ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text); - short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. add-int v1, v2, v3 + ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text); + short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters); - $instructions.add(new Instruction23x(opcode, regA, regB, regC)); - }; + $instructions.add(new Instruction23x(opcode, regA, regB, regC)); + }; insn_format30t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. goto/32 endloop: - ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT30t.text); + : //e.g. goto/32 endloop: + ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT30t.text); - int addressOffset = $offset_or_label.offsetValue; + int addressOffset = $offset_or_label.offsetValue; - $instructions.add(new Instruction30t(opcode, addressOffset)); - }; + $instructions.add(new Instruction30t(opcode, addressOffset)); + }; insn_format31c[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const-string/jumbo v1 "Hello World!" - ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const-string/jumbo v1 "Hello World!" + ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); + StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); - $instructions.add(new Instruction31c(opcode, regA, stringIdItem)); - }; + $instructions.add(new Instruction31c(opcode, regA, stringIdItem)); + }; insn_format31i[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const v0, 123456 - ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const v0, 123456 + ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - int litB = $fixed_32bit_literal.value; + int litB = $fixed_32bit_literal.value; - $instructions.add(new Instruction31i(opcode, regA, litB)); - }; + $instructions.add(new Instruction31i(opcode, regA, litB)); + }; insn_format31t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. fill-array-data v0, ArrayData: - ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text); + : //e.g. fill-array-data v0, ArrayData: + ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - int addressOffset = $offset_or_label.offsetValue; - if (($method::currentAddress + addressOffset) \% 2 != 0) { - addressOffset++; - } + int addressOffset = $offset_or_label.offsetValue; + if (($method::currentAddress + addressOffset) \% 2 != 0) { + addressOffset++; + } - $instructions.add(new Instruction31t(opcode, regA, addressOffset)); - }; + $instructions.add(new Instruction31t(opcode, regA, addressOffset)); + }; insn_format32x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. move/16 v5678, v1234 - ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text); - int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. move/16 v5678, v1234 + ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text); + int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - $instructions.add(new Instruction32x(opcode, regA, regB)); - }; + $instructions.add(new Instruction32x(opcode, regA, regB)); + }; insn_format35c_method[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V - ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); + : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V + ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); - //this depends on the fact that register_list returns a byte[5] - byte[] registers = $register_list.registers; - byte registerCount = $register_list.registerCount; - $outRegisters = registerCount; + //this depends on the fact that register_list returns a byte[5] + byte[] registers = $register_list.registers; + byte registerCount = $register_list.registerCount; + $outRegisters = registerCount; - MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; + MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; - $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem)); - }; + $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem)); + }; insn_format35c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. filled-new-array {v0,v1}, I - ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text); + : //e.g. filled-new-array {v0,v1}, I + ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text); - //this depends on the fact that register_list returns a byte[5] - byte[] registers = $register_list.registers; - byte registerCount = $register_list.registerCount; - $outRegisters = registerCount; + //this depends on the fact that register_list returns a byte[5] + byte[] registers = $register_list.registers; + byte registerCount = $register_list.registerCount; + $outRegisters = registerCount; - TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; + TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; - $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem)); - }; + $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem)); + }; insn_format3rc_method[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; - ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text); - int startRegister = $register_range.startRegister; - int endRegister = $register_range.endRegister; + : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; + ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text); + int startRegister = $register_range.startRegister; + int endRegister = $register_range.endRegister; - int registerCount = endRegister-startRegister+1; - $outRegisters = registerCount; + int registerCount = endRegister-startRegister+1; + $outRegisters = registerCount; - MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; + MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; - $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, methodIdItem)); - }; + $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, methodIdItem)); + }; insn_format3rc_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. filled-new-array/range {v0..v6} I - ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text); - int startRegister = $register_range.startRegister; - int endRegister = $register_range.endRegister; + : //e.g. filled-new-array/range {v0..v6} I + ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text); + int startRegister = $register_range.startRegister; + int endRegister = $register_range.endRegister; - int registerCount = endRegister-startRegister+1; - $outRegisters = registerCount; + int registerCount = endRegister-startRegister+1; + $outRegisters = registerCount; - TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; + TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; - $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, typeIdItem)); - }; + $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, typeIdItem)); + }; insn_format51l_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. const-wide v0, 5000000000L - ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) - { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + : //e.g. const-wide v0, 5000000000L + ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text); + short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); - long litB = $fixed_64bit_literal.value; + long litB = $fixed_64bit_literal.value; - $instructions.add(new Instruction51l(opcode, regA, litB)); - }; + $instructions.add(new Instruction51l(opcode, regA, litB)); + }; insn_array_data_directive[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : //e.g. .array-data 4 1000000 .end array-data - ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) - { - if (($method::currentAddress \% 2) != 0) { - $instructions.add(new Instruction10x(Opcode.NOP)); - $method::currentAddress++; - } + : //e.g. .array-data 4 1000000 .end array-data + ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) + { + if (($method::currentAddress \% 2) != 0) { + $instructions.add(new Instruction10x(Opcode.NOP)); + $method::currentAddress++; + } - int elementWidth = $short_integral_literal.value; - List byteValues = $array_elements.values; + int elementWidth = $short_integral_literal.value; + List byteValues = $array_elements.values; - int length = 0; - for (byte[] byteValue: byteValues) { - length+=byteValue.length; - } + int length = 0; + for (byte[] byteValue: byteValues) { + length+=byteValue.length; + } - byte[] encodedValues = new byte[length]; - int index = 0; - for (byte[] byteValue: byteValues) { - System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length); - index+=byteValue.length; - } + byte[] encodedValues = new byte[length]; + int index = 0; + for (byte[] byteValue: byteValues) { + System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length); + index+=byteValue.length; + } - $instructions.add(new ArrayDataPseudoInstruction(elementWidth, encodedValues)); - }; + $instructions.add(new ArrayDataPseudoInstruction(elementWidth, encodedValues)); + }; insn_packed_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : - ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) - { - if (($method::currentAddress \% 2) != 0) { - $instructions.add(new Instruction10x(Opcode.NOP)); - $method::currentAddress++; - } - Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress); - if (baseAddress == null) { - baseAddress = 0; - } - } - packed_switch_targets[baseAddress]) - { + : + ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) + { + if (($method::currentAddress \% 2) != 0) { + $instructions.add(new Instruction10x(Opcode.NOP)); + $method::currentAddress++; + } + Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress); + if (baseAddress == null) { + baseAddress = 0; + } + } + packed_switch_targets[baseAddress]) + { - int startKey = $fixed_32bit_literal.value; - int[] targets = $packed_switch_targets.targets; + int startKey = $fixed_32bit_literal.value; + int[] targets = $packed_switch_targets.targets; - $instructions.add(new PackedSwitchDataPseudoInstruction(startKey, targets)); - }; + $instructions.add(new PackedSwitchDataPseudoInstruction(startKey, targets)); + }; insn_sparse_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : - ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount] - { - if (($method::currentAddress \% 2) != 0) { - $instructions.add(new Instruction10x(Opcode.NOP)); - $method::currentAddress++; - } - Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress); - if (baseAddress == null) { - baseAddress = 0; - } - } + : + ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount] + { + if (($method::currentAddress \% 2) != 0) { + $instructions.add(new Instruction10x(Opcode.NOP)); + $method::currentAddress++; + } + Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress); + if (baseAddress == null) { + baseAddress = 0; + } + } - sparse_switch_targets[baseAddress, $sparse_switch_target_count.targetCount]) - { - int[] keys = $sparse_switch_keys.keys; - int[] targets = $sparse_switch_targets.targets; + sparse_switch_targets[baseAddress, $sparse_switch_target_count.targetCount]) + { + int[] keys = $sparse_switch_keys.keys; + int[] targets = $sparse_switch_targets.targets; - $instructions.add(new SparseSwitchDataPseudoInstruction(keys, targets)); - }; + $instructions.add(new SparseSwitchDataPseudoInstruction(keys, targets)); + }; nonvoid_type_descriptor returns [TypeIdItem type] - : (PRIMITIVE_TYPE - | CLASS_DESCRIPTOR - | ARRAY_DESCRIPTOR) - { - $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); - }; + : (PRIMITIVE_TYPE + | CLASS_DESCRIPTOR + | ARRAY_DESCRIPTOR) + { + $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + }; reference_type_descriptor returns [TypeIdItem type] - : (CLASS_DESCRIPTOR - | ARRAY_DESCRIPTOR) - { - $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); - }; + : (CLASS_DESCRIPTOR + | ARRAY_DESCRIPTOR) + { + $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + }; @@ -1453,140 +1425,142 @@ reference_type_descriptor returns [TypeIdItem type] class_type_descriptor returns [TypeIdItem type] - : CLASS_DESCRIPTOR - { - $type = TypeIdItem.internTypeIdItem(dexFile, $CLASS_DESCRIPTOR.text); - }; + : CLASS_DESCRIPTOR + { + $type = TypeIdItem.internTypeIdItem(dexFile, $CLASS_DESCRIPTOR.text); + }; type_descriptor returns [TypeIdItem type] - : VOID_TYPE {$type = TypeIdItem.internTypeIdItem(dexFile, "V");} - | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;} - ; + : VOID_TYPE {$type = TypeIdItem.internTypeIdItem(dexFile, "V");} + | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;} + ; short_integral_literal returns[short value] - : long_literal - { - LiteralTools.checkShort($long_literal.value); - $value = (short)$long_literal.value; - } - | integer_literal - { - LiteralTools.checkShort($integer_literal.value); - $value = (short)$integer_literal.value; - } - | short_literal {$value = $short_literal.value;} - | char_literal {$value = (short)$char_literal.value;} - | byte_literal {$value = $byte_literal.value;}; + : long_literal + { + LiteralTools.checkShort($long_literal.value); + $value = (short)$long_literal.value; + } + | integer_literal + { + LiteralTools.checkShort($integer_literal.value); + $value = (short)$integer_literal.value; + } + | short_literal {$value = $short_literal.value;} + | char_literal {$value = (short)$char_literal.value;} + | byte_literal {$value = $byte_literal.value;}; integral_literal returns[int value] - : long_literal - { - LiteralTools.checkInt($long_literal.value); - $value = (int)$long_literal.value; - } - | integer_literal {$value = $integer_literal.value;} - | short_literal {$value = $short_literal.value;} - | byte_literal {$value = $byte_literal.value;}; + : long_literal + { + LiteralTools.checkInt($long_literal.value); + $value = (int)$long_literal.value; + } + | integer_literal {$value = $integer_literal.value;} + | short_literal {$value = $short_literal.value;} + | byte_literal {$value = $byte_literal.value;}; integer_literal returns[int value] - : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); }; + : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); }; long_literal returns[long value] - : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); }; + : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); }; short_literal returns[short value] - : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); }; + : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); }; byte_literal returns[byte value] - : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); }; + : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); }; float_literal returns[float value] - : FLOAT_LITERAL { $value = parseFloat($FLOAT_LITERAL.text); }; + : FLOAT_LITERAL { $value = LiteralTools.parseFloat($FLOAT_LITERAL.text); }; double_literal returns[double value] - : DOUBLE_LITERAL { $value = parseDouble($DOUBLE_LITERAL.text); }; + : DOUBLE_LITERAL { $value = LiteralTools.parseDouble($DOUBLE_LITERAL.text); }; char_literal returns[char value] - : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); }; + : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); }; string_literal returns[String value] - : STRING_LITERAL - { - $value = $STRING_LITERAL.text; - $value = $value.substring(1,$value.length()-1); - }; + : STRING_LITERAL + { + $value = $STRING_LITERAL.text; + $value = $value.substring(1,$value.length()-1); + }; bool_literal returns[boolean value] - : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); }; + : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); }; array_literal returns[EncodedValue[\] values] - : {ArrayList valuesList = new ArrayList();} - ^(I_ENCODED_ARRAY (literal {valuesList.add($literal.encodedValue);})*) - { - $values = new EncodedValue[valuesList.size()]; - valuesList.toArray($values); - }; + : {ArrayList valuesList = new ArrayList();} + ^(I_ENCODED_ARRAY (literal {valuesList.add($literal.encodedValue);})*) + { + $values = new EncodedValue[valuesList.size()]; + valuesList.toArray($values); + }; annotations returns[AnnotationSetItem annotationSetItem] - : {ArrayList annotationList = new ArrayList();} - ^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*) - { - if (annotationList.size() > 0) { - $annotationSetItem = AnnotationSetItem.internAnnotationSetItem(dexFile, annotationList); - } - }; + : {ArrayList annotationList = new ArrayList();} + ^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*) + { + if (annotationList.size() > 0) { + $annotationSetItem = AnnotationSetItem.internAnnotationSetItem(dexFile, annotationList); + } + }; annotation returns[AnnotationItem annotationItem] - : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation) - { - AnnotationVisibility visibility = AnnotationVisibility.valueOf($ANNOTATION_VISIBILITY.text.toUpperCase()); - AnnotationEncodedSubValue encodedAnnotation = new AnnotationEncodedSubValue($subannotation.annotationType, - $subannotation.elementNames, $subannotation.elementValues); - $annotationItem = AnnotationItem.internAnnotationItem(dexFile, visibility, encodedAnnotation); - }; + : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation) + { + AnnotationVisibility visibility = AnnotationVisibility.valueOf($ANNOTATION_VISIBILITY.text.toUpperCase()); + AnnotationEncodedSubValue encodedAnnotation = new AnnotationEncodedSubValue($subannotation.annotationType, + $subannotation.elementNames, $subannotation.elementValues); + $annotationItem = AnnotationItem.internAnnotationItem(dexFile, visibility, encodedAnnotation); + }; annotation_element returns[StringIdItem elementName, EncodedValue elementValue] - : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal) - { - $elementName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - $elementValue = $literal.encodedValue; - }; + : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal) + { + $elementName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); + $elementValue = $literal.encodedValue; + }; subannotation returns[TypeIdItem annotationType, StringIdItem[\] elementNames, EncodedValue[\] elementValues] - : {ArrayList elementNamesList = new ArrayList(); - ArrayList elementValuesList = new ArrayList();} - ^( I_SUBANNOTATION - class_type_descriptor - (annotation_element - { - elementNamesList.add($annotation_element.elementName); - elementValuesList.add($annotation_element.elementValue); - } )* ) - { - $annotationType = $class_type_descriptor.type; - $elementNames = new StringIdItem[elementNamesList.size()]; - elementNamesList.toArray($elementNames); - $elementValues = new EncodedValue[elementValuesList.size()]; - elementValuesList.toArray($elementValues); - }; + : {ArrayList elementNamesList = new ArrayList(); + ArrayList elementValuesList = new ArrayList();} + ^(I_SUBANNOTATION + class_type_descriptor + (annotation_element + { + elementNamesList.add($annotation_element.elementName); + elementValuesList.add($annotation_element.elementValue); + } + )* + ) + { + $annotationType = $class_type_descriptor.type; + $elementNames = new StringIdItem[elementNamesList.size()]; + elementNamesList.toArray($elementNames); + $elementValues = new EncodedValue[elementValuesList.size()]; + elementValuesList.toArray($elementValues); + }; field_literal returns[FieldIdItem value] - : ^(I_ENCODED_FIELD fully_qualified_field) - { - $value = $fully_qualified_field.fieldIdItem; - }; + : ^(I_ENCODED_FIELD fully_qualified_field) + { + $value = $fully_qualified_field.fieldIdItem; + }; method_literal returns[MethodIdItem value] - : ^(I_ENCODED_METHOD fully_qualified_method) - { - $value = $fully_qualified_method.methodIdItem; - }; + : ^(I_ENCODED_METHOD fully_qualified_method) + { + $value = $fully_qualified_method.methodIdItem; + }; enum_literal returns[FieldIdItem value] - : ^(I_ENCODED_ENUM fully_qualified_field) - { - $value = $fully_qualified_field.fieldIdItem; - }; + : ^(I_ENCODED_ENUM fully_qualified_field) + { + $value = $fully_qualified_field.fieldIdItem; + }; diff --git a/brut.apktool.smali/smali/src/main/java/org/jf/smali/InvalidToken.java b/brut.apktool.smali/smali/src/main/java/org/jf/smali/InvalidToken.java index b7b10781..edeb7851 100644 --- a/brut.apktool.smali/smali/src/main/java/org/jf/smali/InvalidToken.java +++ b/brut.apktool.smali/smali/src/main/java/org/jf/smali/InvalidToken.java @@ -28,7 +28,6 @@ package org.jf.smali; -import org.antlr.runtime.CharStream; import org.antlr.runtime.CommonToken; public class InvalidToken extends CommonToken { @@ -37,13 +36,13 @@ public class InvalidToken extends CommonToken { public InvalidToken(String message) { super(smaliParser.INVALID_TOKEN); this.message = message; - this.channel = smaliLexer.ERROR_CHANNEL; + this.channel = smaliParser.ERROR_CHANNEL; } public InvalidToken(String message, String text) { super(smaliParser.INVALID_TOKEN, text); this.message = message; - this.channel = smaliLexer.ERROR_CHANNEL; + this.channel = smaliParser.ERROR_CHANNEL; } public String getMessage() { diff --git a/brut.apktool.smali/smali/src/main/java/org/jf/smali/LiteralTools.java b/brut.apktool.smali/smali/src/main/java/org/jf/smali/LiteralTools.java index 1c7fb784..e2262c1a 100644 --- a/brut.apktool.smali/smali/src/main/java/org/jf/smali/LiteralTools.java +++ b/brut.apktool.smali/smali/src/main/java/org/jf/smali/LiteralTools.java @@ -28,6 +28,9 @@ package org.jf.smali; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class LiteralTools { public static byte parseByte(String byteLiteral) @@ -304,6 +307,42 @@ public class LiteralTools } } + private static Pattern specialFloatRegex = Pattern.compile("((-)?infinityf)|(nanf)", Pattern.CASE_INSENSITIVE); + public static float parseFloat(String floatString) { + Matcher m = specialFloatRegex.matcher(floatString); + if (m.matches()) { + //got an infinity + if (m.start(1) != -1) { + if (m.start(2) != -1) { + return Float.NEGATIVE_INFINITY; + } else { + return Float.POSITIVE_INFINITY; + } + } else { + return Float.NaN; + } + } + return Float.parseFloat(floatString); + } + + private static Pattern specialDoubleRegex = Pattern.compile("((-)?infinityd?)|(nand?)", Pattern.CASE_INSENSITIVE); + public static double parseDouble(String doubleString) { + Matcher m = specialDoubleRegex.matcher(doubleString); + if (m.matches()) { + //got an infinity + if (m.start(1) != -1) { + if (m.start(2) != -1) { + return Double.NEGATIVE_INFINITY; + } else { + return Double.POSITIVE_INFINITY; + } + } else { + return Double.NaN; + } + } + return Double.parseDouble(doubleString); + } + public static byte[] longToBytes(long value) { byte[] bytes = new byte[8]; diff --git a/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java b/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java index e38f8dea..ecd9cf99 100644 --- a/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java +++ b/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java @@ -103,7 +103,6 @@ public class main { boolean fixJumbo = true; boolean fixGoto = true; boolean verboseErrors = false; - boolean oldLexer = false; boolean printTokens = false; boolean apiSet = false; @@ -158,9 +157,6 @@ public class main { case 'V': verboseErrors = true; break; - case 'L': - oldLexer = true; - break; case 'T': printTokens = true; break; @@ -202,7 +198,7 @@ public class main { boolean errors = false; for (File file: filesToProcess) { - if (!assembleSmaliFile(file, dexFile, verboseErrors, oldLexer, printTokens, allowOdex, apiLevel)) { + if (!assembleSmaliFile(file, dexFile, verboseErrors, printTokens, allowOdex, apiLevel)) { errors = true; } } @@ -276,7 +272,7 @@ public class main { } } - private static boolean assembleSmaliFile(File smaliFile, DexFile dexFile, boolean verboseErrors, boolean oldLexer, + private static boolean assembleSmaliFile(File smaliFile, DexFile dexFile, boolean verboseErrors, boolean printTokens, boolean allowOdex, int apiLevel) throws Exception { CommonTokenStream tokens; @@ -285,27 +281,19 @@ public class main { boolean lexerErrors = false; LexerErrorInterface lexer; - if (oldLexer) { - ANTLRFileStream input = new ANTLRFileStream(smaliFile.getAbsolutePath(), "UTF-8"); - input.name = smaliFile.getAbsolutePath(); + FileInputStream fis = new FileInputStream(smaliFile.getAbsolutePath()); + InputStreamReader reader = new InputStreamReader(fis, "UTF-8"); - lexer = new smaliLexer(input); - tokens = new CommonTokenStream((TokenSource)lexer); - } else { - FileInputStream fis = new FileInputStream(smaliFile.getAbsolutePath()); - InputStreamReader reader = new InputStreamReader(fis, "UTF-8"); - - lexer = new smaliFlexLexer(reader); - ((smaliFlexLexer)lexer).setSourceFile(smaliFile); - tokens = new CommonTokenStream((TokenSource)lexer); - } + lexer = new smaliFlexLexer(reader); + ((smaliFlexLexer)lexer).setSourceFile(smaliFile); + tokens = new CommonTokenStream((TokenSource)lexer); if (printTokens) { tokens.getTokens(); for (int i=0; i { - -? {Integer} { return newToken(INTEGER_LITERAL); } + {Integer} { return newToken(POSITIVE_INTEGER_LITERAL); } + - {Integer} { return newToken(NEGATIVE_INTEGER_LITERAL); } -? {Integer} [lL] { return newToken(LONG_LITERAL); } -? {Integer} [sS] { return newToken(SHORT_LITERAL); } -? {Integer} [tT] { return newToken(BYTE_LITERAL); } diff --git a/brut.apktool.smali/smali/src/test/java/LexerTest.java b/brut.apktool.smali/smali/src/test/java/LexerTest.java index 5afc2e2c..074b32ed 100644 --- a/brut.apktool.smali/smali/src/test/java/LexerTest.java +++ b/brut.apktool.smali/smali/src/test/java/LexerTest.java @@ -165,7 +165,7 @@ public class LexerTest { for (int i=0; i") COLON(":") SIMPLE_NAME("sswitch_8") -INTEGER_LITERAL("0x6f3c") +POSITIVE_INTEGER_LITERAL("0x6f3c") ARROW("->") COLON(":") SIMPLE_NAME("sswitch_8") -INTEGER_LITERAL("0x6f41") +POSITIVE_INTEGER_LITERAL("0x6f41") ARROW("->") COLON(":") SIMPLE_NAME("sswitch_8") @@ -368,19 +368,19 @@ PRIMITIVE_TYPE("I") CLOSE_PAREN(")") CLASS_DESCRIPTOR("Lcom/android/internal/telephony/IccCardStatus$CardState;") REGISTERS_DIRECTIVE(".registers") -INTEGER_LITERAL("6") +POSITIVE_INTEGER_LITERAL("6") PARAMETER_DIRECTIVE(".parameter") STRING_LITERAL("\"state\"") PROLOGUE_DIRECTIVE(".prologue") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("59") +POSITIVE_INTEGER_LITERAL("59") INSTRUCTION_FORMAT31t("packed-switch") REGISTER("p1") COMMA(",") COLON(":") SIMPLE_NAME("pswitch_data_26") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("64") +POSITIVE_INTEGER_LITERAL("64") INSTRUCTION_FORMAT21c_TYPE("new-instance") REGISTER("v1") COMMA(",") @@ -466,7 +466,7 @@ VOID_TYPE("V") INSTRUCTION_FORMAT11x("throw") REGISTER("v1") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("60") +POSITIVE_INTEGER_LITERAL("60") COLON(":") SIMPLE_NAME("pswitch_1c") INSTRUCTION_FORMAT21c_FIELD("sget-object") @@ -478,7 +478,7 @@ SIMPLE_NAME("CARDSTATE_ABSENT") COLON(":") CLASS_DESCRIPTOR("Lcom/android/internal/telephony/IccCardStatus$CardState;") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("67") +POSITIVE_INTEGER_LITERAL("67") LOCAL_DIRECTIVE(".local") REGISTER("v0") COMMA(",") @@ -490,7 +490,7 @@ SIMPLE_NAME("goto_1e") INSTRUCTION_FORMAT11x("return-object") REGISTER("v0") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("61") +POSITIVE_INTEGER_LITERAL("61") END_LOCAL_DIRECTIVE(".end local") REGISTER("v0") COLON(":") @@ -509,7 +509,7 @@ INSTRUCTION_FORMAT10t("goto") COLON(":") SIMPLE_NAME("goto_1e") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("62") +POSITIVE_INTEGER_LITERAL("62") END_LOCAL_DIRECTIVE(".end local") REGISTER("v0") COLON(":") @@ -528,12 +528,12 @@ INSTRUCTION_FORMAT10t("goto") COLON(":") SIMPLE_NAME("goto_1e") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("59") +POSITIVE_INTEGER_LITERAL("59") INSTRUCTION_FORMAT10x("nop") COLON(":") SIMPLE_NAME("pswitch_data_26") PACKED_SWITCH_DIRECTIVE(".packed-switch") -INTEGER_LITERAL("0x0") +POSITIVE_INTEGER_LITERAL("0x0") COLON(":") SIMPLE_NAME("pswitch_1c") COLON(":") @@ -550,7 +550,7 @@ PARAM_LIST("IILjava/lang/String;ILandroid/os/Message;") CLOSE_PAREN(")") VOID_TYPE("V") REGISTERS_DIRECTIVE(".registers") -INTEGER_LITERAL("13") +POSITIVE_INTEGER_LITERAL("13") PARAMETER_DIRECTIVE(".parameter") STRING_LITERAL("\"commandInterfaceCFAction\"") PARAMETER_DIRECTIVE(".parameter") @@ -565,13 +565,13 @@ PROLOGUE_DIRECTIVE(".prologue") INSTRUCTION_FORMAT11n("const/4") REGISTER("v3") COMMA(",") -INTEGER_LITERAL("0x1") +POSITIVE_INTEGER_LITERAL("0x1") INSTRUCTION_FORMAT11n("const/4") REGISTER("v4") COMMA(",") -INTEGER_LITERAL("0x0") +POSITIVE_INTEGER_LITERAL("0x0") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("981") +POSITIVE_INTEGER_LITERAL("981") INSTRUCTION_FORMAT35c_METHOD("invoke-direct") OPEN_BRACE("{") REGISTER("p0") @@ -615,14 +615,14 @@ COMMA(",") COLON(":") SIMPLE_NAME("cond_28") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("985") +POSITIVE_INTEGER_LITERAL("985") INSTRUCTION_FORMAT21t("if-nez") REGISTER("p2") COMMA(",") COLON(":") SIMPLE_NAME("cond_2b") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("986") +POSITIVE_INTEGER_LITERAL("986") INSTRUCTION_FORMAT22c_FIELD("iget-object") REGISTER("v0") COMMA(",") @@ -636,7 +636,7 @@ CLASS_DESCRIPTOR("Lcom/android/internal/telephony/gsm/GSMPhone$MyHandler;") INSTRUCTION_FORMAT21s("const/16") REGISTER("v1") COMMA(",") -INTEGER_LITERAL("0xc") +POSITIVE_INTEGER_LITERAL("0xc") INSTRUCTION_FORMAT35c_METHOD("invoke-virtual") OPEN_BRACE("{") REGISTER("p0") @@ -687,7 +687,7 @@ CLASS_DESCRIPTOR("Landroid/os/Message;") INSTRUCTION_FORMAT11x("move-result-object") REGISTER("v6") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("991") +POSITIVE_INTEGER_LITERAL("991") LOCAL_DIRECTIVE(".local") REGISTER("v6") COMMA(",") @@ -737,7 +737,7 @@ PARAM_LIST("IIILjava/lang/String;ILandroid/os/Message;") CLOSE_PAREN(")") VOID_TYPE("V") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("998") +POSITIVE_INTEGER_LITERAL("998") END_LOCAL_DIRECTIVE(".end local") REGISTER("v6") COLON(":") @@ -750,12 +750,12 @@ REGISTER("v2") COMMA(",") REGISTER("v4") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("986") +POSITIVE_INTEGER_LITERAL("986") INSTRUCTION_FORMAT10t("goto") COLON(":") SIMPLE_NAME("goto_1b") LINE_DIRECTIVE(".line") -INTEGER_LITERAL("989") +POSITIVE_INTEGER_LITERAL("989") COLON(":") SIMPLE_NAME("cond_2b") INSTRUCTION_FORMAT12x_OR_ID("move-object") diff --git a/brut.apktool.smali/smali/src/test/resources/LexerTest/ShortLiteralTest.tokens b/brut.apktool.smali/smali/src/test/resources/LexerTest/ShortLiteralTest.tokens index d0a1fabf..d8521c1b 100644 --- a/brut.apktool.smali/smali/src/test/resources/LexerTest/ShortLiteralTest.tokens +++ b/brut.apktool.smali/smali/src/test/resources/LexerTest/ShortLiteralTest.tokens @@ -1,49 +1,49 @@ SHORT_LITERAL("0x0S") -INTEGER_LITERAL("0x00") +POSITIVE_INTEGER_LITERAL("0x00") SHORT_LITERAL("0x1s") -INTEGER_LITERAL("0x1234") +POSITIVE_INTEGER_LITERAL("0x1234") SHORT_LITERAL("0x7fffS") SHORT_LITERAL("0x8000s") -INTEGER_LITERAL("0xFFFF") -INTEGER_LITERAL("-0x00") -INTEGER_LITERAL("-0x01") -INTEGER_LITERAL("-01234") +POSITIVE_INTEGER_LITERAL("0xFFFF") +NEGATIVE_INTEGER_LITERAL("-0x00") +NEGATIVE_INTEGER_LITERAL("-0x01") +NEGATIVE_INTEGER_LITERAL("-01234") SHORT_LITERAL("-01234s") -INTEGER_LITERAL("-0x8000") -INTEGER_LITERAL("-0x1fff") +NEGATIVE_INTEGER_LITERAL("-0x8000") +NEGATIVE_INTEGER_LITERAL("-0x1fff") SHORT_LITERAL("-0x1fffS") -INTEGER_LITERAL("-0x8001") -INTEGER_LITERAL("-0xFFFF") -INTEGER_LITERAL("-0x100000") -INTEGER_LITERAL("0") -INTEGER_LITERAL("1") -INTEGER_LITERAL("12345") +NEGATIVE_INTEGER_LITERAL("-0x8001") +NEGATIVE_INTEGER_LITERAL("-0xFFFF") +NEGATIVE_INTEGER_LITERAL("-0x100000") +POSITIVE_INTEGER_LITERAL("0") +POSITIVE_INTEGER_LITERAL("1") +POSITIVE_INTEGER_LITERAL("12345") SHORT_LITERAL("12345s") -INTEGER_LITERAL("32767") -INTEGER_LITERAL("32678") +POSITIVE_INTEGER_LITERAL("32767") +POSITIVE_INTEGER_LITERAL("32678") SHORT_LITERAL("65535S") -INTEGER_LITERAL("-0") -INTEGER_LITERAL("-1") +NEGATIVE_INTEGER_LITERAL("-0") +NEGATIVE_INTEGER_LITERAL("-1") SHORT_LITERAL("-12345S") -INTEGER_LITERAL("-32767") +NEGATIVE_INTEGER_LITERAL("-32767") SHORT_LITERAL("-32768s") SHORT_LITERAL("-32679s") SHORT_LITERAL("-65535s") -INTEGER_LITERAL("65536") -INTEGER_LITERAL("65600") -INTEGER_LITERAL("00") -INTEGER_LITERAL("01") -INTEGER_LITERAL("012345") +POSITIVE_INTEGER_LITERAL("65536") +POSITIVE_INTEGER_LITERAL("65600") +POSITIVE_INTEGER_LITERAL("00") +POSITIVE_INTEGER_LITERAL("01") +POSITIVE_INTEGER_LITERAL("012345") SHORT_LITERAL("012345s") -INTEGER_LITERAL("077777") -INTEGER_LITERAL("0100000") -INTEGER_LITERAL("0177777") -INTEGER_LITERAL("-00") -INTEGER_LITERAL("-01") -INTEGER_LITERAL("-012345") +POSITIVE_INTEGER_LITERAL("077777") +POSITIVE_INTEGER_LITERAL("0100000") +POSITIVE_INTEGER_LITERAL("0177777") +NEGATIVE_INTEGER_LITERAL("-00") +NEGATIVE_INTEGER_LITERAL("-01") +NEGATIVE_INTEGER_LITERAL("-012345") SHORT_LITERAL("-012345S") -INTEGER_LITERAL("-077777") -INTEGER_LITERAL("-0100000") -INTEGER_LITERAL("-0100001") -INTEGER_LITERAL("-0177777") -INTEGER_LITERAL("0200000") \ No newline at end of file +NEGATIVE_INTEGER_LITERAL("-077777") +NEGATIVE_INTEGER_LITERAL("-0100000") +NEGATIVE_INTEGER_LITERAL("-0100001") +NEGATIVE_INTEGER_LITERAL("-0177777") +POSITIVE_INTEGER_LITERAL("0200000") \ No newline at end of file diff --git a/brut.apktool.smali/util/src/main/java/ds/tree/RadixTreeNode.java b/brut.apktool.smali/util/src/main/java/ds/tree/RadixTreeNode.java index 287e0e98..fabdd389 100644 --- a/brut.apktool.smali/util/src/main/java/ds/tree/RadixTreeNode.java +++ b/brut.apktool.smali/util/src/main/java/ds/tree/RadixTreeNode.java @@ -85,19 +85,19 @@ class RadixTreeNode { this.childern = childern; } - public int getNumberOfMatchingCharacters(String key) { - int numberOfMatchingCharacters = 0; + public int getNumberOfMatchingCharacters(String key) { + int numberOfMatchingCharacters = 0; while (numberOfMatchingCharacters < key.length() && numberOfMatchingCharacters < this.getKey().length()) { if (key.charAt(numberOfMatchingCharacters) != this.getKey().charAt(numberOfMatchingCharacters)) { break; } numberOfMatchingCharacters++; } - return numberOfMatchingCharacters; - } + return numberOfMatchingCharacters; + } @Override public String toString() { - return key; + return key; } } diff --git a/brut.apktool.smali/util/src/main/java/ds/tree/VisitorImpl.java b/brut.apktool.smali/util/src/main/java/ds/tree/VisitorImpl.java index 20409e02..ff4e8d17 100644 --- a/brut.apktool.smali/util/src/main/java/ds/tree/VisitorImpl.java +++ b/brut.apktool.smali/util/src/main/java/ds/tree/VisitorImpl.java @@ -11,17 +11,17 @@ public abstract class VisitorImpl implements Visitor { protected R result; - public VisitorImpl() { - this.result = null; - } + public VisitorImpl() { + this.result = null; + } - public VisitorImpl(R initialValue) { - this.result = initialValue; - } + public VisitorImpl(R initialValue) { + this.result = initialValue; + } - public R getResult() { - return result; - } + public R getResult() { + return result; + } - abstract public void visit(String key, RadixTreeNode parent, RadixTreeNode node); + abstract public void visit(String key, RadixTreeNode parent, RadixTreeNode node); } \ No newline at end of file diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java b/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java index 8405715a..ba42e03a 100644 --- a/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java @@ -114,7 +114,7 @@ public class ClassFileNameHandler { try { FileWriter writer = new FileWriter(f); - //writer.write("test"); + writer.write("test"); writer.flush(); writer.close(); f.delete(); //doesn't throw IOException diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index d4c22fbc..6b307392 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -465,6 +465,7 @@ public class Androlib { // add res folder editOrig.addFolder(new File(appDir, APK_DIRNAME + "/res").getAbsolutePath(), parameters); + System.out.println("file: " + new File(appDir, APK_DIRNAME + "/res").getAbsolutePath()); // add assets, if there if (assetDir != null) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java index 8927026c..591030e9 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/mod/SmaliMod.java @@ -38,26 +38,17 @@ public class SmaliMod { boolean lexerErrors = false; LexerErrorInterface lexer; - if (oldLexer) { - ANTLRInputStream input = new ANTLRInputStream(smaliStream, "UTF-8"); - input.name = name; + InputStreamReader reader = new InputStreamReader(smaliStream, "UTF-8"); - lexer = new smaliLexer(input); - tokens = new CommonTokenStream((TokenSource)lexer); - } else { - InputStreamReader reader = - new InputStreamReader(smaliStream, "UTF-8"); - - lexer = new smaliFlexLexer(reader); - tokens = new CommonTokenStream((TokenSource)lexer); - } + lexer = new smaliFlexLexer(reader); + tokens = new CommonTokenStream((TokenSource)lexer); if (printTokens) { tokens.getTokens(); for (int i=0; i