From 897832aa150cdf53ed7fa2f17dee132d2408e2f3 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 31 Aug 2013 15:37:10 -0700 Subject: [PATCH] Implement try blocks for the method builder --- .../builder/BuilderExceptionHandler.java | 58 +++++++++++++++++++ .../jf/dexlib2/builder/BuilderTryBlock.java | 52 +++++++++++++++++ .../jf/dexlib2/builder/LabelMethodItem.java | 4 ++ .../builder/MethodImplementationBuilder.java | 17 +++--- .../builder/MutableMethodImplementation.java | 18 ++++++ 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderExceptionHandler.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderTryBlock.java diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderExceptionHandler.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderExceptionHandler.java new file mode 100644 index 00000000..a6f537a1 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderExceptionHandler.java @@ -0,0 +1,58 @@ +package org.jf.dexlib2.builder; + +import org.jf.dexlib2.base.BaseExceptionHandler; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +class BuilderExceptionHandler { + static ExceptionHandler newExceptionHandler(@Nullable final TypeReference exceptionType, + @Nonnull final LabelMethodItem handler) { + if (exceptionType == null) { + return newExceptionHandler(handler); + } + return new BaseExceptionHandler() { + @Nullable @Override public String getExceptionType() { + return exceptionType.getType(); + } + + @Override public int getHandlerCodeAddress() { + return handler.getCodeAddress(); + } + + @Nullable @Override public TypeReference getExceptionTypeReference() { + return exceptionType; + } + }; + } + + static ExceptionHandler newExceptionHandler(@Nonnull final LabelMethodItem handler) { + return new BaseExceptionHandler() { + @Nullable @Override public String getExceptionType() { + return null; + } + + @Override public int getHandlerCodeAddress() { + return handler.getCodeAddress(); + } + }; + } + + static ExceptionHandler newExceptionHandler(@Nullable final String exceptionType, + @Nonnull final LabelMethodItem handler) { + if (exceptionType == null) { + return newExceptionHandler(handler); + } + return new BaseExceptionHandler() { + @Nullable @Override public String getExceptionType() { + return exceptionType; + } + + @Override public int getHandlerCodeAddress() { + return handler.getCodeAddress(); + } + }; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderTryBlock.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderTryBlock.java new file mode 100644 index 00000000..20a22ccf --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderTryBlock.java @@ -0,0 +1,52 @@ +package org.jf.dexlib2.builder; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.BaseTryBlock; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +class BuilderTryBlock extends BaseTryBlock { + // We only ever have one exception handler per try block. They are later merged as needed in TryListBuilder + @Nonnull public final ExceptionHandler exceptionHandler; + @Nonnull public final LabelMethodItem start; + // The end location is exclusive, it should point to the codeAddress of the instruction immediately after the last + // covered instruction. + @Nonnull public final LabelMethodItem end; + + public BuilderTryBlock(@Nonnull LabelMethodItem start, @Nonnull LabelMethodItem end, + @Nullable String exceptionType, @Nonnull LabelMethodItem handler) { + this.start = start; + this.end = end; + this.exceptionHandler = BuilderExceptionHandler.newExceptionHandler(exceptionType, handler); + } + + public BuilderTryBlock(@Nonnull LabelMethodItem start, @Nonnull LabelMethodItem end, + @Nullable TypeReference exceptionType, @Nonnull LabelMethodItem handler) { + this.start = start; + this.end = end; + this.exceptionHandler = BuilderExceptionHandler.newExceptionHandler(exceptionType, handler); + } + + public BuilderTryBlock(@Nonnull LabelMethodItem start, @Nonnull LabelMethodItem end, + @Nonnull LabelMethodItem handler) { + this.start = start; + this.end = end; + this.exceptionHandler = BuilderExceptionHandler.newExceptionHandler(handler); + } + + @Override public int getStartCodeAddress() { + return start.getCodeAddress(); + } + + @Override public int getCodeUnitCount() { + return end.getCodeAddress() - start.getCodeAddress(); + } + + @Nonnull @Override public List getExceptionHandlers() { + return ImmutableList.of(exceptionHandler); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java index b9abc909..3fe10414 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/LabelMethodItem.java @@ -7,4 +7,8 @@ public class LabelMethodItem extends MethodItem { LabelMethodItem(MethodLocation location) { this.location = location; } + + public int getCodeAddress() { + return getLocation().getCodeAddress(); + } } 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 2fc49a63..54093268 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodImplementationBuilder.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MethodImplementationBuilder.java @@ -18,11 +18,11 @@ public class MethodImplementationBuilder { @Nonnull private final MutableMethodImplementation impl; - // the current instruction index - private int currentIndex; + private MethodLocation currentLocation; - public MethodImplementationBuilder(@Nonnull MutableMethodImplementation impl) { - this.impl = impl; + public MethodImplementationBuilder() { + this.impl = new MutableMethodImplementation(); + this.currentLocation = impl.instructionList.get(0); } /** @@ -35,18 +35,16 @@ public class MethodImplementationBuilder { */ @Nonnull 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); + currentLocation.addLabel(label); } } else { - label = location.addNewLabel(); + label = currentLocation.addNewLabel(); labels.put(name, label); } @@ -75,13 +73,16 @@ public class MethodImplementationBuilder { public void addCatch(@Nullable TypeReference type, @Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { + impl.addCatch(type, from, to, handler); } public void addCatch(@Nullable String type, @Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { + impl.addCatch(type, from, to, handler); } public void addCatch(@Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { + impl.addCatch(from, to, handler); } public void addLineNumber(int lineNumber) { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java index 73ba1524..5f619788 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java @@ -3,13 +3,17 @@ package org.jf.dexlib2.builder; import com.google.common.collect.Lists; import org.jf.dexlib2.iface.MethodImplementation; import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.iface.reference.TypeReference; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class MutableMethodImplementation { final ArrayList instructionList = Lists.newArrayList(new MethodLocation(null, 0, 0)); + private final ArrayList tryBlocks = Lists.newArrayList(); public MutableMethodImplementation() { } @@ -21,4 +25,18 @@ public class MutableMethodImplementation { public List getInstruction() { return Collections.unmodifiableList(instructionList); } + + public void addCatch(@Nullable TypeReference type, @Nonnull LabelMethodItem from, + @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { + tryBlocks.add(new BuilderTryBlock(from, to, type, handler)); + } + + public void addCatch(@Nullable String type, @Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, + @Nonnull LabelMethodItem handler) { + tryBlocks.add(new BuilderTryBlock(from, to, type, handler)); + } + + public void addCatch(@Nonnull LabelMethodItem from, @Nonnull LabelMethodItem to, @Nonnull LabelMethodItem handler) { + tryBlocks.add(new BuilderTryBlock(from, to, handler)); + } }