diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java index 92641eb60e..a35bf2ef85 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java @@ -163,7 +163,7 @@ public class Rename2 Optional opt = m2.stream().filter(m2m -> m.getName().equals(m2m.getName()) && m.getDescriptor().equals(m2m.getDescriptor())).findAny(); if (!opt.isPresent()) continue; - + Vertex v1 = g1.getVertexFor(m); Vertex v2 = g2.getVertexFor(opt.get()); @@ -251,7 +251,7 @@ public class Rename2 assert e.getFrom() == s; boolean b = false; - if (e.toString().equals("Edge{from=Vertex{object=client.init()V}, to=Vertex{object=static Ljava/lang/String;[] class14.field209}, type=SETFIELD}")) + if (e.toString().equals("Edge{from=Vertex{object=class97.()V}, to=Vertex{object=I class97.field1653}, type=SETFIELD}")) { b = true; } @@ -260,6 +260,10 @@ public class Rename2 continue; // skip solved edges Vertex v = e.getTo(); // end of edge in g1 + if (v.toString().equals("Vertex{object=I class97.field1653}")) + { + b = true; + } List l = new ArrayList<>(); for (Edge e2 : other.getEdges()) @@ -267,17 +271,6 @@ public class Rename2 if (e2.getTo().getOther() != null) continue; // skip solved edges -// if (b2) -// { -// Method m = (Method) e2.getTo().getObject(); -// if (m.getName().equals("method2489")) -// { -// b2 = true; -// } -// } - - // e Edge{from=Vertex{object=client.init()V}, to=Vertex{object=static Ljava/lang/String;[] class14.field209}, type=SETFIELD} - // e2 Edge{from=Vertex{object=client.init()V}, to=Vertex{object=static Ljava/lang/String;[] class89.field1550}, type=SETFIELD} if (!e.getTo().couldBeEqual(e2.getTo())) { // System.out.println(e.getTo() + " != " + e2.getTo()); @@ -300,7 +293,10 @@ public class Rename2 l.add(v2); } - v.merge(l); + if (b) + v.merge(l); + else + v.merge(l); } } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java index aade7a5920..5dd06f07bb 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java @@ -1,5 +1,6 @@ package net.runelite.deob.deobfuscators.rename.graph; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -9,6 +10,7 @@ import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.instruction.types.DupInstruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.LVTInstruction; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.attributes.code.instructions.NewArray; @@ -162,7 +164,10 @@ public class Edge InstructionContext storedCtx = vctx.getInstructionWhichStored(); if (storedCtx == null) - return ctx; // parameter? + return ctx; // initial parameter + + if (vctx.isIsParameter()) + return ctx; // parameter (storedCtx is invoking instruction in another frame). this lvt index is fixed. return resolve(storedCtx, null); } @@ -171,44 +176,70 @@ public class Edge return ctx; } -// private static final String[][] map = { -// {"field1989", "field2042"}, -// {"field164", "field2156"}, -// {"field2904", "field2881"}, -// {"field296", "field287"}, -// {"field297", "field425"}, -// {"field416", "field420"}, -// {"field329", "field331"}, -// {"field2203", "field2216"}, -// {"field2202", "field2222"}, -// {"field2100", "field2109"}, -// }; -// -// private boolean isEqual(SetFieldInstruction sf1, SetFieldInstruction sf2) -// { -// for (int i = 0; i < map.length; ++i) + private List resolveUp( + List ctxs, + StackContext from // popped by ctxs + ) + { + List list = new ArrayList<>(); + + for (InstructionContext ctx : ctxs) + { + if (ctx.getInstruction() instanceof DupInstruction) + { + DupInstruction d = (DupInstruction) ctx.getInstruction(); + //StackContext s = d. + //return resolve(s.getPushed(), s); + } + + list.add(ctx); + } + + return list; +// if (ctx.getInstruction() instanceof SetFieldInstruction) // { -// if (sf1.getMyField() != null && sf1.getMyField().getName().equals(map[i][0]) && -// sf2.getMyField() != null && sf2.getMyField().getName().equals(map[i][1])) -// return true; +// StackContext s = ctx.getPops().get(0); +// return resolve(s.getPushed(), s); // } -// return false; -// } +// + +// +// if (ctx.getInstruction() instanceof LVTInstruction) +// { +// LVTInstruction lvt = (LVTInstruction) ctx.getInstruction(); +// Variables variables = ctx.getVariables(); +// +// if (lvt.store()) +// { +// StackContext s = ctx.getPops().get(0); // is this right? +// return resolve(s.getPushed(), s); +// } +// else +// { +// VariableContext vctx = variables.get(lvt.getVariableIndex()); // variable being loaded +// assert vctx != null; +// +// InstructionContext storedCtx = vctx.getInstructionWhichStored(); +// if (storedCtx == null) +// return ctx; // parameter? +// +// return resolve(storedCtx, null); +// } +// } + + // return ctx; + } private boolean compareSetField(Field field1, Field field2, InstructionContext other) { InstructionContext thisp = resolve(ins.getPops().get(0).getPushed(), ins.getPops().get(0)), otherp = resolve(other.getPops().get(0).getPushed(), other.getPops().get(0)); - return couldBeEqual(field1, field2, thisp, otherp); + return couldBeEqual(field1, field2, thisp, otherp, null); } - private boolean couldBeEqual(Field field1, Field field2, InstructionContext one, InstructionContext two) + private boolean couldBeEqual(Field field1, Field field2, InstructionContext one, InstructionContext two, InstructionContext from) { - if (field2.getName().equals("field209")) - { - int i =5; - } Instruction i1 = one.getInstruction(), i2 = two.getInstruction(); if (i1 instanceof LVTInstruction && i2 instanceof LVTInstruction) @@ -221,8 +252,12 @@ public class Edge VariableContext v1 = one.getVariables().get(l1.getVariableIndex()), v2 = two.getVariables().get(l2.getVariableIndex()); - assert v1.getInstructionWhichStored() == null; - assert v2.getInstructionWhichStored() == null; + assert v1.isIsParameter(); + assert v2.isIsParameter(); + + // resolve() resolves these unless they are parameters, so compare indexes + if (l1.getVariableIndex() != l2.getVariableIndex()) + return false; return v1.getType().equals(v2.getType()); } @@ -262,11 +297,66 @@ public class Edge //int i = 5; } + if (i1 instanceof PushConstantInstruction && i2 instanceof PushConstantInstruction) + { + PushConstantInstruction pc1 = (PushConstantInstruction) i1, pc2 = (PushConstantInstruction) i2; + + return pc1.getConstant().equals(pc2.getConstant()); + } + if (!i1.getClass().equals(i2.getClass())) { return false; } + // check down + assert one.getPops().size() == two.getPops().size(); + for (int i = 0; i < one.getPops().size(); ++i) + { + StackContext s1 = one.getPops().get(i), s2 = two.getPops().get(i); + + if (resolve(s1.getPushed(), s1) == from) + continue; + + if (!couldBeEqual( + field1, field2, + resolve(s1.getPushed(), s1), + resolve(s2.getPushed(), s2), + one + )) + return false; + } + + // check up +// assert one.getPushes().size() == two.getPushes().size(); +// for (int i = 0; i < one.getPushes().size(); ++i) +// { +// StackContext s1 = one.getPushes().get(i), s2 = two.getPushes().get(i); +// List p1 = s1.getPopped(), p2 = s2.getPopped(); // instructions which popped the push +// +// assert p1.size() == p2.size(); +// +// //resolveUp(p1, s1); +// +// for (int j = 0; j < p1.size(); ++i) +// { +// InstructionContext ic1 = p1.get(j), ic2 = p2.get(j); +// +// if (from == ic1) +// continue; +// +//// resolveUp(ic1, s1); +//// resolveUp(ic2, s2); +// +// if (!couldBeEqual( +// field1, field2, +// ic1, ic2, +// one +// )) {} +// //return false; +// } +// } + return true; } } diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index ea388d607b..71016044c6 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -48,12 +48,12 @@ public class Frame // initialize LVT int pos = 0; if (!method.isStatic()) - variables.set(pos++, new VariableContext(new Type(method.getMethods().getClassFile().getName()))); + variables.set(pos++, new VariableContext(new Type(method.getMethods().getClassFile().getName())).markParameter()); NameAndType nat = method.getNameAndType(); for (int i = 0; i < nat.getNumberOfArgs(); ++i) { - variables.set(pos, new VariableContext(new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType())); + variables.set(pos, new VariableContext(new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType()).markParameter()); pos += nat.getDescriptor().getTypeOfArg(i).getSlots(); } @@ -69,9 +69,6 @@ public class Frame if (this.getMethod().isStatic()) { this.nonStatic = ctx.getFrame().nonStatic; -// this.lastField = ctx.getFrame().lastField; -// this.staticReturn = ctx.getFrame(); - //this.ctx = ctx.getFrame().ctx; } // initialize LVT. the last argument is popped first, and is at arguments[0] @@ -80,7 +77,7 @@ public class Frame int lvtOffset = 0; if (!method.isStatic()) - variables.set(lvtOffset++, new VariableContext(ctx, pops.remove(0))); + variables.set(lvtOffset++, new VariableContext(ctx, pops.remove(0)).markParameter()); NameAndType nat = method.getNameAndType(); @@ -88,7 +85,7 @@ public class Frame { StackContext argument = pops.remove(0); - variables.set(lvtOffset, new VariableContext(ctx, argument)); + variables.set(lvtOffset, new VariableContext(ctx, argument).markParameter()); lvtOffset += nat.getDescriptor().getTypeOfArg(i).getSlots(); } diff --git a/src/main/java/net/runelite/deob/execution/InstructionContext.java b/src/main/java/net/runelite/deob/execution/InstructionContext.java index 5cbbf094e4..f0945480e4 100644 --- a/src/main/java/net/runelite/deob/execution/InstructionContext.java +++ b/src/main/java/net/runelite/deob/execution/InstructionContext.java @@ -138,4 +138,10 @@ public class InstructionContext hash = 73 * hash + Objects.hashCode(this.ins); return hash; } + + @Override + public String toString() + { + return "InstructionContext{" + "ins=" + ins + '}'; + } } diff --git a/src/main/java/net/runelite/deob/execution/VariableContext.java b/src/main/java/net/runelite/deob/execution/VariableContext.java index 72d87264f3..d51cd263ce 100644 --- a/src/main/java/net/runelite/deob/execution/VariableContext.java +++ b/src/main/java/net/runelite/deob/execution/VariableContext.java @@ -10,6 +10,7 @@ public class VariableContext private Type type; private List read = new ArrayList<>(); // instructions which reads this private Value value; + private boolean isParameter; // if is a parameter. ctx will be the invoking method (in another frame) public VariableContext(InstructionContext i, StackContext ctx) { @@ -68,5 +69,16 @@ public class VariableContext public List getRead() { return read; - } + } + + public boolean isIsParameter() + { + return isParameter; + } + + public VariableContext markParameter() + { + isParameter = true; + return this; + } }