Split up if/if0s for mapping stuff, maybe
This commit is contained in:
@@ -32,7 +32,7 @@ public abstract class Instruction implements Cloneable
|
||||
public String toString()
|
||||
{
|
||||
Method m = this.getInstructions().getCode().getAttributes().getMethod();
|
||||
return super.toString() + " in " + m;
|
||||
return super.toString() + " in " + m + " at pc " + this.getPc();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -121,8 +121,20 @@ import net.runelite.deob.attributes.code.instructions.IStore_3;
|
||||
import net.runelite.deob.attributes.code.instructions.ISub;
|
||||
import net.runelite.deob.attributes.code.instructions.IUShR;
|
||||
import net.runelite.deob.attributes.code.instructions.IXor;
|
||||
import net.runelite.deob.attributes.code.instructions.If;
|
||||
import net.runelite.deob.attributes.code.instructions.If0;
|
||||
import net.runelite.deob.attributes.code.instructions.IfCmpEq;
|
||||
import net.runelite.deob.attributes.code.instructions.IfCmpGe;
|
||||
import net.runelite.deob.attributes.code.instructions.IfCmpGt;
|
||||
import net.runelite.deob.attributes.code.instructions.IfCmpLe;
|
||||
import net.runelite.deob.attributes.code.instructions.IfCmpLt;
|
||||
import net.runelite.deob.attributes.code.instructions.IfCmpNe;
|
||||
import net.runelite.deob.attributes.code.instructions.IfEq;
|
||||
import net.runelite.deob.attributes.code.instructions.IfGe;
|
||||
import net.runelite.deob.attributes.code.instructions.IfGt;
|
||||
import net.runelite.deob.attributes.code.instructions.IfLe;
|
||||
import net.runelite.deob.attributes.code.instructions.IfLt;
|
||||
import net.runelite.deob.attributes.code.instructions.IfNe;
|
||||
import net.runelite.deob.attributes.code.instructions.IfNonNull;
|
||||
import net.runelite.deob.attributes.code.instructions.IfNull;
|
||||
import net.runelite.deob.attributes.code.instructions.InstanceOf;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeInterface;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeSpecial;
|
||||
@@ -335,20 +347,20 @@ public enum InstructionType
|
||||
FCMPG(0x96, "fcmpg", FCmpG.class),
|
||||
DCMPL(0x97, "dcmpl", DCmpL.class),
|
||||
DCMPG(0x98, "dcmpg", DCmpG.class),
|
||||
IFEQ(0x99, "ifeq", If0.class),
|
||||
IFNE(0x9a, "ifne", If0.class),
|
||||
IFLT(0x9b, "iflt", If0.class),
|
||||
IFGE(0x9c, "ifge", If0.class),
|
||||
IFGT(0x9d, "ifgt", If0.class),
|
||||
IFLE(0x9e, "ifle", If0.class),
|
||||
IF_ICMPEQ(0x9f, "if_icmpeq", If.class),
|
||||
IF_ICMPNE(0xa0, "if_icmpne", If.class),
|
||||
IF_ICMPLT(0xa1, "if_cmplt", If.class),
|
||||
IF_ICMPGE(0xa2, "if_icmpge", If.class),
|
||||
IF_ICMPGT(0xa3, "if_icmpgt", If.class),
|
||||
IF_ICMPLE(0xa4, "if_icmple", If.class),
|
||||
IF_ACMPEQ(0xa5, "if_acmpeq", If.class),
|
||||
IF_ACMPNE(0xa6, "if_acmpne", If.class),
|
||||
IFEQ(0x99, "ifeq", IfEq.class),
|
||||
IFNE(0x9a, "ifne", IfNe.class),
|
||||
IFLT(0x9b, "iflt", IfLt.class),
|
||||
IFGE(0x9c, "ifge", IfGe.class),
|
||||
IFGT(0x9d, "ifgt", IfGt.class),
|
||||
IFLE(0x9e, "ifle", IfLe.class),
|
||||
IF_ICMPEQ(0x9f, "if_icmpeq", IfCmpEq.class),
|
||||
IF_ICMPNE(0xa0, "if_icmpne", IfCmpNe.class),
|
||||
IF_ICMPLT(0xa1, "if_cmplt", IfCmpLt.class),
|
||||
IF_ICMPGE(0xa2, "if_icmpge", IfCmpGe.class),
|
||||
IF_ICMPGT(0xa3, "if_icmpgt", IfCmpGt.class),
|
||||
IF_ICMPLE(0xa4, "if_icmple", IfCmpLe.class),
|
||||
IF_ACMPEQ(0xa5, "if_acmpeq", IfCmpEq.class),
|
||||
IF_ACMPNE(0xa6, "if_acmpne", IfCmpNe.class),
|
||||
GOTO(0xa7, "goto", Goto.class),
|
||||
TABLESWITCH(0xaa, "tableswitch", TableSwitch.class),
|
||||
LOOKUPSWITCH(0xab, "lookupswitch", LookupSwitch.class),
|
||||
@@ -377,8 +389,8 @@ public enum InstructionType
|
||||
MONITOREXIT(0xc3, "monitorexit", MonitorExit.class),
|
||||
WIDE(0xc4, "wide", Wide.class),
|
||||
MULTIANEWARRAY(0xc5, "multianewarray", MultiANewArray.class),
|
||||
IFNULL(0xc6, "ifnull", If0.class),
|
||||
IFNONNULL(0xc7, "ifnonnull", If0.class),
|
||||
IFNULL(0xc6, "ifnull", IfNull.class),
|
||||
IFNONNULL(0xc7, "ifnonnull", IfNonNull.class),
|
||||
GOTO_W(0xc8, "goto_w", GotoW.class);
|
||||
|
||||
private byte code;
|
||||
|
||||
@@ -73,10 +73,12 @@ public class If extends Instruction implements JumpingInstruction, ComparisonIns
|
||||
|
||||
ins.pop(one, two);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
|
||||
Frame other = frame.dup();
|
||||
other.jump(ins, to);
|
||||
|
||||
ins.branch(other);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -74,10 +74,12 @@ public class If0 extends Instruction implements JumpingInstruction, ComparisonIn
|
||||
|
||||
ins.pop(one);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
|
||||
Frame other = frame.dup();
|
||||
other.jump(ins, to);
|
||||
|
||||
ins.branch(other);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
import net.runelite.deob.execution.InstructionContext;
|
||||
|
||||
public class IfCmpEq extends If
|
||||
{
|
||||
public IfCmpEq(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfCmpGe extends If
|
||||
{
|
||||
public IfCmpGe(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfCmpGt extends If
|
||||
{
|
||||
public IfCmpGt(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfCmpLe extends If
|
||||
{
|
||||
public IfCmpLe(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfCmpLt extends If
|
||||
{
|
||||
public IfCmpLt(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfCmpNe extends If
|
||||
{
|
||||
public IfCmpNe(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfEq extends If0
|
||||
{
|
||||
public IfEq(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfGe extends If0
|
||||
{
|
||||
public IfGe(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfGt extends If0
|
||||
{
|
||||
public IfGt(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfLe extends If0
|
||||
{
|
||||
public IfLe(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfLt extends If0
|
||||
{
|
||||
public IfLt(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfNe extends If0
|
||||
{
|
||||
public IfNe(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfNonNull extends If0
|
||||
{
|
||||
public IfNonNull(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.runelite.deob.attributes.code.instructions;
|
||||
|
||||
import net.runelite.deob.attributes.code.InstructionType;
|
||||
import net.runelite.deob.attributes.code.Instructions;
|
||||
|
||||
public class IfNull extends If0
|
||||
{
|
||||
public IfNull(Instructions instructions, InstructionType type, int pc)
|
||||
{
|
||||
super(instructions, type, pc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -118,15 +118,17 @@ public class LookupSwitch extends Instruction implements JumpingInstruction
|
||||
StackContext value = stack.pop();
|
||||
ins.pop(value);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
|
||||
for (Instruction i : branchi)
|
||||
{
|
||||
Frame other = frame.dup();
|
||||
other.jump(ins, i);
|
||||
|
||||
ins.branch(other);
|
||||
}
|
||||
|
||||
frame.jump(ins, defi);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -114,15 +114,17 @@ public class TableSwitch extends Instruction implements JumpingInstruction
|
||||
StackContext value = stack.pop();
|
||||
ins.pop(value);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
|
||||
for (Instruction i : branchi)
|
||||
{
|
||||
Frame other = frame.dup();
|
||||
other.jump(ins, i);
|
||||
|
||||
ins.branch(other);
|
||||
}
|
||||
|
||||
frame.jump(ins, defi);
|
||||
|
||||
frame.addInstructionContext(ins);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,8 +37,6 @@ public class Execution
|
||||
public Set<Instruction> executed = new HashSet<>(); // executed instructions
|
||||
private MultiValueMap<InstructionContext, Method> invokes = new MultiValueMap<>();
|
||||
public MultiValueMap<Instruction, InstructionContext> contexts = new MultiValueMap<>();
|
||||
private boolean buildGraph; // if true the frame graph is built and execution hasJumped also compares previous instructions
|
||||
private Graph graph = new Graph();
|
||||
|
||||
public Execution(ClassGroup group)
|
||||
{
|
||||
@@ -125,7 +123,6 @@ public class Execution
|
||||
|
||||
public void run()
|
||||
{
|
||||
initializeGraph();
|
||||
|
||||
int fcount = 0;
|
||||
while (!frames.isEmpty())
|
||||
@@ -147,106 +144,10 @@ public class Execution
|
||||
System.out.println("Processed " + fcount + " frames");
|
||||
}
|
||||
|
||||
public Collection<InstructionContext> getInstructonContexts(Instruction i)
|
||||
{
|
||||
return contexts.getCollection(i);
|
||||
}
|
||||
|
||||
public boolean isBuildGraph()
|
||||
{
|
||||
return buildGraph;
|
||||
}
|
||||
|
||||
public void setBuildGraph(boolean buildGraph)
|
||||
{
|
||||
this.buildGraph = buildGraph;
|
||||
|
||||
}
|
||||
|
||||
private void initializeGraph()
|
||||
{
|
||||
if (!isBuildGraph())
|
||||
return;
|
||||
|
||||
for (ClassFile cf : this.group.getClasses())
|
||||
{
|
||||
//graph.addVertex(cf, VertexType.CLASS);
|
||||
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
if (m.isStatic() && !m.getName().equals("<clinit>"))
|
||||
continue;
|
||||
|
||||
graph.addVertex(m, VertexType.METHOD);
|
||||
}
|
||||
|
||||
for (Field f : cf.getFields().getFields())
|
||||
{
|
||||
graph.addVertex(f, VertexType.FIELD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void buildGraph(Frame frame, Instruction i, InstructionContext ctx)
|
||||
{
|
||||
if (!isBuildGraph())
|
||||
return;
|
||||
|
||||
assert frame.getMethod() == frame.nonStatic || frame.nonStatic.isStatic() == false;
|
||||
assert ctx.getInstruction() == i;
|
||||
|
||||
if (i instanceof InvokeInstruction)
|
||||
{
|
||||
if (i instanceof InvokeStatic)
|
||||
return;
|
||||
|
||||
InvokeInstruction ii = (InvokeInstruction) i;
|
||||
|
||||
List<Method> methods = ii.getMethods();
|
||||
if (methods.isEmpty())
|
||||
return;
|
||||
|
||||
for (Method m : methods)
|
||||
{
|
||||
graph.addEdge(new Edge(ctx, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(m), EdgeType.INVOKE));
|
||||
graph.addEdge(new Edge(ctx, graph.getVertexFor(m), graph.getVertexFor(frame.nonStatic), EdgeType.INVOKED_FROM));
|
||||
}
|
||||
}
|
||||
else if (i instanceof FieldInstruction)
|
||||
{
|
||||
FieldInstruction fi = (FieldInstruction) i;
|
||||
|
||||
if (fi.getMyField() == null)
|
||||
return;
|
||||
|
||||
EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD;
|
||||
graph.addEdge(new Edge(ctx, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(fi.getMyField()), type));
|
||||
EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM;
|
||||
graph.addEdge(new Edge(ctx, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(frame.nonStatic), typeRev));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<InstructionContext> getInsInExpr(InstructionContext ctx, Set<Instruction> set)
|
||||
{
|
||||
List<InstructionContext> l = new ArrayList<>();
|
||||
|
||||
if (ctx == null || set.contains(ctx.getInstruction()))
|
||||
return l;
|
||||
|
||||
set.add(ctx.getInstruction());
|
||||
|
||||
l.add(ctx);
|
||||
|
||||
for (StackContext s : ctx.getPops())
|
||||
l.addAll(getInsInExpr(s.getPushed(), set));
|
||||
for (StackContext s : ctx.getPushes())
|
||||
for (InstructionContext i : s.getPopped())
|
||||
l.addAll(getInsInExpr(i, set));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
public Graph getGraph()
|
||||
{
|
||||
return graph;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,8 +209,6 @@ public class Frame
|
||||
if (!executing)
|
||||
break;
|
||||
|
||||
execution.buildGraph(this, oldCur, ictx);
|
||||
|
||||
if (oldCur == cur)
|
||||
{
|
||||
int idx = instructions.indexOf(cur);
|
||||
|
||||
@@ -17,6 +17,7 @@ public class InstructionContext
|
||||
private List<StackContext> pushes = new ArrayList<>(); // stack contexts pushed by instruction execution
|
||||
private List<VariableContext> reads = new ArrayList<>(); // lvt reads
|
||||
private List<Method> invokes = new ArrayList<>(); // invokes
|
||||
private List<Frame> branches = new ArrayList<>();
|
||||
|
||||
public InstructionContext(Instruction i, Frame f)
|
||||
{
|
||||
@@ -55,6 +56,14 @@ public class InstructionContext
|
||||
invokes.add(method);
|
||||
}
|
||||
|
||||
public void branch(Frame frame)
|
||||
{
|
||||
assert frame != this.frame;
|
||||
assert !branches.contains(frame);
|
||||
|
||||
branches.add(frame);
|
||||
}
|
||||
|
||||
public Instruction getInstruction()
|
||||
{
|
||||
return ins;
|
||||
|
||||
@@ -23,6 +23,7 @@ public class VariableContext
|
||||
public VariableContext(Type type) // for entrypoints
|
||||
{
|
||||
this.type = type;
|
||||
value = Value.NULL;
|
||||
}
|
||||
|
||||
public VariableContext(InstructionContext i, VariableContext other)
|
||||
|
||||
Reference in New Issue
Block a user