From e170edc52c31af54d1f5e366a4b22cf22f78d688 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Sat, 18 Apr 2009 05:53:05 +0000 Subject: [PATCH] Added support for opcodes using format 12x git-svn-id: https://smali.googlecode.com/svn/trunk@7 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- src/main/antlr3/org/JesusFreke/smali/smali.g | 136 +++++++++++++----- .../org/JesusFreke/smali/smaliTreeWalker.g | 12 +- .../dexlib/code/Format/Format12x.java | 69 +++++++++ src/test/resources/examples/HelloWorld2.smali | 4 +- 4 files changed, 183 insertions(+), 38 deletions(-) create mode 100644 src/main/java/org/JesusFreke/dexlib/code/Format/Format12x.java diff --git a/src/main/antlr3/org/JesusFreke/smali/smali.g b/src/main/antlr3/org/JesusFreke/smali/smali.g index 2c6c5b27..1a081e35 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smali.g +++ b/src/main/antlr3/org/JesusFreke/smali/smali.g @@ -93,14 +93,15 @@ tokens { I_METHOD_RETURN_TYPE; I_REGISTERS; I_STATEMENTS; - I_STATEMENT_FORMAT35c_METHOD; - I_STATEMENT_FORMAT3rc_METHOD; I_STATEMENT_FORMAT10x; I_STATEMENT_FORMAT11x; + I_STATEMENT_FORMAT12x; I_STATEMENT_FORMAT21c_TYPE; I_STATEMENT_FORMAT21c_FIELD; I_STATEMENT_FORMAT22c_FIELD; I_STATEMENT_FORMAT21c_STRING; + I_STATEMENT_FORMAT35c_METHOD; + I_STATEMENT_FORMAT3rc_METHOD; I_REGISTER_RANGE; I_REGISTER_LIST; } @@ -230,7 +231,10 @@ instruction -> ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_NAME_FORMAT10x) | //e.g. move-result-object v1 INSTRUCTION_NAME_FORMAT11x REGISTER - -> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_NAME_FORMAT11x REGISTER) + -> ^(I_STATEMENT_FORMAT11x[$start, "I_STATEMENT_FORMAT11x"] INSTRUCTION_NAME_FORMAT11x REGISTER) + | //e.g. move v1 v2 + INSTRUCTION_NAME_FORMAT12x REGISTER REGISTER + -> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] INSTRUCTION_NAME_FORMAT12x REGISTER REGISTER) | //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream; INSTRUCTION_NAME_FORMAT21c_FIELD REGISTER full_field_name_and_type -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_NAME_FORMAT21c_FIELD REGISTER full_field_name_and_type) @@ -280,6 +284,7 @@ simple_name instruction_name : INSTRUCTION_NAME_FORMAT10x | INSTRUCTION_NAME_FORMAT11x + | INSTRUCTION_NAME_FORMAT12x | INSTRUCTION_NAME_FORMAT21c_FIELD | INSTRUCTION_NAME_FORMAT21c_STRING | INSTRUCTION_NAME_FORMAT21c_TYPE @@ -330,39 +335,6 @@ double_literal ACCESS_SPEC : 'public' | 'private' | 'static' | 'constructor' | 'final'; -INSTRUCTION_NAME_FORMAT35c_METHOD - : 'invoke-virtual' - | 'invoke-super' - | 'invoke-direct' - | 'invoke-static' - | 'invoke-interface' - ; - -INSTRUCTION_NAME_FORMAT3rc_METHOD - : 'invoke-virtual/range' - | 'invoke-super/range' - | 'invoke-direct/range' - | 'invoke-static/range' - | 'invoke-interface/range' - ; - -INSTRUCTION_NAME_FORMAT22c_FIELD - : 'iget' - | 'iget-wide' - | 'iget-object' - | 'iget-boolean' - | 'iget-byte' - | 'iget-char' - | 'iget-short' - | 'iput' - | 'iput-wide' - | 'iput-object' - | 'iput-boolean' - | 'iput-byte' - | 'iput-char' - | 'iput-short' - ; - INSTRUCTION_NAME_FORMAT10x : 'return-void' | 'nop'; @@ -379,6 +351,65 @@ INSTRUCTION_NAME_FORMAT11x | 'monitor-exit' | 'throw'; +INSTRUCTION_NAME_FORMAT12x + : 'move' + | 'move-wide' + | 'move-object' + | 'array-length' + | 'neg-int' + | 'not-int' + | 'neg-long' + | 'not-long' + | 'neg-float' + | 'neg-double' + | 'int-to-long' + | 'int-to-float' + | 'int-to-double' + | 'long-to-int' + | 'long-to-float' + | 'long-to-double' + | 'float-to-int' + | 'float-to-long' + | 'float-to-double' + | 'double-to-int' + | 'double-to-long' + | 'double-to-float' + | 'int-to-byte' + | 'int-to-char' + | 'int-to-short' + | 'add-int/2addr' + | 'sub-int/2addr' + | 'mul-int/2addr' + | 'div-int/2addr' + | 'rem-int/2addr' + | 'and-int/2addr' + | 'or-int/2addr' + | 'xor-int/2addr' + | 'shl-int/2addr' + | 'shr-int/2addr' + | 'ushr-int/2addr' + | 'add-long/2addr' + | 'sub-long/2addr' + | 'mul-long/2addr' + | 'div-long/2addr' + | 'rem-long/2addr' + | 'and-long/2addr' + | 'or-long/2addr' + | 'xor-long/2addr' + | 'shl-long/2addr' + | 'shr-long/2addr' + | 'ushr-long/2addr' + | 'add-float/2addr' + | 'sub-float/2addr' + | 'mul-float/2addr' + | 'div-float/2addr' + | 'rem-float/2addr' + | 'add-double/2addr' + | 'sub-double/2addr' + | 'mul-double/2addr' + | 'div-double/2addr' + | 'rem-double/2addr'; + INSTRUCTION_NAME_FORMAT21c_FIELD : 'sget' | 'sget-wide' @@ -403,6 +434,39 @@ INSTRUCTION_NAME_FORMAT21c_TYPE : 'check-cast' | 'new-instance' | 'const-class'; + +INSTRUCTION_NAME_FORMAT22c_FIELD + : 'iget' + | 'iget-wide' + | 'iget-object' + | 'iget-boolean' + | 'iget-byte' + | 'iget-char' + | 'iget-short' + | 'iput' + | 'iput-wide' + | 'iput-object' + | 'iput-boolean' + | 'iput-byte' + | 'iput-char' + | 'iput-short' + ; + +INSTRUCTION_NAME_FORMAT35c_METHOD + : 'invoke-virtual' + | 'invoke-super' + | 'invoke-direct' + | 'invoke-static' + | 'invoke-interface' + ; + +INSTRUCTION_NAME_FORMAT3rc_METHOD + : 'invoke-virtual/range' + | 'invoke-super/range' + | 'invoke-direct/range' + | 'invoke-static/range' + | 'invoke-interface/range' + ; /*since SIMPLE_NAME is so all-encompassing, it includes all integer literals and a subset of the possible floating point literals. For floating point diff --git a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g index f572a11f..76ab1f7e 100644 --- a/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g +++ b/src/main/antlr3/org/JesusFreke/smali/smaliTreeWalker.g @@ -261,7 +261,16 @@ instruction returns[Instruction instruction] short regA = parseRegister_byte($REGISTER.text); $instruction = Format11x.Format.make(dexFile, opcode.value, regA); - } + } + | //e.g. move v1 v2 + ^(I_STATEMENT_FORMAT12x INSTRUCTION_NAME_FORMAT12x registerA=REGISTER registerB=REGISTER) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_NAME_FORMAT12x.text); + byte regA = parseRegister_nibble($registerA.text); + byte regB = parseRegister_nibble($registerB.text); + + $instruction = Format12x.Format.make(dexFile, opcode.value, regA, regB); + } | //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream; ^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_NAME_FORMAT21c_FIELD REGISTER full_field_name_and_type) { @@ -384,6 +393,7 @@ simple_name instruction_name returns[String value] : INSTRUCTION_NAME_FORMAT10x | INSTRUCTION_NAME_FORMAT11x + | INSTRUCTION_NAME_FORMAT12x | INSTRUCTION_NAME_FORMAT21c_FIELD | INSTRUCTION_NAME_FORMAT21c_STRING | INSTRUCTION_NAME_FORMAT21c_TYPE diff --git a/src/main/java/org/JesusFreke/dexlib/code/Format/Format12x.java b/src/main/java/org/JesusFreke/dexlib/code/Format/Format12x.java new file mode 100644 index 00000000..053799fa --- /dev/null +++ b/src/main/java/org/JesusFreke/dexlib/code/Format/Format12x.java @@ -0,0 +1,69 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2009 Ben Gruver + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.JesusFreke.dexlib.code.Format; + +import org.JesusFreke.dexlib.code.Instruction; +import org.JesusFreke.dexlib.code.Opcode; +import org.JesusFreke.dexlib.DexFile; + +public class Format12x extends Format +{ + public static final Format12x Format = new Format12x(); + + private Format12x() { + } + + public Instruction make(DexFile dexFile, byte opcode, byte regA, byte regB) { + byte[] bytes = new byte[2]; + + Opcode op = Opcode.getOpcodeByValue(opcode); + + checkOpcodeFormat(op); + + if (regA >= 1<<4 || + regB >= 1<<4) { + throw new RuntimeException("The register number must be less than v16"); + } + + bytes[0] = opcode; + bytes[1] = (byte)((regB << 4) | regA); + + return new Instruction(dexFile, bytes, null); + } + + public int getByteCount() + { + return 2; + } + + public String getFormatName() + { + return "12x"; + } +} diff --git a/src/test/resources/examples/HelloWorld2.smali b/src/test/resources/examples/HelloWorld2.smali index 09a9a26e..82c8e7c2 100644 --- a/src/test/resources/examples/HelloWorld2.smali +++ b/src/test/resources/examples/HelloWorld2.smali @@ -86,12 +86,14 @@ invoke-virtual/range {v1 .. v2} java/lang/String.concat(Ljava/lang/String;)Ljava/lang/String; move-result-object v1 + move-object v2 v1 + check-cast v4 Landroid/app/Activity; - invoke-virtual {v0,v1} android/widget/TextView.setText(Ljava/lang/CharSequence;)V + invoke-virtual {v0,v2} android/widget/TextView.setText(Ljava/lang/CharSequence;)V invoke-virtual {v4,v0} org/JesusFreke/HelloWorld2/HelloWorld2.setContentView(Landroid/view/View;)V return-void