Commit db69e06c authored by Anya Helene Bagge's avatar Anya Helene Bagge 🦆
Browse files

various

parent fe195b4d
package inf225.examples;
import com.sun.jdi.*;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.event.*;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.MethodEntryRequest;
import com.sun.jdi.request.StepRequest;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
public class Debugger {
private Class debugee;
public void setDebugee(Class debugee) {
this.debugee = debugee;
}
/**
* Create connector and give it the debuggee's main class, connect this debugger
* to the VM and launch the VM.
*
* @return Virtual Machine for debugging
* @throws Exception
*/
public VirtualMachine connectAndLaunchVirtualMachine() throws Exception {
LaunchingConnector launchingConnector = Bootstrap.virtualMachineManager().defaultConnector();
Map<String, Connector.Argument> connectorArguments = launchingConnector.defaultArguments();
connectorArguments.get("main").setValue(debugee.getName());
connectorArguments.get("options").setValue("-cp " + System.getProperty("java.class.path"));
System.out.println(connectorArguments);
return launchingConnector.launch(connectorArguments);
}
/**
* Enable methodEntryRequest to get notified when a method is entried in the
* debugee class.
*
* @see <a href=
* "https://docs.oracle.com/javase/8/docs/jdk/api/jpda/jdi/com/sun/jdi/event/MethodEntryEvent.html">MethodEntryEvent</a>
*
* @param virtualMachine
*/
public void listenToMethodEntryEvents(VirtualMachine virtualMachine) {
MethodEntryRequest methodEntryRequest = virtualMachine.eventRequestManager().createMethodEntryRequest();
virtualMachine.eventRequestManager().createExceptionRequest(null, true, true).enable();
methodEntryRequest.addClassFilter("*.Test");
methodEntryRequest.enable();
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
System.out.println(System.getProperties().toString().replace(",", ",\n"));
Debugger debugger = new Debugger();
debugger.setDebugee(Test.class);
for (java.lang.reflect.Method m : Test.class.getMethods()) {
// Field field = Test.class.getField("foo");
System.out.println(m.toGenericString());
}
try {
VirtualMachine virtualMachine = debugger.connectAndLaunchVirtualMachine();
debugger.listenToMethodEntryEvents(virtualMachine);
StepRequest request = virtualMachine.eventRequestManager()
.createStepRequest(virtualMachine.allThreads().get(0), StepRequest.STEP_MIN, StepRequest.STEP_INTO);
request.addClassFilter("*.Test");
// request.addCountFilter(1);
request.enable();
EventSet events;
while ((events = virtualMachine.eventQueue().remove()) != null) {
for (Event event : events) {
System.out.println(event);
if (event instanceof MethodEntryEvent) {
Method enteredMethod = ((MethodEntryEvent) event).method();
System.out.println("METHOD: " + enteredMethod.toString());
} else if (event instanceof StepEvent) {
StepEvent stepEvent = (StepEvent) event;
Method method = stepEvent.location().method();
System.out.println(method.name() + ":" + stepEvent.location().codeIndex() + ": "
+ String.format("%02x", method.bytecodes()[(int) stepEvent.location().codeIndex()]));
ThreadReference thread = stepEvent.thread();
if (thread.isSuspended()) {
StackFrame frame = stepEvent.thread().frame(0);
List<LocalVariable> variables = frame.visibleVariables();
for (LocalVariable v : variables) {
System.out.println(v.typeName() + " " + v.name() + " = " + frame.getValue(v));
}
}
System.out.println(request + ", " + stepEvent.thread().isSuspended());
}
virtualMachine.resume();
}
}
} catch (VMDisconnectedException e) {
System.out.println("Virtual Machine is disconnected.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
......@@ -42,9 +42,9 @@ public class Lambdas {
}
public double foo(double a, double b) {
int[] s = {};
String t = "";
return a + b + s[0] + t.length();
return a + b + t.length();
}
public static void printByteCode(Function<Float, Float> fun) throws Exception {
......
package inf225.examples;
public class Test {
String foo = "";
public static void main(String[] args) {
new Test().f();
throw new RuntimeException();
}
public void f() {
int a = 2;
int b = 3;
System.out.println(g(a + b));
}
public int g(int a) {
return a * 2;
}
}
package inf225.examples.asm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.objectweb.asm.Type;
public class ASTNode {
public interface ASTNode {
public interface StatNode extends ASTNode {
}
public interface ExprNode extends ASTNode {
public Type type();
}
public static class Const implements ExprNode {
Object value;
Type type;
public static class Var extends ASTNode {
public Const(Object value, Type type) {
super();
this.value = value;
this.type = type;
}
@Override
public String toString() {
if (value instanceof String)
return String.format("\"%s\"", value.toString().replaceAll("[\"\\\\]", "\\$1"));
else if (value instanceof Number)
return value.toString();
else
return value.getClass().getName() + "(" + value + ")";
}
@Override
public Type type() {
return type;
}
}
public static class Var implements ExprNode {
int slot;
Object type;
public Var(int slot, Object type) {
Type type;
String name;
public Var(int slot, Type type) {
super();
this.slot = slot;
this.type = type;
}
@Override
public String toString() {
return "Var [slot=" + slot + ", type=" + type + "]";
return name != null ? name : "var" + slot + "_" + type;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + slot;
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Var other = (Var) obj;
if (slot != other.slot)
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
@Override
public Type type() {
return type;
}
}
public static class Assign implements StatNode {
Var var;
ExprNode value;
public Assign(Var var, ExprNode value) {
super();
this.var = var;
this.value = value;
}
@Override
public String toString() {
return var + " = " + value + ";";
}
}
public static class Operator extends ASTNode {
public static class Declare implements StatNode {
Var var;
public Declare(Var var) {
super();
this.var = var;
}
@Override
public String toString() {
return var.type.getClassName() + " " + var + ";";
}
}
public static class Return implements StatNode {
ExprNode value;
public Return(ExprNode value) {
super();
this.value = value;
}
@Override
public String toString() {
return "return " + value + ";";
}
}
public static class Operator implements ExprNode {
String operator;
List<ExprNode> args;
Type type;
public Operator(String operator, Type type, ExprNode... args) {
super();
this.operator = operator;
this.args = Arrays.asList(args);
}
@Override
public String toString() {
return operator + args;
}
@Override
public Type type() {
return type;
}
}
public static class Invoke implements ExprNode {
String operator;
ASTNode lhs, rhs;
public Operator(String operator, ASTNode lhs, ASTNode rhs) {
List<ExprNode> args;
Type type;
ExprNode obj;
public Invoke(String operator, Type type, ExprNode obj, ExprNode... args) {
super();
this.operator = operator;
this.lhs = lhs;
this.rhs = rhs;
this.args = Arrays.asList(args);
this.obj = obj;
}
@Override
public String toString() {
return "Operator [operator=" + operator + ", lhs=" + lhs + ", rhs=" + rhs + "]";
return obj.toString() + "." + operator + args;
}
@Override
public Type type() {
return type;
}
}
}
package inf225.examples.asm;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
......@@ -13,9 +18,15 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AnalyzerAdapter;
import org.objectweb.asm.commons.InstructionAdapter;
import inf225.examples.asm.ASTNode.ExprNode;
import inf225.examples.asm.ASTNode.Operator;
import inf225.examples.asm.ASTNode.StatNode;
public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
protected AnalyzerAdapter analyzerAdapter;
protected Deque<ASTNode> stack = new ArrayDeque<>();
protected List<ASTNode.StatNode> statements = new ArrayList<>();
protected Deque<ASTNode.ExprNode> stack = new ArrayDeque<>();
protected Map<String, ASTNode.Var> vars = new HashMap<>();
protected Type methodType;
protected int lineNumber;
private Label label;
......@@ -24,6 +35,15 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
super(api, methodVisitor);
}
protected ASTNode.Var var(int slot, Type type) {
String id = String.format("%d:%s", slot, type);
ASTNode.Var v = vars.get(id);
if(v == null) {
v = new ASTNode.Var(slot, type);
vars.put(id, v);
}
return v;
}
public void visitParameter(final String name, final int access) {
System.out.printf("visitParameter(%s,%d)%n", name, access);
}
......@@ -34,13 +54,15 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void aconst(Object value) {
System.out.printf("aconst %s%n", value);
stack.push(new ASTNode.Const(value, Type.getType(value.getClass())));
}
public void add(Type type) {
System.out.printf("add %s%n", type);
ASTNode rhs = stack.pop();
ASTNode lhs = stack.pop();
stack.push(new ASTNode.Operator("add", lhs, rhs));
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator(type.getDescriptor().toLowerCase() + "add", type, lhs, rhs));
}
public void aload(Type type) {
......@@ -49,6 +71,9 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void and(Type type) {
System.out.printf("and %s%n", type);
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator(type.getDescriptor().toLowerCase() + "and", type, lhs, rhs));
}
public void anew(Type type) {
......@@ -58,6 +83,7 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void areturn(Type type) {
System.out.printf("areturn %s%n", type);
statements.add(new ASTNode.Return(stack.pop()));
}
......@@ -76,10 +102,12 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void cast(Type from, Type to) {
System.out.printf("cast %s, %s%n", from, to);
stack.push(new ASTNode.Operator("cast_" + from + "_" + to, to, stack.pop()));
}
public void cconst(ConstantDynamic constantDynamic) {
System.out.printf("cconst %s%n", constantDynamic);
stack.push(new ASTNode.Const(constantDynamic, null));
}
public void checkcast(Type type) {
......@@ -89,29 +117,51 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void cmpg(Type type) {
System.out.printf("cmpg %s%n", type);
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator(type.getDescriptor().toLowerCase() + "cmpg", type, lhs, rhs));
}
public void cmpl(Type type) {
System.out.printf("cmpl %s%n", type);
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator(type.getDescriptor().toLowerCase() + "cmpl", type, lhs, rhs));
}
public void dconst(double doubleValue) {
System.out.printf("dconst %g%n", doubleValue);
stack.push(new ASTNode.Const(doubleValue, Type.DOUBLE_TYPE));
}
public void div(Type type) {
System.out.printf("div %s%n", type);
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator(type.getDescriptor().toLowerCase() + "div", type, lhs, rhs));
}
public void dup() {
System.out.println("dup");
ExprNode top = stack.pop();
stack.push(top);
stack.push(top);
}
public void dup2() {
System.out.println("dup2");
ExprNode top = stack.pop();
Object type = stackGetType(0);
if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
stack.push(top);
stack.push(top);
} else {
ExprNode top2 = stack.pop();
stack.push(top2);
stack.push(top);
stack.push(top2);
stack.push(top);
}
}
public void dup2X1() {
......@@ -132,6 +182,7 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void fconst(float floatValue) {
System.out.printf("dconst %g%n", floatValue);
stack.push(new ASTNode.Const(floatValue, Type.FLOAT_TYPE));
}
public void getfield(String owner, String name, String descriptor) {
......@@ -149,10 +200,12 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void hconst(Handle handle) {
System.out.printf("hconst %s%n", handle);
stack.push(new ASTNode.Const(handle, null));
}
public void iconst(int intValue) {
System.out.printf("iconst %d%n", intValue);
stack.push(new ASTNode.Const(intValue, Type.INT_TYPE));
}
public void ifacmpeq(Label label) {
......@@ -240,16 +293,22 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
Type methType = Type.getType(descriptor);
Type[] argumentTypes = methType.getArgumentTypes();
Type retType = methType.getReturnType();
ExprNode obj = stack.pop();
System.out.printf("invokeinterface %s, %s, %s %s → %s%n", owner, name, descriptor, //
Arrays.toString(argumentTypes), retType);
ExprNode[] args = (ExprNode[]) Stream.of(argumentTypes).map(t -> stack.pop()).toArray(n -> new ExprNode[n]);
stack.push(new ASTNode.Invoke(name, retType, obj, args));
}
public void invokespecial(String owner, String name, String descriptor, boolean isInterface) {
Type methType = Type.getType(descriptor);
Type objType = Type.getObjectType(owner);
Type[] argumentTypes = methType.getArgumentTypes();
Type retType = methType.getReturnType();
System.out.printf("invokespecial %s, %s, %s, %b %s → %s%n", owner, name, descriptor, isInterface, //
Arrays.toString(argumentTypes), retType);
ExprNode[] args = (ExprNode[]) Stream.of(argumentTypes).map(t -> stack.pop()).toArray(n -> new ExprNode[n]);
stack.push(new ASTNode.Operator(name, retType, args));
}
public void invokestatic(String owner, String name, String descriptor, boolean isInterface) {
......@@ -258,11 +317,19 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
Type retType = methType.getReturnType();
System.out.printf("invokestatic %s, %s, %s, %b %s → %s%n", owner, name, descriptor, isInterface, //
Arrays.toString(argumentTypes), retType);
ExprNode[] args = (ExprNode[]) Stream.of(argumentTypes).map(t -> stack.pop()).toArray(n -> new ExprNode[n]);
stack.push(new ASTNode.Operator(name, retType, args));
}
public void invokevirtual(String owner, String name, String descriptor, boolean isInterface) {
Type methType = Type.getType(descriptor);
Type objType = Type.getObjectType(owner);
Type[] argumentTypes = methType.getArgumentTypes();
Type retType = methType.getReturnType();
ExprNode obj = stack.pop();
System.out.printf("invokevirtual %s, %s, %s, %b%n", owner, name, descriptor, isInterface);
ExprNode[] args = (ExprNode[]) Stream.of(argumentTypes).map(t -> stack.pop()).toArray(n -> new ExprNode[n]);
stack.push(new ASTNode.Invoke(name, retType, obj, args));
}
public void jsr(Label label) {
......@@ -272,16 +339,21 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void lcmp() {
System.out.printf("lcmp%n");
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator("lcmp", Type.LONG_TYPE, lhs, rhs));
}
public void lconst(long longValue) {
System.out.printf("lconst %l%n", longValue);
stack.push(new ASTNode.Const(longValue, Type.LONG_TYPE));
}
public void load(int var, Type type) {
// 'type' depends on the load instruction (e.g., iload, aload, dload, etc), and
// will be one of the primitive types, or an object or array type – in the latter cases
// we can get the actual type from the AnalyzerAdapter
// will be one of the primitive types, or an object or array type – in the
// latter cases
// we can get the actual type from the AnalyzerAdapter
Object localType = localGetType(var);
if (type.getSort() == Type.OBJECT)
type = Type.getObjectType((String) localType);
......@@ -289,7 +361,7 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
type = Type.getType((String) localType);
System.out.printf("load %d, %s (%s)%n", var, type, localGetType(var));
stack.push(new ASTNode.Var(var, localGetType(var)));
stack.push(var(var, type));
}
Object localGetType(int var) {
......@@ -392,6 +464,9 @@ public class ToExpr extends InstructionAdapter implements AnalyzerVisitor {
public void mul(Type type) {
System.out.printf("mul %s | %s %s ↑%n", type, frameTypeToString(stackGetType(0)),
frameTypeToString(stackGetType(1)));
ExprNode rhs = stack.pop();
ExprNode lhs = stack.pop();
stack.push(new ASTNode.Operator(type.getDescriptor().toLowerCase() + "mul", type, lhs, rhs));
}