From 160fc1cdbabb1aafaadde1f8d872574b0666f1dc Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 31 Aug 2013 14:12:58 -0700 Subject: [PATCH] Split off a separate MutableMethodImplementation and implement labels --- .../builder/InstructionMethodItem.java | 7 ++ .../jf/dexlib2/builder/LabelMethodItem.java | 10 +++ .../java/org/jf/dexlib2/builder/LabelRef.java | 11 --- .../builder/MethodImplementationBuilder.java | 90 +++++++++++++++---- .../org/jf/dexlib2/builder/MethodItem.java | 21 +++++ .../jf/dexlib2/builder/MethodLocation.java | 65 ++++++++++++++ .../builder/MutableMethodImplementation.java | 24 +++++ .../dexlib2/builder/SwitchLabelElement.java | 2 +- 8 files changed, 199 insertions(+), 31 deletions(-) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/InstructionMethodItem.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java delete mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/LabelRef.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/MethodItem.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/MethodLocation.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/InstructionMethodItem.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/InstructionMethodItem.java new file mode 100644 index 00000000..c5cdc017 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/InstructionMethodItem.java @@ -0,0 +1,7 @@ +package org.jf.dexlib2.builder; + +import org.jf.dexlib2.iface.instruction.Instruction; + +class InstructionMethodItem extends MethodItem { + public Instruction instruction; +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java new file mode 100644 index 00000000..b9abc909 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java @@ -0,0 +1,10 @@ +package org.jf.dexlib2.builder; + +public class LabelMethodItem extends MethodItem { + LabelMethodItem() { + } + + LabelMethodItem(MethodLocation location) { + this.location = location; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelRef.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelRef.java deleted file mode 100644 index 3a538358..00000000 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelRef.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.jf.dexlib2.builder; - -public class LabelRef { - public boolean isResolved() { - return false; - } - - public int getCodeAddress() { - return 0; - } -} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodImplementationBuilder.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodImplementationBuilder.java index 2f309052..2fc49a63 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodImplementationBuilder.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodImplementationBuilder.java @@ -1,7 +1,6 @@ package org.jf.dexlib2.builder; import org.jf.dexlib2.Opcode; -import org.jf.dexlib2.iface.MethodImplementation; import org.jf.dexlib2.iface.reference.Reference; import org.jf.dexlib2.iface.reference.StringReference; import org.jf.dexlib2.iface.reference.TypeReference; @@ -9,27 +8,80 @@ import org.jf.dexlib2.writer.builder.BuilderStringReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.HashMap; import java.util.List; public class MethodImplementationBuilder { - public MethodImplementationBuilder() { - } - - public MethodImplementation buildMethodImplementation() { - return null; - } + // Contains all named labels - both placed and unplaced + private final HashMap labels = new HashMap(); @Nonnull - public LabelRef addLabel(@Nonnull String name) { - return null; + private final MutableMethodImplementation impl; + + // the current instruction index + private int currentIndex; + + public MethodImplementationBuilder(@Nonnull MutableMethodImplementation impl) { + this.impl = impl; } + /** + * Adds a new named label at the current location. + * + * Any previous unplaced references to a label of this name will now refer to this label/location + * + * @param name The name of the label to add + * @return A LabelRef representing the label + */ @Nonnull - public LabelRef getLabel(@Nonnull String name) { - return null; + public LabelMethodItem addLabel(@Nonnull String name) { + MethodLocation location = impl.instructionList.get(currentIndex); + + LabelMethodItem label = labels.get(name); + + if (label != null) { + if (label.isPlaced()) { + throw new IllegalArgumentException("There is already a label with that name."); + } else { + location.addLabel(label); + } + } else { + label = location.addNewLabel(); + labels.put(name, label); + } + + return label; } - public void addCatch(String type, LabelRef from, LabelRef to, LabelRef using) { + /** + * Get a reference to a label with the given name. + * + * If a label with that name has not been added yet, a new one is created, but is left + * in an unplaced state. It is assumed that addLabel(name) will be called at a later + * point to define the location of the label. + * + * @param name The name of the label to get + * @return A LabelRef representing the label + */ + @Nonnull + public LabelMethodItem getLabel(@Nonnull String name) { + LabelMethodItem label = labels.get(name); + if (label == null) { + label = new LabelMethodItem(); + labels.put(name, label); + } + return label; + } + + public void addCatch(@Nullable TypeReference type, @Nonnull LabelMethodItem from, + @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { + } + + public void addCatch(@Nullable String type, @Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, + @Nonnull LabelMethodItem handler) { + } + + public void addCatch(@Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { } public void addLineNumber(int lineNumber) { @@ -55,7 +107,7 @@ public class MethodImplementationBuilder { } public void addInstruction10t(@Nonnull Opcode opcode, - @Nonnull LabelRef label) { + @Nonnull LabelMethodItem label) { } public void addInstruction10x(@Nonnull Opcode opcode) { @@ -81,7 +133,7 @@ public class MethodImplementationBuilder { } public void addInstruction20t(@Nonnull Opcode opcode, - @Nonnull LabelRef label) { + @Nonnull LabelMethodItem label) { } public void addInstruction21c(@Nonnull Opcode opcode, @@ -106,7 +158,7 @@ public class MethodImplementationBuilder { public void addInstruction21t(@Nonnull Opcode opcode, int registerA, - @Nonnull LabelRef label) { + @Nonnull LabelMethodItem label) { } public void addInstruction22b(@Nonnull Opcode opcode, @@ -130,7 +182,7 @@ public class MethodImplementationBuilder { public void addInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, - @Nonnull LabelRef labelRef) { + @Nonnull LabelMethodItem labelMethodItem) { } public void addInstruction22x(@Nonnull Opcode opcode, @@ -145,7 +197,7 @@ public class MethodImplementationBuilder { } public void addInstruction30t(@Nonnull Opcode opcode, - @Nonnull LabelRef label) { + @Nonnull LabelMethodItem label) { } public void addInstruction31c(@Nonnull Opcode opcode, @@ -160,7 +212,7 @@ public class MethodImplementationBuilder { public void addInstruction31t(@Nonnull Opcode opcode, int registerA, - @Nonnull LabelRef label) { + @Nonnull LabelMethodItem label) { } public void addInstruction32x(@Nonnull Opcode opcode, @@ -189,7 +241,7 @@ public class MethodImplementationBuilder { long literal) { } - public void addPackedSwitchPayload(int startKey, @Nullable List switchElements) { + public void addPackedSwitchPayload(int startKey, @Nullable List switchElements) { } public void addSparseSwitchPayload(@Nullable List switchElements) { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodItem.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodItem.java new file mode 100644 index 00000000..f5ba7d0a --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodItem.java @@ -0,0 +1,21 @@ +package org.jf.dexlib2.builder; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +class MethodItem { + @Nullable + MethodLocation location; + + @Nonnull + public MethodLocation getLocation() { + if (location == null) { + throw new IllegalStateException("Cannot get the address of MethodItem that hasn't been added to a method."); + } + return location; + } + + public boolean isPlaced() { + return location != null; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodLocation.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodLocation.java new file mode 100644 index 00000000..80fc854c --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodLocation.java @@ -0,0 +1,65 @@ +package org.jf.dexlib2.builder; + +import com.google.common.collect.Lists; +import org.jf.dexlib2.iface.instruction.Instruction; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class MethodLocation { + @Nullable Instruction instruction; + int codeAddress; + int index; + + private List labels = Lists.newArrayList(); + + MethodLocation(@Nullable Instruction instruction, + int codeAddress, int index) { + this.instruction = instruction; + this.codeAddress = codeAddress; + this.index = index; + } + + @Nullable + public Instruction getInstruction() { + return instruction; + } + + public int getCodeAddress() { + return codeAddress; + } + + public int getIndex() { + return index; + } + + @Nonnull + public Collection getLabels() { + return Collections.unmodifiableCollection(labels); + } + + public void addLabel(@Nonnull LabelMethodItem label) { + if (label.isPlaced()) { + label.getLocation().removeLabel(label); + } + label.location = this; + labels.add(label); + } + + @Nonnull + public LabelMethodItem addNewLabel() { + LabelMethodItem label = new LabelMethodItem(this); + labels.add(label); + return label; + } + + public void removeLabel(@Nonnull LabelMethodItem label) { + for (int i=0; i { + final ArrayList instructionList = Lists.newArrayList(new MethodLocation(null, 0, 0)); + + public MutableMethodImplementation() { + } + + public MethodImplementation buildMethodImplementation() { + return null; + } + + public List getInstruction() { + return Collections.unmodifiableList(instructionList); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/SwitchLabelElement.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/SwitchLabelElement.java index 0c95710c..bd298f93 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/SwitchLabelElement.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/SwitchLabelElement.java @@ -3,6 +3,6 @@ package org.jf.dexlib2.builder; import javax.annotation.Nonnull; public class SwitchLabelElement { - public SwitchLabelElement(int key, @Nonnull LabelRef dest) { + public SwitchLabelElement(int key, @Nonnull LabelMethodItem dest) { } }