From 2fb16c8f4b39092ca21034c31cd78410bf73b007 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Tue, 16 Jun 2009 03:31:44 +0000 Subject: [PATCH] Fixed an issue with alignment for the pseudo opcodes, and a test to exercise the issue git-svn-id: https://smali.googlecode.com/svn/trunk@153 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- .../Format/ArrayDataPseudoInstruction.java | 16 +++- .../PackedSwitchDataPseudoInstruction.java | 15 +++- .../SparseSwitchDataPseudoInstruction.java | 14 ++++ .../SpecialInstructionPaddingTest.smali | 75 +++++++++++++++++++ .../antlr3/org/jf/smali/smaliTreeWalker.g | 2 +- 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/dexlib/src/main/java/org/jf/dexlib/code/Format/ArrayDataPseudoInstruction.java b/dexlib/src/main/java/org/jf/dexlib/code/Format/ArrayDataPseudoInstruction.java index 55f965b7..3a521483 100644 --- a/dexlib/src/main/java/org/jf/dexlib/code/Format/ArrayDataPseudoInstruction.java +++ b/dexlib/src/main/java/org/jf/dexlib/code/Format/ArrayDataPseudoInstruction.java @@ -39,8 +39,14 @@ import java.util.ArrayList; public class ArrayDataPseudoInstruction extends Instruction { + private int elementWidth; + private List values; + public ArrayDataPseudoInstruction(DexFile dexFile, int elementWidth, List values) { super(dexFile, Opcode.NOP, (IndexedItem)null); + + this.elementWidth = elementWidth; + this.values = values; int byteCount = 0; @@ -88,7 +94,7 @@ public class ArrayDataPseudoInstruction extends Instruction throw new RuntimeException("Invalid opcode byte for an ArrayData pseudo-instruction"); } byte subopcodeByte = input.readByte(); - if (subopcodeByte != 0x02) { + if (subopcodeByte != 0x03) { throw new RuntimeException("Invalid sub-opcode byte for an ArrayData pseudo-instruction"); } @@ -111,4 +117,12 @@ public class ArrayDataPseudoInstruction extends Instruction protected Instruction makeClone() { return new ArrayDataPseudoInstruction(); } + + public int getElementWidth() { + return elementWidth; + } + + public List getValues() { + return values; + } } diff --git a/dexlib/src/main/java/org/jf/dexlib/code/Format/PackedSwitchDataPseudoInstruction.java b/dexlib/src/main/java/org/jf/dexlib/code/Format/PackedSwitchDataPseudoInstruction.java index 8dfea3b6..35abc497 100644 --- a/dexlib/src/main/java/org/jf/dexlib/code/Format/PackedSwitchDataPseudoInstruction.java +++ b/dexlib/src/main/java/org/jf/dexlib/code/Format/PackedSwitchDataPseudoInstruction.java @@ -36,8 +36,13 @@ import org.jf.dexlib.util.Input; public class PackedSwitchDataPseudoInstruction extends Instruction { + private int firstKey; + private int[] targets; + public PackedSwitchDataPseudoInstruction(DexFile dexFile, int firstKey, int[] targets) { super(dexFile, Opcode.NOP, (IndexedItem)null); + this.firstKey = firstKey; + this.targets = targets; if (targets.length > 0xFFFF) { throw new RuntimeException("The packed-switch data contains too many elements. " + @@ -100,6 +105,14 @@ public class PackedSwitchDataPseudoInstruction extends Instruction } public Format getFormat() { - return Format.SparseSwitchData; + return Format.PackedSwitchData; + } + + public int getFirstKey() { + return firstKey; + } + + public int[] getTargets() { + return targets; } } diff --git a/dexlib/src/main/java/org/jf/dexlib/code/Format/SparseSwitchDataPseudoInstruction.java b/dexlib/src/main/java/org/jf/dexlib/code/Format/SparseSwitchDataPseudoInstruction.java index 0fd6beba..03b79347 100644 --- a/dexlib/src/main/java/org/jf/dexlib/code/Format/SparseSwitchDataPseudoInstruction.java +++ b/dexlib/src/main/java/org/jf/dexlib/code/Format/SparseSwitchDataPseudoInstruction.java @@ -36,9 +36,15 @@ import org.jf.dexlib.util.Input; public class SparseSwitchDataPseudoInstruction extends Instruction { + private int[] keys; + private int[] targets; + public SparseSwitchDataPseudoInstruction(DexFile dexFile, int[] keys, int[] targets) { super(dexFile, Opcode.NOP, (IndexedItem)null); + this.keys = keys; + this.targets = targets; + if (keys.length != targets.length) { throw new RuntimeException("The number of keys and offsets don't match"); } @@ -130,4 +136,12 @@ public class SparseSwitchDataPseudoInstruction extends Instruction public Format getFormat() { return Format.SparseSwitchData; } + + public int[] getKeys() { + return keys; + } + + public int[] getTargets() { + return targets; + } } diff --git a/smali-integration-tests/src/test/smali/junit-tests/SpecialInstructionPaddingTest/SpecialInstructionPaddingTest.smali b/smali-integration-tests/src/test/smali/junit-tests/SpecialInstructionPaddingTest/SpecialInstructionPaddingTest.smali index 1291cb9f..fd50c7bf 100644 --- a/smali-integration-tests/src/test/smali/junit-tests/SpecialInstructionPaddingTest/SpecialInstructionPaddingTest.smali +++ b/smali-integration-tests/src/test/smali/junit-tests/SpecialInstructionPaddingTest/SpecialInstructionPaddingTest.smali @@ -63,4 +63,79 @@ PackedSwitch: Label12: Label13: .end packed-switch +.end method + + + +.method public test2()V + .registers 2 + .annotation runtime Lorg/junit/Test; + .end annotation + + const v0, 0 + invoke-static {}, LSpecialInstructionPaddingTest;->paddingTest()I + move-result v0 + + + + const/16 v1, 12 + + #the real test is that dalvik loaded and verified this class. This is + #mostly just to make sure that the method was actually called + invoke-static {v0, v1}, LAssert;->assertEquals(II)V + + return-void +.end method + +.method public static paddingTest()I + .registers 2 + + const v0, 12 + + packed-switch v0, PackedSwitch: + + packed-switch v0, PackedSwitch2: + +Label10: + const v1, 10 + return v1 + +Label11: + const v1, 11 + return v1 + +Label12: + const v1, 12 + return v1 + +Label13: + const v1, 13 + return v1 + +PackedSwitch: + .packed-switch 10 + Label10: + Label11: + Label12: + Label13: + .end packed-switch + + #this tests out an issue that occured where the prior packed switch data starts at a byte offset + #that is 4 byte aligned but isn't 8 byte aligned, which caused the code to report the size of the + #instruction to be 2 bytes more than it should be. + # + #Normally, if things are working correctly, this nop will cause the following packed-switch data + #to be unaligned. But with the above issue, the logic will *think* that the packed switch data + #is aligned, and won't output the extra nop to align it, thus causing a verification error. + nop + +PackedSwitch2: + .packed-switch 10 + Label10: + Label11: + Label12: + Label13: + .end packed-switch + + .end method \ No newline at end of file diff --git a/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g b/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g index 746dab52..4e52d20f 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g @@ -686,7 +686,7 @@ statements[int totalMethodRegisters, int methodParameterRegisters] returns[Array { if ($instruction.instruction != null) { $instructions.add($instruction.instruction); - $method::currentAddress += $instruction.instruction.getSize($method::currentAddress) / 2; + $method::currentAddress += $instruction.instruction.getSize($method::currentAddress * 2) / 2; } })*);