mirror of
https://github.com/revanced/smali.git
synced 2025-05-12 04:14:27 +02:00
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
This commit is contained in:
parent
acf2ddb67e
commit
2fb16c8f4b
@ -39,8 +39,14 @@ import java.util.ArrayList;
|
||||
|
||||
public class ArrayDataPseudoInstruction extends Instruction
|
||||
{
|
||||
private int elementWidth;
|
||||
private List<byte[]> values;
|
||||
|
||||
public ArrayDataPseudoInstruction(DexFile dexFile, int elementWidth, List<byte[]> 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<byte[]> getValues() {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
})*);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user