Implement debug items for the method impl builder

This commit is contained in:
Ben Gruver 2013-09-01 16:44:20 -07:00
parent bb7937fd30
commit 688611814d
10 changed files with 338 additions and 18 deletions

View File

@ -0,0 +1,26 @@
package org.jf.dexlib2.builder;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.iface.debug.*;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class BuilderDebugItem implements DebugItem {
@Nullable MethodLocation location;
public BuilderDebugItem(@Nonnull MethodLocation location) {
this.location = location;
}
@Override public int getCodeAddress() {
if (location == null) {
throw new IllegalStateException("Cannot get the address of a BuilderDebugItem that isn't associated with " +
"a method.");
}
return location.getCodeAddress();
}
}

View File

@ -41,7 +41,7 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
if (label.isPlaced()) {
throw new IllegalArgumentException("There is already a label with that name.");
} else {
currentLocation.addLabel(label);
currentLocation.getLabels().add(label);
}
} else {
label = currentLocation.addNewLabel();
@ -86,25 +86,32 @@ public class MethodImplementationBuilder<ReferenceType extends Reference> {
}
public void addLineNumber(int lineNumber) {
currentLocation.addLineNumber(lineNumber);
}
public void addStartLocal(int registerNumber, @Nullable StringReference name, @Nullable TypeReference type,
@Nullable StringReference signature) {
currentLocation.addStartLocal(registerNumber, name, type, signature);
}
public void addEndLocal(int registerNumber) {
currentLocation.addEndLocal(registerNumber);
}
public void addRestartLocal(int registerNumber) {
currentLocation.addRestartLocal(registerNumber);
}
public void addPrologue() {
currentLocation.addPrologue();
}
public void addEpilogue() {
currentLocation.addEpilogue();
}
public void addSetSourceFile(@Nullable BuilderStringReference sourceFile) {
currentLocation.addSetSourceFile(sourceFile);
}
public void addInstruction10t(@Nonnull Opcode opcode,

View File

@ -1,13 +1,15 @@
package org.jf.dexlib2.builder;
import com.google.common.collect.Lists;
import org.jf.dexlib2.builder.debug.*;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.dexlib2.writer.builder.BuilderStringReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
public class MethodLocation {
@Nullable Instruction instruction;
@ -15,6 +17,7 @@ public class MethodLocation {
int index;
private List<Label> labels = Lists.newArrayList();
List<BuilderDebugItem> debugItems = Lists.newArrayList();
MethodLocation(@Nullable Instruction instruction,
int codeAddress, int index) {
@ -37,16 +40,47 @@ public class MethodLocation {
}
@Nonnull
public Collection<Label> getLabels() {
return Collections.unmodifiableCollection(labels);
public Set<Label> getLabels() {
return new AbstractSet<Label>() {
@Nonnull
@Override public Iterator<Label> iterator() {
final Iterator<Label> it = labels.iterator();
return new Iterator<Label>() {
private @Nullable Label currentLabel = null;
@Override public boolean hasNext() {
return it.hasNext();
}
public void addLabel(@Nonnull Label label) {
if (label.isPlaced()) {
label.getLocation().removeLabel(label);
@Override public Label next() {
currentLabel = it.next();
return currentLabel;
}
label.location = this;
@Override public void remove() {
if (currentLabel != null) {
currentLabel.location = null;
}
it.remove();
}
};
}
@Override public int size() {
return labels.size();
}
@Override public boolean add(@Nonnull Label label) {
if (label.isPlaced()) {
throw new IllegalArgumentException("Cannot add a label that is already placed. You must remove " +
"it from its current location first.");
}
label.location = MethodLocation.this;
labels.add(label);
return true;
}
};
}
@Nonnull
@ -56,10 +90,76 @@ public class MethodLocation {
return label;
}
public void removeLabel(@Nonnull Label label) {
for (int i=0; i<labels.size(); i++) {
labels.remove(label);
@Nonnull
public Set<BuilderDebugItem> getDebugItems() {
return new AbstractSet<BuilderDebugItem>() {
@Nonnull
@Override public Iterator<BuilderDebugItem> iterator() {
final Iterator<BuilderDebugItem> it = debugItems.iterator();
return new Iterator<BuilderDebugItem>() {
private @Nullable BuilderDebugItem currentDebugItem = null;
@Override public boolean hasNext() {
return it.hasNext();
}
label.location = null;
@Override public BuilderDebugItem next() {
currentDebugItem = it.next();
return currentDebugItem;
}
@Override public void remove() {
if (currentDebugItem != null) {
currentDebugItem.location = null;
}
it.remove();
}
};
}
@Override public int size() {
return labels.size();
}
@Override public boolean add(@Nonnull BuilderDebugItem debugItem) {
if (debugItem.location != null) {
throw new IllegalArgumentException("Cannot add a debug item that has already been added to a " +
"method. You must remove it from its current location first.");
}
debugItem.location = MethodLocation.this;
debugItems.add(debugItem);
return true;
}
};
}
public void addLineNumber(int lineNumber) {
debugItems.add(new BuilderLineNumber(this, lineNumber));
}
public void addStartLocal(int registerNumber, @Nullable StringReference name, @Nullable TypeReference type,
@Nullable StringReference signature) {
debugItems.add(new BuilderStartLocal(this, registerNumber, name, type, signature));
}
public void addEndLocal(int registerNumber) {
debugItems.add(new BuilderEndLocal(this, registerNumber));
}
public void addRestartLocal(int registerNumber) {
debugItems.add(new BuilderRestartLocal(this, registerNumber));
}
public void addPrologue() {
debugItems.add(new BuilderPrologueEnd(this));
}
public void addEpilogue() {
debugItems.add(new BuilderEpilogueBegin(this));
}
public void addSetSourceFile(@Nullable BuilderStringReference sourceFile) {
debugItems.add(new BuilderSetSourceFile(this, sourceFile));
}
}

View File

@ -0,0 +1,26 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.EndLocal;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BuilderEndLocal extends BuilderDebugItem implements EndLocal {
private final int register;
public BuilderEndLocal(@Nonnull MethodLocation location,
int register) {
super(location);
this.register = register;
}
@Override public int getRegister() { return register; }
@Nullable @Override public String getName() { return null; }
@Nullable @Override public String getType() { return null; }
@Nullable @Override public String getSignature() { return null; }
@Override public int getDebugItemType() { return DebugItemType.END_LOCAL; }
}

View File

@ -0,0 +1,16 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.EpilogueBegin;
import javax.annotation.Nonnull;
public class BuilderEpilogueBegin extends BuilderDebugItem implements EpilogueBegin {
public BuilderEpilogueBegin(@Nonnull MethodLocation location) {
super(location);
}
@Override public int getDebugItemType() { return DebugItemType.EPILOGUE_BEGIN; }
}

View File

@ -0,0 +1,22 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.LineNumber;
import javax.annotation.Nonnull;
public class BuilderLineNumber extends BuilderDebugItem implements LineNumber {
private final int lineNumber;
public BuilderLineNumber(@Nonnull MethodLocation location,
int lineNumber) {
super(location);
this.lineNumber = lineNumber;
}
@Override public int getLineNumber() { return lineNumber; }
@Override public int getDebugItemType() { return DebugItemType.LINE_NUMBER; }
}

View File

@ -0,0 +1,16 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.PrologueEnd;
import javax.annotation.Nonnull;
public class BuilderPrologueEnd extends BuilderDebugItem implements PrologueEnd {
public BuilderPrologueEnd(@Nonnull MethodLocation location) {
super(location);
}
@Override public int getDebugItemType() { return DebugItemType.PROLOGUE_END; }
}

View File

@ -0,0 +1,26 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.RestartLocal;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BuilderRestartLocal extends BuilderDebugItem implements RestartLocal {
private final int register;
public BuilderRestartLocal(@Nonnull MethodLocation location,
int register) {
super(location);
this.register = register;
}
@Override public int getRegister() { return register; }
@Nullable @Override public String getName() { return null; }
@Nullable @Override public String getType() { return null; }
@Nullable @Override public String getSignature() { return null; }
@Override public int getDebugItemType() { return DebugItemType.RESTART_LOCAL; }
}

View File

@ -0,0 +1,31 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.SetSourceFile;
import org.jf.dexlib2.iface.reference.StringReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BuilderSetSourceFile extends BuilderDebugItem implements SetSourceFile {
@Nullable
private final StringReference sourceFile;
public BuilderSetSourceFile(@Nonnull MethodLocation location,
@Nullable StringReference sourceFile) {
super(location);
this.sourceFile = sourceFile;
}
@Override public int getDebugItemType() { return DebugItemType.SET_SOURCE_FILE; }
@Nullable @Override public String getSourceFile() {
return sourceFile==null?null:sourceFile.getString();
}
@Nullable @Override public StringReference getSourceFileReference() {
return sourceFile;
}
}

View File

@ -0,0 +1,50 @@
package org.jf.dexlib2.builder.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.builder.BuilderDebugItem;
import org.jf.dexlib2.builder.MethodLocation;
import org.jf.dexlib2.iface.debug.StartLocal;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BuilderStartLocal extends BuilderDebugItem implements StartLocal {
private final int register;
@Nullable private final StringReference name;
@Nullable private final TypeReference type;
@Nullable private final StringReference signature;
public BuilderStartLocal(@Nonnull MethodLocation location,
int register,
@Nullable StringReference name,
@Nullable TypeReference type,
@Nullable StringReference signature) {
super(location);
this.register = register;
this.name = name;
this.type = type;
this.signature = signature;
}
@Override public int getRegister() { return register; }
@Nullable @Override public StringReference getNameReference() { return name; }
@Nullable @Override public TypeReference getTypeReference() { return type; }
@Nullable @Override public StringReference getSignatureReference() { return signature; }
@Nullable @Override public String getName() {
return name==null?null:name.getString();
}
@Nullable @Override public String getType() {
return type==null?null:type.getType();
}
@Nullable @Override public String getSignature() {
return signature==null?null:signature.getString();
}
@Override public int getDebugItemType() { return DebugItemType.START_LOCAL; }
}