mirror of
https://github.com/revanced/smali.git
synced 2025-05-28 11:50:12 +02:00
- made the .registers directive optional. it defaults to .registers 0 if not present
- added logic to avoid creating an empty code_item (i.e. for abstract methods) - changed the field and parameter syntax so that there is a colon instead of a whitespace between the field/local name and the following type - changed the member name syntax, so that the initial class is specified with the preceeding 'L' and folling ';', and changed the seperator between the class name and the member name to '->' instead of just another '/' - added the ability to specify members and fields as constants for static fields or annotations (note: dalvik doesn't seem to like embedded field references) - fixed the short and byte literals in the parser (they were mistakenly using the _EMIT token) - fixed an issue with char literals where the value was always a single quote - renamed the CLASS_OR_ARRAY_TYPE_DESCRIPTOR token and related rules to REFERENCE_TYPE_DESCRIPTOR - renamed the FIELD_TYPE_DESCRIPTOR token and related rules to NONVOID_TYPE_DESCRIPTOR git-svn-id: https://smali.googlecode.com/svn/trunk@64 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
5cf0028e73
commit
4250768620
@ -122,31 +122,31 @@ import java.util.ArrayDeque;
|
||||
}
|
||||
|
||||
public Token nextToken() {
|
||||
while (true) {
|
||||
if (tokens.size() > 0) {
|
||||
Token token = tokens.poll();
|
||||
if (token == Token.SKIP_TOKEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println(token.toString());
|
||||
return token;
|
||||
}
|
||||
while (true) {
|
||||
if (tokens.size() > 0) {
|
||||
Token token = tokens.poll();
|
||||
if (token == Token.SKIP_TOKEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println(token.toString());
|
||||
return token;
|
||||
}
|
||||
|
||||
state.channel = Token.DEFAULT_CHANNEL;
|
||||
state.tokenStartCharIndex = input.index();
|
||||
state.tokenStartCharPositionInLine = input.getCharPositionInLine();
|
||||
state.tokenStartLine = input.getLine();
|
||||
state.text = null;
|
||||
if ( input.LA(1)==CharStream.EOF ) {
|
||||
return Token.EOF_TOKEN;
|
||||
}
|
||||
try {
|
||||
mTokens();
|
||||
state.channel = Token.DEFAULT_CHANNEL;
|
||||
state.tokenStartCharIndex = input.index();
|
||||
state.tokenStartCharPositionInLine = input.getCharPositionInLine();
|
||||
state.tokenStartLine = input.getLine();
|
||||
state.text = null;
|
||||
if ( input.LA(1)==CharStream.EOF ) {
|
||||
return Token.EOF_TOKEN;
|
||||
}
|
||||
try {
|
||||
mTokens();
|
||||
|
||||
if (tokens.size() == 0) {
|
||||
emit();
|
||||
}
|
||||
if (tokens.size() == 0) {
|
||||
emit();
|
||||
}
|
||||
}
|
||||
catch (NoViableAltException nva) {
|
||||
reportError(nva);
|
||||
@ -177,11 +177,6 @@ import java.util.ArrayDeque;
|
||||
token.setChannel(channel);
|
||||
tokens.add(token);
|
||||
}
|
||||
|
||||
public void reportError(RecognitionException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -212,8 +207,8 @@ FIELD_PHRASE
|
||||
WS
|
||||
(FIELD_ACCESS_SPEC_EMIT WS)+
|
||||
MEMBER_NAME_EMIT
|
||||
WS
|
||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD
|
||||
COLON_EMIT
|
||||
NONVOID_TYPE_DESCRIPTOR_EMITCHILD
|
||||
WS?
|
||||
(EQUAL_EMIT WS? LITERAL_EMITCHILD)?;
|
||||
|
||||
@ -267,9 +262,7 @@ INSTRUCTION_FORMAT21c_FIELD_PHRASE
|
||||
WS
|
||||
REGISTER_EMIT
|
||||
WS? COMMA_EMIT WS?
|
||||
FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN
|
||||
WS
|
||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
FULLY_QUALIFIED_FIELD_EMITCHILDREN;
|
||||
|
||||
INSTRUCTION_FORMAT21c_STRING_PHRASE
|
||||
: INSTRUCTION_FORMAT21c_STRING_EMIT
|
||||
@ -283,7 +276,7 @@ INSTRUCTION_FORMAT21c_TYPE_PHRASE
|
||||
WS
|
||||
REGISTER_EMIT
|
||||
WS? COMMA_EMIT WS?
|
||||
CLASS_OR_ARRAY_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
REFERENCE_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
|
||||
INSTRUCTION_FORMAT21h_PHRASE
|
||||
: INSTRUCTION_FORMAT21h_EMIT
|
||||
@ -322,9 +315,7 @@ INSTRUCTION_FORMAT22c_FIELD_PHRASE
|
||||
WS? COMMA_EMIT WS?
|
||||
REGISTER_EMIT
|
||||
WS? COMMA_EMIT WS?
|
||||
FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN
|
||||
WS
|
||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
FULLY_QUALIFIED_FIELD_EMITCHILDREN;
|
||||
|
||||
INSTRUCTION_FORMAT22c_TYPE_PHRASE
|
||||
: INSTRUCTION_FORMAT22c_TYPE_EMIT
|
||||
@ -333,7 +324,7 @@ INSTRUCTION_FORMAT22c_TYPE_PHRASE
|
||||
WS? COMMA_EMIT WS?
|
||||
REGISTER_EMIT
|
||||
WS? COMMA_EMIT WS?
|
||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
NONVOID_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
|
||||
INSTRUCTION_FORMAT22s_PHRASE
|
||||
: INSTRUCTION_FORMAT22s_EMIT
|
||||
@ -407,16 +398,14 @@ INSTRUCTION_FORMAT35c_METHOD_PHRASE
|
||||
WS
|
||||
REGISTER_LIST_EMITCHILDREN
|
||||
WS? COMMA_EMIT WS?
|
||||
FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN
|
||||
METHOD_PROTOTYPE_EMITCHILDREN;
|
||||
FULLY_QUALIFIED_METHOD_EMITCHILDREN;
|
||||
|
||||
INSTRUCTION_FORMAT3rc_METHOD_PHRASE
|
||||
: INSTRUCTION_FORMAT3rc_METHOD_EMIT
|
||||
WS
|
||||
REGISTER_RANGE_EMITCHILDREN
|
||||
WS? COMMA_EMIT WS?
|
||||
FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN
|
||||
METHOD_PROTOTYPE_EMITCHILDREN;
|
||||
FULLY_QUALIFIED_METHOD_EMITCHILDREN;
|
||||
|
||||
INSTRUCTION_FORMAT51l_PHRASE
|
||||
: INSTRUCTION_FORMAT51l_EMIT
|
||||
@ -459,7 +448,7 @@ REGISTERS_PHRASE
|
||||
CATCH_PHRASE
|
||||
: CATCH_DIRECTIVE_EMIT
|
||||
WS
|
||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD
|
||||
NONVOID_TYPE_DESCRIPTOR_EMITCHILD
|
||||
WS? '{' WS?
|
||||
(LABEL_EMIT | OFFSET_EMIT)
|
||||
WS '..' WS
|
||||
@ -485,8 +474,8 @@ LOCAL_PHRASE
|
||||
REGISTER_EMIT
|
||||
WS? COMMA_EMIT WS?
|
||||
SIMPLE_NAME_EMIT
|
||||
WS
|
||||
FIELD_TYPE_DESCRIPTOR_EMITCHILD
|
||||
COLON_EMIT
|
||||
NONVOID_TYPE_DESCRIPTOR_EMITCHILD
|
||||
WS?
|
||||
( COMMA_EMIT WS? STRING_LITERAL_EMIT)?;
|
||||
|
||||
@ -673,29 +662,35 @@ fragment REGISTER_RANGE_EMITCHILDREN
|
||||
|
||||
fragment METHOD_PROTOTYPE_EMITCHILDREN
|
||||
: OPEN_PAREN_EMIT
|
||||
(FIELD_TYPE_DESCRIPTOR_EMITCHILD+)?
|
||||
(NONVOID_TYPE_DESCRIPTOR_EMITCHILD+)?
|
||||
CLOSE_PAREN_EMIT
|
||||
TYPE_DESCRIPTOR_EMITCHILD;
|
||||
|
||||
fragment FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN
|
||||
@init {int startPos;}
|
||||
: {startPos = getCharIndex();} (SIMPLE_NAME '/')* token=SIMPLE_NAME {((CommonToken)$token).setStartIndex(startPos); emit($token, CLASS_NAME);}
|
||||
'/'
|
||||
MEMBER_NAME_EMIT;
|
||||
fragment FULLY_QUALIFIED_FIELD_EMITCHILDREN
|
||||
: REFERENCE_TYPE_DESCRIPTOR_EMITCHILD
|
||||
ARROW_EMIT
|
||||
MEMBER_NAME_EMIT
|
||||
COLON_EMIT
|
||||
NONVOID_TYPE_DESCRIPTOR_EMITCHILD;
|
||||
|
||||
fragment FULLY_QUALIFIED_METHOD_EMITCHILDREN
|
||||
: REFERENCE_TYPE_DESCRIPTOR_EMITCHILD
|
||||
ARROW_EMIT
|
||||
MEMBER_NAME_EMIT
|
||||
METHOD_PROTOTYPE_EMITCHILDREN;
|
||||
|
||||
fragment TYPE_DESCRIPTOR_EMITCHILD
|
||||
: PRIMITIVE_TYPE_EMIT
|
||||
| VOID_TYPE_EMIT
|
||||
| CLASS_DESCRIPTOR_EMIT
|
||||
| ARRAY_DESCRIPTOR_EMIT;
|
||||
| ARRAY_DESCRIPTOR_EMIT;
|
||||
|
||||
|
||||
fragment FIELD_TYPE_DESCRIPTOR_EMITCHILD
|
||||
fragment NONVOID_TYPE_DESCRIPTOR_EMITCHILD
|
||||
: PRIMITIVE_TYPE_EMIT
|
||||
| CLASS_DESCRIPTOR_EMIT
|
||||
| ARRAY_DESCRIPTOR_EMIT;
|
||||
|
||||
fragment CLASS_OR_ARRAY_TYPE_DESCRIPTOR_EMITCHILD
|
||||
fragment REFERENCE_TYPE_DESCRIPTOR_EMITCHILD
|
||||
: CLASS_DESCRIPTOR_EMIT
|
||||
| ARRAY_DESCRIPTOR_EMIT;
|
||||
|
||||
@ -724,10 +719,7 @@ fragment CLASS_DESCRIPTOR_EMIT
|
||||
: CLASS_DESCRIPTOR {emit($CLASS_DESCRIPTOR, CLASS_DESCRIPTOR);};
|
||||
|
||||
fragment CLASS_DESCRIPTOR
|
||||
: 'L' CLASS_NAME ';';
|
||||
|
||||
fragment CLASS_NAME
|
||||
: (SIMPLE_NAME '/')* SIMPLE_NAME;
|
||||
: 'L' (SIMPLE_NAME '/')* SIMPLE_NAME ';';
|
||||
|
||||
|
||||
fragment ARRAY_DESCRIPTOR_EMIT
|
||||
@ -848,9 +840,9 @@ fragment LITERAL_EMITCHILD
|
||||
| DOUBLE_LITERAL_EMIT
|
||||
| CHAR_LITERAL_EMIT
|
||||
| BOOL_LITERAL_EMIT
|
||||
| TYPE_DESCRIPTOR_EMITCHILD
|
||||
| ARRAY_LITERAL_EMITCHILDREN
|
||||
| SUBANNOTATION_EMITCHILDREN;
|
||||
| SUBANNOTATION_EMITCHILDREN
|
||||
| TYPE_FIELD_METHOD_LITERAL_EMITCHILDREN;
|
||||
|
||||
fragment SUBANNOTATION_EMITCHILDREN
|
||||
: SUBANNOTATION_START_EMIT
|
||||
@ -894,7 +886,17 @@ fragment ANNOTATION_ELEMENT_EMITCHILDREN
|
||||
EQUAL_EMIT
|
||||
WS?
|
||||
LITERAL_EMITCHILD;
|
||||
|
||||
|
||||
fragment TYPE_FIELD_METHOD_LITERAL_EMITCHILDREN
|
||||
: REFERENCE_TYPE_DESCRIPTOR_EMITCHILD
|
||||
( ARROW_EMIT
|
||||
MEMBER_NAME_EMIT
|
||||
( METHOD_PROTOTYPE_EMITCHILDREN
|
||||
| COLON_EMIT NONVOID_TYPE_DESCRIPTOR_EMITCHILD))?
|
||||
//TODO: allow void and primitive type here?
|
||||
| PRIMITIVE_TYPE_EMIT
|
||||
| VOID_TYPE_EMIT;
|
||||
|
||||
fragment ARRAY_LITERAL_EMITCHILDREN
|
||||
: ARRAY_START_EMIT
|
||||
WS?
|
||||
@ -1414,3 +1416,13 @@ fragment COMMA_EMIT
|
||||
: COMMA {emit($COMMA, COMMA, Token.HIDDEN_CHANNEL);};
|
||||
fragment COMMA
|
||||
: ',';
|
||||
|
||||
fragment COLON_EMIT
|
||||
: COLON {emit($COLON, COLON, Token.HIDDEN_CHANNEL);};
|
||||
fragment COLON
|
||||
: ':';
|
||||
|
||||
fragment ARROW_EMIT
|
||||
: ARROW {emit($ARROW, ARROW);};
|
||||
fragment ARROW
|
||||
: '->';
|
||||
|
@ -56,6 +56,8 @@ tokens {
|
||||
I_ANNOTATION;
|
||||
I_ANNOTATION_ELEMENT;
|
||||
I_SUBANNOTATION;
|
||||
I_ENCODED_FIELD;
|
||||
I_ENCODED_METHOD;
|
||||
I_ENCODED_ARRAY;
|
||||
I_ARRAY_ELEMENT_SIZE;
|
||||
I_ARRAY_ELEMENTS;
|
||||
@ -113,9 +115,6 @@ tokens {
|
||||
I_STATEMENT_SPARSE_SWITCH;
|
||||
I_REGISTER_RANGE;
|
||||
I_REGISTER_LIST;
|
||||
|
||||
CLASS_NAME;
|
||||
MEMBER_NAME;
|
||||
}
|
||||
|
||||
@header {
|
||||
@ -200,11 +199,11 @@ access_list
|
||||
: ACCESS_SPEC+ -> ^(I_ACCESS_LIST[$start,"I_ACCESS_LIST"] ACCESS_SPEC+);
|
||||
|
||||
|
||||
field : FIELD_DIRECTIVE access_list MEMBER_NAME field_type_descriptor literal?
|
||||
field : FIELD_DIRECTIVE access_list MEMBER_NAME nonvoid_type_descriptor literal?
|
||||
( (annotation+ END_FIELD_DIRECTIVE)=> annotation+ END_FIELD_DIRECTIVE
|
||||
| END_FIELD_DIRECTIVE?
|
||||
)
|
||||
-> ^(I_FIELD[$start, "I_FIELD"] MEMBER_NAME access_list ^(I_FIELD_TYPE field_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*));
|
||||
-> ^(I_FIELD[$start, "I_FIELD"] MEMBER_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) ^(I_FIELD_INITIAL_VALUE literal)? ^(I_ANNOTATIONS annotation*));
|
||||
|
||||
method
|
||||
scope {int currentAddress;}
|
||||
@ -215,15 +214,17 @@ method
|
||||
-> ^(I_METHOD[$start, "I_METHOD"] MEMBER_NAME method_prototype access_list statements_and_directives);
|
||||
|
||||
method_prototype
|
||||
: OPEN_PAREN field_type_descriptor* CLOSE_PAREN type_descriptor
|
||||
-> ^(I_METHOD_PROTOTYPE[$start, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_descriptor*);
|
||||
: OPEN_PAREN nonvoid_type_descriptor* CLOSE_PAREN type_descriptor
|
||||
-> ^(I_METHOD_PROTOTYPE[$start, "I_METHOD_PROTOTYPE"] ^(I_METHOD_RETURN_TYPE type_descriptor) nonvoid_type_descriptor*);
|
||||
|
||||
|
||||
fully_qualified_method
|
||||
: CLASS_NAME MEMBER_NAME method_prototype;
|
||||
: reference_type_descriptor ARROW MEMBER_NAME method_prototype
|
||||
-> reference_type_descriptor MEMBER_NAME method_prototype;
|
||||
|
||||
fully_qualified_field
|
||||
: CLASS_NAME MEMBER_NAME field_type_descriptor;
|
||||
: reference_type_descriptor ARROW MEMBER_NAME nonvoid_type_descriptor
|
||||
-> reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor;
|
||||
|
||||
statements_and_directives
|
||||
scope {boolean hasRegistersDirective;}
|
||||
@ -239,13 +240,7 @@ statements_and_directives
|
||||
| ordered_debug_directive
|
||||
| annotation
|
||||
)*
|
||||
{
|
||||
if (!$statements_and_directives::hasRegistersDirective) {
|
||||
//TODO: throw correct exception type here
|
||||
throw new RuntimeException("This method has no register directive");
|
||||
}
|
||||
}
|
||||
-> registers_directive
|
||||
-> ^(I_REGISTERS registers_directive?)
|
||||
^(I_LABELS label*)
|
||||
^(I_STATEMENTS instruction*)
|
||||
^(I_CATCHES catch_directive*)
|
||||
@ -255,11 +250,11 @@ statements_and_directives
|
||||
|
||||
registers_directive
|
||||
: REGISTERS_DIRECTIVE integral_literal
|
||||
-> ^(I_REGISTERS[$start, "I_REGISTERS"] integral_literal);
|
||||
-> integral_literal;
|
||||
|
||||
catch_directive
|
||||
: CATCH_DIRECTIVE field_type_descriptor from=offset_or_label to=offset_or_label using=offset_or_label
|
||||
-> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] field_type_descriptor $from $to $using)
|
||||
: CATCH_DIRECTIVE nonvoid_type_descriptor from=offset_or_label to=offset_or_label using=offset_or_label
|
||||
-> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using)
|
||||
;
|
||||
|
||||
|
||||
@ -290,8 +285,8 @@ line_directive
|
||||
-> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
|
||||
local_directive
|
||||
: LOCAL_DIRECTIVE REGISTER SIMPLE_NAME field_type_descriptor STRING_LITERAL?
|
||||
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER SIMPLE_NAME field_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
: LOCAL_DIRECTIVE REGISTER SIMPLE_NAME nonvoid_type_descriptor 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
|
||||
@ -344,8 +339,8 @@ instruction returns [int size]
|
||||
INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL {$size = Format21c.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL)
|
||||
| //e.g. const-class v2 org/JesusFreke/HelloWorld2/HelloWorld2
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER class_or_array_type_descriptor {$size = Format21c.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER class_or_array_type_descriptor)
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor {$size = Format21c.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
||||
| //e.g. const/high16 v1, 1234
|
||||
INSTRUCTION_FORMAT21h REGISTER integral_literal {$size = Format21h.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT21h[$start, "I_STATEMENT_FORMAT21h"] INSTRUCTION_FORMAT21h REGISTER integral_literal)
|
||||
@ -362,8 +357,8 @@ instruction returns [int size]
|
||||
INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field {$size = Format22c.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field)
|
||||
| //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||
INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER field_type_descriptor {$size = Format22c.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER field_type_descriptor)
|
||||
INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor {$size = Format22c.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor)
|
||||
| //e.g. add-int/lit16 v0, v1, 12345
|
||||
INSTRUCTION_FORMAT22s REGISTER REGISTER integral_literal {$size = Format22s.Format.getByteCount();}
|
||||
-> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] INSTRUCTION_FORMAT22s REGISTER REGISTER integral_literal)
|
||||
@ -496,13 +491,13 @@ register_range
|
||||
: REGISTER REGISTER? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] REGISTER REGISTER?);
|
||||
|
||||
|
||||
field_type_descriptor
|
||||
nonvoid_type_descriptor
|
||||
: PRIMITIVE_TYPE
|
||||
| CLASS_DESCRIPTOR
|
||||
| ARRAY_DESCRIPTOR
|
||||
;
|
||||
|
||||
class_or_array_type_descriptor
|
||||
reference_type_descriptor
|
||||
: CLASS_DESCRIPTOR
|
||||
| ARRAY_DESCRIPTOR;
|
||||
|
||||
@ -541,16 +536,16 @@ fixed_literal returns[int size]
|
||||
literal
|
||||
: INTEGER_LITERAL
|
||||
| LONG_LITERAL
|
||||
| SHORT_LITERAL_EMIT
|
||||
| BYTE_LITERAL_EMIT
|
||||
| SHORT_LITERAL
|
||||
| BYTE_LITERAL
|
||||
| FLOAT_LITERAL
|
||||
| DOUBLE_LITERAL
|
||||
| CHAR_LITERAL
|
||||
| STRING_LITERAL
|
||||
| BOOL_LITERAL
|
||||
| type_descriptor
|
||||
| array_literal
|
||||
| subannotation;
|
||||
| subannotation
|
||||
| type_field_method;
|
||||
|
||||
array_literal
|
||||
: ARRAY_START literal* ARRAY_END
|
||||
@ -568,3 +563,14 @@ annotation_element
|
||||
subannotation
|
||||
: SUBANNOTATION_START CLASS_DESCRIPTOR annotation_element* SUBANNOTATION_END
|
||||
-> ^(I_SUBANNOTATION[$start, "I_SUBANNOTATION"] CLASS_DESCRIPTOR annotation_element*);
|
||||
|
||||
type_field_method
|
||||
: reference_type_descriptor
|
||||
( ARROW MEMBER_NAME
|
||||
( nonvoid_type_descriptor -> ^(I_ENCODED_FIELD reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor)
|
||||
| method_prototype -> ^(I_ENCODED_METHOD reference_type_descriptor MEMBER_NAME method_prototype)
|
||||
)
|
||||
| -> reference_type_descriptor
|
||||
)
|
||||
| PRIMITIVE_TYPE
|
||||
| VOID_TYPE;
|
||||
|
@ -197,11 +197,11 @@ methods returns[List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotationS
|
||||
})*);
|
||||
|
||||
field returns[ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationDirectoryItem.FieldAnnotation fieldAnnotationSet]
|
||||
:^(I_FIELD MEMBER_NAME access_list ^(I_FIELD_TYPE field_type_descriptor) field_initial_value annotations?)
|
||||
:^(I_FIELD MEMBER_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
|
||||
{
|
||||
TypeIdItem classType = classDefItem.getClassType();
|
||||
StringIdItem memberName = new StringIdItem(dexFile, $MEMBER_NAME.text);
|
||||
TypeIdItem fieldType = $field_type_descriptor.type;
|
||||
TypeIdItem fieldType = $nonvoid_type_descriptor.type;
|
||||
|
||||
FieldIdItem fieldIdItem = new FieldIdItem(dexFile, classType, memberName, fieldType);
|
||||
$encodedField = new ClassDataItem.EncodedField(dexFile, fieldIdItem, $access_list.value);
|
||||
@ -239,7 +239,9 @@ literal returns[EncodedValue encodedValue]
|
||||
| bool_literal { $encodedValue = new EncodedValue(dexFile, new BoolEncodedValueSubField($bool_literal.value)); }
|
||||
| type_descriptor { $encodedValue = new EncodedValue(dexFile, new EncodedIndexedItemReference(dexFile, $type_descriptor.type)); }
|
||||
| array_literal { $encodedValue = new EncodedValue(dexFile, new ArrayEncodedValueSubField(dexFile, $array_literal.values)); }
|
||||
| subannotation { $encodedValue = new EncodedValue(dexFile, $subannotation.value); };
|
||||
| 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); };
|
||||
|
||||
|
||||
//everything but string
|
||||
@ -355,46 +357,59 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
||||
parameters
|
||||
ordered_debug_directives
|
||||
annotations
|
||||
)
|
||||
)
|
||||
{
|
||||
MethodIdItem methodIdItem = $method_name_and_prototype.methodIdItem;
|
||||
int registers = $registers_directive.registers;
|
||||
int access = $access_list.value;
|
||||
boolean isStatic = (access & AccessFlags.STATIC) != 0;
|
||||
|
||||
int registers = $registers_directive.registers;
|
||||
ArrayList<Instruction> instructions = $statements.instructions;
|
||||
|
||||
|
||||
int minRegisters = methodIdItem.getParameterRegisterCount((access & AccessFlags.STATIC) != 0);
|
||||
|
||||
if (registers < minRegisters) {
|
||||
//TODO: throw the correct exception type
|
||||
throw new RuntimeException( "This method requires at least " +
|
||||
Integer.toString(minRegisters) +
|
||||
" registers, for the method parameters");
|
||||
}
|
||||
|
||||
Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries(dexFile);
|
||||
List<CodeItem.TryItem> tries = temp.first;
|
||||
List<CodeItem.EncodedCatchHandler> handlers = temp.second;
|
||||
|
||||
|
||||
DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
|
||||
|
||||
int methodParameterCount = methodIdItem.getParameterCount();
|
||||
if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
|
||||
//TODO: throw the correct exception type
|
||||
throw new RuntimeException( "Too many parameter names specified. This method only has " +
|
||||
Integer.toString(methodParameterCount) +
|
||||
" parameters.");
|
||||
}
|
||||
CodeItem codeItem;
|
||||
|
||||
DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
|
||||
if (registers == 0 &&
|
||||
instructions.size() == 0 &&
|
||||
$method::labels.size()== 0 &&
|
||||
(tries == null || tries.size() == 0) &&
|
||||
(handlers == null || handlers.size() == 0) &&
|
||||
debugInfoItem == null) {
|
||||
|
||||
codeItem = null;
|
||||
|
||||
} else {
|
||||
int minRegisters = methodIdItem.getParameterRegisterCount((access & AccessFlags.STATIC) != 0);
|
||||
|
||||
CodeItem codeItem = new CodeItem(dexFile,
|
||||
if (registers < minRegisters) {
|
||||
//TODO: throw the correct exception type
|
||||
throw new RuntimeException( "This method requires at least " +
|
||||
Integer.toString(minRegisters) +
|
||||
" registers, for the method parameters");
|
||||
}
|
||||
|
||||
int methodParameterCount = methodIdItem.getParameterCount();
|
||||
if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
|
||||
//TODO: throw the correct exception type
|
||||
throw new RuntimeException( "Too many parameter names specified. This method only has " +
|
||||
Integer.toString(methodParameterCount) +
|
||||
" parameters.");
|
||||
}
|
||||
|
||||
codeItem = new CodeItem(dexFile,
|
||||
registers,
|
||||
methodIdItem.getParameterRegisterCount(isStatic),
|
||||
instructions,
|
||||
debugInfoItem,
|
||||
tries,
|
||||
handlers);
|
||||
}
|
||||
|
||||
$encodedMethod = new ClassDataItem.EncodedMethod(dexFile, methodIdItem, access, codeItem);
|
||||
|
||||
@ -433,33 +448,34 @@ field_type_list returns[ArrayList<TypeIdItem> types]
|
||||
$types = new ArrayList<TypeIdItem>();
|
||||
}
|
||||
: (
|
||||
field_type_descriptor
|
||||
nonvoid_type_descriptor
|
||||
{
|
||||
$types.add($field_type_descriptor.type);
|
||||
$types.add($nonvoid_type_descriptor.type);
|
||||
}
|
||||
)*;
|
||||
|
||||
|
||||
fully_qualified_method returns[MethodIdItem methodIdItem]
|
||||
: CLASS_NAME MEMBER_NAME method_prototype
|
||||
: reference_type_descriptor MEMBER_NAME method_prototype
|
||||
{
|
||||
TypeIdItem classType = new TypeIdItem(dexFile, "L" + $CLASS_NAME.text + ";");
|
||||
TypeIdItem classType = $reference_type_descriptor.type;
|
||||
StringIdItem methodName = new StringIdItem(dexFile, $MEMBER_NAME.text);
|
||||
ProtoIdItem prototype = $method_prototype.protoIdItem;
|
||||
$methodIdItem = new MethodIdItem(dexFile, classType, methodName, prototype);
|
||||
};
|
||||
|
||||
fully_qualified_field returns[FieldIdItem fieldIdItem]
|
||||
: CLASS_NAME MEMBER_NAME field_type_descriptor
|
||||
: reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor
|
||||
{
|
||||
TypeIdItem classType = new TypeIdItem(dexFile, "L" + $CLASS_NAME.text + ";");
|
||||
TypeIdItem classType = $reference_type_descriptor.type;
|
||||
StringIdItem fieldName = new StringIdItem(dexFile, $MEMBER_NAME.text);
|
||||
TypeIdItem fieldType = $field_type_descriptor.type;
|
||||
TypeIdItem fieldType = $nonvoid_type_descriptor.type;
|
||||
$fieldIdItem = new FieldIdItem(dexFile, classType, fieldName, fieldType);
|
||||
};
|
||||
|
||||
registers_directive returns[int registers]
|
||||
: ^(I_REGISTERS short_integral_literal) {$registers = $short_integral_literal.value;};
|
||||
: {$registers = 0;}
|
||||
^(I_REGISTERS (short_integral_literal {$registers = $short_integral_literal.value;} )? );
|
||||
|
||||
labels
|
||||
: ^(I_LABELS label_def*);
|
||||
@ -480,9 +496,9 @@ label_def
|
||||
catches : ^(I_CATCHES catch_directive*);
|
||||
|
||||
catch_directive
|
||||
: ^(I_CATCH address field_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] using=offset_or_label_absolute[$address.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 = $field_type_descriptor.type;
|
||||
TypeIdItem type = $nonvoid_type_descriptor.type;
|
||||
int startAddress = $from.address;
|
||||
int endAddress = $to.address;
|
||||
int handlerAddress = $using.address;
|
||||
@ -547,14 +563,14 @@ line
|
||||
};
|
||||
|
||||
local
|
||||
: ^(I_LOCAL REGISTER SIMPLE_NAME field_type_descriptor string_literal? address)
|
||||
: ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address)
|
||||
{
|
||||
int registerNumber = parseRegister_short($REGISTER.text);
|
||||
|
||||
if ($string_literal.value != null) {
|
||||
$method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $field_type_descriptor.type.getTypeDescriptor(), $string_literal.value);
|
||||
$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, $field_type_descriptor.type.getTypeDescriptor());
|
||||
$method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor());
|
||||
}
|
||||
};
|
||||
|
||||
@ -725,12 +741,12 @@ instruction returns[Instruction instruction]
|
||||
$instruction = Format21c.Format.make(dexFile, opcode.value, regA, stringIdItem);
|
||||
}
|
||||
| //e.g. const-class v2 org/JesusFreke/HelloWorld2/HelloWorld2
|
||||
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER class_or_array_type_descriptor)
|
||||
^(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);
|
||||
|
||||
TypeIdItem typeIdItem = $class_or_array_type_descriptor.type;
|
||||
TypeIdItem typeIdItem = $reference_type_descriptor.type;
|
||||
|
||||
$instruction = Format21c.Format.make(dexFile, opcode.value, regA, typeIdItem);
|
||||
}
|
||||
@ -793,13 +809,13 @@ instruction returns[Instruction instruction]
|
||||
$instruction = Format22c.Format.make(dexFile, opcode.value, regA, regB, fieldIdItem);
|
||||
}
|
||||
| //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||
^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER field_type_descriptor)
|
||||
^(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);
|
||||
byte regB = parseRegister_nibble($registerB.text);
|
||||
|
||||
TypeIdItem typeIdItem = $field_type_descriptor.type;
|
||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||
|
||||
$instruction = Format22c.Format.make(dexFile, opcode.value, regA, regB, typeIdItem);
|
||||
}
|
||||
@ -1002,7 +1018,7 @@ register_range returns[int startRegister, int endRegister]
|
||||
}
|
||||
;
|
||||
|
||||
field_type_descriptor returns [TypeIdItem type]
|
||||
nonvoid_type_descriptor returns [TypeIdItem type]
|
||||
: (PRIMITIVE_TYPE
|
||||
| CLASS_DESCRIPTOR
|
||||
| ARRAY_DESCRIPTOR)
|
||||
@ -1010,7 +1026,7 @@ field_type_descriptor returns [TypeIdItem type]
|
||||
$type = new TypeIdItem(dexFile, $start.getText());
|
||||
};
|
||||
|
||||
class_or_array_type_descriptor returns [TypeIdItem type]
|
||||
reference_type_descriptor returns [TypeIdItem type]
|
||||
: (CLASS_DESCRIPTOR
|
||||
| ARRAY_DESCRIPTOR)
|
||||
{
|
||||
@ -1025,7 +1041,7 @@ class_type_descriptor returns [TypeIdItem type]
|
||||
|
||||
type_descriptor returns [TypeIdItem type]
|
||||
: VOID_TYPE {$type = new TypeIdItem(dexFile, "V");}
|
||||
| field_type_descriptor {$type = $field_type_descriptor.type;}
|
||||
| nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;}
|
||||
;
|
||||
|
||||
short_integral_literal returns[short value]
|
||||
@ -1072,7 +1088,7 @@ double_literal returns[double value]
|
||||
: DOUBLE_LITERAL { $value = Double.parseDouble($DOUBLE_LITERAL.text); };
|
||||
|
||||
char_literal returns[char value]
|
||||
: CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(0); };
|
||||
: CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); };
|
||||
|
||||
string_literal returns[String value]
|
||||
: STRING_LITERAL
|
||||
@ -1120,4 +1136,15 @@ subannotation returns[AnnotationEncodedValueSubField value]
|
||||
{
|
||||
$value = new AnnotationEncodedValueSubField(dexFile, $class_type_descriptor.type, elements);
|
||||
};
|
||||
|
||||
|
||||
field_literal returns[EncodedIndexedItemReference<FieldIdItem> value]
|
||||
: ^(I_ENCODED_FIELD fully_qualified_field)
|
||||
{
|
||||
$value = new EncodedIndexedItemReference<FieldIdItem>(dexFile, $fully_qualified_field.fieldIdItem);
|
||||
};
|
||||
|
||||
method_literal returns[EncodedIndexedItemReference<MethodIdItem> value]
|
||||
: ^(I_ENCODED_METHOD fully_qualified_method)
|
||||
{
|
||||
$value = new EncodedIndexedItemReference<MethodIdItem>(dexFile, $fully_qualified_method.methodIdItem);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user