Fix mixins with multiple targets, turn injectutil into a interface

This commit is contained in:
Lucwousin
2019-10-30 09:35:21 +01:00
parent b360349dd7
commit 8f2adb8185
5 changed files with 88 additions and 116 deletions

View File

@@ -31,7 +31,7 @@ import net.runelite.asm.pool.Class;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations; import net.runelite.deob.DeobAnnotations;
public class InjectUtil public interface InjectUtil
{ {
/** /**
* Finds a static method in deob and converts it to ob * Finds a static method in deob and converts it to ob
@@ -40,7 +40,7 @@ public class InjectUtil
* @param name The name of the method you want to find * @param name The name of the method you want to find
* @return The obfuscated version of the found method * @return The obfuscated version of the found method
*/ */
public static Method findStaticMethod(InjectData data, String name) throws Injexception static Method findStaticMethod(InjectData data, String name) throws Injexception
{ {
return findStaticMethod(data, name, null, null); return findStaticMethod(data, name, null, null);
} }
@@ -55,10 +55,10 @@ public class InjectUtil
* *
* @return The obfuscated version of the found method * @return The obfuscated version of the found method
*/ */
public static Method findStaticMethod(InjectData data, String name, String classHint, Signature sig) throws Injexception static Method findStaticMethod(InjectData data, String name, String classHint, Signature sig) throws Injexception
{ {
final ClassGroup deob = data.getDeobfuscated(); final ClassGroup deob = data.getDeobfuscated();
Method method = null; Method method;
if (classHint != null) if (classHint != null)
{ {
@@ -95,7 +95,7 @@ public class InjectUtil
throw new Injexception("Static method " + name + " doesn't exist"); throw new Injexception("Static method " + name + " doesn't exist");
} }
private static ClassFile findClassOrThrow(ClassGroup group, String name) throws Injexception static ClassFile findClassOrThrow(ClassGroup group, String name) throws Injexception
{ {
ClassFile clazz = group.findClass(name); ClassFile clazz = group.findClass(name);
if (clazz == null) if (clazz == null)
@@ -112,12 +112,12 @@ public class InjectUtil
* *
* @return The obfuscated version of the found method * @return The obfuscated version of the found method
*/ */
public static Method findStaticMethod(InjectData data, net.runelite.asm.pool.Method pool) throws Injexception static Method findStaticMethod(InjectData data, net.runelite.asm.pool.Method pool) throws Injexception
{ {
return findStaticMethod(data, pool.getName(), pool.getClazz().getName(), pool.getType()); return findStaticMethod(data, pool.getName(), pool.getClazz().getName(), pool.getType());
} }
public static Method findMethodWithArgs(InjectData data, String name, String hintClass, Signature sig) throws Injexception static Method findMethodWithArgs(InjectData data, String name, String hintClass, Signature sig) throws Injexception
{ {
final ClassGroup deob = data.getDeobfuscated(); final ClassGroup deob = data.getDeobfuscated();
if (hintClass != null) if (hintClass != null)
@@ -137,7 +137,7 @@ public class InjectUtil
throw new Injexception("Method called " + name + " with args matching " + sig + " doesn't exist"); throw new Injexception("Method called " + name + " with args matching " + sig + " doesn't exist");
} }
public static Method findMethodWithArgsDeep(InjectData data, ClassFile clazz, String name, Signature sig) throws Injexception static Method findMethodWithArgsDeep(InjectData data, ClassFile clazz, String name, Signature sig) throws Injexception
{ {
do do
for (Method m : clazz.getMethods()) for (Method m : clazz.getMethods())
@@ -151,19 +151,7 @@ public class InjectUtil
/** /**
* Fail-fast implementation of ClassGroup.findStaticMethod * Fail-fast implementation of ClassGroup.findStaticMethod
*/ */
public static Method findStaticMethod(ClassGroup group, String name) throws Injexception static Method findStaticMethod(ClassGroup group, String name, Signature type) throws Injexception
{
Method m = group.findStaticMethod(name);
if (m == null)
throw new Injexception(String.format("Method %s couldn't be found", name));
return m;
}
/**
* Fail-fast implementation of ClassGroup.findStaticMethod
*/
public static Method findStaticMethod(ClassGroup group, String name, Signature type) throws Injexception
{ {
Method m = group.findStaticMethod(name, type); Method m = group.findStaticMethod(name, type);
if (m == null) if (m == null)
@@ -176,20 +164,7 @@ public class InjectUtil
/** /**
* Fail-fast implementation of ClassFile.findMethodDeep * Fail-fast implementation of ClassFile.findMethodDeep
*/ */
public static Method findMethodDeep(ClassFile clazz, String name) throws Injexception static Method findMethodDeep(ClassFile clazz, String name, Signature type) throws Injexception
{
Method m = clazz.findMethodDeep(name);
if (m == null)
{
throw new Injexception(String.format("Method %s couldn't be found", name));
}
return m;
}
/**
* Fail-fast implementation of ClassFile.findMethodDeep
*/
public static Method findMethodDeep(ClassFile clazz, String name, Signature type) throws Injexception
{ {
Method m = clazz.findMethodDeep(name, type); Method m = clazz.findMethodDeep(name, type);
if (m == null) if (m == null)
@@ -204,7 +179,7 @@ public class InjectUtil
* *
* well... * well...
*/ */
public static Field findStaticField(ClassGroup group, String name) throws Injexception static Field findStaticField(ClassGroup group, String name) throws Injexception
{ {
for (ClassFile clazz : group) for (ClassFile clazz : group)
{ {
@@ -227,10 +202,10 @@ public class InjectUtil
* *
* @return The obfuscated version of the found field * @return The obfuscated version of the found field
*/ */
public static Field findStaticField(InjectData data, String name, String classHint, Type type) throws Injexception static Field findStaticField(InjectData data, String name, String classHint, Type type) throws Injexception
{ {
final ClassGroup deob = data.getDeobfuscated(); final ClassGroup deob = data.getDeobfuscated();
Field field = null; Field field;
if (classHint != null) if (classHint != null)
{ {
@@ -279,7 +254,7 @@ public class InjectUtil
* *
* @return The obfuscated version of the found field * @return The obfuscated version of the found field
*/ */
public static Field findStaticField(InjectData data, net.runelite.asm.pool.Field pool) throws Injexception static Field findStaticField(InjectData data, net.runelite.asm.pool.Field pool) throws Injexception
{ {
return findStaticField(data, pool.getName(), pool.getClazz().getName(), pool.getType()); return findStaticField(data, pool.getName(), pool.getClazz().getName(), pool.getType());
} }
@@ -287,7 +262,7 @@ public class InjectUtil
/** /**
* Fail-fast implementation of ClassGroup.findFieldDeep * Fail-fast implementation of ClassGroup.findFieldDeep
*/ */
public static Field findFieldDeep(ClassFile clazz, String name) throws Injexception static Field findFieldDeep(ClassFile clazz, String name) throws Injexception
{ {
do do
{ {
@@ -301,13 +276,13 @@ public class InjectUtil
throw new Injexception("Couldn't find field " + name); throw new Injexception("Couldn't find field " + name);
} }
public static Field findField(InjectData data, String name, String hintClass) throws Injexception static Field findField(InjectData data, String name, String hintClass) throws Injexception
{ {
final ClassGroup deob = data.getDeobfuscated(); final ClassGroup deob = data.getDeobfuscated();
return data.toVanilla(findField(deob, name, hintClass)); return data.toVanilla(findField(deob, name, hintClass));
} }
public static Field findField(ClassGroup group, String name, String hintClass) throws Injexception static Field findField(ClassGroup group, String name, String hintClass) throws Injexception
{ {
Field field; Field field;
if (hintClass != null) if (hintClass != null)
@@ -333,12 +308,12 @@ public class InjectUtil
throw new Injexception("Field " + name + " doesn't exist"); throw new Injexception("Field " + name + " doesn't exist");
} }
public static ClassFile fromApiMethod(InjectData data, RSApiMethod apiMethod) static ClassFile fromApiMethod(InjectData data, RSApiMethod apiMethod)
{ {
return data.toVanilla(data.toDeob(apiMethod.getClazz().getName())); return data.toVanilla(data.toDeob(apiMethod.getClazz().getName()));
} }
public static Signature apiToDeob(InjectData data, Signature api) static Signature apiToDeob(InjectData data, Signature api)
{ {
return new Signature.Builder() return new Signature.Builder()
.setReturnType(apiToDeob(data, api.getReturnValue())) .setReturnType(apiToDeob(data, api.getReturnValue()))
@@ -349,7 +324,7 @@ public class InjectUtil
).build(); ).build();
} }
public static Type apiToDeob(InjectData data, Type api) static Type apiToDeob(InjectData data, Type api)
{ {
if (api.isPrimitive()) if (api.isPrimitive())
{ {
@@ -392,7 +367,7 @@ public class InjectUtil
return api; return api;
} }
public static Type deobToVanilla(InjectData data, Type deobT) static Type deobToVanilla(InjectData data, Type deobT)
{ {
if (deobT.isPrimitive()) if (deobT.isPrimitive())
{ {
@@ -408,12 +383,12 @@ public class InjectUtil
return Type.getType("L" + data.toVanilla(deobClass).getName() + ";", deobT.getDimensions()); return Type.getType("L" + data.toVanilla(deobClass).getName() + ";", deobT.getDimensions());
} }
public static boolean apiToDeobSigEquals(InjectData data, Signature deobSig, Signature apiSig) static boolean apiToDeobSigEquals(InjectData data, Signature deobSig, Signature apiSig)
{ {
return deobSig.equals(apiToDeob(data, apiSig)); return deobSig.equals(apiToDeob(data, apiSig));
} }
public static boolean argsMatch(Signature a, Signature b) static boolean argsMatch(Signature a, Signature b)
{ {
List<Type> aa = a.getArguments(); List<Type> aa = a.getArguments();
List<Type> bb = b.getArguments(); List<Type> bb = b.getArguments();
@@ -439,7 +414,7 @@ public class InjectUtil
* *
* If the annotation doesn't exist return the current name instead. * If the annotation doesn't exist return the current name instead.
*/ */
public static <T extends Annotated & Named> String getObfuscatedName(T from) static <T extends Annotated & Named> String getObfuscatedName(T from)
{ {
Annotation name = from.getAnnotations().find(DeobAnnotations.OBFUSCATED_NAME); Annotation name = from.getAnnotations().find(DeobAnnotations.OBFUSCATED_NAME);
return name == null ? from.getName() : name.getElement().getString(); return name == null ? from.getName() : name.getElement().getString();
@@ -448,7 +423,7 @@ public class InjectUtil
/** /**
* Gets the value of the @Export annotation on the object. * Gets the value of the @Export annotation on the object.
*/ */
public static String getExportedName(Annotated from) static String getExportedName(Annotated from)
{ {
Annotation export = from.getAnnotations().find(DeobAnnotations.EXPORT); Annotation export = from.getAnnotations().find(DeobAnnotations.EXPORT);
return export == null ? null : export.getElement().getString(); return export == null ? null : export.getElement().getString();
@@ -457,7 +432,7 @@ public class InjectUtil
/** /**
* Creates the correct load instruction for the variable with Type type and var index index. * Creates the correct load instruction for the variable with Type type and var index index.
*/ */
public static Instruction createLoadForTypeIndex(Instructions instructions, Type type, int index) static Instruction createLoadForTypeIndex(Instructions instructions, Type type, int index)
{ {
if (type.getDimensions() > 0 || !type.isPrimitive()) if (type.getDimensions() > 0 || !type.isPrimitive())
{ {
@@ -486,7 +461,7 @@ public class InjectUtil
/** /**
* Creates the right return instruction for an object with Type type * Creates the right return instruction for an object with Type type
*/ */
public static Instruction createReturnForType(Instructions instructions, Type type) static Instruction createReturnForType(Instructions instructions, Type type)
{ {
if (!type.isPrimitive()) if (!type.isPrimitive())
{ {
@@ -514,7 +489,7 @@ public class InjectUtil
} }
} }
public static Instruction createInvokeFor(Instructions instructions, net.runelite.asm.pool.Method method, boolean isStatic) static Instruction createInvokeFor(Instructions instructions, net.runelite.asm.pool.Method method, boolean isStatic)
{ {
if (isStatic) if (isStatic)
{ {
@@ -525,4 +500,14 @@ public class InjectUtil
return new InvokeVirtual(instructions, method); return new InvokeVirtual(instructions, method);
} }
} }
/**
* Legit fuck annotations
*/
static ClassFile getVanillaClassFromAnnotationString(InjectData data, Annotation annotation)
{
Object v = annotation.getElement().getValue();
String str = ((org.objectweb.asm.Type) v).getInternalName();
return data.toVanilla(data.toDeob(str));
}
} }

View File

@@ -19,6 +19,7 @@ import net.runelite.asm.Method;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code; import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.ArrayElement;
import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instruction.types.FieldInstruction; import net.runelite.asm.attributes.code.instruction.types.FieldInstruction;
@@ -28,7 +29,6 @@ import net.runelite.asm.attributes.code.instruction.types.PushConstantInstructio
import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction; import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction;
import net.runelite.asm.attributes.code.instructions.ALoad; import net.runelite.asm.attributes.code.instructions.ALoad;
import net.runelite.asm.attributes.code.instructions.ANewArray; import net.runelite.asm.attributes.code.instructions.ANewArray;
import net.runelite.asm.attributes.code.instructions.CheckCast;
import net.runelite.asm.attributes.code.instructions.GetField; import net.runelite.asm.attributes.code.instructions.GetField;
import net.runelite.asm.attributes.code.instructions.ILoad; import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.InvokeDynamic; import net.runelite.asm.attributes.code.instructions.InvokeDynamic;
@@ -78,7 +78,7 @@ public class MixinInjector extends AbstractInjector
for (Map.Entry<Provider<ClassFile>, List<ClassFile>> entry : mixinTargets.entrySet()) for (Map.Entry<Provider<ClassFile>, List<ClassFile>> entry : mixinTargets.entrySet())
{ {
findShadowFields(entry.getKey(), entry.getValue()); findShadowFields(entry.getKey());
} }
log.info("Shadowed {} fields", shadowFields.size()); log.info("Shadowed {} fields", shadowFields.size());
@@ -106,8 +106,6 @@ public class MixinInjector extends AbstractInjector
// to make sure we aren't changing code in all classes at once // to make sure we aren't changing code in all classes at once
if (MIXIN.equals(annotation.getType())) if (MIXIN.equals(annotation.getType()))
{ {
final String str = ((org.objectweb.asm.Type) annotation.getElement().getValue()).getInternalName();
builder.put( builder.put(
new Provider<ClassFile>() new Provider<ClassFile>()
{ {
@@ -117,7 +115,7 @@ public class MixinInjector extends AbstractInjector
return mixinClass; return mixinClass;
} }
}, },
ImmutableList.of(inject.toVanilla(inject.toDeob(str))) ImmutableList.of(InjectUtil.getVanillaClassFromAnnotationString(inject, annotation))
); );
} }
else if (MIXINS.equals(annotation.getType())) else if (MIXINS.equals(annotation.getType()))
@@ -141,15 +139,18 @@ public class MixinInjector extends AbstractInjector
} }
}; };
final List<ClassFile> targetClasses = annotation assert annotation.getElement() instanceof ArrayElement;
.getElements() ArrayElement arr = (ArrayElement) annotation.getElement();
.stream()
.map(e -> ((org.objectweb.asm.Type) e.getValue()).getInternalName())
.map(inject::toDeob)
.map(inject::toVanilla)
.collect(ImmutableList.toImmutableList());
builder.put(mixinProvider, targetClasses); ImmutableList.Builder<ClassFile> b = ImmutableList.builder();
for (Object ob : arr)
{
assert ob instanceof Annotation;
b.add(InjectUtil.getVanillaClassFromAnnotationString(inject, (Annotation) ob));
}
builder.put(mixinProvider, b.build());
} }
} }
} }
@@ -195,7 +196,7 @@ public class MixinInjector extends AbstractInjector
} }
} }
private void findShadowFields(Provider<ClassFile> mixinProvider, List<ClassFile> targetClasses) throws Injexception private void findShadowFields(Provider<ClassFile> mixinProvider) throws Injexception
{ {
final ClassFile mixinClass = mixinProvider.get(); final ClassFile mixinClass = mixinProvider.get();
@@ -267,7 +268,7 @@ public class MixinInjector extends AbstractInjector
throw new Injexception("Mixin methods cannot have more parameters than their corresponding ob method"); throw new Injexception("Mixin methods cannot have more parameters than their corresponding ob method");
} }
Method copy = new Method(targetClass, "copy$" + copiedName, sourceMethod.getObfuscatedSignature()); Method copy = new Method(targetClass, "copy$" + copiedName, sourceMethod.getDescriptor());
moveCode(copy, sourceMethod.getCode()); moveCode(copy, sourceMethod.getCode());
copy.setAccessFlags(sourceMethod.getAccessFlags()); copy.setAccessFlags(sourceMethod.getAccessFlags());
copy.setPublic(); copy.setPublic();
@@ -444,32 +445,32 @@ public class MixinInjector extends AbstractInjector
throw new Injexception("Mixin methods cannot have more parameters than their corresponding ob method"); throw new Injexception("Mixin methods cannot have more parameters than their corresponding ob method");
} }
Type returnType = mixinMethod.getDescriptor().getReturnValue(); //Type returnType = mixinMethod.getDescriptor().getReturnValue();
Type deobReturnType = InjectUtil.apiToDeob(inject, returnType); //Type deobReturnType = InjectUtil.apiToDeob(inject, returnType);
if (!returnType.equals(deobReturnType)) //if (!returnType.equals(deobReturnType))
{ //{
ClassFile deobReturnTypeClassFile = inject.getDeobfuscated() // ClassFile deobReturnTypeClassFile = inject.getDeobfuscated()
.findClass(deobReturnType.getInternalName()); // .findClass(deobReturnType.getInternalName());
if (deobReturnTypeClassFile != null) // if (deobReturnTypeClassFile != null)
{ // {
ClassFile obReturnTypeClass = inject.toVanilla(deobReturnTypeClassFile); // ClassFile obReturnTypeClass = inject.toVanilla(deobReturnTypeClassFile);
Instructions instructions = mixinMethod.getCode().getInstructions(); // Instructions instructions = mixinMethod.getCode().getInstructions();
ListIterator<Instruction> listIter = instructions.listIterator(); // ListIterator<Instruction> listIter = instructions.listIterator();
while (listIter.hasNext()) // while (listIter.hasNext())
{ // {
Instruction instr = listIter.next(); // Instruction instr = listIter.next();
if (instr instanceof ReturnInstruction) // if (instr instanceof ReturnInstruction)
{ // {
listIter.previous(); // listIter.previous();
CheckCast checkCast = new CheckCast(instructions); // CheckCast checkCast = new CheckCast(instructions);
checkCast.setType(new Type(obReturnTypeClass.getName())); // checkCast.setType(new Type(obReturnTypeClass.getName()));
listIter.add(checkCast); // listIter.add(checkCast);
listIter.next(); // listIter.next();
} // }
} // }
} // }
} //}
moveCode(obMethod, mixinMethod.getCode()); moveCode(obMethod, mixinMethod.getCode());

View File

@@ -10,7 +10,7 @@ public class RSApiClassVisitor extends ClassVisitor
{ {
private final RSApiClass apiClass; private final RSApiClass apiClass;
public RSApiClassVisitor(RSApiClass apiClass) RSApiClassVisitor(RSApiClass apiClass)
{ {
super(Opcodes.ASM5); super(Opcodes.ASM5);
this.apiClass = apiClass; this.apiClass = apiClass;

View File

@@ -1,42 +1,27 @@
package com.openosrs.injector.rsapi; package com.openosrs.injector.rsapi;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element; import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
public class RSApiMethodAnnotationVisitor extends AnnotationVisitor public class RSApiMethodAnnotationVisitor extends AnnotationVisitor
{ {
private final RSApiMethod method;
private final Type type;
private final Annotation annotation; private final Annotation annotation;
public RSApiMethodAnnotationVisitor(RSApiMethod method, Type type) RSApiMethodAnnotationVisitor(Annotation annotation)
{ {
super(Opcodes.ASM5); super(Opcodes.ASM5);
this.method = method; this.annotation = annotation;
this.type = type;
annotation = new Annotation(method.getAnnotations());
annotation.setType(type);
} }
@Override @Override
public void visit(String name, Object value) public void visit(String name, Object value)
{ {
Element element = new Element(annotation); Element element = new SimpleElement(name, value);
element.setName(name);
element.setValue(value);
annotation.addElement(element); annotation.addElement(element);
} }
@Override
public void visitEnd()
{
method.getAnnotations().addAnnotation(annotation);
}
} }

View File

@@ -1,6 +1,7 @@
package com.openosrs.injector.rsapi; package com.openosrs.injector.rsapi;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@@ -17,8 +18,8 @@ public class RSApiMethodVisitor extends MethodVisitor
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) public AnnotationVisitor visitAnnotation(String descriptor, boolean visible)
{ {
final Type type = new Type(descriptor); Annotation annotation = new Annotation(new Type(descriptor));
this.method.getAnnotations().addAnnotation(annotation);
return new RSApiMethodAnnotationVisitor(method, type); return new RSApiMethodAnnotationVisitor(annotation);
} }
} }