Add graphbuilder to statically build graph

This commit is contained in:
Adam
2015-12-12 15:19:55 -05:00
parent 540c1ac5af
commit 3ce0b0a7b9
4 changed files with 226 additions and 1 deletions

View File

@@ -46,6 +46,17 @@ public class Graph
return v;
}
public void removeVertex(Object o)
{
Vertex v = this.getVertexFor(o);
assert v.getEdges().isEmpty();
assert v.getEdgesFrom().isEmpty();
verticies.remove(v);
o2v.remove(o);
}
public void addEdge(Edge e)
{
e.getFrom().addEdge(e);

View File

@@ -0,0 +1,169 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.util.HashSet;
import java.util.List;
import net.runelite.deob.ClassFile;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.Code;
import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
public class GraphBuilder
{
public static Graph build(ClassGroup group)
{
// statically build
Graph g = new Graph();
// add verticies
for (ClassFile cf : group.getClasses())
{
//g.addVertex(cf, VertexType.CLASS);
for (Field f : cf.getFields().getFields())
{
g.addVertex(f, VertexType.FIELD);
}
for (Method m : cf.getMethods().getMethods())
{
g.addVertex(m, VertexType.METHOD);
}
}
for (ClassFile cf : group.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
processMethod(g, m);
}
}
// remove static methods
for (ClassFile cf : group.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
if (m.isStatic() && !m.getName().equals("<clinit>"))
{
removeMethod(g, m);
Vertex v = g.getVertexFor(m);
assert v.getEdges().isEmpty();
assert v.getEdgesFrom().isEmpty();
g.removeVertex(m);
}
}
}
return g;
}
private static void processMethod(Graph graph, Method method)
{
Code code = method.getCode();
if (code == null)
return;
for (Instruction i : code.getInstructions().getInstructions())
{
if (i instanceof InvokeInstruction)
{
if (i instanceof InvokeStatic)
return;
InvokeInstruction ii = (InvokeInstruction) i;
List<Method> methods = ii.getMethods();
if (methods.isEmpty())
return;
Vertex methodVertex = graph.getVertexFor(method);
for (Method m : methods)
{
Vertex otherMethodVertex = graph.getVertexFor(m);
graph.addEdge(new Edge(null, methodVertex, otherMethodVertex, EdgeType.INVOKE));
graph.addEdge(new Edge(null, otherMethodVertex, methodVertex, EdgeType.INVOKED_FROM));
}
}
else if (i instanceof FieldInstruction)
{
FieldInstruction fi = (FieldInstruction) i;
if (fi.getMyField() == null)
return;
Vertex methodVertex = graph.getVertexFor(method),
fieldVertex = graph.getVertexFor(fi.getMyField());
EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD;
graph.addEdge(new Edge(null, methodVertex, fieldVertex, type));
EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM;
graph.addEdge(new Edge(null, fieldVertex, methodVertex, typeRev));
}
}
}
private static void removeMethod(Graph g, Method m)
{
Vertex v = g.getVertexFor(m);
// for every object that points to m, make it point to
// everything that m points to, with edge type of the edge from m.
for (Edge e : new HashSet<>(v.getEdgesFrom()))
{
// edge is TO v
assert e.getTo() == v;
Vertex from = e.getFrom();
// add an edge from -> everything v is to
for (Edge e2 : new HashSet<>(v.getEdges()))
{
assert e2.getFrom() == v;
Vertex to = e2.getTo();
EdgeType type = e2.getType();
// add edge
from.addEdge(new Edge(null, from, to, type));
}
// remove
from.removeEdge(e);
}
// for every object m points to, everything that points to m should point to it.
for (Edge e : new HashSet<>(v.getEdges()))
{
assert e.getFrom() == v;
Vertex to = e.getTo();
EdgeType type = e.getType();
for (Edge e2 : new HashSet<>(v.getEdgesFrom()))
{
assert e2.getTo() == v;
// add edge from -> to
Vertex from = e2.getFrom();
from.addEdge(new Edge(null, from, to, type));
}
v.removeEdge(e);
}
}
}

View File

@@ -31,7 +31,8 @@ public class Vertex
private final Object object;
private VertexType type;
private final Set<Edge> edges = new HashSet<>();
private final Set<Edge> edges = new HashSet<>(),
from = new HashSet<>();
private Collection<Vertex> mightBe;
private Vertex is;
@@ -107,6 +108,9 @@ public class Vertex
public void addEdge(Edge edge)
{
assert edge.getFrom() == this;
//assert edge.getTo() != this;
if (edges.contains(edge))
//if (c != null)
{
@@ -118,15 +122,38 @@ public class Vertex
return;
}
Vertex to = edge.getTo();
assert to.from.contains(edge) == false;
edges.add(edge);
to.from.add(edge);
//edges.put(edge, edge);
}
public void removeEdge(Edge edge)
{
assert edge.getFrom() == this;
assert edges.contains(edge);
Vertex to = edge.getTo();
assert to.from.contains(edge);
edges.remove(edge);
to.from.remove(edge);
}
public Set<Edge> getEdges()
{
return edges;
}
public Set<Edge> getEdgesFrom()
{
return from;
}
public void merge(Collection<Vertex> maybe)
{
boolean b = false;

View File

@@ -0,0 +1,18 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.io.File;
import java.io.IOException;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.util.JarUtil;
import org.junit.Test;
public class GraphBuilderTest
{
@Test
public void test() throws IOException
{
ClassGroup group = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
GraphBuilder.build(group);
}
}