diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g b/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g index ff08138e..d11805bb 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliLexer.g @@ -232,7 +232,7 @@ REGISTERS_PHRASE INSTRUCTION_FORMAT10t_PHRASE : INSTRUCTION_FORMAT10t_EMIT WS - LABEL_EMIT; + (LABEL_EMIT | OFFSET_EMIT); INSTRUCTION_FORMAT10x_PHRASE : INSTRUCTION_FORMAT10x_EMIT; @@ -306,6 +306,12 @@ INSTRUCTION_FORMAT3rc_METHOD_PHRASE FULLY_QUALIFIED_MEMBER_NAME_EMITCHILDREN METHOD_PROTOTYPE_EMITCHILDREN; + +fragment OFFSET_EMIT + : OFFSET {emit($OFFSET, OFFSET);}; +fragment OFFSET + : ('+' | '-') INTEGER_LITERAL; + fragment LABEL_EMIT : LABEL {emit($LABEL, LABEL);}; LABEL diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliParser.g b/src/main/antlr3/org/JesusFreke/smali/smaliParser.g index 9fca81ff..627d840f 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliParser.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliParser.g @@ -130,8 +130,9 @@ label instruction returns [int size] : //e.g. goto endloop: - INSTRUCTION_FORMAT10t LABEL {$size = Format10t.Format.getByteCount();} - -> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t LABEL) + //e.g. goto +3 + INSTRUCTION_FORMAT10t (LABEL | OFFSET){$size = Format10t.Format.getByteCount();} + -> ^(I_STATEMENT_FORMAT10t[$start, "I_STATEMENT_FORMAT10t"] INSTRUCTION_FORMAT10t LABEL? OFFSET?) | //e.g. return INSTRUCTION_FORMAT10x {$size = Format10x.Format.getByteCount();} -> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x) diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g index 4cf71dc9..079ee377 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g @@ -305,22 +305,38 @@ label returns[String labelName] String label = $LABEL.text; return label.substring(0, label.length()-1); }; - - -instruction returns[Instruction instruction] - : //e.g. goto endloop: - ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t label_ref) + +offset returns[int offsetValue] + : OFFSET + { + String offsetText = $OFFSET.text; + if (offsetText.startsWith("+")) { + offsetText = offsetText.substring(1); + } + $offsetValue = Integer.parseInt(offsetText); + }; + +offset_or_label returns[int offsetValue] + : offset {$offsetValue = $offset.offsetValue;} + | label_ref { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text); - int labelAddress = $label_ref.labelAddress; int currentAddress = $method::currentAddress; - int addressOffset = labelAddress - currentAddress; + $offsetValue = labelAddress-currentAddress; + }; + +instruction returns[Instruction instruction] + : //e.g. goto endloop: + ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text); + + int addressOffset = $offset_or_label.offsetValue; if (addressOffset < Byte.MIN_VALUE || addressOffset > Byte.MAX_VALUE) { //TODO: throw correct exception type - throw new RuntimeException("The offset to the given label is out of range. The offset is " + Integer.toString(addressOffset) + ". The range for this opcode is [-128, 127]."); + throw new RuntimeException("The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-128, 127]."); } $instruction = Format10t.Format.make(dexFile, opcode.value, (byte)addressOffset); diff --git a/src/test/resources/examples/HelloWorld2.smali b/src/test/resources/examples/HelloWorld2.smali index 3c78fb4a..7bce08f4 100644 --- a/src/test/resources/examples/HelloWorld2.smali +++ b/src/test/resources/examples/HelloWorld2.smali @@ -19,6 +19,7 @@ ;-8 ;7 ;But this should! +;But this should! .method static constructor ()V ;test @@ -145,6 +146,7 @@ + ;test format10t with a label goto SKIP: const-string v1, "This shouldn't be displayed!" @@ -159,6 +161,19 @@ move-result-object v2 + ;test format10t with an offset + goto +3 + + const-string v1, "This shouldn't be displayed!" + + const-string v1,"But this should!" + + invoke-virtual {v2, v1}, java/lang/String/concat(Ljava/lang/String;)Ljava/lang/String; + move-result-object v2 + + invoke-virtual {v2, v3}, java/lang/String/concat(Ljava/lang/String;)Ljava/lang/String; + move-result-object v2 + check-cast v4, Landroid/app/Activity;