diff --git a/build.gradle.kts b/build.gradle.kts index 3c702cc..b4c2b9c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ plugins { } group = "com.openosrs" -version = "1.0.2" +version = "1.0.2.1" repositories { mavenCentral() diff --git a/src/main/java/com/openosrs/injector/InjectUtil.java b/src/main/java/com/openosrs/injector/InjectUtil.java index f8a7ad5..9ac265f 100644 --- a/src/main/java/com/openosrs/injector/InjectUtil.java +++ b/src/main/java/com/openosrs/injector/InjectUtil.java @@ -13,6 +13,7 @@ import static com.openosrs.injector.rsapi.RSApi.API_BASE; import com.openosrs.injector.rsapi.RSApiClass; import com.openosrs.injector.rsapi.RSApiMethod; import java.util.List; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; import net.runelite.asm.Annotated; @@ -30,14 +31,18 @@ import net.runelite.asm.attributes.code.instructions.ALoad; import net.runelite.asm.attributes.code.instructions.DLoad; import net.runelite.asm.attributes.code.instructions.FLoad; import net.runelite.asm.attributes.code.instructions.ILoad; +import net.runelite.asm.attributes.code.instructions.IMul; import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeVirtual; +import net.runelite.asm.attributes.code.instructions.LDC; import net.runelite.asm.attributes.code.instructions.LLoad; +import net.runelite.asm.attributes.code.instructions.LMul; import net.runelite.asm.attributes.code.instructions.Return; import net.runelite.asm.attributes.code.instructions.VReturn; import net.runelite.asm.pool.Class; import net.runelite.asm.signature.Signature; import net.runelite.deob.DeobAnnotations; +import net.runelite.deob.deobfuscators.arithmetic.DMath; import org.jetbrains.annotations.Nullable; public interface InjectUtil @@ -208,7 +213,7 @@ public interface InjectUtil field = clazz.findField(name, type); if (field != null) - return data.toVanilla(field); + return field; } for (ClassFile clazz : deob) @@ -219,7 +224,7 @@ public interface InjectUtil field = clazz.findField(name, type); if (field != null) - return data.toVanilla(field); + return field; } throw new Injexception(String.format("Static field %s doesn't exist", (type != null ? type + " " : "") + name)); @@ -450,4 +455,27 @@ public interface InjectUtil String str = ((org.objectweb.asm.Type) v).getInternalName(); return data.toVanilla(data.toDeob(str)); } + + /** + * Add after the get + */ + static void injectObfuscatedGetter(Number getter, Instructions instrs, Consumer into) + { + into.accept(new LDC(instrs, getter)); + + if (getter instanceof Integer) + into.accept(new IMul(instrs)); + else if (getter instanceof Long) + into.accept(new LMul(instrs)); + } + + /** + * Add IN FRONT of the put + * + * @param getter should be the same value as for the getter (straight from ObfuscatedGetter) + */ + static void injectObfuscatedSetter(Number getter, Instructions instrs, Consumer into) + { + injectObfuscatedGetter(DMath.modInverse(getter), instrs, into); + } } diff --git a/src/main/java/com/openosrs/injector/injectors/MixinInjector.java b/src/main/java/com/openosrs/injector/injectors/MixinInjector.java index 0015b6a..e2b3ffb 100644 --- a/src/main/java/com/openosrs/injector/injectors/MixinInjector.java +++ b/src/main/java/com/openosrs/injector/injectors/MixinInjector.java @@ -53,10 +53,12 @@ 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; +import net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.asm.attributes.code.instruction.types.InvokeInstruction; import net.runelite.asm.attributes.code.instruction.types.LVTInstruction; import net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction; +import net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.asm.attributes.code.instructions.ALoad; import net.runelite.asm.attributes.code.instructions.ANewArray; import net.runelite.asm.attributes.code.instructions.CheckCast; @@ -68,7 +70,10 @@ import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.Pop; import net.runelite.asm.attributes.code.instructions.PutField; import net.runelite.asm.signature.Signature; +import net.runelite.deob.DeobAnnotations; import net.runelite.deob.util.JarUtil; +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; public class MixinInjector extends AbstractInjector { @@ -82,7 +87,7 @@ public class MixinInjector extends AbstractInjector private static final String MIXIN_BASE = "net/runelite/mixins/"; private final Map injectedFields = new HashMap<>(); - private final Map shadowFields = new HashMap<>(); + private final Map shadowFields = new HashMap<>(); private int copied = 0, replaced = 0, injected = 0; public MixinInjector(InjectData inject) @@ -230,11 +235,23 @@ public class MixinInjector extends AbstractInjector String shadowed = shadow.getElement().getString(); Field targetField = injectedFields.get(shadowed); + Number getter = null; if (targetField == null) - targetField = InjectUtil.findStaticField(inject, shadowed, null, InjectUtil.apiToDeob(inject, field.getType())); + { + final Field deobTargetField = InjectUtil.findStaticField(inject, shadowed, null, InjectUtil.apiToDeob(inject, field.getType())); + targetField = inject.toVanilla(deobTargetField); - shadowFields.put(field.getPoolField(), targetField); + getter = DeobAnnotations.getObfuscatedGetter(deobTargetField); + } + + if ((targetField.getAccessFlags() & Opcodes.ACC_PRIVATE) != 0) + throw new Injexception("Shadowed fields can't be private"); + + shadowFields.put( + field.getPoolField(), + new ShadowField(targetField, getter) + ); } } @@ -569,9 +586,25 @@ public class MixinInjector extends AbstractInjector { FieldInstruction fi = (FieldInstruction) i; - Field shadowed = shadowFields.get(fi.getField()); - if (shadowed != null) + ShadowField shadowField = shadowFields.get(fi.getField()); + + if (shadowField != null) { + Field shadowed = shadowField.targetField; + if (shadowField.obfuscatedGetter != null) + { + if (i instanceof SetFieldInstruction) + { + iterator.previous(); + InjectUtil.injectObfuscatedSetter(shadowField.obfuscatedGetter, i.getInstructions(), iterator::add); + iterator.next(); + } + else if (i instanceof GetFieldInstruction) + { + InjectUtil.injectObfuscatedGetter(shadowField.obfuscatedGetter, i.getInstructions(), iterator::add); + } + } + fi.setField(shadowed.getPoolField()); } else if (fi.getField().getClazz().getName().equals(mixinCf.getName())) @@ -670,4 +703,13 @@ public class MixinInjector extends AbstractInjector private Method obMethod; private boolean hasGarbageValue; } + + @AllArgsConstructor + private static class ShadowField + { + private Field targetField; + + @Nullable + private Number obfuscatedGetter; + } } diff --git a/src/main/java/com/openosrs/injector/injectors/RSApiInjector.java b/src/main/java/com/openosrs/injector/injectors/RSApiInjector.java index b50f0d7..6fb1bec 100644 --- a/src/main/java/com/openosrs/injector/injectors/RSApiInjector.java +++ b/src/main/java/com/openosrs/injector/injectors/RSApiInjector.java @@ -51,7 +51,6 @@ import net.runelite.asm.Method; import net.runelite.asm.Type; import net.runelite.asm.signature.Signature; import net.runelite.deob.DeobAnnotations; -import net.runelite.deob.deobfuscators.arithmetic.DMath; public class RSApiInjector extends AbstractInjector { @@ -273,7 +272,7 @@ public class RSApiInjector extends AbstractInjector targetClass, apiMethod, targetField, - modInverseOrNull(getter) + getter ); } else @@ -289,13 +288,4 @@ public class RSApiInjector extends AbstractInjector } } } - - private static Number modInverseOrNull(Number getter) - { - if (getter == null) - return null; - - // inverse getter to get the setter - return DMath.modInverse(getter); - } } diff --git a/src/main/java/com/openosrs/injector/injectors/rsapi/InjectGetter.java b/src/main/java/com/openosrs/injector/injectors/rsapi/InjectGetter.java index 80d2e68..e738e92 100644 --- a/src/main/java/com/openosrs/injector/injectors/rsapi/InjectGetter.java +++ b/src/main/java/com/openosrs/injector/injectors/rsapi/InjectGetter.java @@ -43,9 +43,6 @@ import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.instructions.ALoad; import net.runelite.asm.attributes.code.instructions.GetField; import net.runelite.asm.attributes.code.instructions.GetStatic; -import net.runelite.asm.attributes.code.instructions.IMul; -import net.runelite.asm.attributes.code.instructions.LDC; -import net.runelite.asm.attributes.code.instructions.LMul; import net.runelite.asm.signature.Signature; public class InjectGetter @@ -53,9 +50,7 @@ public class InjectGetter public static void inject(ClassFile targetClass, RSApiMethod apiMethod, Field field, Number getter) throws Injexception { if (targetClass.findMethod(apiMethod.getName(), apiMethod.getSignature()) != null) - { throw new Injexception("Duplicate getter method " + apiMethod.getMethod().toString()); - } final String name = apiMethod.getName(); final Signature sig = apiMethod.getSignature(); @@ -79,16 +74,8 @@ public class InjectGetter ins.add(new GetField(instructions, field.getPoolField())); } - if (getter instanceof Integer) - { - ins.add(new LDC(instructions, getter)); - ins.add(new IMul(instructions)); - } - else if (getter instanceof Long) - { - ins.add(new LDC(instructions, getter)); - ins.add(new LMul(instructions)); - } + if (getter != null) + InjectUtil.injectObfuscatedGetter(getter, instructions, ins::add); ins.add(InjectUtil.createReturnForType(instructions, field.getType())); diff --git a/src/main/java/com/openosrs/injector/injectors/rsapi/InjectSetter.java b/src/main/java/com/openosrs/injector/injectors/rsapi/InjectSetter.java index ef70b9d..6510af1 100644 --- a/src/main/java/com/openosrs/injector/injectors/rsapi/InjectSetter.java +++ b/src/main/java/com/openosrs/injector/injectors/rsapi/InjectSetter.java @@ -43,8 +43,6 @@ import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.instructions.ALoad; import net.runelite.asm.attributes.code.instructions.CheckCast; -import net.runelite.asm.attributes.code.instructions.IMul; -import net.runelite.asm.attributes.code.instructions.LDC; import net.runelite.asm.attributes.code.instructions.PutField; import net.runelite.asm.attributes.code.instructions.PutStatic; import net.runelite.asm.attributes.code.instructions.VReturn; @@ -52,12 +50,10 @@ import net.runelite.asm.signature.Signature; public class InjectSetter { - public static void inject(ClassFile targetClass, RSApiMethod apiMethod, Field field, Number setter) throws Injexception + public static void inject(ClassFile targetClass, RSApiMethod apiMethod, Field field, Number getter) throws Injexception { if (targetClass.findMethod(apiMethod.getName(), apiMethod.getSignature()) != null) - { throw new Injexception("Duplicate setter method " + apiMethod.getMethod().toString()); - } final String name = apiMethod.getName(); final Signature sig = apiMethod.getSignature(); @@ -73,9 +69,7 @@ public class InjectSetter // load this if (!field.isStatic()) - { ins.add(new ALoad(instructions, 0)); - } // load argument final Type argumentType = sig.getTypeOfArg(0); @@ -90,25 +84,13 @@ public class InjectSetter ins.add(checkCast); } - if (setter instanceof Integer) - { - ins.add(new LDC(instructions, setter)); - ins.add(new IMul(instructions)); - } - else if (setter instanceof Long) - { - ins.add(new LDC(instructions, setter)); - ins.add(new IMul(instructions)); - } + if (getter != null) + InjectUtil.injectObfuscatedSetter(getter, instructions, ins::add); if (field.isStatic()) - { ins.add(new PutStatic(instructions, field)); - } else - { ins.add(new PutField(instructions, field)); - } ins.add(new VReturn(instructions)); diff --git a/src/test/java/com/openosrs/injector/injectors/MixinInjectorTest.java b/src/test/java/com/openosrs/injector/injectors/MixinInjectorTest.java index cdb794a..aea7fe5 100644 --- a/src/test/java/com/openosrs/injector/injectors/MixinInjectorTest.java +++ b/src/test/java/com/openosrs/injector/injectors/MixinInjectorTest.java @@ -32,6 +32,7 @@ import java.io.InputStream; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.ListIterator; import java.util.Map; import javax.inject.Provider; import net.runelite.api.mixins.Copy; @@ -42,12 +43,15 @@ import net.runelite.asm.ClassGroup; import net.runelite.asm.Field; import net.runelite.asm.Method; import static net.runelite.asm.Type.INT; +import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.instructions.GetStatic; +import net.runelite.asm.attributes.code.instructions.IMul; import net.runelite.asm.attributes.code.instructions.InvokeVirtual; import net.runelite.asm.attributes.code.instructions.LDC; import net.runelite.asm.signature.Signature; import net.runelite.asm.visitors.ClassFileVisitor; import net.runelite.deob.util.JarUtil; +import net.runelite.mapping.ObfuscatedGetter; import net.runelite.mapping.ObfuscatedName; import net.runelite.mapping.ObfuscatedSignature; import static org.junit.Assert.assertEquals; @@ -61,7 +65,8 @@ import static org.objectweb.asm.Opcodes.ACC_STATIC; class DeobTarget { @ObfuscatedName("ob_foo4") - private static int foo4; + @ObfuscatedGetter(intValue = 1157381415) + static int foo4; @ObfuscatedName("ob_foo3") @ObfuscatedSignature( @@ -77,7 +82,7 @@ class DeobTarget class VanillaTarget { - private static int ob_foo4; + static int ob_foo4; private void ob_foo3(int garbageValue) { @@ -208,6 +213,8 @@ public class MixinInjectorTest return true; }) .count(), 1); + + assert getStaticHasGetter(ob_foo3, "ob_foo4"); // Check that the "foo3()" call in the new code body was mapped to the copy assertEquals(ob_foo3 .getCode() @@ -272,6 +279,20 @@ public class MixinInjectorTest .count(), 1); } + private boolean getStaticHasGetter(Method ob_foo3, String gottenField) + { + ListIterator it = ob_foo3.getCode().getInstructions().listIterator(); + Instruction i; + while (it.hasNext() && + !((i = it.next()) instanceof GetStatic && + ((GetStatic) i).getField().getName().equals(gottenField))); + + return + (i = it.next()) instanceof LDC && + ((LDC) i).getConstantAsInt() == 1157381415 && + it.next() instanceof IMul; + } + private static ClassFile loadClass(Class clazz) { try (InputStream is = clazz.getClassLoader().getResourceAsStream(clazz.getName().replace('.', '/') + ".class"))