From cb3e0ea38a669633b8daefd538750c8ded46f524 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sun, 9 Oct 2011 01:17:14 -0400 Subject: [PATCH] Improve the way sparse/packed switch data blocks are found and processed --- .../Format/PackedSwitchMethodItem.java | 58 ++++++++++++---- .../Format/SparseSwitchMethodItem.java | 68 +++++++++++-------- .../baksmali/Adaptors/MethodDefinition.java | 16 +++-- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/PackedSwitchMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/PackedSwitchMethodItem.java index fd75a3c3..d991d646 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/PackedSwitchMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/PackedSwitchMethodItem.java @@ -40,9 +40,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class PackedSwitchMethodItem extends InstructionMethodItem - implements Iterable { - private final List labels; +public class PackedSwitchMethodItem extends InstructionMethodItem { + private final List targets; public PackedSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, PackedSwitchDataPseudoInstruction instruction) { @@ -50,13 +49,29 @@ public class PackedSwitchMethodItem extends InstructionMethodItem(); + targets = new ArrayList(); Iterator iterator = instruction.iterateKeysAndTargets(); - while (iterator.hasNext()) { - PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); - LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_"); - label = methodDefinition.getLabelCache().internLabel(label); - labels.add(label); + + if (baseCodeAddress >= 0) { + while (iterator.hasNext()) { + PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); + PackedSwitchLabelTarget packedSwitchLabelTarget = new PackedSwitchLabelTarget(); + + + LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_"); + label = methodDefinition.getLabelCache().internLabel(label); + packedSwitchLabelTarget.Target = label; + targets.add(packedSwitchLabelTarget); + } + } else { + while (iterator.hasNext()) { + PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); + PackedSwitchOffsetTarget packedSwitchOffsetTarget = new PackedSwitchOffsetTarget(); + + + packedSwitchOffsetTarget.Target = target.targetAddressOffset; + targets.add(packedSwitchOffsetTarget); + } } } @@ -66,8 +81,8 @@ public class PackedSwitchMethodItem extends InstructionMethodItem iterator() { - return labels.iterator(); + private static abstract class PackedSwitchTarget { + public abstract void writeTargetTo(IndentingWriter writer) throws IOException; + } + + private static class PackedSwitchLabelTarget extends PackedSwitchTarget { + public LabelMethodItem Target; + public void writeTargetTo(IndentingWriter writer) throws IOException { + Target.writeTo(writer); + } + } + + private static class PackedSwitchOffsetTarget extends PackedSwitchTarget { + public int Target; + public void writeTargetTo(IndentingWriter writer) throws IOException { + if (Target >= 0) { + writer.write('+'); + } + writer.printSignedIntAsDec(Target); + } } } diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java index ba3209ab..5c7ec545 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java @@ -40,8 +40,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class SparseSwitchMethodItem extends InstructionMethodItem - implements Iterable { +public class SparseSwitchMethodItem extends InstructionMethodItem { private final List targets; public SparseSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, @@ -52,16 +51,28 @@ public class SparseSwitchMethodItem extends InstructionMethodItem(); Iterator iterator = instruction.iterateKeysAndTargets(); - while (iterator.hasNext()) { - SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); - SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget(); - sparseSwitchTarget.Key = target.key; + if (baseCodeAddress != 0) { + while (iterator.hasNext()) { + SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); + SparseSwitchLabelTarget sparseSwitchLabelTarget = new SparseSwitchLabelTarget(); + sparseSwitchLabelTarget.Key = target.key; - LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_"); - label = methodDefinition.getLabelCache().internLabel(label); - sparseSwitchTarget.Target = label; + LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_"); + label = methodDefinition.getLabelCache().internLabel(label); + sparseSwitchLabelTarget.Target = label; - targets.add(sparseSwitchTarget); + targets.add(sparseSwitchLabelTarget); + } + } else { + //if we couldn't determine a base address, just use relative offsets rather than labels + while (iterator.hasNext()) { + SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); + SparseSwitchOffsetTarget sparseSwitchOffsetTarget = new SparseSwitchOffsetTarget(); + sparseSwitchOffsetTarget.Key = target.key; + + sparseSwitchOffsetTarget.Target = target.targetAddressOffset; + targets.add(sparseSwitchOffsetTarget); + } } } @@ -72,7 +83,7 @@ public class SparseSwitchMethodItem extends InstructionMethodItem "); - target.Target.writeTo(writer); + target.writeTargetTo(writer); writer.write('\n'); } writer.deindent(4); @@ -80,26 +91,25 @@ public class SparseSwitchMethodItem extends InstructionMethodItem iterator() { - return new Iterator() { - private Iterator iterator = targets.iterator(); - - public boolean hasNext() { - return iterator.hasNext(); - } - - public LabelMethodItem next() { - return iterator.next().Target; - } - - public void remove() { - iterator.remove(); - } - }; + private static abstract class SparseSwitchTarget { + public int Key; + public abstract void writeTargetTo(IndentingWriter writer) throws IOException; } - private static class SparseSwitchTarget { - public int Key; + private static class SparseSwitchLabelTarget extends SparseSwitchTarget { public LabelMethodItem Target; + public void writeTargetTo(IndentingWriter writer) throws IOException { + Target.writeTo(writer); + } + } + + private static class SparseSwitchOffsetTarget extends SparseSwitchTarget { + public int Target; + public void writeTargetTo(IndentingWriter writer) throws IOException { + if (Target >= 0) { + writer.write('+'); + } + writer.printSignedIntAsDec(Target); + } } } diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java index 815a295b..70071b65 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java @@ -239,8 +239,12 @@ public class MethodDefinition { int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1); if (packedSwitchBaseAddress == -1) { - throw new RuntimeException("Could not find the packed switch statement corresponding to the packed " + - "switch data at address " + packedSwitchDataAddress); + Instruction[] instructions = encodedMethod.codeItem.getInstructions(); + int index = instructionMap.get(packedSwitchDataAddress); + + if (instructions[index].opcode == Opcode.NOP) { + packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress+2, -1); + } } return packedSwitchBaseAddress; @@ -250,8 +254,12 @@ public class MethodDefinition { int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1); if (sparseSwitchBaseAddress == -1) { - throw new RuntimeException("Could not find the sparse switch statement corresponding to the sparse " + - "switch data at address " + sparseSwitchDataAddress); + Instruction[] instructions = encodedMethod.codeItem.getInstructions(); + int index = instructionMap.get(sparseSwitchDataAddress); + + if (instructions[index].opcode == Opcode.NOP) { + sparseSwitchBaseAddress = this.packedSwitchMap.get(sparseSwitchDataAddress+2, -1); + } } return sparseSwitchBaseAddress;