Implement try blocks for the method builder

This commit is contained in:
Ben Gruver 2013-08-31 15:37:10 -07:00
parent 160fc1cdba
commit 897832aa15
5 changed files with 141 additions and 8 deletions

View File

@ -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();
}
};
}
}

View File

@ -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<ExceptionHandler> {
// 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<? extends ExceptionHandler> getExceptionHandlers() {
return ImmutableList.of(exceptionHandler);
}
}

View File

@ -7,4 +7,8 @@ public class LabelMethodItem extends MethodItem {
LabelMethodItem(MethodLocation location) {
this.location = location;
}
public int getCodeAddress() {
return getLocation().getCodeAddress();
}
}

View File

@ -18,11 +18,11 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
@Nonnull
private final MutableMethodImplementation<ReferenceType> impl;
// the current instruction index
private int currentIndex;
private MethodLocation currentLocation;
public MethodImplementationBuilder(@Nonnull MutableMethodImplementation<ReferenceType> impl) {
this.impl = impl;
public MethodImplementationBuilder() {
this.impl = new MutableMethodImplementation<ReferenceType>();
this.currentLocation = impl.instructionList.get(0);
}
/**
@ -35,18 +35,16 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
*/
@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<ReferenceType extends Reference> {
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) {

View File

@ -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<ReferenceType extends Reference> {
final ArrayList<MethodLocation> instructionList = Lists.newArrayList(new MethodLocation(null, 0, 0));
private final ArrayList<BuilderTryBlock> tryBlocks = Lists.newArrayList();
public MutableMethodImplementation() {
}
@ -21,4 +25,18 @@ public class MutableMethodImplementation<ReferenceType extends Reference> {
public List<MethodLocation> 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));
}
}