Instead execute static functions inline as if they arent there to build the graph. Involved changing the executor to execute new frames as they appear. Can match my simple test method.

This commit is contained in:
Adam
2015-11-15 20:46:23 -05:00
parent c71c67fae3
commit 5e4458ae6e
5 changed files with 76 additions and 62 deletions

View File

@@ -34,6 +34,11 @@
<artifactId>gson</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>

View File

@@ -129,41 +129,35 @@ public class Rename
groupOne = one;
groupTwo = two;
Execution eone = new Execution(one);
eone.setBuildGraph(true);
eone.setFollowInvokes(false);
eone.populateInitialMethods();
List<Method> initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
eone.run();
Execution etwo = new Execution(two);
etwo.setBuildGraph(true);
etwo.setFollowInvokes(false);
etwo.populateInitialMethods();
List<Method> initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
etwo.run();
assert initial1.size() == initial2.size();
for (int i = 0; i < initial1.size(); ++i)
{
Method m1 = initial1.get(i), m2 = initial2.get(i);
assert m1.getName().equals(m2.getName());
objMap.put(m1, m2);
}
// Execution eone = new Execution(one);
// eone.setBuildGraph(true);
// eone.setFollowInvokes(false);
// eone.populateInitialMethods();
// List<Method> initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
// eone.run();
//
// Execution etwo = new Execution(two);
// etwo.setBuildGraph(true);
// etwo.setFollowInvokes(false);
// etwo.populateInitialMethods();
// List<Method> initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
// etwo.run();
//
// assert initial1.size() == initial2.size();
//
// for (int i = 0; i < initial1.size(); ++i)
// {
// Method m1 = initial1.get(i), m2 = initial2.get(i);
//
// assert m1.getName().equals(m2.getName());
//
// objMap.put(m1, m2);
// }
// process(
// initial1.get(0).getMethod(),
// initial2.get(0).getMethod()
// );
// processed.add(initial1.get(0).getMethod());
// process(
// one.findClass("class143").findMethod("run"),
// two.findClass("class143").findMethod("run")
// );
// processed.add(one.findClass("client").findMethod("init"));
process(
one.findClass("class143").findMethod("method3014"),
two.findClass("class143").findMethod("method2966")
);
for (;;)
{

View File

@@ -115,15 +115,16 @@ public class Execution
public void invoke(InstructionContext from, Method to)
{
if (!this.isFollowInvokes())
if (!this.isFollowInvokes() && !to.isStatic())
return;
if (hasInvoked(from, to))
return;
// if (hasInvoked(from, to))
// return;
Frame f = new Frame(this, to);
f.initialize(from);
this.addFrame(f);
frames.add(0, f);
//this.addFrame(f);
}
public void addMethod(Method to)

View File

@@ -19,6 +19,7 @@ import net.runelite.deob.pool.NameAndType;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.util.IdGen;
import org.apache.commons.collections4.map.MultiValueMap;
import org.apache.commons.lang3.mutable.MutableInt;
public class Frame
{
@@ -30,8 +31,9 @@ public class Frame
private Variables variables;
private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame
private MethodContext ctx;
protected int prevVertex = -1;
private List<Method> prevInvokes;
protected MutableInt prevVertex = new MutableInt(-1);
//protected int prevVertex = -1;
//private List<Method> prevInvokes;
public Frame(Execution execution, Method method)
{
@@ -68,6 +70,12 @@ public class Frame
// initialize frame from invoking context
assert ctx.getInstruction() instanceof InvokeInstruction;
if (this.getMethod().isStatic())
{
this.ctx = ctx.getFrame().ctx; // share ctx if this method is static
this.prevVertex = ctx.getFrame().prevVertex;
}
// initialize LVT. the last argument is popped first, and is at arguments[0]
List<StackContext> pops = ctx.getPops();
pops = Lists.reverse(new ArrayList<>(pops)); // reverse the list so first argument is at index 0
@@ -101,8 +109,8 @@ public class Frame
this.stack = new Stack(other.stack);
this.variables = new Variables(other.variables);
this.ctx = other.ctx;
this.prevVertex = other.prevVertex;
this.prevInvokes = other.prevInvokes;
this.prevVertex = new MutableInt(other.prevVertex);
//this.prevInvokes = other.prevInvokes;
}
public Frame dup()
@@ -193,12 +201,15 @@ public class Frame
execution.executed.add(oldCur);
if (!execution.frames.isEmpty() && execution.frames.get(0) != this)
break;
processExceptions(oldCur);
if (oldCur instanceof InvokeInstruction)
{
InvokeInstruction ii = (InvokeInstruction) oldCur;
this.prevInvokes = ii.getMethods();
// this.prevInvokes = ii.getMethods();
}
if (!executing)
@@ -253,7 +264,7 @@ public class Frame
assert to.getInstructions() == method.getCode().getInstructions();
assert method.getCode().getInstructions().getInstructions().contains(to);
if (ctx.hasJumped(this.prevInvokes, from, to))
if (ctx.hasJumped(prevVertex, from, to))
{
executing = false;
return;

View File

@@ -15,24 +15,25 @@ import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
import net.runelite.deob.util.IdGen;
import org.apache.commons.collections4.map.MultiValueMap;
import org.apache.commons.lang3.mutable.MutableInt;
class MIKey
{
private List<Method> method;
private int prevVertex;
private InstructionContext ictx;
public MIKey(List<Method> method, InstructionContext ictx)
public MIKey(int prevVertex, InstructionContext ictx)
{
this.method = method;
this.prevVertex = prevVertex;
this.ictx = ictx;
}
@Override
public int hashCode()
{
int hash = 5;
hash = 61 * hash + Objects.hashCode(this.method);
hash = 61 * hash + Objects.hashCode(this.ictx);
int hash = 7;
hash = 97 * hash + this.prevVertex;
hash = 97 * hash + Objects.hashCode(this.ictx);
return hash;
}
@@ -52,7 +53,7 @@ class MIKey
return false;
}
final MIKey other = (MIKey) obj;
if (!Objects.equals(this.method, other.method))
if (this.prevVertex != other.prevVertex)
{
return false;
}
@@ -62,8 +63,6 @@ class MIKey
}
return true;
}
}
public class MethodContext
@@ -90,10 +89,10 @@ public class MethodContext
return graph;
}
protected boolean hasJumped(List<Method> fromm, InstructionContext from, Instruction to)
protected boolean hasJumped(MutableInt prevVertex, InstructionContext from, Instruction to)
{
// with this true, there are so many frames I can't run a full execution without oom.
MIKey key = execution.isBuildGraph() ? new MIKey(fromm, from) : new MIKey(null, from);
MIKey key = execution.isBuildGraph() ? new MIKey(prevVertex.intValue(), from) : new MIKey(-1, from);
Collection<Instruction> i = visited.getCollection(key);
if (i != null && i.contains(to))
return true;
@@ -124,8 +123,8 @@ public class MethodContext
if (i instanceof InvokeInstruction)
{
// if (i instanceof InvokeStatic)
// return;
if (i instanceof InvokeStatic)
return;
InvokeInstruction ii = (InvokeInstruction) i;
@@ -145,12 +144,12 @@ public class MethodContext
return;
}
if (frame.prevVertex == -1)
if (frame.prevVertex.intValue() == -1)
{
int id = getIdFor(i);
//int id = ids.get();
//graph.add(id);
frame.prevVertex = id;
frame.prevVertex.setValue(id);
//this.idMap.put(id, i);
return;
}
@@ -160,12 +159,16 @@ public class MethodContext
//graph.add(id);
//idMap.put(id, i);
if (id == frame.prevVertex)
if (frame.prevVertex.intValue() == id)
return;
DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex, id);
InvokeInstruction from = (InvokeInstruction) this.idMap.get(frame.prevVertex.intValue()), to = (InvokeInstruction) this.idMap.get(id);
System.out.println("Added edge " + from.getMethods().get(0).getMethods().getClassFile().getName() + "." + from.getMethods().get(0).getName() +
" to " + to.getMethods().get(0).getMethods().getClassFile().getName() + "." + to.getMethods().get(0).getName());
DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex.intValue(), id);
graph.add(edge);
frame.prevVertex = id;
frame.prevVertex.setValue(id);
}
}