mirror of
https://github.com/revanced/smali.git
synced 2025-05-23 18:16:23 +02:00
Initial stub MethodImplementationBuilder and integration into smali
This commit is contained in:
parent
a81c962f00
commit
766f285a70
11
dexlib2/src/main/java/org/jf/dexlib2/builder/LabelRef.java
Normal file
11
dexlib2/src/main/java/org/jf/dexlib2/builder/LabelRef.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.jf.dexlib2.builder;
|
||||
|
||||
public class LabelRef {
|
||||
public boolean isResolved() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getCodeAddress() {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
package org.jf.dexlib2.builder;
|
||||
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.iface.MethodImplementation;
|
||||
import org.jf.dexlib2.iface.reference.Reference;
|
||||
import org.jf.dexlib2.iface.reference.StringReference;
|
||||
import org.jf.dexlib2.iface.reference.TypeReference;
|
||||
import org.jf.dexlib2.writer.builder.BuilderStringReference;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class MethodImplementationBuilder<ReferenceType extends Reference> {
|
||||
public MethodImplementationBuilder() {
|
||||
}
|
||||
|
||||
public MethodImplementation buildMethodImplementation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public LabelRef addLabel(@Nonnull String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public LabelRef getLabel(@Nonnull String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addCatch(String type, LabelRef from, LabelRef to, LabelRef using) {
|
||||
}
|
||||
|
||||
public void addLineNumber(int lineNumber) {
|
||||
}
|
||||
|
||||
public void addStartLocal(int registerNumber, @Nullable StringReference name, @Nullable TypeReference type,
|
||||
@Nullable StringReference signature) {
|
||||
}
|
||||
|
||||
public void addEndLocal(int registerNumber) {
|
||||
}
|
||||
|
||||
public void addRestartLocal(int registerNumber) {
|
||||
}
|
||||
|
||||
public void addPrologue() {
|
||||
}
|
||||
|
||||
public void addEpilogue() {
|
||||
}
|
||||
|
||||
public void addSetSourceFile(@Nullable BuilderStringReference sourceFile) {
|
||||
}
|
||||
|
||||
public void addInstruction10t(@Nonnull Opcode opcode,
|
||||
@Nonnull LabelRef label) {
|
||||
}
|
||||
|
||||
public void addInstruction10x(@Nonnull Opcode opcode) {
|
||||
}
|
||||
|
||||
public void addInstruction11n(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int literal) {
|
||||
}
|
||||
|
||||
public void addInstruction11x(@Nonnull Opcode opcode,
|
||||
int registerA) {
|
||||
}
|
||||
|
||||
public void addInstruction12x(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB) {
|
||||
}
|
||||
|
||||
public void addInstruction20bc(@Nonnull Opcode opcode,
|
||||
int verificationError,
|
||||
@Nonnull ReferenceType reference) {
|
||||
}
|
||||
|
||||
public void addInstruction20t(@Nonnull Opcode opcode,
|
||||
@Nonnull LabelRef label) {
|
||||
}
|
||||
|
||||
public void addInstruction21c(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
@Nonnull ReferenceType reference) {
|
||||
}
|
||||
|
||||
public void addInstruction21ih(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int literal) {
|
||||
}
|
||||
|
||||
public void addInstruction21lh(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
long literal) {
|
||||
}
|
||||
|
||||
public void addInstruction21s(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int literal) {
|
||||
}
|
||||
|
||||
public void addInstruction21t(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
@Nonnull LabelRef label) {
|
||||
}
|
||||
|
||||
public void addInstruction22b(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB,
|
||||
int literal) {
|
||||
}
|
||||
|
||||
public void addInstruction22c(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB,
|
||||
@Nonnull ReferenceType reference) {
|
||||
}
|
||||
|
||||
public void addInstruction22s(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB,
|
||||
int literal) {
|
||||
}
|
||||
|
||||
public void addInstruction22t(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB,
|
||||
@Nonnull LabelRef labelRef) {
|
||||
}
|
||||
|
||||
public void addInstruction22x(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB) {
|
||||
}
|
||||
|
||||
public void addInstruction23x(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB,
|
||||
int registerC) {
|
||||
}
|
||||
|
||||
public void addInstruction30t(@Nonnull Opcode opcode,
|
||||
@Nonnull LabelRef label) {
|
||||
}
|
||||
|
||||
public void addInstruction31c(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
@Nonnull ReferenceType reference) {
|
||||
}
|
||||
|
||||
public void addInstruction31i(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int literal) {
|
||||
}
|
||||
|
||||
public void addInstruction31t(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
@Nonnull LabelRef label) {
|
||||
}
|
||||
|
||||
public void addInstruction32x(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
int registerB) {
|
||||
}
|
||||
|
||||
public void addInstruction35c(@Nonnull Opcode opcode,
|
||||
int registerCount,
|
||||
int registerC,
|
||||
int registerD,
|
||||
int registerE,
|
||||
int registerF,
|
||||
int registerG,
|
||||
@Nonnull ReferenceType reference) {
|
||||
}
|
||||
|
||||
public void addInstruction3rc(@Nonnull Opcode opcode,
|
||||
int startRegister,
|
||||
int registerCount,
|
||||
@Nonnull ReferenceType reference) {
|
||||
}
|
||||
|
||||
public void addInstruction51l(@Nonnull Opcode opcode,
|
||||
int registerA,
|
||||
long literal) {
|
||||
}
|
||||
|
||||
public void addPackedSwitchPayload(int startKey, @Nullable List<? extends LabelRef> switchElements) {
|
||||
}
|
||||
|
||||
public void addSparseSwitchPayload(@Nullable List<? extends SwitchLabelElement> switchElements) {
|
||||
}
|
||||
|
||||
public void addArrayPayload(int elementWidth, @Nullable List<Number> arrayElements) {
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.jf.dexlib2.builder;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SwitchLabelElement {
|
||||
public SwitchLabelElement(int key, @Nonnull LabelRef dest) {
|
||||
}
|
||||
}
|
@ -164,10 +164,24 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
return context.stringPool.internString(string);
|
||||
}
|
||||
|
||||
@Nullable public BuilderStringReference internNullableStringReference(@Nullable String string) {
|
||||
if (string != null) {
|
||||
return internStringReference(string);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull public BuilderTypeReference internTypeReference(@Nonnull String type) {
|
||||
return context.typePool.internType(type);
|
||||
}
|
||||
|
||||
@Nullable public BuilderTypeReference internNullableTypeReference(@Nullable String type) {
|
||||
if (type != null) {
|
||||
return internTypeReference(type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull public BuilderFieldReference internFieldReference(@Nonnull FieldReference field) {
|
||||
return context.fieldPool.internField(field);
|
||||
}
|
||||
|
@ -187,7 +187,6 @@ tokens {
|
||||
I_METHOD_RETURN_TYPE;
|
||||
I_REGISTERS;
|
||||
I_LOCALS;
|
||||
I_LABELS;
|
||||
I_LABEL;
|
||||
I_ANNOTATIONS;
|
||||
I_ANNOTATION;
|
||||
@ -201,26 +200,20 @@ tokens {
|
||||
I_ARRAY_ELEMENTS;
|
||||
I_PACKED_SWITCH_START_KEY;
|
||||
I_PACKED_SWITCH_ELEMENTS;
|
||||
I_PACKED_SWITCH_DECLARATION;
|
||||
I_PACKED_SWITCH_DECLARATIONS;
|
||||
I_SPARSE_SWITCH_ELEMENTS;
|
||||
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_ORDERED_METHOD_ITEMS;
|
||||
I_STATEMENT_FORMAT10t;
|
||||
I_STATEMENT_FORMAT10x;
|
||||
I_STATEMENT_FORMAT11n;
|
||||
@ -509,9 +502,7 @@ field
|
||||
);
|
||||
|
||||
method
|
||||
scope {int currentAddress;}
|
||||
: {$method::currentAddress = 0;}
|
||||
METHOD_DIRECTIVE access_list method_name method_prototype statements_and_directives
|
||||
: 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);
|
||||
|
||||
@ -519,36 +510,31 @@ statements_and_directives
|
||||
scope
|
||||
{
|
||||
boolean hasRegistersDirective;
|
||||
List<CommonTree> packedSwitchDeclarations;
|
||||
List<CommonTree> sparseSwitchDeclarations;
|
||||
List<CommonTree> methodAnnotations;
|
||||
}
|
||||
: {
|
||||
$method::currentAddress = 0;
|
||||
$statements_and_directives::hasRegistersDirective = false;
|
||||
$statements_and_directives::packedSwitchDeclarations = new ArrayList<CommonTree>();
|
||||
$statements_and_directives::sparseSwitchDeclarations = new ArrayList<CommonTree>();
|
||||
$statements_and_directives::methodAnnotations = new ArrayList<CommonTree>();
|
||||
}
|
||||
( instruction {$method::currentAddress += $instruction.size/2;}
|
||||
( ordered_method_item
|
||||
| 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_ORDERED_METHOD_ITEMS ordered_method_item*)
|
||||
^(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)};
|
||||
|
||||
/* Method items whose order/location is important */
|
||||
ordered_method_item
|
||||
: label
|
||||
| instruction
|
||||
| debug_directive;
|
||||
|
||||
registers_directive
|
||||
: (
|
||||
directive=REGISTERS_DIRECTIVE regCount=integral_literal -> ^(I_REGISTERS[$REGISTERS_DIRECTIVE, "I_REGISTERS"] $regCount)
|
||||
@ -679,15 +665,15 @@ fixed_32bit_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;};
|
||||
fixed_literal
|
||||
: integer_literal
|
||||
| LONG_LITERAL
|
||||
| SHORT_LITERAL
|
||||
| BYTE_LITERAL
|
||||
| float_literal
|
||||
| double_literal
|
||||
| CHAR_LITERAL
|
||||
| BOOL_LITERAL;
|
||||
|
||||
array_literal
|
||||
: OPEN_BRACE (literal (COMMA literal)* | ) CLOSE_BRACE
|
||||
@ -730,7 +716,7 @@ fully_qualified_field
|
||||
-> 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);
|
||||
|
||||
label_ref
|
||||
: COLON simple_name -> simple_name;
|
||||
@ -747,11 +733,11 @@ verification_error_reference
|
||||
|
||||
catch_directive
|
||||
: CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref DOTDOT to=label_ref CLOSE_BRACE using=label_ref
|
||||
-> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using);
|
||||
-> ^(I_CATCH[$start, "I_CATCH"] nonvoid_type_descriptor $from $to $using);
|
||||
|
||||
catchall_directive
|
||||
: CATCHALL_DIRECTIVE OPEN_BRACE from=label_ref DOTDOT to=label_ref CLOSE_BRACE using=label_ref
|
||||
-> ^(I_CATCHALL[$start, "I_CATCHALL"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] $from $to $using);
|
||||
-> ^(I_CATCHALL[$start, "I_CATCHALL"] $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
|
||||
@ -768,7 +754,7 @@ parameter_directive
|
||||
-> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS))
|
||||
);
|
||||
|
||||
ordered_debug_directive
|
||||
debug_directive
|
||||
: line_directive
|
||||
| local_directive
|
||||
| end_local_directive
|
||||
@ -779,33 +765,32 @@ ordered_debug_directive
|
||||
|
||||
line_directive
|
||||
: LINE_DIRECTIVE integral_literal
|
||||
-> ^(I_LINE[$start, "I_LINE"] integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_LINE[$start, "I_LINE"] integral_literal);
|
||||
|
||||
local_directive
|
||||
: LOCAL_DIRECTIVE REGISTER (COMMA (NULL_LITERAL | name=STRING_LITERAL) COLON (VOID_TYPE | nonvoid_type_descriptor)
|
||||
(COMMA signature=STRING_LITERAL)? )?
|
||||
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER NULL_LITERAL? $name? nonvoid_type_descriptor? $signature?
|
||||
I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER NULL_LITERAL? $name? nonvoid_type_descriptor? $signature?);
|
||||
|
||||
end_local_directive
|
||||
: END_LOCAL_DIRECTIVE REGISTER
|
||||
-> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_END_LOCAL[$start, "I_END_LOCAL"] REGISTER);
|
||||
|
||||
restart_local_directive
|
||||
: RESTART_LOCAL_DIRECTIVE REGISTER
|
||||
-> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_RESTART_LOCAL[$start, "I_RESTART_LOCAL"] REGISTER);
|
||||
|
||||
prologue_directive
|
||||
: PROLOGUE_DIRECTIVE
|
||||
-> ^(I_PROLOGUE[$start, "I_PROLOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_PROLOGUE[$start, "I_PROLOGUE"]);
|
||||
|
||||
epilogue_directive
|
||||
: EPILOGUE_DIRECTIVE
|
||||
-> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_EPILOGUE[$start, "I_EPILOGUE"]);
|
||||
|
||||
source_directive
|
||||
: SOURCE_DIRECTIVE STRING_LITERAL?
|
||||
-> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||
-> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL?);
|
||||
|
||||
instruction_format12x
|
||||
: INSTRUCTION_FORMAT12x
|
||||
@ -821,88 +806,88 @@ instruction_format31i
|
||||
|
||||
|
||||
|
||||
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_format21ih { $size = $insn_format21ih.size; }
|
||||
| insn_format21lh { $size = $insn_format21lh.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; };
|
||||
instruction
|
||||
: insn_format10t
|
||||
| insn_format10x
|
||||
| insn_format10x_odex
|
||||
| insn_format11n
|
||||
| insn_format11x
|
||||
| insn_format12x
|
||||
| insn_format20bc
|
||||
| insn_format20t
|
||||
| insn_format21c_field
|
||||
| insn_format21c_field_odex
|
||||
| insn_format21c_string
|
||||
| insn_format21c_type
|
||||
| insn_format21ih
|
||||
| insn_format21lh
|
||||
| insn_format21s
|
||||
| insn_format21t
|
||||
| insn_format22b
|
||||
| insn_format22c_field
|
||||
| insn_format22c_field_odex
|
||||
| insn_format22c_type
|
||||
| insn_format22cs_field
|
||||
| insn_format22s
|
||||
| insn_format22t
|
||||
| insn_format22x
|
||||
| insn_format23x
|
||||
| insn_format30t
|
||||
| insn_format31c
|
||||
| insn_format31i
|
||||
| insn_format31t
|
||||
| insn_format32x
|
||||
| insn_format35c_method
|
||||
| insn_format35c_type
|
||||
| insn_format35c_method_odex
|
||||
| insn_format35mi_method
|
||||
| insn_format35ms_method
|
||||
| insn_format3rc_method
|
||||
| insn_format3rc_method_odex
|
||||
| insn_format3rc_type
|
||||
| insn_format3rmi_method
|
||||
| insn_format3rms_method
|
||||
| insn_format51l
|
||||
| insn_array_data_directive
|
||||
| insn_packed_switch_directive
|
||||
| insn_sparse_switch_directive;
|
||||
|
||||
insn_format10t returns [int size]
|
||||
insn_format10t
|
||||
: //e.g. goto endloop:
|
||||
//e.g. goto +3
|
||||
INSTRUCTION_FORMAT10t label_ref {$size = Format.Format10t.size;}
|
||||
INSTRUCTION_FORMAT10t label_ref
|
||||
-> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t label_ref);
|
||||
|
||||
insn_format10x returns [int size]
|
||||
insn_format10x
|
||||
: //e.g. return-void
|
||||
INSTRUCTION_FORMAT10x {$size = Format.Format10x.size;}
|
||||
INSTRUCTION_FORMAT10x
|
||||
-> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x);
|
||||
|
||||
insn_format10x_odex returns [int size]
|
||||
insn_format10x_odex
|
||||
: //e.g. return-void-barrier
|
||||
INSTRUCTION_FORMAT10x_ODEX {$size = Format.Format10x.size;}
|
||||
INSTRUCTION_FORMAT10x_ODEX
|
||||
{
|
||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT10x_ODEX.text);
|
||||
};
|
||||
|
||||
insn_format11n returns [int size]
|
||||
insn_format11n
|
||||
: //e.g. const/4 v0, 5
|
||||
INSTRUCTION_FORMAT11n REGISTER COMMA integral_literal {$size = Format.Format11n.size;}
|
||||
INSTRUCTION_FORMAT11n REGISTER COMMA integral_literal
|
||||
-> ^(I_STATEMENT_FORMAT11n[$start, "I_STATEMENT_FORMAT11n"] INSTRUCTION_FORMAT11n REGISTER integral_literal);
|
||||
|
||||
insn_format11x returns [int size]
|
||||
insn_format11x
|
||||
: //e.g. move-result-object v1
|
||||
INSTRUCTION_FORMAT11x REGISTER {$size = Format.Format11x.size;}
|
||||
INSTRUCTION_FORMAT11x REGISTER
|
||||
-> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_FORMAT11x REGISTER);
|
||||
|
||||
insn_format12x returns [int size]
|
||||
insn_format12x
|
||||
: //e.g. move v1 v2
|
||||
instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;}
|
||||
instruction_format12x REGISTER COMMA REGISTER
|
||||
-> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER);
|
||||
|
||||
insn_format20bc returns [int size]
|
||||
insn_format20bc
|
||||
: //e.g. throw-verification-error generic-error, Lsome/class;
|
||||
INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;}
|
||||
INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference
|
||||
{
|
||||
if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) {
|
||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text);
|
||||
@ -910,19 +895,19 @@ insn_format20bc returns [int size]
|
||||
}
|
||||
-> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference);
|
||||
|
||||
insn_format20t returns [int size]
|
||||
insn_format20t
|
||||
: //e.g. goto/16 endloop:
|
||||
INSTRUCTION_FORMAT20t label_ref {$size = Format.Format20t.size;}
|
||||
INSTRUCTION_FORMAT20t label_ref
|
||||
-> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref);
|
||||
|
||||
insn_format21c_field returns [int size]
|
||||
insn_format21c_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;}
|
||||
INSTRUCTION_FORMAT21c_FIELD REGISTER COMMA fully_qualified_field
|
||||
-> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field);
|
||||
|
||||
insn_format21c_field_odex returns [int size]
|
||||
insn_format21c_field_odex
|
||||
: //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;}
|
||||
INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER COMMA fully_qualified_field
|
||||
{
|
||||
if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) {
|
||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT21c_FIELD_ODEX.text);
|
||||
@ -930,49 +915,49 @@ insn_format21c_field_odex returns [int size]
|
||||
}
|
||||
-> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER fully_qualified_field);
|
||||
|
||||
insn_format21c_string returns [int size]
|
||||
insn_format21c_string
|
||||
: //e.g. const-string v1, "Hello World!"
|
||||
INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;}
|
||||
INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL
|
||||
-> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL);
|
||||
|
||||
insn_format21c_type returns [int size]
|
||||
insn_format21c_type
|
||||
: //e.g. const-class v2, Lorg/jf/HelloWorld2/HelloWorld2;
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;}
|
||||
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor
|
||||
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor);
|
||||
|
||||
insn_format21ih returns [int size]
|
||||
insn_format21ih
|
||||
: //e.g. const/high16 v1, 1234
|
||||
INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal {$size = Format.Format21ih.size;}
|
||||
INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal
|
||||
-> ^(I_STATEMENT_FORMAT21ih[$start, "I_STATEMENT_FORMAT21ih"] INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal);
|
||||
|
||||
insn_format21lh returns [int size]
|
||||
insn_format21lh
|
||||
: //e.g. const-wide/high16 v1, 1234
|
||||
INSTRUCTION_FORMAT21lh REGISTER COMMA fixed_32bit_literal {$size = Format.Format21lh.size;}
|
||||
INSTRUCTION_FORMAT21lh REGISTER COMMA fixed_32bit_literal
|
||||
-> ^(I_STATEMENT_FORMAT21lh[$start, "I_STATEMENT_FORMAT21lh"] INSTRUCTION_FORMAT21lh REGISTER fixed_32bit_literal);
|
||||
|
||||
insn_format21s returns [int size]
|
||||
insn_format21s
|
||||
: //e.g. const/16 v1, 1234
|
||||
INSTRUCTION_FORMAT21s REGISTER COMMA integral_literal {$size = Format.Format21s.size;}
|
||||
INSTRUCTION_FORMAT21s REGISTER COMMA integral_literal
|
||||
-> ^(I_STATEMENT_FORMAT21s[$start, "I_STATEMENT_FORMAT21s"] INSTRUCTION_FORMAT21s REGISTER integral_literal);
|
||||
|
||||
insn_format21t returns [int size]
|
||||
insn_format21t
|
||||
: //e.g. if-eqz v0, endloop:
|
||||
INSTRUCTION_FORMAT21t REGISTER COMMA (label_ref) {$size = Format.Format21t.size;}
|
||||
INSTRUCTION_FORMAT21t REGISTER COMMA label_ref
|
||||
-> ^(I_STATEMENT_FORMAT21t[$start, "I_STATEMENT_FORMAT21t"] INSTRUCTION_FORMAT21t REGISTER label_ref);
|
||||
|
||||
insn_format22b returns [int size]
|
||||
insn_format22b
|
||||
: //e.g. add-int v0, v1, 123
|
||||
INSTRUCTION_FORMAT22b REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22b.size;}
|
||||
INSTRUCTION_FORMAT22b REGISTER COMMA REGISTER COMMA integral_literal
|
||||
-> ^(I_STATEMENT_FORMAT22b[$start, "I_STATEMENT_FORMAT22b"] INSTRUCTION_FORMAT22b REGISTER REGISTER integral_literal);
|
||||
|
||||
insn_format22c_field returns [int size]
|
||||
insn_format22c_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;}
|
||||
INSTRUCTION_FORMAT22c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field
|
||||
-> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD REGISTER REGISTER fully_qualified_field);
|
||||
|
||||
insn_format22c_field_odex returns [int size]
|
||||
insn_format22c_field_odex
|
||||
: //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;}
|
||||
INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field
|
||||
{
|
||||
if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) {
|
||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22c_FIELD_ODEX.text);
|
||||
@ -980,146 +965,131 @@ insn_format22c_field_odex returns [int size]
|
||||
}
|
||||
-> ^(I_STATEMENT_FORMAT22c_FIELD[$start, "I_STATEMENT_FORMAT22c_FIELD"] INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER REGISTER fully_qualified_field);
|
||||
|
||||
insn_format22c_type returns [int size]
|
||||
insn_format22c_type
|
||||
: //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||
INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format22c.size;}
|
||||
INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor
|
||||
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor);
|
||||
|
||||
insn_format22cs_field returns [int size]
|
||||
insn_format22cs_field
|
||||
: //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]
|
||||
insn_format22s
|
||||
: //e.g. add-int/lit16 v0, v1, 12345
|
||||
instruction_format22s REGISTER COMMA REGISTER COMMA integral_literal {$size = Format.Format22s.size;}
|
||||
instruction_format22s REGISTER COMMA REGISTER COMMA integral_literal
|
||||
-> ^(I_STATEMENT_FORMAT22s[$start, "I_STATEMENT_FORMAT22s"] instruction_format22s REGISTER REGISTER integral_literal);
|
||||
|
||||
insn_format22t returns [int size]
|
||||
insn_format22t
|
||||
: //e.g. if-eq v0, v1, endloop:
|
||||
INSTRUCTION_FORMAT22t REGISTER COMMA REGISTER COMMA label_ref {$size = Format.Format22t.size;}
|
||||
INSTRUCTION_FORMAT22t REGISTER COMMA REGISTER COMMA label_ref
|
||||
-> ^(I_STATEMENT_FORMAT22t[$start, "I_STATEMENT_FFORMAT22t"] INSTRUCTION_FORMAT22t REGISTER REGISTER label_ref);
|
||||
|
||||
insn_format22x returns [int size]
|
||||
insn_format22x
|
||||
: //e.g. move/from16 v1, v1234
|
||||
INSTRUCTION_FORMAT22x REGISTER COMMA REGISTER {$size = Format.Format22x.size;}
|
||||
INSTRUCTION_FORMAT22x REGISTER COMMA REGISTER
|
||||
-> ^(I_STATEMENT_FORMAT22x[$start, "I_STATEMENT_FORMAT22x"] INSTRUCTION_FORMAT22x REGISTER REGISTER);
|
||||
|
||||
insn_format23x returns [int size]
|
||||
insn_format23x
|
||||
: //e.g. add-int v1, v2, v3
|
||||
INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER {$size = Format.Format23x.size;}
|
||||
INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER
|
||||
-> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER);
|
||||
|
||||
insn_format30t returns [int size]
|
||||
insn_format30t
|
||||
: //e.g. goto/32 endloop:
|
||||
INSTRUCTION_FORMAT30t label_ref {$size = Format.Format30t.size;}
|
||||
INSTRUCTION_FORMAT30t label_ref
|
||||
-> ^(I_STATEMENT_FORMAT30t[$start, "I_STATEMENT_FORMAT30t"] INSTRUCTION_FORMAT30t label_ref);
|
||||
|
||||
insn_format31c returns [int size]
|
||||
insn_format31c
|
||||
: //e.g. const-string/jumbo v1 "Hello World!"
|
||||
INSTRUCTION_FORMAT31c REGISTER COMMA STRING_LITERAL {$size = Format.Format31c.size;}
|
||||
INSTRUCTION_FORMAT31c REGISTER COMMA STRING_LITERAL
|
||||
->^(I_STATEMENT_FORMAT31c[$start, "I_STATEMENT_FORMAT31c"] INSTRUCTION_FORMAT31c REGISTER STRING_LITERAL);
|
||||
|
||||
insn_format31i returns [int size]
|
||||
insn_format31i
|
||||
: //e.g. const v0, 123456
|
||||
instruction_format31i REGISTER COMMA fixed_32bit_literal {$size = Format.Format31i.size;}
|
||||
instruction_format31i REGISTER COMMA fixed_32bit_literal
|
||||
-> ^(I_STATEMENT_FORMAT31i[$start, "I_STATEMENT_FORMAT31i"] instruction_format31i REGISTER fixed_32bit_literal);
|
||||
|
||||
insn_format31t returns [int size]
|
||||
insn_format31t
|
||||
: //e.g. fill-array-data v0, ArrayData:
|
||||
INSTRUCTION_FORMAT31t REGISTER COMMA label_ref {$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.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.tree.dupNode());
|
||||
$statements_and_directives::sparseSwitchDeclarations.add(root);
|
||||
}
|
||||
}
|
||||
INSTRUCTION_FORMAT31t REGISTER COMMA label_ref
|
||||
-> ^(I_STATEMENT_FORMAT31t[$start, "I_STATEMENT_FORMAT31t"] INSTRUCTION_FORMAT31t REGISTER label_ref);
|
||||
|
||||
insn_format32x returns [int size]
|
||||
insn_format32x
|
||||
: //e.g. move/16 v4567, v1234
|
||||
INSTRUCTION_FORMAT32x REGISTER COMMA REGISTER {$size = Format.Format32x.size;}
|
||||
INSTRUCTION_FORMAT32x REGISTER COMMA REGISTER
|
||||
-> ^(I_STATEMENT_FORMAT32x[$start, "I_STATEMENT_FORMAT32x"] INSTRUCTION_FORMAT32x REGISTER REGISTER);
|
||||
|
||||
insn_format35c_method returns [int size]
|
||||
insn_format35c_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;}
|
||||
INSTRUCTION_FORMAT35c_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method
|
||||
-> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method);
|
||||
|
||||
insn_format35c_type returns [int size]
|
||||
insn_format35c_type
|
||||
: //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;}
|
||||
INSTRUCTION_FORMAT35c_TYPE OPEN_BRACE register_list CLOSE_BRACE COMMA nonvoid_type_descriptor
|
||||
-> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor);
|
||||
|
||||
insn_format35c_method_odex returns [int size]
|
||||
insn_format35c_method_odex
|
||||
: //e.g. invoke-direct {p0}, Ljava/lang/Object;-><init>()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]
|
||||
insn_format35mi_method
|
||||
: //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]
|
||||
insn_format35ms_method
|
||||
: //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]
|
||||
insn_format3rc_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;}
|
||||
INSTRUCTION_FORMAT3rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method
|
||||
-> ^(I_STATEMENT_FORMAT3rc_METHOD[$start, "I_STATEMENT_FORMAT3rc_METHOD"] INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method);
|
||||
|
||||
insn_format3rc_method_odex returns [int size]
|
||||
insn_format3rc_method_odex
|
||||
: //e.g. invoke-object-init/range {p0}, Ljava/lang/Object;-><init>()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]
|
||||
insn_format3rc_type
|
||||
: //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;}
|
||||
INSTRUCTION_FORMAT3rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor
|
||||
-> ^(I_STATEMENT_FORMAT3rc_TYPE[$start, "I_STATEMENT_FORMAT3rc_TYPE"] INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor);
|
||||
|
||||
insn_format3rmi_method returns [int size]
|
||||
insn_format3rmi_method
|
||||
: //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]
|
||||
insn_format3rms_method
|
||||
: //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]
|
||||
insn_format51l
|
||||
: //e.g. const-wide v0, 5000000000L
|
||||
INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;}
|
||||
INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal
|
||||
-> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal);
|
||||
|
||||
insn_array_data_directive returns [int size]
|
||||
insn_array_data_directive
|
||||
: ARRAY_DATA_DIRECTIVE
|
||||
parsed_integer_literal
|
||||
{
|
||||
@ -1128,32 +1098,25 @@ insn_array_data_directive returns [int size]
|
||||
throw new SemanticException(input, $start, "Invalid element width: \%d. Must be 1, 2, 4 or 8", elementWidth);
|
||||
}
|
||||
}
|
||||
|
||||
(fixed_literal {$size+=elementWidth;})* END_ARRAY_DATA_DIRECTIVE
|
||||
{$size = (($size + 1) & ~1) + 8;}
|
||||
fixed_literal* END_ARRAY_DATA_DIRECTIVE
|
||||
|
||||
-> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE parsed_integer_literal)
|
||||
^(I_ARRAY_ELEMENTS fixed_literal*));
|
||||
|
||||
insn_packed_switch_directive returns [int size]
|
||||
insn_packed_switch_directive
|
||||
: PACKED_SWITCH_DIRECTIVE
|
||||
fixed_32bit_literal
|
||||
|
||||
(switch_target += label_ref {$size+=4;})*
|
||||
|
||||
END_PACKED_SWITCH_DIRECTIVE {$size = $size + 8;}
|
||||
|
||||
label_ref*
|
||||
END_PACKED_SWITCH_DIRECTIVE
|
||||
-> ^(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_ELEMENTS[$start, "I_PACKED_SWITCH_ELEMENTS"]
|
||||
$switch_target*)
|
||||
label_ref*)
|
||||
);
|
||||
|
||||
insn_sparse_switch_directive returns [int size]
|
||||
insn_sparse_switch_directive
|
||||
: SPARSE_SWITCH_DIRECTIVE
|
||||
(fixed_32bit_literal ARROW switch_target += label_ref {$size += 8;})*
|
||||
|
||||
END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;}
|
||||
|
||||
(fixed_32bit_literal ARROW label_ref)*
|
||||
END_SPARSE_SWITCH_DIRECTIVE
|
||||
-> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
||||
^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal $switch_target)*));
|
||||
^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal label_ref)*));
|
@ -36,33 +36,39 @@ options {
|
||||
@header {
|
||||
package org.jf.smali;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.regex.*;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.antlr.runtime.BitSet;
|
||||
import org.antlr.runtime.*;
|
||||
import org.antlr.runtime.tree.CommonTree;
|
||||
import org.antlr.runtime.tree.TreeNodeStream;
|
||||
import org.antlr.runtime.tree.TreeParser;
|
||||
import org.antlr.runtime.tree.TreeRuleReturnScope;
|
||||
import org.jf.dexlib2.*;
|
||||
import org.jf.dexlib2.dexbacked.raw.*;
|
||||
import org.jf.dexlib2.iface.*;
|
||||
import org.jf.dexlib2.iface.debug.DebugItem;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.SwitchElement;
|
||||
import org.jf.dexlib2.iface.instruction.formats.*;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.dexlib2.builder.LabelRef;
|
||||
import org.jf.dexlib2.builder.MethodImplementationBuilder;
|
||||
import org.jf.dexlib2.builder.SwitchLabelElement;
|
||||
import org.jf.dexlib2.iface.Annotation;
|
||||
import org.jf.dexlib2.iface.AnnotationElement;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.MethodImplementation;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.immutable.*;
|
||||
import org.jf.dexlib2.immutable.debug.*;
|
||||
import org.jf.dexlib2.immutable.instruction.*;
|
||||
import org.jf.dexlib2.immutable.reference.*;
|
||||
import org.jf.dexlib2.immutable.ImmutableAnnotation;
|
||||
import org.jf.dexlib2.immutable.ImmutableAnnotationElement;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableTypeReference;
|
||||
import org.jf.dexlib2.immutable.value.*;
|
||||
import org.jf.dexlib2.util.MethodUtil;
|
||||
import org.jf.dexlib2.writer.InstructionFactory;
|
||||
import org.jf.dexlib2.writer.builder.*;
|
||||
import org.jf.dexlib2.util.MethodUtil;
|
||||
import org.jf.util.LinearSearch;
|
||||
|
||||
import java.util.*;
|
||||
}
|
||||
|
||||
@members {
|
||||
@ -320,51 +326,38 @@ array_elements returns[List<Number> elements]
|
||||
$elements.add($fixed_64bit_literal_number.value);
|
||||
})*);
|
||||
|
||||
packed_switch_elements[int baseAddress, int firstKey] returns[List<SwitchElement> elements]
|
||||
packed_switch_elements returns[List<LabelRef> elements]
|
||||
@init {$elements = Lists.newArrayList();}
|
||||
:
|
||||
^(I_PACKED_SWITCH_ELEMENTS
|
||||
|
||||
(relative_label
|
||||
{
|
||||
$elements.add(new ImmutableSwitchElement(firstKey++,
|
||||
($method::currentAddress + $relative_label.offsetValue) - $baseAddress));
|
||||
})*
|
||||
(label_ref { $elements.add($label_ref.label); })*
|
||||
);
|
||||
|
||||
sparse_switch_elements[int baseAddress] returns[List<SwitchElement> elements]
|
||||
sparse_switch_elements returns[List<SwitchLabelElement> elements]
|
||||
@init {$elements = Lists.newArrayList();}
|
||||
:
|
||||
^(I_SPARSE_SWITCH_ELEMENTS
|
||||
(fixed_32bit_literal relative_label
|
||||
(fixed_32bit_literal label_ref
|
||||
{
|
||||
$elements.add(new ImmutableSwitchElement($fixed_32bit_literal.value,
|
||||
($method::currentAddress + $relative_label.offsetValue) - $baseAddress));
|
||||
|
||||
$elements.add(new SwitchLabelElement($fixed_32bit_literal.value, $label_ref.label));
|
||||
})*
|
||||
);
|
||||
|
||||
method returns[BuilderMethod ret]
|
||||
scope
|
||||
{
|
||||
HashMap<String, Integer> labels;
|
||||
int currentAddress;
|
||||
HashMap<Integer, Integer> packedSwitchDeclarations;
|
||||
HashMap<Integer, Integer> sparseSwitchDeclarations;
|
||||
boolean isStatic;
|
||||
int totalMethodRegisters;
|
||||
int methodParameterRegisters;
|
||||
MethodImplementationBuilder methodBuilder;
|
||||
}
|
||||
@init
|
||||
{
|
||||
$method::totalMethodRegisters = 0;
|
||||
$method::methodParameterRegisters = 0;
|
||||
int accessFlags = 0;
|
||||
$method::labels = new HashMap<String, Integer>();
|
||||
$method::currentAddress = 0;
|
||||
$method::packedSwitchDeclarations = new HashMap<Integer, Integer>();
|
||||
$method::sparseSwitchDeclarations = new HashMap<Integer, Integer>();
|
||||
$method::isStatic = false;
|
||||
$method::methodBuilder = new MethodImplementationBuilder();
|
||||
}
|
||||
:
|
||||
^(I_METHOD
|
||||
@ -385,20 +378,14 @@ method returns[BuilderMethod ret]
|
||||
}
|
||||
}
|
||||
)?
|
||||
labels
|
||||
packed_switch_declarations
|
||||
sparse_switch_declarations
|
||||
statements
|
||||
ordered_method_items
|
||||
catches
|
||||
parameters[$method_name_and_prototype.parameters]
|
||||
ordered_debug_directives
|
||||
annotations
|
||||
)
|
||||
{
|
||||
MethodImplementation methodImplementation = null;
|
||||
List<BuilderTryBlock> tryBlocks = $catches.tryBlocks;
|
||||
List<BuilderDebugItem> debugItems = $ordered_debug_directives.debugItems;
|
||||
|
||||
BuilderMethodImplementation methodImplementation = null;
|
||||
|
||||
boolean isAbstract = false;
|
||||
boolean isNative = false;
|
||||
@ -409,7 +396,7 @@ method returns[BuilderMethod ret]
|
||||
isNative = true;
|
||||
}
|
||||
|
||||
if ($statements.instructions.size() == 0) {
|
||||
/*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");
|
||||
}
|
||||
@ -429,7 +416,7 @@ method returns[BuilderMethod ret]
|
||||
}
|
||||
}
|
||||
|
||||
if ($method::labels.size() > 0) {
|
||||
if (labels.size() > 0) {
|
||||
throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType);
|
||||
}
|
||||
|
||||
@ -440,8 +427,8 @@ method returns[BuilderMethod ret]
|
||||
if (debugItems != null && debugItems.size() > 0) {
|
||||
throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType);
|
||||
}
|
||||
} else {
|
||||
if (isAbstract) {
|
||||
} else */{
|
||||
/*if (isAbstract) {
|
||||
throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions");
|
||||
}
|
||||
if (isNative) {
|
||||
@ -456,13 +443,9 @@ method returns[BuilderMethod ret]
|
||||
throw new SemanticException(input, $registers_directive.start, "This method requires at least " +
|
||||
Integer.toString($method::methodParameterRegisters) +
|
||||
" registers, for the method parameters");
|
||||
}
|
||||
}*/
|
||||
|
||||
methodImplementation = dexBuilder.internMethodImplementation(
|
||||
$method::totalMethodRegisters,
|
||||
$statements.instructions,
|
||||
tryBlocks,
|
||||
debugItems);
|
||||
methodImplementation = $method::methodBuilder.buildMethodImplementation();
|
||||
}
|
||||
|
||||
$ret = dexBuilder.internMethod(
|
||||
@ -472,7 +455,8 @@ method returns[BuilderMethod ret]
|
||||
$method_name_and_prototype.returnType,
|
||||
accessFlags,
|
||||
$annotations.annotations,
|
||||
methodImplementation);
|
||||
// TODO: refactor to accept MethodImplementation (not BuilderMethodImplementation)
|
||||
null);
|
||||
};
|
||||
|
||||
method_prototype returns[List<String> parameters, String returnType]
|
||||
@ -534,86 +518,27 @@ registers_directive returns[boolean isLocalsDirective, int registers]
|
||||
short_integral_literal {$registers = $short_integral_literal.value;}
|
||||
);
|
||||
|
||||
labels
|
||||
: ^(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.");
|
||||
}
|
||||
|
||||
$method::labels.put($SIMPLE_NAME.text, $address.address);
|
||||
};
|
||||
|
||||
packed_switch_declarations
|
||||
: ^(I_PACKED_SWITCH_DECLARATIONS packed_switch_declaration*);
|
||||
packed_switch_declaration
|
||||
: ^(I_PACKED_SWITCH_DECLARATION address absolute_label[$address.address])
|
||||
{
|
||||
int switchDataAddress = $absolute_label.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*);
|
||||
sparse_switch_declaration
|
||||
: ^(I_SPARSE_SWITCH_DECLARATION address absolute_label[$address.address])
|
||||
{
|
||||
int switchDataAddress = $absolute_label.address;
|
||||
if ((switchDataAddress \% 2) != 0) {
|
||||
switchDataAddress++;
|
||||
}
|
||||
if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) {
|
||||
$method::sparseSwitchDeclarations.put(switchDataAddress, $address.address);
|
||||
}
|
||||
};
|
||||
: ^(I_LABEL SIMPLE_NAME)
|
||||
{
|
||||
$method::methodBuilder.addLabel($SIMPLE_NAME.text);
|
||||
};
|
||||
|
||||
catches returns[List<BuilderTryBlock> tryBlocks]
|
||||
@init {tryBlocks = Lists.newArrayList();}
|
||||
: ^(I_CATCHES (catch_directive { tryBlocks.add($catch_directive.tryBlock); })*
|
||||
(catchall_directive { tryBlocks.add($catchall_directive.tryBlock); })*);
|
||||
: ^(I_CATCHES catch_directive* catchall_directive*);
|
||||
|
||||
catch_directive returns[BuilderTryBlock tryBlock]
|
||||
: ^(I_CATCH address nonvoid_type_descriptor from=absolute_label[$address.address] to=absolute_label[$address.address]
|
||||
using=absolute_label[$address.address])
|
||||
{
|
||||
String type = $nonvoid_type_descriptor.type;
|
||||
int startAddress = $from.address;
|
||||
int endAddress = $to.address;
|
||||
int handlerAddress = $using.address;
|
||||
catch_directive
|
||||
: ^(I_CATCH nonvoid_type_descriptor from=label_ref to=label_ref using=label_ref)
|
||||
{
|
||||
$method::methodBuilder.addCatch($nonvoid_type_descriptor.type, $from.label, $to.label, $using.label);
|
||||
};
|
||||
|
||||
// We always create try blocks with a single exception handler. These will be merged appropriately when written
|
||||
// to a dex file
|
||||
$tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress,
|
||||
ImmutableList.of(dexBuilder.internExceptionHandler(type, handlerAddress)));
|
||||
};
|
||||
|
||||
catchall_directive returns[BuilderTryBlock tryBlock]
|
||||
: ^(I_CATCHALL address from=absolute_label[$address.address] to=absolute_label[$address.address]
|
||||
using=absolute_label[$address.address])
|
||||
{
|
||||
int startAddress = $from.address;
|
||||
int endAddress = $to.address;
|
||||
int handlerAddress = $using.address;
|
||||
|
||||
// We always create try blocks with a single exception handler. These will be merged appropriately when written
|
||||
// to a dex file
|
||||
$tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress,
|
||||
ImmutableList.of(dexBuilder.internExceptionHandler(null, handlerAddress)));
|
||||
};
|
||||
|
||||
address returns[int address]
|
||||
: I_ADDRESS
|
||||
{
|
||||
$address = Integer.parseInt($I_ADDRESS.text);
|
||||
};
|
||||
catchall_directive
|
||||
: ^(I_CATCHALL from=label_ref to=label_ref using=label_ref)
|
||||
{
|
||||
$method::methodBuilder.addCatch(null, $from.label, $to.label, $using.label);
|
||||
};
|
||||
|
||||
parameters[List<SmaliMethodParameter> parameters]
|
||||
: ^(I_PARAMETERS (parameter[parameters])*);
|
||||
@ -652,99 +577,68 @@ parameter[List<SmaliMethodParameter> parameters]
|
||||
}
|
||||
};
|
||||
|
||||
ordered_debug_directives returns[List<BuilderDebugItem> debugItems]
|
||||
@init {debugItems = Lists.newArrayList();}
|
||||
: ^(I_ORDERED_DEBUG_DIRECTIVES
|
||||
( line { $debugItems.add($line.debugItem); }
|
||||
| local { $debugItems.add($local.debugItem); }
|
||||
| end_local { $debugItems.add($end_local.debugItem); }
|
||||
| restart_local { $debugItems.add($restart_local.debugItem); }
|
||||
| prologue { $debugItems.add($prologue.debugItem); }
|
||||
| epilogue { $debugItems.add($epilogue.debugItem); }
|
||||
| source { $debugItems.add($source.debugItem); }
|
||||
)*
|
||||
);
|
||||
debug_directive
|
||||
: line
|
||||
| local
|
||||
| end_local
|
||||
| restart_local
|
||||
| prologue
|
||||
| epilogue
|
||||
| source;
|
||||
|
||||
line returns[BuilderDebugItem debugItem]
|
||||
: ^(I_LINE integral_literal address)
|
||||
line
|
||||
: ^(I_LINE integral_literal)
|
||||
{
|
||||
$debugItem = dexBuilder.internLineNumber($address.address, $integral_literal.value);
|
||||
$method::methodBuilder.addLineNumber($integral_literal.value);
|
||||
};
|
||||
|
||||
local returns[BuilderDebugItem debugItem]
|
||||
: ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)? address)
|
||||
local
|
||||
: ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)?)
|
||||
{
|
||||
int registerNumber = parseRegister_short($REGISTER.text);
|
||||
|
||||
$debugItem = dexBuilder.internStartLocal($address.address, registerNumber, $name.value,
|
||||
$nonvoid_type_descriptor.type, $signature.value);
|
||||
$method::methodBuilder.addStartLocal(registerNumber,
|
||||
dexBuilder.internNullableStringReference($name.value),
|
||||
dexBuilder.internNullableTypeReference($nonvoid_type_descriptor.type),
|
||||
dexBuilder.internNullableStringReference($signature.value));
|
||||
};
|
||||
|
||||
end_local returns[BuilderDebugItem debugItem]
|
||||
: ^(I_END_LOCAL REGISTER address)
|
||||
end_local
|
||||
: ^(I_END_LOCAL REGISTER)
|
||||
{
|
||||
int registerNumber = parseRegister_short($REGISTER.text);
|
||||
|
||||
$debugItem = dexBuilder.internEndLocal($address.address, registerNumber);
|
||||
$method::methodBuilder.addEndLocal(registerNumber);
|
||||
};
|
||||
|
||||
restart_local returns[BuilderDebugItem debugItem]
|
||||
: ^(I_RESTART_LOCAL REGISTER address)
|
||||
restart_local
|
||||
: ^(I_RESTART_LOCAL REGISTER)
|
||||
{
|
||||
int registerNumber = parseRegister_short($REGISTER.text);
|
||||
|
||||
$debugItem = dexBuilder.internRestartLocal($address.address, registerNumber);
|
||||
$method::methodBuilder.addRestartLocal(registerNumber);
|
||||
};
|
||||
|
||||
prologue returns[BuilderDebugItem debugItem]
|
||||
: ^(I_PROLOGUE address)
|
||||
prologue
|
||||
: I_PROLOGUE
|
||||
{
|
||||
$debugItem = dexBuilder.internPrologueEnd($address.address);
|
||||
$method::methodBuilder.addPrologue();
|
||||
};
|
||||
|
||||
epilogue returns[BuilderDebugItem debugItem]
|
||||
: ^(I_EPILOGUE address)
|
||||
epilogue
|
||||
: I_EPILOGUE
|
||||
{
|
||||
$debugItem = dexBuilder.internEpilogueBegin($address.address);
|
||||
$method::methodBuilder.addEpilogue();
|
||||
};
|
||||
|
||||
source returns[BuilderDebugItem debugItem]
|
||||
: ^(I_SOURCE string_literal? address)
|
||||
source
|
||||
: ^(I_SOURCE string_literal?)
|
||||
{
|
||||
$debugItem = dexBuilder.internSetSourceFile($address.address, $string_literal.value);
|
||||
$method::methodBuilder.addSetSourceFile(dexBuilder.internNullableStringReference($string_literal.value));
|
||||
};
|
||||
|
||||
statements returns[List<BuilderInstruction> instructions, int maxOutRegisters]
|
||||
@init
|
||||
{
|
||||
$instructions = Lists.newArrayList();
|
||||
$maxOutRegisters = 0;
|
||||
}
|
||||
: ^(I_STATEMENTS (instruction[$instructions]
|
||||
{
|
||||
$method::currentAddress += $instructions.get($instructions.size() - 1).getCodeUnits();
|
||||
if ($maxOutRegisters < $instruction.outRegisters) {
|
||||
$maxOutRegisters = $instruction.outRegisters;
|
||||
}
|
||||
})*);
|
||||
ordered_method_items
|
||||
: ^(I_ORDERED_METHOD_ITEMS (label_def | instruction | debug_directive)*);
|
||||
|
||||
label_ref returns[int labelAddress]
|
||||
: 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.");
|
||||
}
|
||||
|
||||
$labelAddress = labelAdd;
|
||||
};
|
||||
|
||||
absolute_label[int baseAddress] returns[int address]
|
||||
: label_ref {$address = $label_ref.labelAddress;};
|
||||
|
||||
relative_label returns[int offsetValue]
|
||||
: label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
|
||||
label_ref returns[LabelRef label]
|
||||
: SIMPLE_NAME { $label = $method::methodBuilder.getLabel($SIMPLE_NAME.text); };
|
||||
|
||||
register_list returns[byte[\] registers, byte registerCount]
|
||||
@init
|
||||
@ -803,68 +697,63 @@ verification_error_type returns[int verificationError]
|
||||
$verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text);
|
||||
};
|
||||
|
||||
instruction[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
: insn_format10t[$instructions] { $outRegisters = $insn_format10t.outRegisters; }
|
||||
| insn_format10x[$instructions] { $outRegisters = $insn_format10x.outRegisters; }
|
||||
| insn_format11n[$instructions] { $outRegisters = $insn_format11n.outRegisters; }
|
||||
| insn_format11x[$instructions] { $outRegisters = $insn_format11x.outRegisters; }
|
||||
| insn_format12x[$instructions] { $outRegisters = $insn_format12x.outRegisters; }
|
||||
| insn_format20bc[$instructions] { $outRegisters = $insn_format20bc.outRegisters; }
|
||||
| insn_format20t[$instructions] { $outRegisters = $insn_format20t.outRegisters; }
|
||||
| insn_format21c_field[$instructions] { $outRegisters = $insn_format21c_field.outRegisters; }
|
||||
| insn_format21c_string[$instructions] { $outRegisters = $insn_format21c_string.outRegisters; }
|
||||
| insn_format21c_type[$instructions] { $outRegisters = $insn_format21c_type.outRegisters; }
|
||||
| insn_format21ih[$instructions] { $outRegisters = $insn_format21ih.outRegisters; }
|
||||
| insn_format21lh[$instructions] { $outRegisters = $insn_format21lh.outRegisters; }
|
||||
| insn_format21s[$instructions] { $outRegisters = $insn_format21s.outRegisters; }
|
||||
| insn_format21t[$instructions] { $outRegisters = $insn_format21t.outRegisters; }
|
||||
| insn_format22b[$instructions] { $outRegisters = $insn_format22b.outRegisters; }
|
||||
| insn_format22c_field[$instructions] { $outRegisters = $insn_format22c_field.outRegisters; }
|
||||
| insn_format22c_type[$instructions] { $outRegisters = $insn_format22c_type.outRegisters; }
|
||||
| insn_format22s[$instructions] { $outRegisters = $insn_format22s.outRegisters; }
|
||||
| insn_format22t[$instructions] { $outRegisters = $insn_format22t.outRegisters; }
|
||||
| insn_format22x[$instructions] { $outRegisters = $insn_format22x.outRegisters; }
|
||||
| insn_format23x[$instructions] { $outRegisters = $insn_format23x.outRegisters; }
|
||||
| insn_format30t[$instructions] { $outRegisters = $insn_format30t.outRegisters; }
|
||||
| insn_format31c[$instructions] { $outRegisters = $insn_format31c.outRegisters; }
|
||||
| insn_format31i[$instructions] { $outRegisters = $insn_format31i.outRegisters; }
|
||||
| insn_format31t[$instructions] { $outRegisters = $insn_format31t.outRegisters; }
|
||||
| insn_format32x[$instructions] { $outRegisters = $insn_format32x.outRegisters; }
|
||||
| insn_format35c_method[$instructions] { $outRegisters = $insn_format35c_method.outRegisters; }
|
||||
| insn_format35c_type[$instructions] { $outRegisters = $insn_format35c_type.outRegisters; }
|
||||
| insn_format3rc_method[$instructions] { $outRegisters = $insn_format3rc_method.outRegisters; }
|
||||
| insn_format3rc_type[$instructions] { $outRegisters = $insn_format3rc_type.outRegisters; }
|
||||
| insn_format51l_type[$instructions] { $outRegisters = $insn_format51l_type.outRegisters; }
|
||||
| insn_array_data_directive[$instructions] { $outRegisters = $insn_array_data_directive.outRegisters; }
|
||||
| insn_packed_switch_directive[$instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; }
|
||||
| insn_sparse_switch_directive[$instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; };
|
||||
catch [Exception ex] {
|
||||
reportError(new SemanticException(input, $start, ex.getMessage()));
|
||||
recover(input, null);
|
||||
}
|
||||
instruction
|
||||
: insn_format10t
|
||||
| insn_format10x
|
||||
| insn_format11n
|
||||
| insn_format11x
|
||||
| insn_format12x
|
||||
| insn_format20bc
|
||||
| insn_format20t
|
||||
| insn_format21c_field
|
||||
| insn_format21c_string
|
||||
| insn_format21c_type
|
||||
| insn_format21ih
|
||||
| insn_format21lh
|
||||
| insn_format21s
|
||||
| insn_format21t
|
||||
| insn_format22b
|
||||
| insn_format22c_field
|
||||
| insn_format22c_type
|
||||
| insn_format22s
|
||||
| insn_format22t
|
||||
| insn_format22x
|
||||
| insn_format23x
|
||||
| insn_format30t
|
||||
| insn_format31c
|
||||
| insn_format31i
|
||||
| insn_format31t
|
||||
| insn_format32x
|
||||
| insn_format35c_method
|
||||
| insn_format35c_type
|
||||
| insn_format3rc_method
|
||||
| insn_format3rc_type
|
||||
| insn_format51l_type
|
||||
| insn_array_data_directive
|
||||
| insn_packed_switch_directive
|
||||
| insn_sparse_switch_directive;
|
||||
catch [Exception ex] {
|
||||
reportError(new SemanticException(input, $start, ex.getMessage()));
|
||||
recover(input, null);
|
||||
}
|
||||
|
||||
|
||||
insn_format10t[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format10t
|
||||
: //e.g. goto endloop:
|
||||
{$outRegisters = 0;}
|
||||
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t relative_label)
|
||||
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t label_ref)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
|
||||
|
||||
int addressOffset = $relative_label.offsetValue;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction10t(opcode, addressOffset));
|
||||
$method::methodBuilder.addInstruction10t(opcode, $label_ref.label);
|
||||
};
|
||||
|
||||
insn_format10x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format10x
|
||||
: //e.g. return
|
||||
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
|
||||
$instructions.add(instructionFactory.makeInstruction10x(opcode));
|
||||
$method::methodBuilder.addInstruction10x(opcode);
|
||||
};
|
||||
|
||||
insn_format11n[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format11n
|
||||
: //e.g. const/4 v0, 5
|
||||
^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
|
||||
{
|
||||
@ -874,20 +763,20 @@ insn_format11n[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
short litB = $short_integral_literal.value;
|
||||
LiteralTools.checkNibble(litB);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction11n(opcode, regA, litB));
|
||||
$method::methodBuilder.addInstruction11n(opcode, regA, litB);
|
||||
};
|
||||
|
||||
insn_format11x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format11x
|
||||
: //e.g. move-result-object v1
|
||||
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
|
||||
short regA = parseRegister_byte($REGISTER.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction11x(opcode, regA));
|
||||
$method::methodBuilder.addInstruction11x(opcode, regA);
|
||||
};
|
||||
|
||||
insn_format12x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format12x
|
||||
: //e.g. move v1 v2
|
||||
^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
|
||||
{
|
||||
@ -895,10 +784,10 @@ insn_format12x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
byte regA = parseRegister_nibble($registerA.text);
|
||||
byte regB = parseRegister_nibble($registerB.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction12x(opcode, regA, regB));
|
||||
$method::methodBuilder.addInstruction12x(opcode, regA, regB);
|
||||
};
|
||||
|
||||
insn_format20bc[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format20bc
|
||||
: //e.g. throw-verification-error generic-error, Lsome/class;
|
||||
^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference)
|
||||
{
|
||||
@ -907,22 +796,19 @@ insn_format20bc[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
int verificationError = $verification_error_type.verificationError;
|
||||
ImmutableReference referencedItem = $verification_error_reference.reference;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction20bc(opcode, verificationError,
|
||||
dexBuilder.internReference(referencedItem)));
|
||||
$method::methodBuilder.addInstruction20bc(opcode, verificationError,
|
||||
dexBuilder.internReference(referencedItem));
|
||||
};
|
||||
|
||||
insn_format20t[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format20t
|
||||
: //e.g. goto/16 endloop:
|
||||
^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t relative_label)
|
||||
^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t label_ref)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20t.text);
|
||||
|
||||
int addressOffset = $relative_label.offsetValue;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction20t(opcode, addressOffset));
|
||||
$method::methodBuilder.addInstruction20t(opcode, $label_ref.label);
|
||||
};
|
||||
|
||||
insn_format21c_field[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21c_field
|
||||
: //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)
|
||||
{
|
||||
@ -931,33 +817,33 @@ insn_format21c_field[List<BuilderInstruction> instructions] returns[int outRegis
|
||||
|
||||
ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
|
||||
dexBuilder.internFieldReference(fieldReference)));
|
||||
$method::methodBuilder.addInstruction21c(opcode, regA,
|
||||
dexBuilder.internFieldReference(fieldReference));
|
||||
};
|
||||
|
||||
insn_format21c_string[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21c_string
|
||||
: //e.g. const-string v1, "Hello World!"
|
||||
^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
|
||||
short regA = parseRegister_byte($REGISTER.text);
|
||||
|
||||
instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
|
||||
dexBuilder.internStringReference($string_literal.value)));
|
||||
$method::methodBuilder.addInstruction21c(opcode, regA,
|
||||
dexBuilder.internStringReference($string_literal.value));
|
||||
};
|
||||
|
||||
insn_format21c_type[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21c_type
|
||||
: //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2
|
||||
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
|
||||
short regA = parseRegister_byte($REGISTER.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
|
||||
dexBuilder.internTypeReference($reference_type_descriptor.type)));
|
||||
$method::methodBuilder.addInstruction21c(opcode, regA,
|
||||
dexBuilder.internTypeReference($reference_type_descriptor.type));
|
||||
};
|
||||
|
||||
insn_format21ih[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21ih
|
||||
: //e.g. const/high16 v1, 1234
|
||||
^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
|
||||
{
|
||||
@ -966,10 +852,10 @@ insn_format21ih[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
|
||||
int litB = $fixed_32bit_literal.value;
|
||||
|
||||
instructions.add(instructionFactory.makeInstruction21ih(opcode, regA, litB));
|
||||
$method::methodBuilder.addInstruction21ih(opcode, regA, litB);
|
||||
};
|
||||
|
||||
insn_format21lh[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21lh
|
||||
: //e.g. const-wide/high16 v1, 1234
|
||||
^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal)
|
||||
{
|
||||
@ -978,10 +864,10 @@ insn_format21lh[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
|
||||
long litB = $fixed_64bit_literal.value;
|
||||
|
||||
instructions.add(instructionFactory.makeInstruction21lh(opcode, regA, litB));
|
||||
$method::methodBuilder.addInstruction21lh(opcode, regA, litB);
|
||||
};
|
||||
|
||||
insn_format21s[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21s
|
||||
: //e.g. const/16 v1, 1234
|
||||
^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
|
||||
{
|
||||
@ -990,26 +876,20 @@ insn_format21s[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
|
||||
short litB = $short_integral_literal.value;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction21s(opcode, regA, litB));
|
||||
$method::methodBuilder.addInstruction21s(opcode, regA, litB);
|
||||
};
|
||||
|
||||
insn_format21t[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format21t
|
||||
: //e.g. if-eqz v0, endloop:
|
||||
^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER relative_label)
|
||||
^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER label_ref)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21t.text);
|
||||
short regA = parseRegister_byte($REGISTER.text);
|
||||
|
||||
int addressOffset = $relative_label.offsetValue;
|
||||
|
||||
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
||||
throw new SemanticException(input, $relative_label.start, "The label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||
}
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction21t(opcode, regA, addressOffset));
|
||||
$method::methodBuilder.addInstruction21t(opcode, regA, $label_ref.label);
|
||||
};
|
||||
|
||||
insn_format22b[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format22b
|
||||
: //e.g. add-int v0, v1, 123
|
||||
^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
|
||||
{
|
||||
@ -1020,10 +900,10 @@ insn_format22b[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
short litC = $short_integral_literal.value;
|
||||
LiteralTools.checkByte(litC);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction22b(opcode, regA, regB, litC));
|
||||
$method::methodBuilder.addInstruction22b(opcode, regA, regB, litC);
|
||||
};
|
||||
|
||||
insn_format22c_field[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format22c_field
|
||||
: //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)
|
||||
{
|
||||
@ -1033,11 +913,11 @@ insn_format22c_field[List<BuilderInstruction> instructions] returns[int outRegis
|
||||
|
||||
ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB,
|
||||
dexBuilder.internFieldReference(fieldReference)));
|
||||
$method::methodBuilder.addInstruction22c(opcode, regA, regB,
|
||||
dexBuilder.internFieldReference(fieldReference));
|
||||
};
|
||||
|
||||
insn_format22c_type[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format22c_type
|
||||
: //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||
^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
|
||||
{
|
||||
@ -1045,11 +925,11 @@ insn_format22c_type[List<BuilderInstruction> instructions] returns[int outRegist
|
||||
byte regA = parseRegister_nibble($registerA.text);
|
||||
byte regB = parseRegister_nibble($registerB.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB,
|
||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
||||
$method::methodBuilder.addInstruction22c(opcode, regA, regB,
|
||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type));
|
||||
};
|
||||
|
||||
insn_format22s[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format22s
|
||||
: //e.g. add-int/lit16 v0, v1, 12345
|
||||
^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
|
||||
{
|
||||
@ -1059,27 +939,21 @@ insn_format22s[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
|
||||
short litC = $short_integral_literal.value;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction22s(opcode, regA, regB, litC));
|
||||
$method::methodBuilder.addInstruction22s(opcode, regA, regB, litC);
|
||||
};
|
||||
|
||||
insn_format22t[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format22t
|
||||
: //e.g. if-eq v0, v1, endloop:
|
||||
^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER relative_label)
|
||||
^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER label_ref)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22t.text);
|
||||
byte regA = parseRegister_nibble($registerA.text);
|
||||
byte regB = parseRegister_nibble($registerB.text);
|
||||
|
||||
int addressOffset = $relative_label.offsetValue;
|
||||
|
||||
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
||||
throw new SemanticException(input, $relative_label.start, "The label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||
}
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction22t(opcode, regA, regB, addressOffset));
|
||||
$method::methodBuilder.addInstruction22t(opcode, regA, regB, $label_ref.label);
|
||||
};
|
||||
|
||||
insn_format22x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format22x
|
||||
: //e.g. move/from16 v1, v1234
|
||||
^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
|
||||
{
|
||||
@ -1087,10 +961,10 @@ insn_format22x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
short regA = parseRegister_byte($registerA.text);
|
||||
int regB = parseRegister_short($registerB.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction22x(opcode, regA, regB));
|
||||
$method::methodBuilder.addInstruction22x(opcode, regA, regB);
|
||||
};
|
||||
|
||||
insn_format23x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format23x
|
||||
: //e.g. add-int v1, v2, v3
|
||||
^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
|
||||
{
|
||||
@ -1099,32 +973,30 @@ insn_format23x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
short regB = parseRegister_byte($registerB.text);
|
||||
short regC = parseRegister_byte($registerC.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction23x(opcode, regA, regB, regC));
|
||||
$method::methodBuilder.addInstruction23x(opcode, regA, regB, regC);
|
||||
};
|
||||
|
||||
insn_format30t[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format30t
|
||||
: //e.g. goto/32 endloop:
|
||||
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t relative_label)
|
||||
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT30t.text);
|
||||
|
||||
int addressOffset = $relative_label.offsetValue;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction30t(opcode, addressOffset));
|
||||
$method::methodBuilder.addInstruction30t(opcode, $label_ref.label);
|
||||
};
|
||||
|
||||
insn_format31c[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format31c
|
||||
: //e.g. const-string/jumbo v1 "Hello World!"
|
||||
^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
|
||||
short regA = parseRegister_byte($REGISTER.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction31c(opcode, regA,
|
||||
dexBuilder.internStringReference($string_literal.value)));
|
||||
$method::methodBuilder.addInstruction31c(opcode, regA,
|
||||
dexBuilder.internStringReference($string_literal.value));
|
||||
};
|
||||
|
||||
insn_format31i[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format31i
|
||||
: //e.g. const v0, 123456
|
||||
^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
||||
{
|
||||
@ -1133,26 +1005,21 @@ insn_format31i[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
|
||||
int litB = $fixed_32bit_literal.value;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction31i(opcode, regA, litB));
|
||||
$method::methodBuilder.addInstruction31i(opcode, regA, litB);
|
||||
};
|
||||
|
||||
insn_format31t[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format31t
|
||||
: //e.g. fill-array-data v0, ArrayData:
|
||||
^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER relative_label)
|
||||
^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER label_ref)
|
||||
{
|
||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31t.text);
|
||||
|
||||
short regA = parseRegister_byte($REGISTER.text);
|
||||
|
||||
int addressOffset = $relative_label.offsetValue;
|
||||
if (($method::currentAddress + addressOffset) \% 2 != 0) {
|
||||
addressOffset++;
|
||||
}
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction31t(opcode, regA, addressOffset));
|
||||
$method::methodBuilder.addInstruction31t(opcode, regA, $label_ref.label);
|
||||
};
|
||||
|
||||
insn_format32x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format32x
|
||||
: //e.g. move/16 v5678, v1234
|
||||
^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
|
||||
{
|
||||
@ -1160,10 +1027,10 @@ insn_format32x[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
int regA = parseRegister_short($registerA.text);
|
||||
int regB = parseRegister_short($registerB.text);
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction32x(opcode, regA, regB));
|
||||
$method::methodBuilder.addInstruction32x(opcode, regA, regB);
|
||||
};
|
||||
|
||||
insn_format35c_method[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format35c_method
|
||||
: //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
|
||||
^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method)
|
||||
{
|
||||
@ -1172,15 +1039,14 @@ insn_format35c_method[List<BuilderInstruction> instructions] returns[int outRegi
|
||||
//this depends on the fact that register_list returns a byte[5]
|
||||
byte[] registers = $register_list.registers;
|
||||
byte registerCount = $register_list.registerCount;
|
||||
$outRegisters = registerCount;
|
||||
|
||||
ImmutableMethodReference methodReference = $fully_qualified_method.methodReference;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1],
|
||||
registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference)));
|
||||
$method::methodBuilder.addInstruction35c(opcode, registerCount, registers[0], registers[1],
|
||||
registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference));
|
||||
};
|
||||
|
||||
insn_format35c_type[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format35c_type
|
||||
: //e.g. filled-new-array {v0,v1}, I
|
||||
^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor)
|
||||
{
|
||||
@ -1189,13 +1055,12 @@ insn_format35c_type[List<BuilderInstruction> instructions] returns[int outRegist
|
||||
//this depends on the fact that register_list returns a byte[5]
|
||||
byte[] registers = $register_list.registers;
|
||||
byte registerCount = $register_list.registerCount;
|
||||
$outRegisters = registerCount;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1],
|
||||
registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
||||
$method::methodBuilder.addInstruction35c(opcode, registerCount, registers[0], registers[1],
|
||||
registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type));
|
||||
};
|
||||
|
||||
insn_format3rc_method[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format3rc_method
|
||||
: //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 fully_qualified_method)
|
||||
{
|
||||
@ -1204,15 +1069,14 @@ insn_format3rc_method[List<BuilderInstruction> instructions] returns[int outRegi
|
||||
int endRegister = $register_range.endRegister;
|
||||
|
||||
int registerCount = endRegister-startRegister+1;
|
||||
$outRegisters = registerCount;
|
||||
|
||||
ImmutableMethodReference methodReference = $fully_qualified_method.methodReference;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount,
|
||||
dexBuilder.internMethodReference(methodReference)));
|
||||
$method::methodBuilder.addInstruction3rc(opcode, startRegister, registerCount,
|
||||
dexBuilder.internMethodReference(methodReference));
|
||||
};
|
||||
|
||||
insn_format3rc_type[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format3rc_type
|
||||
: //e.g. filled-new-array/range {v0..v6} I
|
||||
^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor)
|
||||
{
|
||||
@ -1221,13 +1085,12 @@ insn_format3rc_type[List<BuilderInstruction> instructions] returns[int outRegist
|
||||
int endRegister = $register_range.endRegister;
|
||||
|
||||
int registerCount = endRegister-startRegister+1;
|
||||
$outRegisters = registerCount;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount,
|
||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
||||
$method::methodBuilder.addInstruction3rc(opcode, startRegister, registerCount,
|
||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type));
|
||||
};
|
||||
|
||||
insn_format51l_type[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_format51l_type
|
||||
: //e.g. const-wide v0, 5000000000L
|
||||
^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
|
||||
{
|
||||
@ -1236,45 +1099,32 @@ insn_format51l_type[List<BuilderInstruction> instructions] returns[int outRegist
|
||||
|
||||
long litB = $fixed_64bit_literal.value;
|
||||
|
||||
$instructions.add(instructionFactory.makeInstruction51l(opcode, regA, litB));
|
||||
$method::methodBuilder.addInstruction51l(opcode, regA, litB);
|
||||
};
|
||||
|
||||
insn_array_data_directive[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_array_data_directive
|
||||
: //e.g. .array-data 4 1000000 .end array-data
|
||||
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
|
||||
{
|
||||
int elementWidth = $short_integral_literal.value;
|
||||
List<Number> elements = $array_elements.elements;
|
||||
|
||||
$instructions.add(instructionFactory.makeArrayPayload(elementWidth, $array_elements.elements));
|
||||
$method::methodBuilder.addArrayPayload(elementWidth, $array_elements.elements);
|
||||
};
|
||||
|
||||
insn_packed_switch_directive[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_packed_switch_directive
|
||||
:
|
||||
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal)
|
||||
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) packed_switch_elements)
|
||||
{
|
||||
int startKey = $fixed_32bit_literal.value;
|
||||
Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress);
|
||||
if (baseAddress == null) {
|
||||
baseAddress = 0;
|
||||
}
|
||||
}
|
||||
packed_switch_elements[baseAddress, startKey])
|
||||
{
|
||||
$instructions.add(instructionFactory.makePackedSwitchPayload($packed_switch_elements.elements));
|
||||
$method::methodBuilder.addPackedSwitchPayload(startKey, $packed_switch_elements.elements);
|
||||
};
|
||||
|
||||
insn_sparse_switch_directive[List<BuilderInstruction> instructions] returns[int outRegisters]
|
||||
insn_sparse_switch_directive
|
||||
:
|
||||
^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements)
|
||||
{
|
||||
Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress);
|
||||
if (baseAddress == null) {
|
||||
baseAddress = 0;
|
||||
}
|
||||
}
|
||||
^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements[baseAddress])
|
||||
{
|
||||
$instructions.add(instructionFactory.makeSparseSwitchPayload($sparse_switch_elements.elements));
|
||||
$method::methodBuilder.addSparseSwitchPayload($sparse_switch_elements.elements);
|
||||
};
|
||||
|
||||
nonvoid_type_descriptor returns [String type]
|
||||
@ -1285,7 +1135,6 @@ nonvoid_type_descriptor returns [String type]
|
||||
$type = $start.getText();
|
||||
};
|
||||
|
||||
|
||||
reference_type_descriptor returns [String type]
|
||||
: (CLASS_DESCRIPTOR
|
||||
| ARRAY_DESCRIPTOR)
|
||||
|
Loading…
x
Reference in New Issue
Block a user