From d54c635f847be8f72ff08ea43e82d0c22fe8e954 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Wed, 3 Jun 2009 07:05:59 +0000 Subject: [PATCH] - Added support for enum literals - added "Enums" example, that shows how to construct an enum class - added an enum value to the AnnotationValues example, to show how enum values are specified in an annotation git-svn-id: https://smali.googlecode.com/svn/trunk@71 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- .../antlr3/org/JesusFreke/smali/smaliLexer.g | 17 +++++- .../antlr3/org/JesusFreke/smali/smaliParser.g | 14 ++++- .../org/JesusFreke/smali/smaliTreeWalker.g | 9 ++- .../EncodedIndexedItemReference.java | 11 +++- .../AnnotationWithValues.smali | 4 ++ .../examples/AnnotationValues/Enum.smali | 52 +++++++++++++++++ .../examples/AnnotationValues/Main.smali | 4 +- src/test/resources/examples/Enums/Enum.smali | 57 +++++++++++++++++++ src/test/resources/examples/Enums/Main.smali | 15 +++++ 9 files changed, 175 insertions(+), 8 deletions(-) create mode 100644 src/test/resources/examples/AnnotationValues/Enum.smali create mode 100644 src/test/resources/examples/Enums/Enum.smali create mode 100644 src/test/resources/examples/Enums/Main.smali diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g b/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g index f993efc6..748c0b2e 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g @@ -841,7 +841,8 @@ fragment LITERAL_EMITCHILD | BOOL_LITERAL_EMIT | ARRAY_LITERAL_EMITCHILDREN | SUBANNOTATION_EMITCHILDREN - | TYPE_FIELD_METHOD_LITERAL_EMITCHILDREN; + | TYPE_FIELD_METHOD_LITERAL_EMITCHILDREN + | ENUM_LITERAL_EMITCHILDREN; fragment SUBANNOTATION_EMITCHILDREN : SUBANNOTATION_START_EMIT @@ -895,6 +896,20 @@ fragment TYPE_FIELD_METHOD_LITERAL_EMITCHILDREN //TODO: allow void and primitive type here? | PRIMITIVE_TYPE_EMIT | VOID_TYPE_EMIT; + +fragment ENUM_EMIT + : ENUM {emit($ENUM, ENUM);}; +fragment ENUM + : '.enum'; + +fragment ENUM_LITERAL_EMITCHILDREN + : ENUM_EMIT + WS + REFERENCE_TYPE_DESCRIPTOR_EMITCHILD + ARROW_EMIT + MEMBER_NAME_EMIT + COLON_EMIT + REFERENCE_TYPE_DESCRIPTOR_EMITCHILD; fragment ARRAY_LITERAL_EMITCHILDREN : ARRAY_START_EMIT diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliParser.g b/src/main/antlr3/org/JesusFreke/smali/smaliParser.g index c77a012f..316d5fcc 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliParser.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliParser.g @@ -58,6 +58,7 @@ tokens { I_SUBANNOTATION; I_ENCODED_FIELD; I_ENCODED_METHOD; + I_ENCODED_ENUM; I_ENCODED_ARRAY; I_ARRAY_ELEMENT_SIZE; I_ARRAY_ELEMENTS; @@ -545,7 +546,8 @@ literal | BOOL_LITERAL | array_literal | subannotation - | type_field_method; + | type_field_method_literal + | enum_literal; array_literal : ARRAY_START literal* ARRAY_END @@ -564,7 +566,7 @@ subannotation : SUBANNOTATION_START CLASS_DESCRIPTOR annotation_element* SUBANNOTATION_END -> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*); -type_field_method +type_field_method_literal : reference_type_descriptor ( ARROW MEMBER_NAME ( nonvoid_type_descriptor -> ^(I_ENCODED_FIELD reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor) @@ -574,3 +576,11 @@ type_field_method ) | PRIMITIVE_TYPE | VOID_TYPE; + +enum_literal + : ENUM + reference_type_descriptor + ARROW + MEMBER_NAME + reference_type_descriptor + -> ^(I_ENCODED_ENUM reference_type_descriptor MEMBER_NAME reference_type_descriptor); diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g index a901973c..495ca5cd 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g @@ -241,7 +241,8 @@ literal returns[EncodedValue encodedValue] | array_literal { $encodedValue = new EncodedValue(dexFile, new ArrayEncodedValueSubField(dexFile, $array_literal.values)); } | subannotation { $encodedValue = new EncodedValue(dexFile, $subannotation.value); } | field_literal { $encodedValue = new EncodedValue(dexFile, $field_literal.value); } - | method_literal { $encodedValue = new EncodedValue(dexFile, $method_literal.value); }; + | method_literal { $encodedValue = new EncodedValue(dexFile, $method_literal.value); } + | enum_literal { $encodedValue = new EncodedValue(dexFile, $enum_literal.value); }; //everything but string @@ -1148,3 +1149,9 @@ method_literal returns[EncodedIndexedItemReference value] { $value = new EncodedIndexedItemReference(dexFile, $fully_qualified_method.methodIdItem); }; + +enum_literal returns[EncodedIndexedItemReference value] + : ^(I_ENCODED_ENUM fully_qualified_field) + { + $value = new EncodedIndexedItemReference(dexFile, $fully_qualified_field.fieldIdItem, true); + }; diff --git a/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java index 37ad0103..00e90dca 100644 --- a/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java +++ b/src/main/java/org/JesusFreke/dexlib/EncodedValue/EncodedIndexedItemReference.java @@ -46,14 +46,21 @@ public class EncodedIndexedItemReference> this.section = section; } - //TODO: implement support for enum values public EncodedIndexedItemReference(DexFile dexFile, T item) { + this(dexFile, item, false); + } + + public EncodedIndexedItemReference(DexFile dexFile, T item, boolean isEnum) { if (item.getClass() == StringIdItem.class) { valueType = ValueType.VALUE_STRING; } else if (item.getClass() == TypeIdItem.class) { valueType = ValueType.VALUE_TYPE; } else if (item.getClass() == FieldIdItem.class) { - valueType = ValueType.VALUE_FIELD; + if (isEnum) { + valueType = ValueType.VALUE_ENUM; + } else { + valueType = ValueType.VALUE_FIELD; + } } else if (item.getClass() == MethodIdItem.class) { valueType = ValueType.VALUE_METHOD; } diff --git a/src/test/resources/examples/AnnotationValues/AnnotationWithValues.smali b/src/test/resources/examples/AnnotationValues/AnnotationWithValues.smali index 532ac1ad..417faa5f 100644 --- a/src/test/resources/examples/AnnotationValues/AnnotationWithValues.smali +++ b/src/test/resources/examples/AnnotationValues/AnnotationWithValues.smali @@ -42,6 +42,9 @@ ;.method public abstract fieldValue()Ljava/lang/reflect/Field; ;.end method +.method public abstract enumValue()LEnum; +.end method + .annotation system Ldalvik/annotation/AnnotationDefault; value = .subannotation LAnnotationWithValues; booleanValue = false @@ -58,6 +61,7 @@ .end subannotation typeValue = L10; methodValue = L10;->11()V + enumValue = .enum LEnum;->12:LEnum; .end subannotation .end annotation diff --git a/src/test/resources/examples/AnnotationValues/Enum.smali b/src/test/resources/examples/AnnotationValues/Enum.smali new file mode 100644 index 00000000..f965d6e8 --- /dev/null +++ b/src/test/resources/examples/AnnotationValues/Enum.smali @@ -0,0 +1,52 @@ +.class public final enum LEnum; +.super Ljava/lang/Enum; + +.field private static final synthetic $VALUES:[LEnum; + +.field public static final enum 12:LEnum; + +.method static constructor ()V + .registers 4 + + const/4 v3, 1 + const/4 v2, 0 + new-instance v0, LEnum; + const-string v1, "12" + invoke-direct {v0, v1, v2}, LEnum;->(Ljava/lang/String;I)V + sput-object v0, LEnum;->12:LEnum; + + const/4 v0, 1 + new-array v0, v0, [LEnum; + sget-object v1, LEnum;->12:LEnum; + aput-object v1, v0, v2 + + sput-object v0, LEnum;->$VALUES:[LEnum; + return-void +.end method + +.method private constructor (Ljava/lang/String;I)V + .registers 3 + + invoke-direct {v0, v1, v2}, Ljava/lang/Enum;->(Ljava/lang/String;I)V + return-void +.end method + +.method public static valueOf(Ljava/lang/String;)LEnum; + .registers 2 + + const-class v0, LEnum; + invoke-static {v0, v1}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + move-result-object v1 + check-cast v1, LEnum; + return-object v1 +.end method + +.method public static values()[LEnum; + .registers 1 + + sget-object v0, LEnum;->$VALUES:[LEnum; + invoke-virtual {v0}, [LEnum;->clone()Ljava/lang/Object; + move-result-object v0 + check-cast v0, [LEnum; + return-object v0 +.end method \ No newline at end of file diff --git a/src/test/resources/examples/AnnotationValues/Main.smali b/src/test/resources/examples/AnnotationValues/Main.smali index d199e53c..82376e0a 100644 --- a/src/test/resources/examples/AnnotationValues/Main.smali +++ b/src/test/resources/examples/AnnotationValues/Main.smali @@ -2,9 +2,9 @@ .super Ljava/lang/Object; ;expected output: -;@AnnotationWithValues(booleanValue=false, byteValue=1, charValue=2, doubleValue=7.0, floatValue=6.0, intValue=4, longValue=5, methodValue=public static void 10.11(), shortValue=3, stringValue=8, subAnnotationValue=@SubAnnotation(stringValue=9), typeValue=class 10) +;@AnnotationWithValues(booleanValue=false, byteValue=1, charValue=2, doubleValue=7.0, enumValue=12, floatValue=6.0, intValue=4, longValue=5, methodValue=public static void 10.11(), shortValue=3, stringValue=8, subAnnotationValue=@SubAnnotation(stringValue=9), typeValue=class 10) + - .method public static main([Ljava/lang/String;)V .registers 3 diff --git a/src/test/resources/examples/Enums/Enum.smali b/src/test/resources/examples/Enums/Enum.smali new file mode 100644 index 00000000..2082ff78 --- /dev/null +++ b/src/test/resources/examples/Enums/Enum.smali @@ -0,0 +1,57 @@ +.class public final enum LEnum; +.super Ljava/lang/Enum; + +.field private static final synthetic $VALUES:[LEnum; + +.field public static final enum VALUE1:LEnum; +.field public static final enum VALUE2:LEnum; + +.method static constructor ()V + .registers 4 + + const/4 v3, 1 + const/4 v2, 0 + new-instance v0, LEnum; + const-string v1, "VALUE1" + invoke-direct {v0, v1, v2}, LEnum;->(Ljava/lang/String;I)V + sput-object v0, LEnum;->VALUE1:LEnum; + new-instance v0, LEnum; + const-string v1, "VALUE2" + invoke-direct {v0, v1, v3}, LEnum;->(Ljava/lang/String;I)V + sput-object v0, LEnum;->VALUE2:LEnum; + const/4 v0, 2 + new-array v0, v0, [LEnum; + sget-object v1, LEnum;->VALUE1:LEnum; + aput-object v1, v0, v2 + sget-object v1, LEnum;->VALUE2:LEnum; + aput-object v1, v0, v3 + sput-object v0, LEnum;->$VALUES:[LEnum; + return-void +.end method + +.method private constructor (Ljava/lang/String;I)V + .registers 3 + + invoke-direct {v0, v1, v2}, Ljava/lang/Enum;->(Ljava/lang/String;I)V + return-void +.end method + +.method public static valueof(Ljava/lang/String;)LEnum; + .registers 2 + + const-class v0, LEnum; + invoke-static {v0, v1}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + move-result-object v1 + check-cast v1, LEnum; + return-object v1 +.end method + +.method public static values()[LEnum; + .registers 1 + + sget-object v0, LEnum;->$VALUES:[LEnum; + invoke-virtual {v0}, [LEnum;->clone()Ljava/lang/Object; + move-result-object v0 + check-cast v0, [LEnum; + return-object v0 +.end method \ No newline at end of file diff --git a/src/test/resources/examples/Enums/Main.smali b/src/test/resources/examples/Enums/Main.smali new file mode 100644 index 00000000..65354193 --- /dev/null +++ b/src/test/resources/examples/Enums/Main.smali @@ -0,0 +1,15 @@ +.class public LMain; +.super Ljava/lang/Object; + + + +.method public static main([Ljava/lang/String;)V + .registers 2 + + sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; + sget-object v1, LEnum;->VALUE1:LEnum; + + invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + + return-void +.end method \ No newline at end of file