mirror of
https://github.com/revanced/smali.git
synced 2025-05-15 05:37:05 +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
|
public class ArrayDataPseudoInstruction extends Instruction
|
||||||
{
|
{
|
||||||
|
private int elementWidth;
|
||||||
|
private List<byte[]> values;
|
||||||
|
|
||||||
public ArrayDataPseudoInstruction(DexFile dexFile, int elementWidth, List<byte[]> values) {
|
public ArrayDataPseudoInstruction(DexFile dexFile, int elementWidth, List<byte[]> values) {
|
||||||
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
||||||
|
|
||||||
|
this.elementWidth = elementWidth;
|
||||||
|
this.values = values;
|
||||||
|
|
||||||
int byteCount = 0;
|
int byteCount = 0;
|
||||||
|
|
||||||
@ -88,7 +94,7 @@ public class ArrayDataPseudoInstruction extends Instruction
|
|||||||
throw new RuntimeException("Invalid opcode byte for an ArrayData pseudo-instruction");
|
throw new RuntimeException("Invalid opcode byte for an ArrayData pseudo-instruction");
|
||||||
}
|
}
|
||||||
byte subopcodeByte = input.readByte();
|
byte subopcodeByte = input.readByte();
|
||||||
if (subopcodeByte != 0x02) {
|
if (subopcodeByte != 0x03) {
|
||||||
throw new RuntimeException("Invalid sub-opcode byte for an ArrayData pseudo-instruction");
|
throw new RuntimeException("Invalid sub-opcode byte for an ArrayData pseudo-instruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,4 +117,12 @@ public class ArrayDataPseudoInstruction extends Instruction
|
|||||||
protected Instruction makeClone() {
|
protected Instruction makeClone() {
|
||||||
return new ArrayDataPseudoInstruction();
|
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
|
public class PackedSwitchDataPseudoInstruction extends Instruction
|
||||||
{
|
{
|
||||||
|
private int firstKey;
|
||||||
|
private int[] targets;
|
||||||
|
|
||||||
public PackedSwitchDataPseudoInstruction(DexFile dexFile, int firstKey, int[] targets) {
|
public PackedSwitchDataPseudoInstruction(DexFile dexFile, int firstKey, int[] targets) {
|
||||||
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
||||||
|
this.firstKey = firstKey;
|
||||||
|
this.targets = targets;
|
||||||
|
|
||||||
if (targets.length > 0xFFFF) {
|
if (targets.length > 0xFFFF) {
|
||||||
throw new RuntimeException("The packed-switch data contains too many elements. " +
|
throw new RuntimeException("The packed-switch data contains too many elements. " +
|
||||||
@ -100,6 +105,14 @@ public class PackedSwitchDataPseudoInstruction extends Instruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Format getFormat() {
|
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
|
public class SparseSwitchDataPseudoInstruction extends Instruction
|
||||||
{
|
{
|
||||||
|
private int[] keys;
|
||||||
|
private int[] targets;
|
||||||
|
|
||||||
public SparseSwitchDataPseudoInstruction(DexFile dexFile, int[] keys, int[] targets) {
|
public SparseSwitchDataPseudoInstruction(DexFile dexFile, int[] keys, int[] targets) {
|
||||||
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
super(dexFile, Opcode.NOP, (IndexedItem)null);
|
||||||
|
|
||||||
|
this.keys = keys;
|
||||||
|
this.targets = targets;
|
||||||
|
|
||||||
if (keys.length != targets.length) {
|
if (keys.length != targets.length) {
|
||||||
throw new RuntimeException("The number of keys and offsets don't match");
|
throw new RuntimeException("The number of keys and offsets don't match");
|
||||||
}
|
}
|
||||||
@ -130,4 +136,12 @@ public class SparseSwitchDataPseudoInstruction extends Instruction
|
|||||||
public Format getFormat() {
|
public Format getFormat() {
|
||||||
return Format.SparseSwitchData;
|
return Format.SparseSwitchData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int[] getKeys() {
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getTargets() {
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,4 +63,79 @@ PackedSwitch:
|
|||||||
Label12:
|
Label12:
|
||||||
Label13:
|
Label13:
|
||||||
.end packed-switch
|
.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
|
.end method
|
@ -686,7 +686,7 @@ statements[int totalMethodRegisters, int methodParameterRegisters] returns[Array
|
|||||||
{
|
{
|
||||||
if ($instruction.instruction != null) {
|
if ($instruction.instruction != null) {
|
||||||
$instructions.add($instruction.instruction);
|
$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