From 8f2adb818575ca4ebdf7795edacb182499b41407 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Wed, 30 Oct 2019 09:35:21 +0100 Subject: [PATCH] Fix mixins with multiple targets, turn injectutil into a interface --- .../com/openosrs/injector/InjectUtil.java | 91 ++++++++----------- .../injector/injectors/MixinInjector.java | 81 +++++++++-------- .../injector/rsapi/RSApiClassVisitor.java | 2 +- .../rsapi/RSApiMethodAnnotationVisitor.java | 23 +---- .../injector/rsapi/RSApiMethodVisitor.java | 7 +- 5 files changed, 88 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/openosrs/injector/InjectUtil.java b/src/main/java/com/openosrs/injector/InjectUtil.java index cededbd..870e2bb 100644 --- a/src/main/java/com/openosrs/injector/InjectUtil.java +++ b/src/main/java/com/openosrs/injector/InjectUtil.java @@ -31,7 +31,7 @@ import net.runelite.asm.pool.Class; import net.runelite.asm.signature.Signature; import net.runelite.deob.DeobAnnotations; -public class InjectUtil +public interface InjectUtil { /** * 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 * @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); } @@ -55,10 +55,10 @@ public class InjectUtil * * @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(); - Method method = null; + Method method; if (classHint != null) { @@ -95,7 +95,7 @@ public class InjectUtil 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); if (clazz == null) @@ -112,12 +112,12 @@ public class InjectUtil * * @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()); } - 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(); if (hintClass != null) @@ -137,7 +137,7 @@ public class InjectUtil 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 for (Method m : clazz.getMethods()) @@ -151,19 +151,7 @@ public class InjectUtil /** * Fail-fast implementation of ClassGroup.findStaticMethod */ - public static Method findStaticMethod(ClassGroup group, String name) 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 + static Method findStaticMethod(ClassGroup group, String name, Signature type) throws Injexception { Method m = group.findStaticMethod(name, type); if (m == null) @@ -176,20 +164,7 @@ public class InjectUtil /** * Fail-fast implementation of ClassFile.findMethodDeep */ - public static Method findMethodDeep(ClassFile clazz, String name) 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 + static Method findMethodDeep(ClassFile clazz, String name, Signature type) throws Injexception { Method m = clazz.findMethodDeep(name, type); if (m == null) @@ -204,7 +179,7 @@ public class InjectUtil * * well... */ - public static Field findStaticField(ClassGroup group, String name) throws Injexception + static Field findStaticField(ClassGroup group, String name) throws Injexception { for (ClassFile clazz : group) { @@ -227,10 +202,10 @@ public class InjectUtil * * @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(); - Field field = null; + Field field; if (classHint != null) { @@ -279,7 +254,7 @@ public class InjectUtil * * @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()); } @@ -287,7 +262,7 @@ public class InjectUtil /** * 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 { @@ -301,13 +276,13 @@ public class InjectUtil 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(); 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; if (hintClass != null) @@ -333,12 +308,12 @@ public class InjectUtil 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())); } - public static Signature apiToDeob(InjectData data, Signature api) + static Signature apiToDeob(InjectData data, Signature api) { return new Signature.Builder() .setReturnType(apiToDeob(data, api.getReturnValue())) @@ -349,7 +324,7 @@ public class InjectUtil ).build(); } - public static Type apiToDeob(InjectData data, Type api) + static Type apiToDeob(InjectData data, Type api) { if (api.isPrimitive()) { @@ -392,7 +367,7 @@ public class InjectUtil return api; } - public static Type deobToVanilla(InjectData data, Type deobT) + static Type deobToVanilla(InjectData data, Type deobT) { if (deobT.isPrimitive()) { @@ -408,12 +383,12 @@ public class InjectUtil 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)); } - public static boolean argsMatch(Signature a, Signature b) + static boolean argsMatch(Signature a, Signature b) { List aa = a.getArguments(); List bb = b.getArguments(); @@ -439,7 +414,7 @@ public class InjectUtil * * If the annotation doesn't exist return the current name instead. */ - public static String getObfuscatedName(T from) + static String getObfuscatedName(T from) { Annotation name = from.getAnnotations().find(DeobAnnotations.OBFUSCATED_NAME); 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. */ - public static String getExportedName(Annotated from) + static String getExportedName(Annotated from) { Annotation export = from.getAnnotations().find(DeobAnnotations.EXPORT); 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. */ - 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()) { @@ -486,7 +461,7 @@ public class InjectUtil /** * 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()) { @@ -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) { @@ -525,4 +500,14 @@ public class InjectUtil 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)); + } } diff --git a/src/main/java/com/openosrs/injector/injectors/MixinInjector.java b/src/main/java/com/openosrs/injector/injectors/MixinInjector.java index 0b55d68..ed4ecbe 100644 --- a/src/main/java/com/openosrs/injector/injectors/MixinInjector.java +++ b/src/main/java/com/openosrs/injector/injectors/MixinInjector.java @@ -19,6 +19,7 @@ import net.runelite.asm.Method; import net.runelite.asm.Type; import net.runelite.asm.attributes.Code; 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.Instructions; 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.instructions.ALoad; 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.ILoad; import net.runelite.asm.attributes.code.instructions.InvokeDynamic; @@ -78,7 +78,7 @@ public class MixinInjector extends AbstractInjector for (Map.Entry, List> entry : mixinTargets.entrySet()) { - findShadowFields(entry.getKey(), entry.getValue()); + findShadowFields(entry.getKey()); } 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 if (MIXIN.equals(annotation.getType())) { - final String str = ((org.objectweb.asm.Type) annotation.getElement().getValue()).getInternalName(); - builder.put( new Provider() { @@ -117,7 +115,7 @@ public class MixinInjector extends AbstractInjector return mixinClass; } }, - ImmutableList.of(inject.toVanilla(inject.toDeob(str))) + ImmutableList.of(InjectUtil.getVanillaClassFromAnnotationString(inject, annotation)) ); } else if (MIXINS.equals(annotation.getType())) @@ -141,15 +139,18 @@ public class MixinInjector extends AbstractInjector } }; - final List targetClasses = annotation - .getElements() - .stream() - .map(e -> ((org.objectweb.asm.Type) e.getValue()).getInternalName()) - .map(inject::toDeob) - .map(inject::toVanilla) - .collect(ImmutableList.toImmutableList()); + assert annotation.getElement() instanceof ArrayElement; + ArrayElement arr = (ArrayElement) annotation.getElement(); - builder.put(mixinProvider, targetClasses); + ImmutableList.Builder 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 mixinProvider, List targetClasses) throws Injexception + private void findShadowFields(Provider mixinProvider) throws Injexception { 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"); } - Method copy = new Method(targetClass, "copy$" + copiedName, sourceMethod.getObfuscatedSignature()); + Method copy = new Method(targetClass, "copy$" + copiedName, sourceMethod.getDescriptor()); moveCode(copy, sourceMethod.getCode()); copy.setAccessFlags(sourceMethod.getAccessFlags()); 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"); } - Type returnType = mixinMethod.getDescriptor().getReturnValue(); - Type deobReturnType = InjectUtil.apiToDeob(inject, returnType); - if (!returnType.equals(deobReturnType)) - { - ClassFile deobReturnTypeClassFile = inject.getDeobfuscated() - .findClass(deobReturnType.getInternalName()); - if (deobReturnTypeClassFile != null) - { - ClassFile obReturnTypeClass = inject.toVanilla(deobReturnTypeClassFile); + //Type returnType = mixinMethod.getDescriptor().getReturnValue(); + //Type deobReturnType = InjectUtil.apiToDeob(inject, returnType); + //if (!returnType.equals(deobReturnType)) + //{ + // ClassFile deobReturnTypeClassFile = inject.getDeobfuscated() + // .findClass(deobReturnType.getInternalName()); + // if (deobReturnTypeClassFile != null) + // { + // ClassFile obReturnTypeClass = inject.toVanilla(deobReturnTypeClassFile); - Instructions instructions = mixinMethod.getCode().getInstructions(); - ListIterator listIter = instructions.listIterator(); - while (listIter.hasNext()) - { - Instruction instr = listIter.next(); - if (instr instanceof ReturnInstruction) - { - listIter.previous(); - CheckCast checkCast = new CheckCast(instructions); - checkCast.setType(new Type(obReturnTypeClass.getName())); - listIter.add(checkCast); - listIter.next(); - } - } - } - } + // Instructions instructions = mixinMethod.getCode().getInstructions(); + // ListIterator listIter = instructions.listIterator(); + // while (listIter.hasNext()) + // { + // Instruction instr = listIter.next(); + // if (instr instanceof ReturnInstruction) + // { + // listIter.previous(); + // CheckCast checkCast = new CheckCast(instructions); + // checkCast.setType(new Type(obReturnTypeClass.getName())); + // listIter.add(checkCast); + // listIter.next(); + // } + // } + // } + //} moveCode(obMethod, mixinMethod.getCode()); diff --git a/src/main/java/com/openosrs/injector/rsapi/RSApiClassVisitor.java b/src/main/java/com/openosrs/injector/rsapi/RSApiClassVisitor.java index 48905c2..9f626df 100644 --- a/src/main/java/com/openosrs/injector/rsapi/RSApiClassVisitor.java +++ b/src/main/java/com/openosrs/injector/rsapi/RSApiClassVisitor.java @@ -10,7 +10,7 @@ public class RSApiClassVisitor extends ClassVisitor { private final RSApiClass apiClass; - public RSApiClassVisitor(RSApiClass apiClass) + RSApiClassVisitor(RSApiClass apiClass) { super(Opcodes.ASM5); this.apiClass = apiClass; diff --git a/src/main/java/com/openosrs/injector/rsapi/RSApiMethodAnnotationVisitor.java b/src/main/java/com/openosrs/injector/rsapi/RSApiMethodAnnotationVisitor.java index 1b87832..9be72f0 100644 --- a/src/main/java/com/openosrs/injector/rsapi/RSApiMethodAnnotationVisitor.java +++ b/src/main/java/com/openosrs/injector/rsapi/RSApiMethodAnnotationVisitor.java @@ -1,42 +1,27 @@ package com.openosrs.injector.rsapi; -import net.runelite.asm.Type; import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Element; +import net.runelite.asm.attributes.annotation.SimpleElement; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Opcodes; public class RSApiMethodAnnotationVisitor extends AnnotationVisitor { - private final RSApiMethod method; - private final Type type; private final Annotation annotation; - public RSApiMethodAnnotationVisitor(RSApiMethod method, Type type) + RSApiMethodAnnotationVisitor(Annotation annotation) { super(Opcodes.ASM5); - this.method = method; - this.type = type; - - annotation = new Annotation(method.getAnnotations()); - annotation.setType(type); + this.annotation = annotation; } @Override public void visit(String name, Object value) { - Element element = new Element(annotation); - - element.setName(name); - element.setValue(value); + Element element = new SimpleElement(name, value); annotation.addElement(element); } - - @Override - public void visitEnd() - { - method.getAnnotations().addAnnotation(annotation); - } } diff --git a/src/main/java/com/openosrs/injector/rsapi/RSApiMethodVisitor.java b/src/main/java/com/openosrs/injector/rsapi/RSApiMethodVisitor.java index 0f2a22b..4ebf504 100644 --- a/src/main/java/com/openosrs/injector/rsapi/RSApiMethodVisitor.java +++ b/src/main/java/com/openosrs/injector/rsapi/RSApiMethodVisitor.java @@ -1,6 +1,7 @@ package com.openosrs.injector.rsapi; import net.runelite.asm.Type; +import net.runelite.asm.attributes.annotation.Annotation; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -17,8 +18,8 @@ public class RSApiMethodVisitor extends MethodVisitor public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - final Type type = new Type(descriptor); - - return new RSApiMethodAnnotationVisitor(method, type); + Annotation annotation = new Annotation(new Type(descriptor)); + this.method.getAnnotations().addAnnotation(annotation); + return new RSApiMethodAnnotationVisitor(annotation); } }