From 1c084171edead45b68979fa8cc4e1439429569cf Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Wed, 18 Mar 2015 20:01:49 -0700 Subject: [PATCH] Duplicate a switch payload that is refered to multiple times --- .../Format/InstructionMethodItem.java | 29 +++-- .../baksmali/Adaptors/MethodDefinition.java | 75 +++++++++-- .../org/jf/baksmali/BaksmaliTestUtils.java | 64 +++++++--- .../java/org/jf/baksmali/DisassemblyTest.java | 104 +++++++++++++++ .../java/org/jf/baksmali/MultiSwitchTest.java | 42 +++++++ .../java/org/jf/baksmali/RoundtripTest.java | 23 +--- .../MultiSwitchTest/MultiSwitchInput.dex | Bin 0 -> 616 bytes .../MultiSwitchTest/MultiSwitchInput.smali | 72 +++++++++++ .../MultiSwitchTest/MultiSwitchOutput.smali | 119 ++++++++++++++++++ 9 files changed, 473 insertions(+), 55 deletions(-) create mode 100644 brut.apktool.smali/baksmali/src/test/java/org/jf/baksmali/DisassemblyTest.java create mode 100644 brut.apktool.smali/baksmali/src/test/java/org/jf/baksmali/MultiSwitchTest.java create mode 100644 brut.apktool.smali/baksmali/src/test/resources/MultiSwitchTest/MultiSwitchInput.dex create mode 100644 brut.apktool.smali/baksmali/src/test/resources/MultiSwitchTest/MultiSwitchInput.smali create mode 100644 brut.apktool.smali/baksmali/src/test/resources/MultiSwitchTest/MultiSwitchOutput.smali diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java index 7e080354..0950e326 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java @@ -130,26 +130,37 @@ public class InstructionMethodItem extends MethodItem { } if (instruction instanceof Instruction31t) { - Opcode payloadOpcode; + boolean validPayload = true; + switch (instruction.getOpcode()) { case PACKED_SWITCH: - payloadOpcode = Opcode.PACKED_SWITCH_PAYLOAD; + int baseAddress = methodDef.getPackedSwitchBaseAddress( + this.codeAddress + ((Instruction31t)instruction).getCodeOffset()); + if (baseAddress == -1) { + validPayload = false; + } break; case SPARSE_SWITCH: - payloadOpcode = Opcode.SPARSE_SWITCH_PAYLOAD; + baseAddress = methodDef.getSparseSwitchBaseAddress( + this.codeAddress + ((Instruction31t)instruction).getCodeOffset()); + if (baseAddress == -1) { + validPayload = false; + } break; case FILL_ARRAY_DATA: - payloadOpcode = Opcode.ARRAY_PAYLOAD; + try { + methodDef.findPayloadOffset(this.codeAddress + ((Instruction31t)instruction).getCodeOffset(), + Opcode.ARRAY_PAYLOAD); + } catch (InvalidSwitchPayload ex) { + validPayload = false; + } break; default: throw new ExceptionWithContext("Invalid 31t opcode: %s", instruction.getOpcode()); } - try { - methodDef.findSwitchPayload(this.codeAddress + ((Instruction31t)instruction).getCodeOffset(), - payloadOpcode); - } catch (InvalidSwitchPayload ex) { - writer.write("#invalid payload reference"); + if (!validPayload) { + writer.write("#invalid payload reference\n"); commentOutInstruction = true; } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java index eb5caa67..4081a75c 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java @@ -29,6 +29,7 @@ package org.jf.baksmali.Adaptors; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import org.jf.baksmali.Adaptors.Debug.DebugMethodItem; import org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory; import org.jf.baksmali.baksmaliOptions; @@ -45,11 +46,14 @@ import org.jf.dexlib2.iface.debug.DebugItem; import org.jf.dexlib2.iface.instruction.Instruction; import org.jf.dexlib2.iface.instruction.OffsetInstruction; import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.formats.Instruction31t; import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.instruction.ImmutableInstruction31t; import org.jf.dexlib2.util.InstructionOffsetMap; import org.jf.dexlib2.util.InstructionOffsetMap.InvalidInstructionOffset; import org.jf.dexlib2.util.ReferenceUtil; import org.jf.dexlib2.util.SyntheticAccessorResolver; +import org.jf.dexlib2.util.SyntheticAccessorResolver.AccessedMember; import org.jf.dexlib2.util.TypeUtils; import org.jf.util.ExceptionWithContext; import org.jf.util.IndentingWriter; @@ -65,6 +69,8 @@ public class MethodDefinition { @Nonnull public final Method method; @Nonnull public final MethodImplementation methodImpl; @Nonnull public final ImmutableList instructions; + @Nonnull public final List effectiveInstructions; + @Nonnull public final ImmutableList methodParameters; public RegisterFormatter registerFormatter; @@ -86,10 +92,15 @@ public class MethodDefinition { instructions = ImmutableList.copyOf(methodImpl.getInstructions()); methodParameters = ImmutableList.copyOf(method.getParameters()); + effectiveInstructions = Lists.newArrayList(instructions); + packedSwitchMap = new SparseIntArray(0); sparseSwitchMap = new SparseIntArray(0); instructionOffsetMap = new InstructionOffsetMap(instructions); + int endOffset = instructionOffsetMap.getInstructionCodeOffset(instructions.size()-1) + + instructions.get(instructions.size()-1).getCodeUnits(); + for (int i=0; i methodItems) { int currentCodeAddress = 0; - for (int i=0; iOs>5R6*USy*8#Ot4;$iyVRy?obLpKx1QJVJCke!OGIY zXvq)w2eec+zIS(<5S_cXGy8Vu?d{ApoI$d(vnR9tyQ-eOe7bMr{`lc1o~W$9e-uup zO-rOJB7^#F7A~-<5?MqeoMf--UjA5 zNntGh(JTJfvqHU0kRxKlQ=7Wfr*^7#*l+vp@wMyQ&8lQ;Eq$fSZGCZ8K00kVwqKRZ z!DX+b{he)p%j@X2E2=JQ9cGof+CFz0B`?S}q}SCw&oLy :sswitch_7 + 0xf -> :sswitch_9 + 0x14 -> :sswitch_8 + 0x63 -> :sswitch_a + .end sparse-switch +.end method \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/MultiSwitchTest/MultiSwitchOutput.smali b/brut.apktool.smali/baksmali/src/test/resources/MultiSwitchTest/MultiSwitchOutput.smali new file mode 100644 index 00000000..f3aeeed5 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/MultiSwitchTest/MultiSwitchOutput.smali @@ -0,0 +1,119 @@ +.class public LMultiSwitch; +.super Ljava/lang/Object; +.source "Format31t.smali" + + +# virtual methods +.method public multi-packed-switch()V + .registers 1 + + const p0, 0xc + + packed-switch p0, :pswitch_data_14 + + goto :goto_b + + :pswitch_7 + return-void + + :pswitch_8 + return-void + + :pswitch_9 + return-void + + :pswitch_a + return-void + + :goto_b + packed-switch p0, :pswitch_data_20 + + nop + + :pswitch_f + return-void + + :pswitch_10 + return-void + + :pswitch_11 + return-void + + :pswitch_12 + return-void + + nop + + :pswitch_data_14 + .packed-switch 0xa + :pswitch_7 + :pswitch_8 + :pswitch_9 + :pswitch_a + .end packed-switch + + :pswitch_data_20 + .packed-switch 0xa + :pswitch_f + :pswitch_10 + :pswitch_11 + :pswitch_12 + .end packed-switch +.end method + +.method public multi-sparse-switch()V + .registers 1 + + const p0, 0xd + + sparse-switch p0, :sswitch_data_14 + + goto :goto_b + + :sswitch_7 + return-void + + :sswitch_8 + return-void + + :sswitch_9 + return-void + + :sswitch_a + return-void + + :goto_b + sparse-switch p0, :sswitch_data_26 + + nop + + :sswitch_f + return-void + + :sswitch_10 + return-void + + :sswitch_11 + return-void + + :sswitch_12 + return-void + + nop + + :sswitch_data_14 + .sparse-switch + 0xa -> :sswitch_7 + 0xf -> :sswitch_9 + 0x14 -> :sswitch_8 + 0x63 -> :sswitch_a + .end sparse-switch + + :sswitch_data_26 + .sparse-switch + 0xa -> :sswitch_f + 0xf -> :sswitch_11 + 0x14 -> :sswitch_10 + 0x63 -> :sswitch_12 + .end sparse-switch +.end method