Tweak how array descriptors are parsed

This is needed to allow smalidea to have an outer array type element to
represent the type as a whole, and an inner class type element for the
actual element type
This commit is contained in:
Ben Gruver 2014-03-26 20:23:15 -07:00
parent b4b9c6c387
commit 2fd677db88
9 changed files with 110 additions and 60 deletions

View File

@ -39,7 +39,7 @@ tokens {
ANNOTATION_DIRECTIVE; ANNOTATION_DIRECTIVE;
ANNOTATION_VISIBILITY; ANNOTATION_VISIBILITY;
ARRAY_DATA_DIRECTIVE; ARRAY_DATA_DIRECTIVE;
ARRAY_DESCRIPTOR; ARRAY_TYPE_PREFIX;
ARROW; ARROW;
BOOL_LITERAL; BOOL_LITERAL;
BYTE_LITERAL; BYTE_LITERAL;
@ -369,16 +369,12 @@ import org.jf.dexlib2.Opcodes;
case '[': case '[':
{ {
int i = typeStartIndex; int i = typeStartIndex;
while (str.charAt(++i) == '['); while (str.charAt(++i) == '[');
if (str.charAt(i++) == 'L') { token.setType(ARRAY_TYPE_PREFIX);
while (str.charAt(i++) != ';'); token.setText(str.substring(typeStartIndex, i));
} token.setStopIndex(baseToken.getStartIndex() + i - 1);
break;
token.setType(ARRAY_DESCRIPTOR);
token.setText(str.substring(typeStartIndex, i));
token.setStopIndex(baseToken.getStartIndex() + i - 1);
break;
} }
default: default:
throw new RuntimeException(String.format("Invalid character '\%c' in param list \"\%s\" at position \%d", str.charAt(typeStartIndex), str, typeStartIndex)); throw new RuntimeException(String.format("Invalid character '\%c' in param list \"\%s\" at position \%d", str.charAt(typeStartIndex), str, typeStartIndex));
@ -591,20 +587,23 @@ param_list
| PARAM_LIST_OR_ID_START PRIMITIVE_TYPE* PARAM_LIST_OR_ID_END -> PRIMITIVE_TYPE* | PARAM_LIST_OR_ID_START PRIMITIVE_TYPE* PARAM_LIST_OR_ID_END -> PRIMITIVE_TYPE*
| nonvoid_type_descriptor*; | nonvoid_type_descriptor*;
array_descriptor
: ARRAY_TYPE_PREFIX (PRIMITIVE_TYPE | CLASS_DESCRIPTOR);
type_descriptor type_descriptor
: VOID_TYPE : VOID_TYPE
| PRIMITIVE_TYPE | PRIMITIVE_TYPE
| CLASS_DESCRIPTOR | CLASS_DESCRIPTOR
| ARRAY_DESCRIPTOR; | array_descriptor;
nonvoid_type_descriptor nonvoid_type_descriptor
: PRIMITIVE_TYPE : PRIMITIVE_TYPE
| CLASS_DESCRIPTOR | CLASS_DESCRIPTOR
| ARRAY_DESCRIPTOR; | array_descriptor;
reference_type_descriptor reference_type_descriptor
: CLASS_DESCRIPTOR : CLASS_DESCRIPTOR
| ARRAY_DESCRIPTOR; | array_descriptor;
integer_literal integer_literal
: POSITIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$POSITIVE_INTEGER_LITERAL] : POSITIVE_INTEGER_LITERAL -> INTEGER_LITERAL[$POSITIVE_INTEGER_LITERAL]

View File

@ -1146,20 +1146,20 @@ insn_sparse_switch_directive
$method::methodBuilder.addInstruction(new BuilderSparseSwitchPayload($sparse_switch_elements.elements)); $method::methodBuilder.addInstruction(new BuilderSparseSwitchPayload($sparse_switch_elements.elements));
}; };
array_descriptor returns [String type]
: ARRAY_TYPE_PREFIX ( PRIMITIVE_TYPE { $type = $ARRAY_TYPE_PREFIX.text + $PRIMITIVE_TYPE.text; }
| CLASS_DESCRIPTOR { $type = $ARRAY_TYPE_PREFIX.text + $CLASS_DESCRIPTOR.text; });
nonvoid_type_descriptor returns [String type] nonvoid_type_descriptor returns [String type]
: (PRIMITIVE_TYPE : (PRIMITIVE_TYPE { $type = $text; }
| CLASS_DESCRIPTOR | CLASS_DESCRIPTOR { $type = $text; }
| ARRAY_DESCRIPTOR) | array_descriptor { $type = $array_descriptor.type; })
{ ;
$type = $start.getText();
};
reference_type_descriptor returns [String type] reference_type_descriptor returns [String type]
: (CLASS_DESCRIPTOR : (CLASS_DESCRIPTOR { $type = $text; }
| ARRAY_DESCRIPTOR) | array_descriptor { $type = $array_descriptor.type; })
{ ;
$type = $start.getText();
};
type_descriptor returns [String type] type_descriptor returns [String type]
: VOID_TYPE {$type = "V";} : VOID_TYPE {$type = "V";}

View File

@ -231,13 +231,14 @@ PrimitiveType = [ZBSCIJFD]
ClassDescriptor = L ({SimpleName} "/")* {SimpleName} ; ClassDescriptor = L ({SimpleName} "/")* {SimpleName} ;
ArrayDescriptor = "[" + ({PrimitiveType} | {ClassDescriptor}) ArrayPrefix = "["+
Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | {PrimitiveType})
%state PARAM_LIST_OR_ID %state PARAM_LIST_OR_ID
%state PARAM_LIST %state PARAM_LIST
%state ARRAY_DESCRIPTOR
%state STRING %state STRING
%state CHAR %state CHAR
@ -314,7 +315,7 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor}
<PARAM_LIST> { <PARAM_LIST> {
{PrimitiveType} { return newToken(PRIMITIVE_TYPE); } {PrimitiveType} { return newToken(PRIMITIVE_TYPE); }
{ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); } {ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); }
{ArrayDescriptor} { return newToken(ARRAY_DESCRIPTOR); } {ArrayPrefix} { return newToken(ARRAY_TYPE_PREFIX); }
[^] { yypushback(1); yybegin(YYINITIAL); return newToken(PARAM_LIST_END); } [^] { yypushback(1); yybegin(YYINITIAL); return newToken(PARAM_LIST_END); }
<<EOF>> { yybegin(YYINITIAL); return newToken(PARAM_LIST_END); } <<EOF>> { yybegin(YYINITIAL); return newToken(PARAM_LIST_END); }
} }
@ -611,12 +612,24 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor}
} }
} }
<ARRAY_DESCRIPTOR> {
{PrimitiveType} { yybegin(YYINITIAL); return newToken(PRIMITIVE_TYPE); }
{ClassDescriptor} { yybegin(YYINITIAL); return newToken(CLASS_DESCRIPTOR); }
[^] { yypushback(1); yybegin(YYINITIAL); }
}
/*Types*/ /*Types*/
<YYINITIAL> { <YYINITIAL> {
{PrimitiveType} { return newToken(PRIMITIVE_TYPE); } {PrimitiveType} { return newToken(PRIMITIVE_TYPE); }
V { return newToken(VOID_TYPE); } V { return newToken(VOID_TYPE); }
{ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); } {ClassDescriptor} { return newToken(CLASS_DESCRIPTOR); }
{ArrayDescriptor} { return newToken(ARRAY_DESCRIPTOR); }
// we have to drop into a separate state so that we don't parse something like
// "[I->" as "[" followed by "I-" as a SIMPLE_NAME
{ArrayPrefix} {
yybegin(ARRAY_DESCRIPTOR);
return newToken(ARRAY_TYPE_PREFIX);
}
{PrimitiveType} {PrimitiveType}+ { {PrimitiveType} {PrimitiveType}+ {
yypushback(yylength()); yypushback(yylength());

View File

@ -184,7 +184,8 @@ REGISTER("v0")
COMMA(",") COMMA(",")
REGISTER("v0") REGISTER("v0")
COMMA(",") COMMA(",")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
INSTRUCTION_FORMAT31t("fill-array-data") INSTRUCTION_FORMAT31t("fill-array-data")
REGISTER("v0") REGISTER("v0")
COMMA(",") COMMA(",")
@ -197,7 +198,8 @@ CLASS_DESCRIPTOR("Lcom/android/internal/os/BatteryStatsImpl;")
ARROW("->") ARROW("->")
SIMPLE_NAME("PROC_WAKELOCKS_FORMAT") SIMPLE_NAME("PROC_WAKELOCKS_FORMAT")
COLON(":") COLON(":")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
LINE_DIRECTIVE(".line") LINE_DIRECTIVE(".line")
POSITIVE_INTEGER_LITERAL("3495") POSITIVE_INTEGER_LITERAL("3495")
INSTRUCTION_FORMAT21c_TYPE("new-instance") INSTRUCTION_FORMAT21c_TYPE("new-instance")

View File

@ -23,6 +23,8 @@ LI/I/I;
[D [D
[Ljava/lang/String; [Ljava/lang/String;
[LI/I/I; [LI/I/I;
[[LI/I/I;
[[I
IIIII IIIII
ZBSCIJFD ZBSCIJFD
@ -50,3 +52,5 @@ L[Ljava/lang/String;
<linit> <linit>
III III
[I->clone()Ljava/lang/Object;

View File

@ -13,16 +13,30 @@ CLASS_DESCRIPTOR("LI;")
CLASS_DESCRIPTOR("LV;") CLASS_DESCRIPTOR("LV;")
CLASS_DESCRIPTOR("LI/I/I;") CLASS_DESCRIPTOR("LI/I/I;")
ARRAY_DESCRIPTOR("[Z") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[B") PRIMITIVE_TYPE("Z")
ARRAY_DESCRIPTOR("[S") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[C") PRIMITIVE_TYPE("B")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[J") PRIMITIVE_TYPE("S")
ARRAY_DESCRIPTOR("[F") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[D") PRIMITIVE_TYPE("C")
ARRAY_DESCRIPTOR("[Ljava/lang/String;") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[LI/I/I;") PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("J")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("F")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("D")
ARRAY_TYPE_PREFIX("[")
CLASS_DESCRIPTOR("Ljava/lang/String;")
ARRAY_TYPE_PREFIX("[")
CLASS_DESCRIPTOR("LI/I/I;")
ARRAY_TYPE_PREFIX("[[")
CLASS_DESCRIPTOR("LI/I/I;")
ARRAY_TYPE_PREFIX("[[")
PRIMITIVE_TYPE("I")
PARAM_LIST_OR_ID_START("") PARAM_LIST_OR_ID_START("")
PRIMITIVE_TYPE("I") PRIMITIVE_TYPE("I")
@ -46,8 +60,10 @@ PARAM_LIST_OR_ID_END("")
PARAM_LIST_START("") PARAM_LIST_START("")
PRIMITIVE_TYPE("I") PRIMITIVE_TYPE("I")
CLASS_DESCRIPTOR("La;") CLASS_DESCRIPTOR("La;")
ARRAY_DESCRIPTOR("[La;") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[I") CLASS_DESCRIPTOR("La;")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
PARAM_LIST_END("") PARAM_LIST_END("")
PARAM_LIST_START("") PARAM_LIST_START("")
@ -56,19 +72,26 @@ CLASS_DESCRIPTOR("Ljava/lang/String;")
PARAM_LIST_END("") PARAM_LIST_END("")
PARAM_LIST_START("") PARAM_LIST_START("")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[I") PRIMITIVE_TYPE("I")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
PARAM_LIST_END("") PARAM_LIST_END("")
PARAM_LIST_START("") PARAM_LIST_START("")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[Z") PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("Z")
PARAM_LIST_END("") PARAM_LIST_END("")
PARAM_LIST_START("") PARAM_LIST_START("")
ARRAY_DESCRIPTOR("[I") ARRAY_TYPE_PREFIX("[")
ARRAY_DESCRIPTOR("[Ljava/lang/String;") PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")
CLASS_DESCRIPTOR("Ljava/lang/String;")
PARAM_LIST_END("") PARAM_LIST_END("")
MEMBER_NAME("<init>") MEMBER_NAME("<init>")
@ -79,12 +102,12 @@ MEMBER_NAME("<init->")
SIMPLE_NAME("Ljava") INVALID_TOKEN("/") SIMPLE_NAME("lang") INVALID_TOKEN("/") SIMPLE_NAME("String") SIMPLE_NAME("Ljava") INVALID_TOKEN("/") SIMPLE_NAME("lang") INVALID_TOKEN("/") SIMPLE_NAME("String")
SIMPLE_NAME("L") INVALID_TOKEN(";") SIMPLE_NAME("L") INVALID_TOKEN(";")
SIMPLE_NAME("LI") SIMPLE_NAME("LI")
SIMPLE_NAME("L") ARRAY_DESCRIPTOR("[Ljava/lang/String;") SIMPLE_NAME("L") ARRAY_TYPE_PREFIX("[") CLASS_DESCRIPTOR("Ljava/lang/String;")
INVALID_TOKEN("[") ARRAY_TYPE_PREFIX("[")
INVALID_TOKEN("[") VOID_TYPE("V") ARRAY_TYPE_PREFIX("[") VOID_TYPE("V")
INVALID_TOKEN("[") SIMPLE_NAME("java") INVALID_TOKEN("/") SIMPLE_NAME("lang") INVALID_TOKEN("/") SIMPLE_NAME("String") INVALID_TOKEN(";") ARRAY_TYPE_PREFIX("[") SIMPLE_NAME("java") INVALID_TOKEN("/") SIMPLE_NAME("lang") INVALID_TOKEN("/") SIMPLE_NAME("String") INVALID_TOKEN(";")
INVALID_TOKEN("[") INVALID_TOKEN(";") ARRAY_TYPE_PREFIX("[") INVALID_TOKEN(";")
MEMBER_NAME("<linit>") MEMBER_NAME("<linit>")
@ -93,3 +116,11 @@ PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I") PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I") PRIMITIVE_TYPE("I")
PARAM_LIST_OR_ID_END("") PARAM_LIST_OR_ID_END("")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
ARROW("->")
SIMPLE_NAME("clone")
OPEN_PAREN("(")
CLOSE_PAREN(")")
CLASS_DESCRIPTOR("Ljava/lang/Object;")

View File

@ -347,7 +347,7 @@ class_descriptor
array_descriptor array_descriptor
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: ARRAY_DESCRIPTOR; : ARRAY_TYPE_PREFIX (primitive_type | class_descriptor);
finally { marker.done(SmaliElementTypes.ARRAY_TYPE); } finally { marker.done(SmaliElementTypes.ARRAY_TYPE); }
void_type void_type

View File

@ -50,7 +50,7 @@ public class SmaliTokens {
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType ANNOTATION_DIRECTIVE; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType ANNOTATION_DIRECTIVE;
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType ANNOTATION_VISIBILITY; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType ANNOTATION_VISIBILITY;
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType ARRAY_DATA_DIRECTIVE; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType ARRAY_DATA_DIRECTIVE;
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType ARRAY_DESCRIPTOR; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType ARRAY_TYPE_PREFIX;
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType ARROW; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType ARROW;
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType BOOL_LITERAL; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType BOOL_LITERAL;
@SuppressWarnings({"UnusedDeclaration"}) public static IElementType BYTE_LITERAL; @SuppressWarnings({"UnusedDeclaration"}) public static IElementType BYTE_LITERAL;
@ -169,7 +169,7 @@ public class SmaliTokens {
tokenColors.put("ANNOTATION_DIRECTIVE", SmaliHighlightingColors.DIRECTIVE); tokenColors.put("ANNOTATION_DIRECTIVE", SmaliHighlightingColors.DIRECTIVE);
tokenColors.put("ANNOTATION_VISIBILITY", SmaliHighlightingColors.ACCESS); tokenColors.put("ANNOTATION_VISIBILITY", SmaliHighlightingColors.ACCESS);
tokenColors.put("ARRAY_DATA_DIRECTIVE", SmaliHighlightingColors.DIRECTIVE); tokenColors.put("ARRAY_DATA_DIRECTIVE", SmaliHighlightingColors.DIRECTIVE);
tokenColors.put("ARRAY_DESCRIPTOR", SmaliHighlightingColors.TYPE); tokenColors.put("ARRAY_TYPE_PREFIX", SmaliHighlightingColors.TYPE);
tokenColors.put("ARROW", SmaliHighlightingColors.ARROW); tokenColors.put("ARROW", SmaliHighlightingColors.ARROW);
tokenColors.put("BOOL_LITERAL", SmaliHighlightingColors.LITERAL); tokenColors.put("BOOL_LITERAL", SmaliHighlightingColors.LITERAL);
tokenColors.put("BYTE_LITERAL", SmaliHighlightingColors.NUMBER); tokenColors.put("BYTE_LITERAL", SmaliHighlightingColors.NUMBER);

View File

@ -72,7 +72,8 @@ public class SmaliLexerTest extends LexerTestCase {
"WHITE_SPACE (' ')\n" + "WHITE_SPACE (' ')\n" +
"SIMPLE_NAME ('main')\n" + "SIMPLE_NAME ('main')\n" +
"OPEN_PAREN ('(')\n" + "OPEN_PAREN ('(')\n" +
"ARRAY_DESCRIPTOR ('[Ljava/lang/String;')\n" + "ARRAY_TYPE_PREFIX ('[')\n" +
"CLASS_DESCRIPTOR ('Ljava/lang/String;')\n" +
"CLOSE_PAREN (')')\n" + "CLOSE_PAREN (')')\n" +
"VOID_TYPE ('V')\n" + "VOID_TYPE ('V')\n" +
"WHITE_SPACE ('\\n ')\n" + "WHITE_SPACE ('\\n ')\n" +