From c8de336727bfe8e56998332fe97ad5c0e32e50fa Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 19 Nov 2011 14:57:59 -0800 Subject: [PATCH] Use Format 35c for invoke-direct-empty, and get rid of Format 35s --- .../Format/InstructionMethodItem.java | 1 - .../dexlib/Code/Analysis/MethodAnalyzer.java | 2 +- .../org/jf/dexlib/Code/Format/Format.java | 1 - .../jf/dexlib/Code/Format/Instruction35c.java | 15 +- .../jf/dexlib/Code/Format/Instruction35s.java | 160 ------------------ .../main/java/org/jf/dexlib/Code/Opcode.java | 2 +- .../src/main/antlr3/org/jf/smali/smaliLexer.g | 6 +- .../main/antlr3/org/jf/smali/smaliParser.g | 6 +- smali/src/main/jflex/smaliLexer.flex | 8 +- .../LexerTest/InstructionTest.tokens | 2 +- 10 files changed, 21 insertions(+), 182 deletions(-) delete mode 100644 dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35s.java diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java index f852a03d..b783c8bd 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java @@ -181,7 +181,6 @@ public class InstructionMethodItem extends MethodItem { writeThirdRegister(writer); return true; case Format35c: - case Format35s: writeOpcode(writer); writer.write(' '); writeInvokeRegisters(writer); diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java index 5a79b9e0..1b13d22a 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java @@ -3463,7 +3463,7 @@ public class MethodAnalyzer { } private void analyzeInvokeDirectEmpty(AnalyzedInstruction analyzedInstruction) { - Instruction35s instruction = (Instruction35s)analyzedInstruction.instruction; + Instruction35c instruction = (Instruction35c)analyzedInstruction.instruction; Instruction35c deodexedInstruction = new Instruction35c(Opcode.INVOKE_DIRECT, instruction.getRegCount(), instruction.getRegisterD(), instruction.getRegisterE(), instruction.getRegisterF(), diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java index 030570d6..a6064054 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java @@ -55,7 +55,6 @@ public enum Format { Format31t(Instruction31t.Factory, 6), Format32x(Instruction32x.Factory, 6), Format35c(Instruction35c.Factory, 6), - Format35s(Instruction35s.Factory, 6), Format35mi(Instruction35mi.Factory, 6), Format35ms(Instruction35ms.Factory, 6), Format3rc(Instruction3rc.Factory, 6), diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java index 1fad2777..dfe69fec 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java @@ -66,23 +66,19 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi throw new RuntimeException("All register args must fit in 4 bits"); } + checkItem(opcode, referencedItem, regCount); + this.regCount = (byte)regCount; this.regA = regA; this.regD = regD; this.regE = regE; this.regF = regF; this.regG = regG; - - checkItem(opcode, referencedItem, regCount); } protected Instruction35c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { super(dexFile, opcode, buffer, bufferIndex); - if (getRegCount() > 5) { - throw new RuntimeException("regCount cannot be greater than 5"); - } - this.regCount = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]); this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]); this.regD = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]); @@ -90,6 +86,10 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi this.regF = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]); this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]); + if (getRegCount() > 5) { + throw new RuntimeException("regCount cannot be greater than 5"); + } + checkItem(opcode, getReferencedItem(), getRegCount()); } @@ -148,7 +148,8 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } - } else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value) { + } else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value || + opcode == INVOKE_DIRECT_EMPTY) { //check data for invoke-* opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35s.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35s.java deleted file mode 100644 index 562a0562..00000000 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35s.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * [The "BSD licence"] - * Copyright (c) 2010 Ben Gruver (JesusFreke) - * 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.jf.dexlib.Code.Format; - -import org.jf.dexlib.Code.FiveRegisterInstruction; -import org.jf.dexlib.Code.Instruction; -import org.jf.dexlib.Code.InstructionWithReference; -import org.jf.dexlib.Code.Opcode; -import org.jf.dexlib.DexFile; -import org.jf.dexlib.Item; -import org.jf.dexlib.MethodIdItem; -import org.jf.dexlib.TypeIdItem; -import org.jf.dexlib.Util.AnnotatedOutput; -import org.jf.dexlib.Util.NumberUtils; - -import static org.jf.dexlib.Code.Opcode.*; - -public class Instruction35s extends InstructionWithReference implements FiveRegisterInstruction { - public static final Instruction.InstructionFactory Factory = new Factory(); - private byte regCount; - private byte regA; - private byte regD; - private byte regE; - private byte regF; - private byte regG; - - public Instruction35s(Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG, - byte regA, Item referencedItem) { - super(opcode, referencedItem); - - if (regCount > 5) { - throw new RuntimeException("regCount cannot be greater than 5"); - } - - if (regD >= 1 << 4 || - regE >= 1 << 4 || - regF >= 1 << 4 || - regG >= 1 << 4 || - regA >= 1 << 4) { - throw new RuntimeException("All register args must fit in 4 bits"); - } - - checkItem(opcode, referencedItem, regCount); - - this.regCount = (byte)regCount; - this.regA = regA; - this.regD = regD; - this.regE = regE; - this.regF = regF; - this.regG = regG; - } - - protected Instruction35s(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { - super(dexFile, opcode, buffer, bufferIndex); - - if (getRegCount() > 5) { - throw new RuntimeException("regCount cannot be greater than 5"); - } - - checkItem(opcode, getReferencedItem(), getRegCount()); - - this.regCount = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]); - this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]); - this.regD = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]); - this.regE = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 4]); - this.regF = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]); - this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]); - } - - protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) { - out.writeByte(opcode.value); - out.writeByte((regCount << 4) | regA); - out.writeShort(getReferencedItem().getIndex()); - out.writeByte((regE << 4) | regD); - out.writeByte((regG << 4) | regF); - } - - public Format getFormat() { - return Format.Format35s; - } - - public int getRegCount() { - return regCount; - } - - public byte getRegisterA() { - return regA; - } - - public byte getRegisterD() { - return regD; - } - - public byte getRegisterE() { - return regE; - } - - public byte getRegisterF() { - return regF; - } - - public byte getRegisterG() { - return regG; - } - - private static void checkItem(Opcode opcode, Item item, int regCount) { - if (opcode == FILLED_NEW_ARRAY) { - //check data for filled-new-array opcode - String type = ((TypeIdItem) item).getTypeDescriptor(); - if (type.charAt(0) != '[') { - throw new RuntimeException("The type must be an array type"); - } - if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { - throw new RuntimeException("The type cannot be an array of longs or doubles"); - } - } else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value) { - //check data for invoke-* opcodes - MethodIdItem methodIdItem = (MethodIdItem) item; - int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); - if (opcode != INVOKE_STATIC) { - parameterRegisterCount++; - } - if (parameterRegisterCount != regCount) { - throw new RuntimeException("regCount does not match the number of arguments of the method"); - } - } - } - - private static class Factory implements Instruction.InstructionFactory { - public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { - return new Instruction35s(dexFile, opcode, buffer, bufferIndex); - } - } -} diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java index 93bbdb7c..7cc2d784 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java @@ -266,7 +266,7 @@ public enum Opcode THROW_VERIFICATION_ERROR((short)0xed, "throw-verification-error", ReferenceType.none, Format.Format20bc, Opcode.ODEX_ONLY | Opcode.CAN_THROW), EXECUTE_INLINE((short)0xee, "execute-inline", ReferenceType.none, Format.Format35mi, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), EXECUTE_INLINE_RANGE((short)0xef, "execute-inline/range", ReferenceType.none, Format.Format3rmi, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_DIRECT_EMPTY((short)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35s, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_DIRECT_EMPTY((short)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35c, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_OBJECT_INIT_RANGE((short)0xf0, "invoke-object-init/range", ReferenceType.method, Format.Format3rc, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), IGET_QUICK((short)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), IGET_WIDE_QUICK((short)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), diff --git a/smali/src/main/antlr3/org/jf/smali/smaliLexer.g b/smali/src/main/antlr3/org/jf/smali/smaliLexer.g index d1984b1d..8cb499c2 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliLexer.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliLexer.g @@ -660,12 +660,12 @@ INSTRUCTION_FORMAT35c_METHOD | 'invoke-static' | 'invoke-interface'; +INSTRUCTION_FORMAT35c_METHOD_ODEX + : 'invoke-direct-empty'; + INSTRUCTION_FORMAT35c_TYPE : 'filled-new-array'; -INSTRUCTION_FORMAT35s_METHOD - : 'invoke-direct-empty'; - INSTRUCTION_FORMAT35mi_METHOD : 'execute-inline'; diff --git a/smali/src/main/antlr3/org/jf/smali/smaliParser.g b/smali/src/main/antlr3/org/jf/smali/smaliParser.g index 3dc77e85..0eb834d1 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliParser.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliParser.g @@ -463,8 +463,8 @@ simple_name | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID] | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t] | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] + | INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX] | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] - | INSTRUCTION_FORMAT35s_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35s_METHOD] | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l]; @@ -810,9 +810,9 @@ instruction returns [int size] INSTRUCTION_FORMAT35c_TYPE OPEN_BRACE register_list CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format35c.size;} -> ^(I_STATEMENT_FORMAT35c_TYPE[$start, "I_STATEMENT_FORMAT35c_TYPE"] INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor) | //e.g. invoke-direct {p0}, Ljava/lang/Object;->()V - INSTRUCTION_FORMAT35s_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method + INSTRUCTION_FORMAT35c_METHOD_ODEX OPEN_BRACE register_list CLOSE_BRACE COMMA fully_qualified_method { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35s_METHOD.text); + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT35c_METHOD_ODEX.text); } | //e.g. execute-inline {v0, v1}, inline@0x4 INSTRUCTION_FORMAT35mi_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA INLINE_INDEX diff --git a/smali/src/main/jflex/smaliLexer.flex b/smali/src/main/jflex/smaliLexer.flex index ff72c3c1..79323de2 100644 --- a/smali/src/main/jflex/smaliLexer.flex +++ b/smali/src/main/jflex/smaliLexer.flex @@ -529,12 +529,12 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} return newToken(INSTRUCTION_FORMAT35c_METHOD); } - "filled-new-array" { - return newToken(INSTRUCTION_FORMAT35c_TYPE); + "invoke-direct-empty" { + return newToken(INSTRUCTION_FORMAT35c_METHOD_ODEX); } - "invoke-direct-empty" { - return newToken(INSTRUCTION_FORMAT35s_METHOD); + "filled-new-array" { + return newToken(INSTRUCTION_FORMAT35c_TYPE); } "execute-inline" { diff --git a/smali/src/test/resources/LexerTest/InstructionTest.tokens b/smali/src/test/resources/LexerTest/InstructionTest.tokens index 7b4860c3..9c649895 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.tokens +++ b/smali/src/test/resources/LexerTest/InstructionTest.tokens @@ -209,7 +209,7 @@ INSTRUCTION_FORMAT35c_METHOD("invoke-direct") INSTRUCTION_FORMAT35c_METHOD("invoke-static") INSTRUCTION_FORMAT35c_METHOD("invoke-interface") INSTRUCTION_FORMAT35c_TYPE("filled-new-array") -INSTRUCTION_FORMAT35s_METHOD("invoke-direct-empty") +INSTRUCTION_FORMAT35c_METHOD_ODEX("invoke-direct-empty") INSTRUCTION_FORMAT3rc_METHOD_ODEX("invoke-object-init/range") INSTRUCTION_FORMAT20bc("throw-verification-error") INSTRUCTION_FORMAT35mi_METHOD("execute-inline")