From c6d3620ab724cf443fd885ff9cfb61dd2c15b764 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 6 Mar 2016 15:28:11 -0500 Subject: [PATCH] Method injection works, need to @Import annotate stuff though probably. --- src/main/java/net/runelite/deob/Method.java | 19 ++++--- .../net/runelite/deob/attributes/Code.java | 9 ++-- .../code/instructions/GetField.java | 1 + .../code/instructions/GetStatic.java | 1 + .../attributes/code/instructions/Return.java | 4 +- .../net/runelite/deob/injection/Inject.java | 53 +++++++++++++++++-- .../runelite/deob/injection/InjectTest.java | 23 ++++++-- 7 files changed, 89 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index a29ba9a7fe..2182faf77d 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -17,13 +17,13 @@ import java.util.List; public class Method { - public static final int ACC_PUBLIC = 0x1; - public static final int ACC_PRIVATE = 0x2; - public static final int ACC_PROTECTED = 0x4; - public static final int ACC_STATIC = 0x8; - public static final int ACC_FINAL = 0x10; - public static final int ACC_SYNCHRONIZED = 0x20; - public static final int ACC_ABSTRACT = 0x400; + public static final short ACC_PUBLIC = 0x1; + public static final short ACC_PRIVATE = 0x2; + public static final short ACC_PROTECTED = 0x4; + public static final short ACC_STATIC = 0x8; + public static final short ACC_FINAL = 0x10; + public static final short ACC_SYNCHRONIZED = 0x20; + public static final short ACC_ABSTRACT = 0x400; private Methods methods; @@ -95,6 +95,11 @@ public class Method { return accessFlags; } + + public void setAccessFlags(short accessFlags) + { + this.accessFlags = accessFlags; + } public String getName() { diff --git a/src/main/java/net/runelite/deob/attributes/Code.java b/src/main/java/net/runelite/deob/attributes/Code.java index f12e766fe0..4f1b1ef2df 100644 --- a/src/main/java/net/runelite/deob/attributes/Code.java +++ b/src/main/java/net/runelite/deob/attributes/Code.java @@ -9,6 +9,7 @@ import net.runelite.deob.attributes.code.instruction.types.LVTInstruction; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import net.runelite.deob.signature.Signature; public class Code extends Attribute { @@ -68,8 +69,10 @@ public class Code extends Attribute private int getMaxLocalsFromSig() { Method m = super.getAttributes().getMethod(); - int num = m.isStatic() ? 0 : 1; - num += m.getDescriptor().size(); + int num = m.isStatic() ? -1 : 0; + Signature sig = m.getDescriptor(); + for (int i = 0; i < sig.size(); ++i) + num += sig.getTypeOfArg(i).getSlots(); return num; } @@ -84,7 +87,7 @@ public class Code extends Attribute LVTInstruction lvt = (LVTInstruction) ins; if (lvt.getVariableIndex() > max) - max = lvt.getVariableIndex(); + max = lvt.getVariableIndex(); // XXX if this is long or double and highest lvt, requires 2 slots } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java index c88844e5b5..712d7a1ea9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java @@ -35,6 +35,7 @@ public class GetField extends Instruction implements GetFieldInstruction super(instructions, InstructionType.GETFIELD, -1); this.field = field; + length += 2; } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index edce841f16..3c73029e20 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -35,6 +35,7 @@ public class GetStatic extends Instruction implements GetFieldInstruction super(instructions, InstructionType.GETSTATIC, -1); this.field = field; + length += 2; } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Return.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Return.java index 1c929146e3..50fd6b64c7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Return.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Return.java @@ -17,9 +17,9 @@ public class Return extends Instruction implements ReturnInstruction super(instructions, type, pc); } - public Return(Instructions instructions) + public Return(Instructions instructions, InstructionType type) { - super(instructions, InstructionType.RETURN, -1); + super(instructions, type, -1); } @Override diff --git a/src/main/java/net/runelite/deob/injection/Inject.java b/src/main/java/net/runelite/deob/injection/Inject.java index 2ff14c41ca..fa516c3f51 100644 --- a/src/main/java/net/runelite/deob/injection/Inject.java +++ b/src/main/java/net/runelite/deob/injection/Inject.java @@ -14,6 +14,7 @@ import net.runelite.deob.attributes.Attributes; import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.annotation.Annotation; import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instructions.ALoad; import net.runelite.deob.attributes.code.instructions.GetField; @@ -63,13 +64,18 @@ public class Inject { if (t.isPrimitive()) return t; + + if (!t.isObfuscatedType() && !t.getType().equals("client")) + return t; String className = t.getType(); + className = className.substring(1, className.length() - 1); // remove L ; ClassFile cf = deobfuscated.findClass(className); + assert cf != null; Annotations an = cf.getAttributes().getAnnotations(); String obfuscatedName = an.find(OBFUSCATED_NAME).getElement().getString(); - return new Type(obfuscatedName, t.getArrayDims()); + return new Type("L" + obfuscatedName + ";", t.getArrayDims()); } private Signature toObSignature(Signature s) @@ -115,8 +121,11 @@ public class Inject getter = (Number) getterAnnotation.getElement().getValue().getObject(); // the ob jar is the same as the vanilla so this field must exist in this class. - - Field otherf = other.findField(new NameAndType(obfuscatedName, toObType(f.getType()))); + + Type obType = toObType(f.getType()); + Field otherf = other.findField(new NameAndType(obfuscatedName, obType)); + if (otherf == null) + otherf = other.findField(new NameAndType(obfuscatedName, obType)); assert otherf != null; assert f.isStatic() == otherf.isStatic(); @@ -127,6 +136,11 @@ public class Inject java.lang.Class targetApiClass = f.isStatic() ? clientClass : implementingClass; // target api class for getter java.lang.reflect.Method apiMethod = findImportMethodOnApi(targetApiClass, exportedName); + if (apiMethod == null) + { + System.out.println("no api method"); + continue; + } injectGetter(targetClass, apiMethod, otherf, getter); } @@ -135,7 +149,7 @@ public class Inject { an = m.getAttributes().getAnnotations(); - if (an.find(EXPORT) == null) + if (an == null || an.find(EXPORT) == null) continue; // not an exported method String exportedName = an.find(EXPORT).getElement().getString(); @@ -204,6 +218,7 @@ public class Inject Signature sig = new Signature(); sig.setTypeOfReturnValue(field.getType()); Method getterMethod = new Method(clazz.getMethods(), method.getName(), sig); + getterMethod.setAccessFlags(Method.ACC_PUBLIC); Attributes methodAttributes = getterMethod.getAttributes(); @@ -216,16 +231,22 @@ public class Inject if (field.isStatic()) { + code.setMaxStack(1); + ins.add(new GetStatic(instructions, field.getPoolField())); } else { + code.setMaxStack(2); + ins.add(new ALoad(instructions, 0)); ins.add(new GetField(instructions, field.getPoolField())); } if (getter != null) { + code.setMaxStack(2); + assert getter instanceof Integer || getter instanceof Long; if (getter instanceof Integer) @@ -239,8 +260,30 @@ public class Inject ins.add(new LMul(instructions)); } } + + InstructionType returnType; + if (field.getType().isPrimitive() && field.getType().getArrayDims() == 0) + { + switch (field.getType().getType()) + { + case "Z": + case "I": + returnType = InstructionType.IRETURN; + break; + case "J": + returnType = InstructionType.LRETURN; + break; + default: + assert false; + return; + } + } + else + { + returnType = InstructionType.ARETURN; + } - ins.add(new Return(instructions)); + ins.add(new Return(instructions, returnType)); clazz.getMethods().addMethod(getterMethod); } diff --git a/src/test/java/net/runelite/deob/injection/InjectTest.java b/src/test/java/net/runelite/deob/injection/InjectTest.java index 9925435985..6beb315ba7 100644 --- a/src/test/java/net/runelite/deob/injection/InjectTest.java +++ b/src/test/java/net/runelite/deob/injection/InjectTest.java @@ -10,19 +10,34 @@ import java.io.IOException; import net.runelite.deob.ClassGroup; import net.runelite.deob.runeloader.MappingImporter; import net.runelite.deob.util.JarUtil; +import org.junit.After; +import org.junit.Before; import org.junit.Test; public class InjectTest { private static final File DEOBFUSCATED = new File("d:/rs/07/adamin.jar"); private static final File VANILLA = new File(MappingImporter.class.getResource("/gamepack_v16.jar").getFile()); + private static final File OUT = new File("d:/rs/07/adamout.jar"); + + private ClassGroup deob, vanilla; + + @Before + public void before() throws IOException + { + deob = JarUtil.loadJar(DEOBFUSCATED); + vanilla = JarUtil.loadJar(VANILLA); + } + + @After + public void after() throws IOException + { + JarUtil.saveJar(vanilla, OUT); + } @Test - public void testRun() throws IOException + public void testRun() { - ClassGroup deob = JarUtil.loadJar(DEOBFUSCATED), - vanilla = JarUtil.loadJar(VANILLA); - Inject instance = new Inject(deob, vanilla); instance.run(); }