Invoker cast args + object args

This commit is contained in:
Clisprail
2014-05-16 20:31:06 +02:00
parent 3721d20bd8
commit f0de9e9fa2
4 changed files with 28 additions and 10 deletions
@@ -3,6 +3,7 @@ package org.parabot.core.asm.adapters;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
import org.parabot.core.asm.ASMUtils; import org.parabot.core.asm.ASMUtils;
@@ -26,13 +27,14 @@ public class AddInvokerAdapter implements Opcodes, Injectable {
private String instanceCast; private String instanceCast;
private String mName; private String mName;
private String mDesc; private String mDesc;
private String argsCheckCast;
private boolean isStatic; private boolean isStatic;
public AddInvokerAdapter(final ClassNode methodLocation, public AddInvokerAdapter(final ClassNode methodLocation,
final ClassNode into, final MethodNode mn, final String mName, final String mDesc, final String argsDesc, final ClassNode into, final MethodNode mn, final String mName, final String mDesc, final String argsDesc,
final String returnDesc, final String methodName, final String returnDesc, final String methodName,
boolean isInterface, String instanceCast) { boolean isInterface, String instanceCast, String argsCheckCastDesc) {
this.into = into; this.into = into;
this.methodLocation = methodLocation; this.methodLocation = methodLocation;
this.mName = mName; this.mName = mName;
@@ -43,12 +45,16 @@ public class AddInvokerAdapter implements Opcodes, Injectable {
this.methodName = methodName; this.methodName = methodName;
this.isInterface = isInterface; this.isInterface = isInterface;
this.instanceCast = instanceCast; this.instanceCast = instanceCast;
this.argsCheckCast = argsCheckCastDesc;
} }
@Override @Override
public void inject() { public void inject() {
String mArgsDesc = argsCheckCast == null ? this.argsDesc : this.argsCheckCast;
MethodNode m = new MethodNode(ACC_PUBLIC, this.methodName, MethodNode m = new MethodNode(ACC_PUBLIC, this.methodName,
this.argsDesc + this.returnDesc, null, null); mArgsDesc + this.returnDesc, null, null);
if(!isInterface) { if(!isInterface) {
isStatic = (this.mn.access & ACC_STATIC) != 0; isStatic = (this.mn.access & ACC_STATIC) != 0;
@@ -73,9 +79,18 @@ public class AddInvokerAdapter implements Opcodes, Injectable {
} }
if (!this.argsDesc.equals("()")) { if (!this.argsDesc.equals("()")) {
for (int i = 1; i < this.argsDesc.length() - 1; i++) { Type[] castArgs = argsCheckCast == null ? null : Type.getArgumentTypes(argsCheckCast + "V");
m.visitVarInsn(ASMUtils.getLoadOpcode(this.argsDesc.substring( Type[] methodArgs = Type.getArgumentTypes(argsDesc + "V");
i, i + 1)), i);
for(int i = 0; i < methodArgs.length; i++) {
m.visitVarInsn(ASMUtils.getLoadOpcode(methodArgs[i].getDescriptor()), i + 1);
if(castArgs != null && !castArgs[i].getDescriptor().equals(methodArgs[i].getDescriptor())) {
String cast = methodArgs[i].getDescriptor();
if(cast.startsWith("L")) {
cast = cast.substring(1).replace(";", "");
}
m.visitTypeInsn(CHECKCAST, cast);
}
} }
} }
@@ -22,6 +22,7 @@ public class Invoker implements Injectable {
private String methodName; private String methodName;
private boolean isInterface; private boolean isInterface;
private String instanceCast; private String instanceCast;
private String argsCheckCastDesc;
private String mName; private String mName;
private String mDesc; private String mDesc;
@@ -29,11 +30,11 @@ public class Invoker implements Injectable {
public Invoker(String methodLoc, String invMethName, String argsDesc, public Invoker(String methodLoc, String invMethName, String argsDesc,
String returnDesc, String methodName) { String returnDesc, String methodName) {
this(methodLoc, methodLoc, invMethName, argsDesc, returnDesc, this(methodLoc, methodLoc, invMethName, argsDesc, returnDesc,
methodName, false, null); methodName, false, null, null);
} }
public Invoker(String into, String methodLoc, String invMethName, public Invoker(String into, String methodLoc, String invMethName,
String argsDesc, String returnDesc, String methodName, boolean isInterface, String instanceCast) { String argsDesc, String returnDesc, String methodName, boolean isInterface, String instanceCast, String argsCheckCastDesc) {
this.into = ASMUtils.getClass(into); this.into = ASMUtils.getClass(into);
this.methodLocation = ASMUtils.getClass(methodLoc); this.methodLocation = ASMUtils.getClass(methodLoc);
this.mn = getMethod(this.methodLocation, invMethName, argsDesc); this.mn = getMethod(this.methodLocation, invMethName, argsDesc);
@@ -45,6 +46,7 @@ public class Invoker implements Injectable {
this.mName = invMethName; this.mName = invMethName;
this.mDesc = argsDesc + returnDesc; this.mDesc = argsDesc + returnDesc;
this.argsCheckCastDesc = argsCheckCastDesc;
} }
private static MethodNode getMethod(ClassNode into, String name, String desc) { private static MethodNode getMethod(ClassNode into, String name, String desc) {
@@ -74,7 +76,7 @@ public class Invoker implements Injectable {
*/ */
public AddInvokerAdapter getAdapter() { public AddInvokerAdapter getAdapter() {
return new AddInvokerAdapter(this.methodLocation, this.into, this.mn, this.mName, this.mDesc, return new AddInvokerAdapter(this.methodLocation, this.into, this.mn, this.mName, this.mDesc,
this.argsDesc, this.returnDesc, this.methodName, this.isInterface, this.instanceCast); this.argsDesc, this.returnDesc, this.methodName, this.isInterface, this.instanceCast, this.argsCheckCastDesc);
} }
} }
@@ -185,7 +185,7 @@ public class JSONHookParser extends HookParser {
String clazz = o.containsKey("class") ? this.get(o, "class") : interfaces.get(this.get(o, "accessor")); String clazz = o.containsKey("class") ? this.get(o, "class") : interfaces.get(this.get(o, "accessor"));
String into = o.containsKey("into") ? this.get(o, "into") : clazz; String into = o.containsKey("into") ? this.get(o, "into") : clazz;
i[j] = new Invoker(into, clazz, this.get(o, "invokemethod"), this.get(o, "argdesc"), this.get(o, "desc"), this.get(o, "method"), false, null); i[j] = new Invoker(into, clazz, this.get(o, "invokemethod"), this.get(o, "argdesc"), this.get(o, "desc"), this.get(o, "method"), false, null, null);
} }
return i; return i;
} }
@@ -348,9 +348,10 @@ public class XMLHookParser extends HookParser {
final boolean isInterface = isSet("interface", addInvoker) ? Boolean.parseBoolean(getValue("interface", addInvoker)) : false; final boolean isInterface = isSet("interface", addInvoker) ? Boolean.parseBoolean(getValue("interface", addInvoker)) : false;
final String instanceCast = isSet("instancecast", addInvoker) ? getValue("instancecast", addInvoker) : null; final String instanceCast = isSet("instancecast", addInvoker) ? getValue("instancecast", addInvoker) : null;
final String checkCastArgsDesc = isSet("castargs", addInvoker) ? getValue("castargs", addInvoker) : null;
final Invoker invoker = new Invoker(into, className, invMethodName, final Invoker invoker = new Invoker(into, className, invMethodName,
argsDesc, returnDesc, methodName, isInterface, instanceCast); argsDesc, returnDesc, methodName, isInterface, instanceCast, checkCastArgsDesc);
invokerList.add(invoker); invokerList.add(invoker);
} }
return invokerList.toArray(new Invoker[invokerList.size()]); return invokerList.toArray(new Invoker[invokerList.size()]);