Don't delete constructors because it might containe stuff we actually want. Instead rename to init and invoke from constructors. Magic.

This commit is contained in:
Adam
2016-03-11 20:59:48 -05:00
parent 6e79aece20
commit 419e0da7c1
2 changed files with 52 additions and 2 deletions

View File

@@ -25,6 +25,8 @@ public class Method
public static final short ACC_SYNCHRONIZED = 0x20; public static final short ACC_SYNCHRONIZED = 0x20;
public static final short ACC_ABSTRACT = 0x400; public static final short ACC_ABSTRACT = 0x400;
public static final short ACCESS_MODIFIERS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED;
private Methods methods; private Methods methods;
private short accessFlags; private short accessFlags;
@@ -146,6 +148,11 @@ public class Method
return (accessFlags & ACC_PRIVATE) != 0; return (accessFlags & ACC_PRIVATE) != 0;
} }
public void setPrivate()
{
accessFlags = (short) ((accessFlags & ~ACCESS_MODIFIERS) | ACC_PRIVATE);
}
public Exceptions getExceptions() public Exceptions getExceptions()
{ {
return (Exceptions) attributes.findType(AttributeType.EXCEPTIONS); return (Exceptions) attributes.findType(AttributeType.EXCEPTIONS);

View File

@@ -19,8 +19,10 @@ import net.runelite.deob.attributes.code.instructions.DLoad;
import net.runelite.deob.attributes.code.instructions.FLoad; import net.runelite.deob.attributes.code.instructions.FLoad;
import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.ILoad;
import net.runelite.deob.attributes.code.instructions.InvokeSpecial; import net.runelite.deob.attributes.code.instructions.InvokeSpecial;
import net.runelite.deob.attributes.code.instructions.InvokeVirtual;
import net.runelite.deob.attributes.code.instructions.LLoad; import net.runelite.deob.attributes.code.instructions.LLoad;
import net.runelite.deob.attributes.code.instructions.New; import net.runelite.deob.attributes.code.instructions.New;
import net.runelite.deob.attributes.code.instructions.Pop;
import net.runelite.deob.attributes.code.instructions.Return; import net.runelite.deob.attributes.code.instructions.Return;
import net.runelite.deob.signature.Type; import net.runelite.deob.signature.Type;
@@ -86,15 +88,46 @@ public class InjectReplace
replaceNew(classToInject); replaceNew(classToInject);
} }
private static final String INITFN = "init";
private void injectConstructors(ClassFile classToInject) private void injectConstructors(ClassFile classToInject)
{ {
// Delete compiler generate constructors // Delete compiler generate constructors
Methods methods = classToInject.getMethods(); Methods methods = classToInject.getMethods();
Methods vanillaMethods = vanilla.getMethods(); Methods vanillaMethods = vanilla.getMethods();
for (Method m : new ArrayList<>(methods.getMethods())) boolean seen = false;
for (Method m : methods.getMethods())
if (m.getName().equals("<init>")) if (m.getName().equals("<init>"))
methods.removeMethod(m); {
assert seen == false; // only one ctor allowed
seen = true;
Code code = m.getCode();
Instructions instructions = code.getInstructions();
m.setName(INITFN); // magic
// replace invokespecial call
for (Instruction i : instructions.getInstructions())
{
if (!(i instanceof InvokeSpecial))
continue;
InvokeSpecial is = (InvokeSpecial) i;
net.runelite.deob.pool.Method method = (net.runelite.deob.pool.Method) is.getMethod();
assert method.getNameAndType().getDescriptor().size() == 0; // Replace classes must extend Object so this must be Object.init()
instructions.replace(i, new Pop(instructions)); // pop this
break;
}
m.setPrivate();
// now we'll just add a call to init in the constructors
}
// Add constructors // Add constructors
for (Method m : vanillaMethods.getMethods()) for (Method m : vanillaMethods.getMethods())
@@ -154,6 +187,15 @@ public class InjectReplace
} }
ins.add(new InvokeSpecial(instructions, m.getPoolMethod())); ins.add(new InvokeSpecial(instructions, m.getPoolMethod()));
// invoke our init func if it exists
Method initfn = methods.findMethod(INITFN);
if (initfn != null)
{
ins.add(new ALoad(instructions, 0)); // this
ins.add(new InvokeVirtual(instructions, initfn.getPoolMethod()));
}
ins.add(new Return(instructions, InstructionType.RETURN)); ins.add(new Return(instructions, InstructionType.RETURN));
methods.addMethod(constructor); methods.addMethod(constructor);
@@ -293,6 +335,7 @@ public class InjectReplace
if (i instanceof New) if (i instanceof New)
{ {
New n = (New) i; New n = (New) i;
if (!n.getNewClass().equals(vanilla.getPoolClass())) if (!n.getNewClass().equals(vanilla.getPoolClass()))
continue; continue;