Method injection works, need to @Import annotate stuff though probably.
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ public class GetField extends Instruction implements GetFieldInstruction
|
||||
super(instructions, InstructionType.GETFIELD, -1);
|
||||
|
||||
this.field = field;
|
||||
length += 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,7 @@ public class GetStatic extends Instruction implements GetFieldInstruction
|
||||
super(instructions, InstructionType.GETSTATIC, -1);
|
||||
|
||||
this.field = field;
|
||||
length += 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user