From 796bc816ee36ac042157d70363d0ad62820f7d2c Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Wed, 30 Oct 2019 10:08:37 +0100 Subject: [PATCH 1/9] Change RS api types to the ones used in rsclient --- .../src/main/java/net/runelite/rs/api/RSClient.java | 6 +++--- .../src/main/java/net/runelite/rs/api/RSWidget.java | 2 +- .../main/java/net/runelite/rs/api/RSWorldMapElement.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index a726a2a385..c0f8542430 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -454,11 +454,11 @@ public interface RSClient extends RSGameShell, Client @Import("archive8") @Override - RSAbstractArchive getIndexSprites(); + RSArchive getIndexSprites(); @Import("archive12") @Override - RSAbstractArchive getIndexScripts(); + RSArchive getIndexScripts(); @Import("widgetClickMasks") @Override @@ -1040,7 +1040,7 @@ public interface RSClient extends RSGameShell, Client RSPcmStreamMixer getSoundEffectAudioQueue(); @Import("archive4") - RSAbstractArchive getIndexCache4(); + RSArchive getIndexCache4(); @Import("decimator") RSDecimator getSoundEffectResampler(); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index f292e9c117..78ec802de9 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -446,7 +446,7 @@ public interface RSWidget extends Widget @Import("getFont") @Override - RSAbstractFont getFont(); + RSFont getFont(); @Import("fill") @Override diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapElement.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapElement.java index f627dd8a63..297da4c8e9 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapElement.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWorldMapElement.java @@ -5,7 +5,7 @@ import net.runelite.mapping.Import; public interface RSWorldMapElement extends RSDualNode, MapElementConfig { - @Import("getSprite") + @Import("getSpriteBool") @Override RSSprite getMapIcon(boolean var1); } From e9991bccdccac41d1c4e609b0ebfc056d7f0ec47 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Wed, 30 Oct 2019 10:09:59 +0100 Subject: [PATCH 2/9] Change rs api package to openosrs --- runescape-api/runescape-api.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runescape-api/runescape-api.gradle.kts b/runescape-api/runescape-api.gradle.kts index 5746b30ae4..2d9532a92e 100644 --- a/runescape-api/runescape-api.gradle.kts +++ b/runescape-api/runescape-api.gradle.kts @@ -23,7 +23,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -group = "us.runelitepl.rs" +group = "com.openosrs.rs" description = "RuneScape API" dependencies { From c84f0d5b10c2caf0cf7ea288a07e1ce0f97c6bcc Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Wed, 30 Oct 2019 10:13:08 +0100 Subject: [PATCH 3/9] Add annotations dep to deob --- deobfuscator/deobfuscator.gradle.kts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/deobfuscator/deobfuscator.gradle.kts b/deobfuscator/deobfuscator.gradle.kts index c818fa5808..a307aa9b04 100644 --- a/deobfuscator/deobfuscator.gradle.kts +++ b/deobfuscator/deobfuscator.gradle.kts @@ -35,11 +35,12 @@ dependencies { deobjars(group = "net.runelite.rs", name = "vanilla", version = ProjectVersions.rsversion.toString()) deobjars(project(":runescape-client")) - implementation(Libraries.gson) - implementation(Libraries.guava) - implementation(Libraries.fernflower) + implementation(Libraries.annotations) implementation(Libraries.asmAll) implementation(Libraries.asmUtil) + implementation(Libraries.fernflower) + implementation(Libraries.gson) + implementation(Libraries.guava) implementation(Libraries.slf4jApi) implementation(project(":runelite-api")) implementation(project(":runescape-api")) From f93984a743cb8c3a8870513675807867d72c727f Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Wed, 30 Oct 2019 10:30:37 +0100 Subject: [PATCH 4/9] Deob changes for injector and general usability --- .../main/java/net/runelite/asm/Annotated.java | 17 +++++ .../main/java/net/runelite/asm/ClassFile.java | 8 +-- .../java/net/runelite/asm/ClassGroup.java | 18 ++++- .../src/main/java/net/runelite/asm/Field.java | 9 +-- .../java/net/runelite/asm/Interfaces.java | 10 ++- .../main/java/net/runelite/asm/Method.java | 6 +- .../src/main/java/net/runelite/asm/Named.java | 6 ++ .../runelite/asm/attributes/Annotations.java | 27 +++++--- .../net/runelite/asm/attributes/Code.java | 19 +++--- .../asm/attributes/annotation/Annotation.java | 61 +++++++++++------ .../attributes/annotation/ArrayElement.java | 42 ++++++++++++ .../asm/attributes/annotation/Element.java | 57 +++++++++++----- .../attributes/annotation/SimpleElement.java | 15 ++++ .../asm/attributes/code/Instructions.java | 26 ++++++- ...tor.java => AnnotationElementVisitor.java} | 59 ++++++++++------ .../asm/visitors/ClassAnnotationVisitor.java | 68 ------------------- .../asm/visitors/ClassFieldVisitor.java | 24 +++---- .../asm/visitors/ClassFileVisitor.java | 9 ++- .../runelite/asm/visitors/CodeVisitor.java | 14 ++-- .../asm/visitors/FieldAnnotationVisitor.java | 68 ------------------- .../net/runelite/deob/DeobAnnotations.java | 2 +- .../runelite/deob/deobfuscators/Renamer.java | 1 + .../constparam/ConstantParameter.java | 10 ++- .../mapping/AnnotationMapper.java | 15 ++-- .../deob/updater/AnnotationAdder.java | 23 +++---- .../deob/updater/AnnotationCopier.java | 10 ++- .../deob/updater/AnnotationRenamer.java | 4 -- .../java/net/runelite/deob/util/JarUtil.java | 37 ++++++++++ .../java/net/runelite/osb/HookImporter.java | 5 +- 29 files changed, 365 insertions(+), 305 deletions(-) create mode 100644 deobfuscator/src/main/java/net/runelite/asm/Annotated.java create mode 100644 deobfuscator/src/main/java/net/runelite/asm/Named.java create mode 100644 deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/ArrayElement.java create mode 100644 deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/SimpleElement.java rename deobfuscator/src/main/java/net/runelite/asm/visitors/{MethodAnnotationVisitor.java => AnnotationElementVisitor.java} (62%) delete mode 100644 deobfuscator/src/main/java/net/runelite/asm/visitors/ClassAnnotationVisitor.java delete mode 100644 deobfuscator/src/main/java/net/runelite/asm/visitors/FieldAnnotationVisitor.java diff --git a/deobfuscator/src/main/java/net/runelite/asm/Annotated.java b/deobfuscator/src/main/java/net/runelite/asm/Annotated.java new file mode 100644 index 0000000000..4645fa23a2 --- /dev/null +++ b/deobfuscator/src/main/java/net/runelite/asm/Annotated.java @@ -0,0 +1,17 @@ +package net.runelite.asm; + +import java.util.Iterator; +import net.runelite.asm.attributes.Annotations; +import net.runelite.asm.attributes.annotation.Annotation; +import org.jetbrains.annotations.NotNull; + +public interface Annotated extends Iterable +{ + Annotations getAnnotations(); + + @NotNull + default Iterator iterator() + { + return getAnnotations().iterator(); + } +} diff --git a/deobfuscator/src/main/java/net/runelite/asm/ClassFile.java b/deobfuscator/src/main/java/net/runelite/asm/ClassFile.java index a5f3a6ecb6..fd2ba5a40a 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/ClassFile.java +++ b/deobfuscator/src/main/java/net/runelite/asm/ClassFile.java @@ -31,13 +31,12 @@ import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.pool.Class; import net.runelite.asm.signature.Signature; import static net.runelite.deob.DeobAnnotations.*; -import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -public class ClassFile +public class ClassFile implements Annotated, Named { private ClassGroup group; @@ -100,10 +99,9 @@ public class ClassFile visitor.visit(version, access, name.getName(), null, super_class.getName(), ints); visitor.visitSource(source, null); - for (Annotation annotation : annotations.getAnnotations()) + for (Annotation annotation : annotations) { - AnnotationVisitor av = visitor.visitAnnotation(annotation.getType().toString(), true); - annotation.accept(av); + annotation.accept(visitor.visitAnnotation(annotation.getType().toString(), true)); } for (Field field : fields) diff --git a/deobfuscator/src/main/java/net/runelite/asm/ClassGroup.java b/deobfuscator/src/main/java/net/runelite/asm/ClassGroup.java index 33ab161acc..fabde88742 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/ClassGroup.java +++ b/deobfuscator/src/main/java/net/runelite/asm/ClassGroup.java @@ -27,13 +27,16 @@ package net.runelite.asm; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import net.runelite.asm.attributes.Code; import net.runelite.asm.signature.Signature; import static net.runelite.deob.DeobAnnotations.*; +import org.jetbrains.annotations.NotNull; -public class ClassGroup +public class ClassGroup implements Iterable { private final List classes = new ArrayList<>(); // to keep order private final Map classMap = new HashMap<>(); @@ -156,4 +159,17 @@ public class ClassGroup return findClass(name); } + + @NotNull + @Override + public Iterator iterator() + { + return this.classes.iterator(); + } + + @Override + public void forEach(Consumer action) + { + this.classes.forEach(action); + } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/Field.java b/deobfuscator/src/main/java/net/runelite/asm/Field.java index 39590b021c..1a9fd7a776 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/Field.java +++ b/deobfuscator/src/main/java/net/runelite/asm/Field.java @@ -27,15 +27,13 @@ package net.runelite.asm; import net.runelite.asm.attributes.Annotations; import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.deob.DeobAnnotations; -import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Opcodes; - import static org.objectweb.asm.Opcodes.ACC_PRIVATE; import static org.objectweb.asm.Opcodes.ACC_PROTECTED; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -public class Field +public class Field implements Annotated, Named { public static final int ACCESS_MODIFIERS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED; @@ -53,15 +51,14 @@ public class Field this.name = name; this.type = type; - annotations = new Annotations(); + this.annotations = new Annotations(); } public void accept(FieldVisitor visitor) { for (Annotation annotation : annotations.getAnnotations()) { - AnnotationVisitor av = visitor.visitAnnotation(annotation.getType().toString(), true); - annotation.accept(av); + annotation.accept(visitor.visitAnnotation(annotation.getType().toString(), true)); } visitor.visitEnd(); diff --git a/deobfuscator/src/main/java/net/runelite/asm/Interfaces.java b/deobfuscator/src/main/java/net/runelite/asm/Interfaces.java index f5994ad1d3..9bc15d5100 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/Interfaces.java +++ b/deobfuscator/src/main/java/net/runelite/asm/Interfaces.java @@ -25,12 +25,14 @@ package net.runelite.asm; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; import net.runelite.asm.pool.Class; import net.runelite.deob.DeobAnnotations; +import org.jetbrains.annotations.NotNull; -public class Interfaces +public class Interfaces implements Iterable { private final ClassFile classFile; @@ -107,4 +109,10 @@ public class Interfaces return names; } + + @NotNull + public Iterator iterator() + { + return this.interfaces.iterator(); + } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/Method.java b/deobfuscator/src/main/java/net/runelite/asm/Method.java index ad7394c7be..b13e98aa3f 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/Method.java +++ b/deobfuscator/src/main/java/net/runelite/asm/Method.java @@ -36,7 +36,6 @@ import net.runelite.asm.attributes.code.Parameter; import net.runelite.asm.attributes.code.instruction.types.LVTInstruction; import net.runelite.asm.signature.Signature; import net.runelite.deob.DeobAnnotations; -import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import static org.objectweb.asm.Opcodes.ACC_FINAL; @@ -47,7 +46,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED; -public class Method +public class Method implements Annotated, Named { public static final int ACCESS_MODIFIERS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED; @@ -92,8 +91,7 @@ public class Method for (Annotation annotation : annotations.getAnnotations()) { - AnnotationVisitor av = visitor.visitAnnotation(annotation.getType().toString(), true); - annotation.accept(av); + annotation.accept(visitor.visitAnnotation(annotation.getType().toString(), true)); } if (code != null) diff --git a/deobfuscator/src/main/java/net/runelite/asm/Named.java b/deobfuscator/src/main/java/net/runelite/asm/Named.java new file mode 100644 index 0000000000..ec2bc0b6a9 --- /dev/null +++ b/deobfuscator/src/main/java/net/runelite/asm/Named.java @@ -0,0 +1,6 @@ +package net.runelite.asm; + +public interface Named +{ + String getName(); +} diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/Annotations.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/Annotations.java index b14d761c28..7c1a6ba535 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/attributes/Annotations.java +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/Annotations.java @@ -26,13 +26,16 @@ package net.runelite.asm.attributes; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; 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.jetbrains.annotations.NotNull; -public class Annotations +public class Annotations implements Iterable { private final List annotations = new ArrayList<>(); @@ -40,7 +43,7 @@ public class Annotations { return annotations; } - + public void addAnnotation(Annotation annotation) { annotations.add(annotation); @@ -55,7 +58,7 @@ public class Annotations { annotations.clear(); } - + public Annotation find(Type type) { for (Annotation a : annotations) @@ -68,18 +71,22 @@ public class Annotations { return annotations.size(); } - + public Annotation addAnnotation(Type type, String name, Object value) { - Annotation annotation = new Annotation(this); - annotation.setType(type); + Annotation annotation = new Annotation(type); addAnnotation(annotation); - - Element element = new Element(annotation); - element.setName(name); - element.setValue(value); + + Element element = new SimpleElement(name, value); annotation.addElement(element); return annotation; } + + @NotNull + @Override + public Iterator iterator() + { + return this.annotations.iterator(); + } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/Code.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/Code.java index b20c183fea..58c759844a 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/attributes/Code.java +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/Code.java @@ -41,11 +41,11 @@ public class Code private int maxStack; private Instructions instructions; private final Exceptions exceptions; - + public Code(Method method) { this.method = method; - + exceptions = new Exceptions(this); instructions = new Instructions(this); } @@ -59,12 +59,12 @@ public class Code { return maxStack; } - + public void setMaxStack(int maxStack) { this.maxStack = maxStack; } - + private int getMaxLocalsFromSig() { Method m = getMethod(); @@ -77,12 +77,11 @@ public class Code /** * calculates the size of the lvt required for this method - * @return */ public int getMaxLocals() { int max = -1; - + for (Instruction ins : instructions.getInstructions()) { if (ins instanceof LVTInstruction) @@ -96,19 +95,19 @@ public class Code } } } - + int fromSig = getMaxLocalsFromSig(); if (fromSig > max) max = fromSig; - + return max; } - + public Exceptions getExceptions() { return exceptions; } - + public Instructions getInstructions() { return instructions; diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Annotation.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Annotation.java index 7c727eb788..6f3a459eb3 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Annotation.java +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Annotation.java @@ -26,30 +26,26 @@ package net.runelite.asm.attributes.annotation; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; - import net.runelite.asm.Type; -import net.runelite.asm.attributes.Annotations; +import org.jetbrains.annotations.NotNull; import org.objectweb.asm.AnnotationVisitor; -public class Annotation +public class Annotation extends Element> implements Iterable { - private final Annotations annotations; - private Type type; - private final List elements = new ArrayList<>(); + private final Type type; - public Annotation(Annotations annotations) + public Annotation(Type type) { - this.annotations = annotations; + this.value = new ArrayList<>(); + this.type = type; } - public Annotations getAnnotations() - { - return annotations; - } - - public void setType(Type type) + public Annotation(String name, Type type) { + this.value = new ArrayList<>(); + this.name = name; this.type = type; } @@ -60,23 +56,44 @@ public class Annotation public List getElements() { - return elements; + return value; } - + public Element getElement() { - return elements.get(0); + return value.get(0); } - + public void addElement(Element element) { - elements.add(element); + value.add(element); } - + + @Override + public final void setValue(List value) + { + throw new UnsupportedOperationException(); + } + public void accept(AnnotationVisitor visitor) { - for (Element element : elements) - visitor.visit(element.getName(), element.getValue()); + if (visitor == null) + { + return; + } + + for (Element element : this) + { + accept(visitor, element.name, element.value); + } + visitor.visitEnd(); } + + @NotNull + @Override + public Iterator iterator() + { + return this.value.iterator(); + } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/ArrayElement.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/ArrayElement.java new file mode 100644 index 0000000000..b7e2b7ef84 --- /dev/null +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/ArrayElement.java @@ -0,0 +1,42 @@ +package net.runelite.asm.attributes.annotation; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; +import org.jetbrains.annotations.NotNull; + +public class ArrayElement extends Element implements Iterable +{ + public ArrayElement(String name) + { + this.name = name; + this.value = new ArrayList<>(); + } + + @SuppressWarnings("unchecked") + public void addValue(Object value) + { + this.value.add(value); + } + + @Override + public final void setValue(List value) + { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + @SuppressWarnings("unchecked") + public Iterator iterator() + { + return this.value.iterator(); + } + + @SuppressWarnings("unchecked") + public Stream stream() + { + return this.value.stream(); + } +} diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Element.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Element.java index 18fdfa33f4..10b59b5b27 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Element.java +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/Element.java @@ -25,21 +25,14 @@ package net.runelite.asm.attributes.annotation; -public class Element -{ - private final Annotation annotation; - private String name; - private Object value; - - public Element(Annotation annotation) - { - this.annotation = annotation; - } +import java.util.List; +import org.objectweb.asm.AnnotationVisitor; - public Annotation getAnnotation() - { - return annotation; - } +public abstract class Element +{ + String name = "value"; + + T value; public String getName() { @@ -51,18 +44,48 @@ public class Element this.name = name; } - public Object getValue() + public T getValue() { return value; } - public void setValue(Object value) + public void setValue(T value) { this.value = value; } - + public String getString() { return value.toString(); } + + public static void accept(AnnotationVisitor visitor, final String name, final Object value) + { + if (visitor == null) + { + return; + } + + if (value instanceof Annotation) + { + Annotation annotation = (Annotation) value; + annotation.accept(visitor.visitAnnotation(name, annotation.getType().toString())); + } + else if (value instanceof List) + { + AnnotationVisitor arr = visitor.visitArray(name); + List arrayValue = (List) value; + + for (Object o : arrayValue) + { + accept(arr, null, o); + } + + arr.visitEnd(); + } + else + { + visitor.visit(name, value); + } + } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/SimpleElement.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/SimpleElement.java new file mode 100644 index 0000000000..52e25e295c --- /dev/null +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/annotation/SimpleElement.java @@ -0,0 +1,15 @@ +package net.runelite.asm.attributes.annotation; + +public class SimpleElement extends Element +{ + public SimpleElement(Object value) + { + this.value = value; + } + + public SimpleElement(String name, Object value) + { + this.name = name; + this.value = value; + } +} diff --git a/deobfuscator/src/main/java/net/runelite/asm/attributes/code/Instructions.java b/deobfuscator/src/main/java/net/runelite/asm/attributes/code/Instructions.java index a528950d0a..212c168998 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/attributes/code/Instructions.java +++ b/deobfuscator/src/main/java/net/runelite/asm/attributes/code/Instructions.java @@ -26,11 +26,14 @@ package net.runelite.asm.attributes.code; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; import net.runelite.asm.attributes.Code; +import org.jetbrains.annotations.NotNull; -public class Instructions +public class Instructions implements Iterable { private final Code code; private final List instructions = new ArrayList<>(); @@ -186,4 +189,25 @@ public class Instructions return i; } + + public int size() + { + return this.instructions.size(); + } + + @NotNull + public Iterator iterator() + { + return this.instructions.iterator(); + } + + public ListIterator listIterator() + { + return this.instructions.listIterator(); + } + + public ListIterator listIterator(int i) + { + return this.instructions.listIterator(i); + } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/visitors/MethodAnnotationVisitor.java b/deobfuscator/src/main/java/net/runelite/asm/visitors/AnnotationElementVisitor.java similarity index 62% rename from deobfuscator/src/main/java/net/runelite/asm/visitors/MethodAnnotationVisitor.java rename to deobfuscator/src/main/java/net/runelite/asm/visitors/AnnotationElementVisitor.java index bcce61aedd..7bd5811813 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/visitors/MethodAnnotationVisitor.java +++ b/deobfuscator/src/main/java/net/runelite/asm/visitors/AnnotationElementVisitor.java @@ -25,44 +25,59 @@ package net.runelite.asm.visitors; -import net.runelite.asm.Method; 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.ArrayElement; +import net.runelite.asm.attributes.annotation.SimpleElement; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Opcodes; -public class MethodAnnotationVisitor extends AnnotationVisitor +public class AnnotationElementVisitor extends AnnotationVisitor { - private final Method method; - private final Type type; private final Annotation annotation; - - public MethodAnnotationVisitor(Method method, Type type) + + AnnotationElementVisitor(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); - + SimpleElement element = new SimpleElement(name, value); annotation.addElement(element); } - + @Override - public void visitEnd() + public AnnotationVisitor visitArray(String name) { - method.getAnnotations().addAnnotation(annotation); + ArrayElement element = new ArrayElement(name); + this.annotation.addElement(element); + return new AnnotationVisitor(Opcodes.ASM5) + { + @Override + public void visit(String name, Object value) + { + element.addValue(value); + } + + @Override + public AnnotationVisitor visitAnnotation(String name, String descriptor) + { + Annotation annotation = new Annotation(name, new Type(descriptor)); + element.addValue(annotation); + return new AnnotationElementVisitor(annotation); + } + }; + } + + @Override + public AnnotationVisitor visitAnnotation(String name, String descriptor) + { + Annotation annotation = new Annotation(name, new Type(descriptor)); + this.annotation.addElement(annotation); + return new AnnotationElementVisitor(annotation); } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassAnnotationVisitor.java b/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassAnnotationVisitor.java deleted file mode 100644 index f9f62fc82a..0000000000 --- a/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassAnnotationVisitor.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package net.runelite.asm.visitors; - -import net.runelite.asm.ClassFile; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.annotation.Annotation; -import net.runelite.asm.attributes.annotation.Element; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Opcodes; - -public class ClassAnnotationVisitor extends AnnotationVisitor -{ - private final ClassFile classFile; - private final Type type; - private final Annotation annotation; - - public ClassAnnotationVisitor(ClassFile classFile, Type type) - { - super(Opcodes.ASM5); - - this.classFile = classFile; - this.type = type; - - annotation = new Annotation(classFile.getAnnotations()); - annotation.setType(type); - } - - @Override - public void visit(String name, Object value) - { - Element element = new Element(annotation); - - element.setName(name); - element.setValue(value); - - annotation.addElement(element); - } - - @Override - public void visitEnd() - { - classFile.getAnnotations().addAnnotation(annotation); - } -} diff --git a/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFieldVisitor.java b/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFieldVisitor.java index 37478d26e3..c9012b162c 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFieldVisitor.java +++ b/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFieldVisitor.java @@ -22,12 +22,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.asm.visitors; import net.runelite.asm.ClassFile; import net.runelite.asm.Field; import net.runelite.asm.Type; +import net.runelite.asm.attributes.annotation.Annotation; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Attribute; import org.objectweb.asm.FieldVisitor; @@ -35,25 +35,25 @@ import org.objectweb.asm.Opcodes; public class ClassFieldVisitor extends FieldVisitor { - private final ClassFile classFile; private final Field field; - public ClassFieldVisitor(ClassFile cf, int access, String name, Type desc, Object value) + ClassFieldVisitor(ClassFile cf, int access, String name, Type desc, Object value) { super(Opcodes.ASM5); - this.classFile = cf; + this.field = new Field(cf, name, desc); + this.field.setAccessFlags(access); + this.field.setValue(value); - field = new Field(cf, name, desc); - field.setAccessFlags(access); - field.setValue(value); + cf.addField(field); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - Type type = new Type(desc); - return new FieldAnnotationVisitor(field, type); + Annotation element = new Annotation(new Type(desc)); + this.field.getAnnotations().addAnnotation(element); + return new AnnotationElementVisitor(element); } @Override @@ -61,10 +61,4 @@ public class ClassFieldVisitor extends FieldVisitor { System.out.println(attr); } - - @Override - public void visitEnd() - { - classFile.addField(field); - } } diff --git a/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFileVisitor.java b/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFileVisitor.java index abaf4e919d..d96ec550b1 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFileVisitor.java +++ b/deobfuscator/src/main/java/net/runelite/asm/visitors/ClassFileVisitor.java @@ -27,6 +27,7 @@ package net.runelite.asm.visitors; import net.runelite.asm.ClassFile; import net.runelite.asm.Type; +import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.signature.Signature; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassVisitor; @@ -55,7 +56,7 @@ public class ClassFileVisitor extends ClassVisitor classFile.setSuperName(superName); classFile.setVersion(version); classFile.setAccess(access); - + for (String inter : interfaces) classFile.getInterfaces().addInterface(new net.runelite.asm.pool.Class(inter)); } @@ -69,8 +70,10 @@ public class ClassFileVisitor extends ClassVisitor @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - Type type = new Type(desc); - return new ClassAnnotationVisitor(classFile, type); + Annotation annotation = new Annotation(new Type(desc)); + classFile.getAnnotations().addAnnotation(annotation); + + return new AnnotationElementVisitor(annotation); } @Override diff --git a/deobfuscator/src/main/java/net/runelite/asm/visitors/CodeVisitor.java b/deobfuscator/src/main/java/net/runelite/asm/visitors/CodeVisitor.java index d01873b83b..7746cd7a7a 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/visitors/CodeVisitor.java +++ b/deobfuscator/src/main/java/net/runelite/asm/visitors/CodeVisitor.java @@ -32,6 +32,7 @@ import net.runelite.asm.ClassFile; 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.code.Exceptions; import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.InstructionType; @@ -72,18 +73,14 @@ import static org.objectweb.asm.Opcodes.ICONST_5; import static org.objectweb.asm.Opcodes.ICONST_M1; import static org.objectweb.asm.Opcodes.LCONST_0; import static org.objectweb.asm.Opcodes.LCONST_1; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class CodeVisitor extends MethodVisitor { - private static final Logger logger = LoggerFactory.getLogger(CodeVisitor.class); - private final ClassFile classFile; private final Method method; private Code code; - public CodeVisitor(ClassFile classFile, int access, String name, Signature signature, String[] sexceptions) + CodeVisitor(ClassFile classFile, int access, String name, Signature signature, String[] sexceptions) { super(Opcodes.ASM5); @@ -111,8 +108,9 @@ public class CodeVisitor extends MethodVisitor @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - Type type = new Type(desc); - return new MethodAnnotationVisitor(method, type); + Annotation element = new Annotation(new Type(desc)); + this.method.getAnnotations().addAnnotation(element); + return new AnnotationElementVisitor(element); } @Override @@ -333,7 +331,7 @@ public class CodeVisitor extends MethodVisitor if (cst instanceof org.objectweb.asm.Type) { org.objectweb.asm.Type t = (org.objectweb.asm.Type) cst; - entry = new net.runelite.asm.pool.Class((String) t.getClassName()); + entry = new net.runelite.asm.pool.Class(t.getClassName()); } LDC ldc = new LDC(code.getInstructions(), entry); diff --git a/deobfuscator/src/main/java/net/runelite/asm/visitors/FieldAnnotationVisitor.java b/deobfuscator/src/main/java/net/runelite/asm/visitors/FieldAnnotationVisitor.java deleted file mode 100644 index 962328f272..0000000000 --- a/deobfuscator/src/main/java/net/runelite/asm/visitors/FieldAnnotationVisitor.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package net.runelite.asm.visitors; - -import net.runelite.asm.Field; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.annotation.Annotation; -import net.runelite.asm.attributes.annotation.Element; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Opcodes; - -public class FieldAnnotationVisitor extends AnnotationVisitor -{ - private final Field field; - private final Type type; - private final Annotation annotation; - - public FieldAnnotationVisitor(Field field, Type type) - { - super(Opcodes.ASM5); - - this.field = field; - this.type = type; - - annotation = new Annotation(field.getAnnotations()); - annotation.setType(type); - } - - @Override - public void visit(String name, Object value) - { - Element element = new Element(annotation); - - element.setName(name); - element.setValue(value); - - annotation.addElement(element); - } - - @Override - public void visitEnd() - { - field.getAnnotations().addAnnotation(annotation); - } -} diff --git a/deobfuscator/src/main/java/net/runelite/deob/DeobAnnotations.java b/deobfuscator/src/main/java/net/runelite/deob/DeobAnnotations.java index 2881148caa..6294574e74 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/DeobAnnotations.java +++ b/deobfuscator/src/main/java/net/runelite/deob/DeobAnnotations.java @@ -95,7 +95,7 @@ public class DeobAnnotations { return null; } - + return (Number) an.getElement().getValue(); } diff --git a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/Renamer.java b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/Renamer.java index 418802ef5a..588b840918 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/Renamer.java +++ b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/Renamer.java @@ -193,6 +193,7 @@ public class Renamer implements Deobfuscator } @Override + @SuppressWarnings("unchecked") public void run(ClassGroup group) { group.buildClassGraph(); diff --git a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/constparam/ConstantParameter.java b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/constparam/ConstantParameter.java index 0970a9b3e1..b2a0c369b3 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/constparam/ConstantParameter.java +++ b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/constparam/ConstantParameter.java @@ -37,6 +37,7 @@ import net.runelite.asm.Method; import net.runelite.asm.attributes.Annotations; import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Element; +import net.runelite.asm.attributes.annotation.SimpleElement; import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.InstructionType; import net.runelite.asm.attributes.code.Instructions; @@ -113,7 +114,6 @@ public class ConstantParameter implements Deobfuscator List pops = invokeCtx.getPops(); - outer: // object is popped first, then param 1, 2, 3, etc. double and long take two slots. for (int lvtOffset = offset, parameterIndex = 0; parameterIndex < method.getDescriptor().size(); @@ -451,9 +451,7 @@ public class ConstantParameter implements Deobfuscator } // Add garbage value - Element element = new Element(obfuscatedSignature); - element.setName("garbageValue"); - element.setValue(value.toString()); + Element element = new SimpleElement("garbageValue", value.toString()); obfuscatedSignature.addElement(element); } } @@ -464,12 +462,12 @@ public class ConstantParameter implements Deobfuscator public void run(ClassGroup group) { Execution execution = new Execution(group); - execution.addExecutionVisitor(i -> findParameters(i)); + execution.addExecutionVisitor(this::findParameters); execution.populateInitialMethods(); execution.run(); execution = new Execution(group); - execution.addMethodContextVisitor(mc -> findDeadParameters(mc)); + execution.addMethodContextVisitor(this::findDeadParameters); execution.populateInitialMethods(); execution.run(); diff --git a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/mapping/AnnotationMapper.java b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/mapping/AnnotationMapper.java index 87e01ac4ae..bd60ec165e 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/mapping/AnnotationMapper.java +++ b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/mapping/AnnotationMapper.java @@ -32,6 +32,7 @@ import net.runelite.asm.Method; import net.runelite.asm.attributes.Annotations; import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Element; +import net.runelite.asm.attributes.annotation.SimpleElement; import net.runelite.deob.DeobAnnotations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +40,7 @@ import org.slf4j.LoggerFactory; public class AnnotationMapper { private static final Logger logger = LoggerFactory.getLogger(AnnotationMapper.class); - + private final ClassGroup source, target; private final ParallelExecutorMapping mapping; @@ -119,20 +120,17 @@ public class AnnotationMapper if (from.getAnnotations() == null) return count; - + for (Annotation a : from.getAnnotations()) { if (isCopyable(a)) { - Annotation annotation = new Annotation(to); - annotation.setType(a.getType()); + Annotation annotation = new Annotation(a.getType()); to.addAnnotation(annotation); for (Element e : a.getElements()) { - Element element = new Element(annotation); - element.setName(e.getName()); - element.setValue(e.getValue()); + Element element = new SimpleElement(e.getName(), e.getValue()); annotation.addElement(element); } @@ -155,7 +153,6 @@ public class AnnotationMapper private boolean isCopyable(Annotation a) { return a.getType().equals(DeobAnnotations.EXPORT) - || a.getType().equals(DeobAnnotations.IMPLEMENTS) - || a.getType().equals(DeobAnnotations.HOOK); + || a.getType().equals(DeobAnnotations.IMPLEMENTS); } } diff --git a/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationAdder.java b/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationAdder.java index a01628d863..d2c3d62034 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationAdder.java +++ b/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationAdder.java @@ -8,6 +8,7 @@ import net.runelite.asm.Method; import net.runelite.asm.attributes.Annotations; import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Element; +import net.runelite.asm.attributes.annotation.SimpleElement; import net.runelite.deob.Deob; import net.runelite.deob.DeobAnnotations; import org.slf4j.Logger; @@ -23,6 +24,7 @@ public class AnnotationAdder private final ClassGroup group; private final Logger log = LoggerFactory.getLogger(AnnotationAdder.class); + @SuppressWarnings("unchecked") public void run() { int impl = 0; @@ -50,12 +52,9 @@ public class AnnotationAdder { Annotations an = c.getAnnotations(); - Annotation implAn = new Annotation(an); - implAn.setType(DeobAnnotations.IMPLEMENTS); + Annotation implAn = new Annotation(DeobAnnotations.IMPLEMENTS); - Element value = new Element(implAn); - value.setValue(c.getClassName()); - value.setName("value"); + Element value = new SimpleElement(c.getClassName()); implAn.addElement(value); an.addAnnotation(implAn); @@ -81,12 +80,9 @@ public class AnnotationAdder Annotation a = an.find(DeobAnnotations.EXPORT); if (a == null) { - a = new Annotation(an); - a.setType(DeobAnnotations.EXPORT); + a = new Annotation(DeobAnnotations.EXPORT); - Element value = new Element(a); - value.setValue(fieldName); - value.setName("value"); + Element value = new SimpleElement(fieldName); a.addElement(value); an.addAnnotation(a); @@ -114,12 +110,9 @@ public class AnnotationAdder Annotation a = an.find(DeobAnnotations.EXPORT); if (a == null) { - a = new Annotation(an); - a.setType(DeobAnnotations.EXPORT); + a = new Annotation(DeobAnnotations.EXPORT); - Element value = new Element(a); - value.setValue(methodName); - value.setName("value"); + Element value = new SimpleElement(methodName); a.addElement(value); an.addAnnotation(a); diff --git a/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationCopier.java b/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationCopier.java index 0c594cfe19..5d495b9029 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationCopier.java +++ b/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationCopier.java @@ -34,6 +34,7 @@ import net.runelite.asm.Type; import net.runelite.asm.attributes.Annotations; import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.annotation.Element; +import net.runelite.asm.attributes.annotation.SimpleElement; public class AnnotationCopier { @@ -97,15 +98,12 @@ public class AnnotationCopier { if (!isType(a.getType())) continue; - - Annotation a2 = new Annotation(an2); - a2.setType(a.getType()); + + Annotation a2 = new Annotation(a.getType()); for (Element element : a.getElements()) { - Element element2 = new Element(a2); - element2.setName(element.getName()); - element2.setValue(element.getValue()); + Element element2 = new SimpleElement(element.getName(), element.getValue()); a2.addElement(element2); } diff --git a/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationRenamer.java b/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationRenamer.java index 7d0f2f03d2..da920899bc 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationRenamer.java +++ b/deobfuscator/src/main/java/net/runelite/deob/updater/AnnotationRenamer.java @@ -34,13 +34,9 @@ import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.deob.DeobAnnotations; import net.runelite.deob.deobfuscators.Renamer; import net.runelite.deob.util.NameMappings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class AnnotationRenamer { - private static final Logger logger = LoggerFactory.getLogger(AnnotationRenamer.class); - private ClassGroup group; public AnnotationRenamer(ClassGroup group) diff --git a/deobfuscator/src/main/java/net/runelite/deob/util/JarUtil.java b/deobfuscator/src/main/java/net/runelite/deob/util/JarUtil.java index 1b0435d3d0..67364468c0 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/util/JarUtil.java +++ b/deobfuscator/src/main/java/net/runelite/deob/util/JarUtil.java @@ -25,9 +25,11 @@ package net.runelite.deob.util; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Collection; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -79,6 +81,41 @@ public class JarUtil return group; } + public static ClassFile loadClass(byte[] bytes) + { + ClassReader reader = new ClassReader(bytes); + ClassFileVisitor cv = new ClassFileVisitor(); + reader.accept(cv, ClassReader.SKIP_FRAMES); + return cv.getClassFile(); + } + + public static ClassGroup loadClasses(Collection files) throws IOException + { + final ClassGroup group = new ClassGroup(); + + for (File file : files) + { + if (!file.getName().endsWith(".class")) + { + continue; + } + + try (InputStream is = new FileInputStream(file)) + { + ClassReader reader = new ClassReader(is); + ClassFileVisitor cv = new ClassFileVisitor(); + + reader.accept(cv, ClassReader.SKIP_FRAMES); + + group.addClass(cv.getClassFile()); + } + } + + group.initialize(); + + return group; + } + public static void saveJar(ClassGroup group, File jarfile) throws IOException { try (JarOutputStream jout = new JarOutputStream(new FileOutputStream(jarfile), new Manifest())) diff --git a/deobfuscator/src/test/java/net/runelite/osb/HookImporter.java b/deobfuscator/src/test/java/net/runelite/osb/HookImporter.java index bf8e2bed2b..dbb17bfe55 100644 --- a/deobfuscator/src/test/java/net/runelite/osb/HookImporter.java +++ b/deobfuscator/src/test/java/net/runelite/osb/HookImporter.java @@ -276,8 +276,7 @@ public class HookImporter { for (Element e : a.getElements()) { - String str = (String) e.getValue(); - return str; + return (String) e.getValue(); } } } @@ -288,7 +287,7 @@ public class HookImporter private Signature getObfuscatedMethodSignature(Method method) { String sig = getAnnotation(method.getAnnotations(), OBFUSCATED_SIGNATURE); - if (sig.isEmpty() == false) + if (!sig.isEmpty()) { return toObSignature(new Signature(sig)); // if it is annoted, use that } From 3b36541b30060738348ea858952dab9faeaaa763 Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Wed, 30 Oct 2019 10:31:44 +0100 Subject: [PATCH 5/9] Remove duplicate api annotations --- .../java/net/runelite/mapping/Export.java | 40 ------------------- .../java/net/runelite/mapping/Import.java | 40 ------------------- .../runelite/mapping/ObfuscatedGetter.java | 39 ------------------ .../java/net/runelite/mapping/Protect.java | 40 ------------------- 4 files changed, 159 deletions(-) delete mode 100644 runelite-api/src/main/java/net/runelite/mapping/Export.java delete mode 100644 runelite-api/src/main/java/net/runelite/mapping/Import.java delete mode 100644 runelite-api/src/main/java/net/runelite/mapping/ObfuscatedGetter.java delete mode 100644 runelite-api/src/main/java/net/runelite/mapping/Protect.java diff --git a/runelite-api/src/main/java/net/runelite/mapping/Export.java b/runelite-api/src/main/java/net/runelite/mapping/Export.java deleted file mode 100644 index cd789618cd..0000000000 --- a/runelite-api/src/main/java/net/runelite/mapping/Export.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.mapping; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target( -{ - ElementType.FIELD, ElementType.METHOD -}) -public @interface Export -{ - String value(); -} diff --git a/runelite-api/src/main/java/net/runelite/mapping/Import.java b/runelite-api/src/main/java/net/runelite/mapping/Import.java deleted file mode 100644 index 97e4e81d7f..0000000000 --- a/runelite-api/src/main/java/net/runelite/mapping/Import.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.mapping; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target( -{ - ElementType.FIELD, ElementType.METHOD -}) -public @interface Import -{ - String value(); -} diff --git a/runelite-api/src/main/java/net/runelite/mapping/ObfuscatedGetter.java b/runelite-api/src/main/java/net/runelite/mapping/ObfuscatedGetter.java deleted file mode 100644 index b8e2873006..0000000000 --- a/runelite-api/src/main/java/net/runelite/mapping/ObfuscatedGetter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.mapping; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface ObfuscatedGetter -{ - int intValue() default 0; - - long longValue() default 0L; -} diff --git a/runelite-api/src/main/java/net/runelite/mapping/Protect.java b/runelite-api/src/main/java/net/runelite/mapping/Protect.java deleted file mode 100644 index a5c780a94d..0000000000 --- a/runelite-api/src/main/java/net/runelite/mapping/Protect.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.mapping; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Used to indicate a method can only be called from within mixins. - * Calling methods annotated with this annotation outside mixins results in a AbstractMethodError. - * Only works in net.runelite.rs.api.* - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -public @interface Protect -{ -} From e0142c7f77f08d1672788b807cd06ecd5643051d Mon Sep 17 00:00:00 2001 From: Lucwousin Date: Thu, 31 Oct 2019 01:00:10 +0100 Subject: [PATCH 6/9] Remove injector plugin --- injector-plugin/injector-plugin.gradle.kts | 83 -- .../java/net/runelite/injector/Inject.java | 580 ---------- .../runelite/injector/InjectConstruct.java | 171 --- .../net/runelite/injector/InjectGetter.java | 155 --- .../net/runelite/injector/InjectHook.java | 396 ------- .../runelite/injector/InjectHookMethod.java | 255 ----- .../net/runelite/injector/InjectInvoker.java | 291 ----- .../net/runelite/injector/InjectMojo.java | 152 --- .../net/runelite/injector/InjectSetter.java | 158 --- .../net/runelite/injector/InjectUtil.java | 281 ----- .../runelite/injector/InjectionException.java | 44 - .../java/net/runelite/injector/Injector.java | 85 -- .../runelite/injector/InjectorValidator.java | 196 ---- .../net/runelite/injector/MixinInjector.java | 998 ------------------ .../injector/raw/ClearColorBuffer.java | 124 --- .../injector/raw/DrawAfterWidgets.java | 264 ----- .../net/runelite/injector/raw/DrawMenu.java | 135 --- .../injector/raw/HidePlayerAttacks.java | 202 ---- .../net/runelite/injector/raw/Occluder.java | 83 -- .../net/runelite/injector/raw/RenderDraw.java | 86 -- .../net/runelite/injector/raw/ScriptVM.java | 306 ------ .../injector/InjectConstructTest.java | 63 -- .../runelite/injector/InjectSetterTest.java | 116 -- .../net/runelite/injector/InjectTest.java | 74 -- .../runelite/injector/MixinInjectorTest.java | 267 ----- .../injector/raw/DrawAfterWidgetsTest.java | 80 -- .../drawafterwidgets/Client_deob153.class | Bin 103334 -> 0 bytes .../drawafterwidgets/Client_deob160.class | Bin 126443 -> 0 bytes .../drawafterwidgets/Client_deob180.class | Bin 119603 -> 0 bytes .../drawafterwidgets/Client_ob153.class | Bin 645897 -> 0 bytes .../drawafterwidgets/Client_ob160.class | Bin 691407 -> 0 bytes .../drawafterwidgets/Client_ob180.class | Bin 705642 -> 0 bytes .../Rasterizer2D_deob153.class | Bin 16462 -> 0 bytes .../Rasterizer2D_deob160.class | Bin 16628 -> 0 bytes .../Rasterizer2D_deob180.class | Bin 13344 -> 0 bytes .../drawafterwidgets/Rasterizer2D_ob153.class | Bin 52056 -> 0 bytes .../drawafterwidgets/Rasterizer2D_ob160.class | Bin 50268 -> 0 bytes .../drawafterwidgets/Rasterizer2D_ob180.class | Bin 43336 -> 0 bytes runelite-client/runelite-client.gradle.kts | 2 - 39 files changed, 5647 deletions(-) delete mode 100644 injector-plugin/injector-plugin.gradle.kts delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/Inject.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectHook.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectionException.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/Injector.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/DrawMenu.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/HidePlayerAttacks.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/Occluder.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/RenderDraw.java delete mode 100644 injector-plugin/src/main/java/net/runelite/injector/raw/ScriptVM.java delete mode 100644 injector-plugin/src/test/java/net/runelite/injector/InjectConstructTest.java delete mode 100644 injector-plugin/src/test/java/net/runelite/injector/InjectSetterTest.java delete mode 100644 injector-plugin/src/test/java/net/runelite/injector/InjectTest.java delete mode 100644 injector-plugin/src/test/java/net/runelite/injector/MixinInjectorTest.java delete mode 100644 injector-plugin/src/test/java/net/runelite/injector/raw/DrawAfterWidgetsTest.java delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Client_deob153.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Client_deob160.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Client_deob180.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Client_ob153.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Client_ob160.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Client_ob180.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Rasterizer2D_deob153.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Rasterizer2D_deob160.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Rasterizer2D_deob180.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Rasterizer2D_ob153.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Rasterizer2D_ob160.class delete mode 100644 injector-plugin/src/test/resources/drawafterwidgets/Rasterizer2D_ob180.class diff --git a/injector-plugin/injector-plugin.gradle.kts b/injector-plugin/injector-plugin.gradle.kts deleted file mode 100644 index 97d3974575..0000000000 --- a/injector-plugin/injector-plugin.gradle.kts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2019 Owain van Brakel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -group = "com.openosrs.rs" -description = "Injector" - -val deobfuscatedJar = "${project.extra["rootPath"]}/runescape-client/build/libs/runescape-client-${ProjectVersions.rlVersion}.jar" -val vanillaJar = "${buildDir}/vanilla-${ProjectVersions.rsversion}.jar" - -val vanilla = configurations.create("vanilla") - -dependencies { - annotationProcessor(Libraries.sisu) - - compileOnly(Libraries.mavenPluginAnnotations) - - implementation(Libraries.guava) - implementation(Libraries.mavenPluginApi) - implementation(Libraries.asmAll) - implementation(Libraries.asmUtil) - implementation(project(":deobfuscator")) - implementation(project(":runelite-mixins")) - implementation(project(":runelite-api")) - implementation(project(":runescape-api")) - - testImplementation(Libraries.junit) - testImplementation(Libraries.mockitoCore) - testImplementation(project(":deobfuscator")) - testImplementation(project(path = ":deobfuscator", configuration = "testArchives")) - - vanilla(Libraries.vanilla) -} - -tasks { - register("copyVanilla") { - copy { - from(configurations.get("vanilla")) - into("$buildDir") - } - } - - register("inject") { - dependsOn("copyVanilla") - - classpath = project.sourceSets.main.get().runtimeClasspath - main = "net.runelite.injector.Injector" - args(listOf(deobfuscatedJar, vanillaJar, project.extra["injectedClassesPath"])) - } - - compileJava { - dependsOn(":runescape-client:build") - - inputs.dir(project(":runescape-client").projectDir.absolutePath) - inputs.dir(project(":runescape-api").projectDir.absolutePath) - inputs.dir(project(":runelite-mixins").projectDir.absolutePath) - } - - jar { - dependsOn("inject") - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/Inject.java b/injector-plugin/src/main/java/net/runelite/injector/Inject.java deleted file mode 100644 index 4a87466311..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/Inject.java +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.util.HashMap; -import java.util.Map; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.asm.Field; -import net.runelite.asm.Interfaces; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Annotations; -import net.runelite.asm.attributes.annotation.Annotation; -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.DLoad; -import net.runelite.asm.attributes.code.instructions.FLoad; -import net.runelite.asm.attributes.code.instructions.ILoad; -import net.runelite.asm.attributes.code.instructions.LLoad; -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 static net.runelite.injector.InjectUtil.getFieldType; -import net.runelite.injector.raw.ClearColorBuffer; -import net.runelite.injector.raw.DrawAfterWidgets; -import net.runelite.injector.raw.Occluder; -import net.runelite.injector.raw.RasterizerAlpha; -import net.runelite.injector.raw.RenderDraw; -import net.runelite.injector.raw.ScriptVM; -import net.runelite.mapping.Import; -import net.runelite.rs.api.RSClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import net.runelite.injector.raw.HidePlayerAttacks; - -public class Inject -{ - public static final java.lang.Class CLIENT_CLASS = RSClient.class; - public static final String API_PACKAGE_BASE = "net.runelite.rs.api.RS"; - public static final String RL_API_PACKAGE_BASE = "net.runelite.api."; - private static final Logger logger = LoggerFactory.getLogger(Inject.class); - private final InjectHookMethod hookMethod = new InjectHookMethod(this); - - private final InjectGetter getters = new InjectGetter(this); - private final InjectSetter setters = new InjectSetter(this); - private final InjectInvoker invokes = new InjectInvoker(this); - private final InjectConstruct construct = new InjectConstruct(this); - - private final MixinInjector mixinInjector = new MixinInjector(this); - - // deobfuscated contains exports etc to apply to vanilla - private final ClassGroup deobfuscated, vanilla; - - public Inject(ClassGroup deobfuscated, ClassGroup vanilla) - { - this.deobfuscated = deobfuscated; - this.vanilla = vanilla; - } - - /** - * Convert a java.lang.Class to a Type - * - * @param c - * @return - */ - public static Type classToType(java.lang.Class c) - { - int dimms = 0; - while (c.isArray()) - { - c = c.getComponentType(); - ++dimms; - } - - if (c.isPrimitive()) - { - String s; - - switch (c.getName()) - { - case "int": - s = "I"; - break; - case "long": - s = "J"; - break; - case "boolean": - s = "Z"; - break; - case "char": - s = "C"; - break; - case "short": - s = "S"; - break; - case "float": - s = "F"; - break; - case "double": - s = "D"; - break; - case "byte": - s = "B"; - break; - case "void": - s = "V"; - break; - default: - throw new RuntimeException("unknown primitive type " + c.getName()); - } - - return Type.getType(s, dimms); - } - - return Type.getType("L" + c.getName().replace('.', '/') + ";", dimms); - } - - public Signature getMethodSignature(Method m) - { - Signature signature = m.getDescriptor(); - - Annotation obfSignature = m.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE); - if (obfSignature != null) - { - //Annotation exists. Signature was updated by us during deobfuscation - signature = DeobAnnotations.getObfuscatedSignature(m); - } - - return signature; - } - - /** - * Build a Signature from a java method - * - * @param method - * @return - */ - public Signature javaMethodToSignature(java.lang.reflect.Method method) - { - Signature.Builder builder = new Signature.Builder() - .setReturnType(classToType(method.getReturnType())); - for (java.lang.Class clazz : method.getParameterTypes()) - { - builder.addArgument(classToType(clazz)); - } - return builder.build(); - } - - public void run() throws InjectionException - { - Map implemented = new HashMap<>(); - - // inject interfaces first, so the validateTypeIsConvertibleTo - // check below works - for (ClassFile cf : deobfuscated.getClasses()) - { - Annotations an = cf.getAnnotations(); - - if (an == null || an.size() == 0) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(an); - if (obfuscatedName == null) - { - obfuscatedName = cf.getName(); - } - - ClassFile other = vanilla.findClass(obfuscatedName); - assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName; - - java.lang.Class implementingClass = injectInterface(cf, other); - // it can not implement an interface but still have exported static fields, which are - // moved to client - - implemented.put(cf, implementingClass); - } - - // Has to be done before mixins - // well, can be done after really - // but why do that when you can do it before - new RasterizerAlpha(this).inject(); - - // requires interfaces to be injected - mixinInjector.inject(); - construct.inject(implemented); - - for (ClassFile cf : deobfuscated.getClasses()) - { - java.lang.Class implementingClass = implemented.get(cf); - Annotations an = cf.getAnnotations(); - - if (an == null || an.size() == 0) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(an); - if (obfuscatedName == null) - { - obfuscatedName = cf.getName(); - } - - ClassFile other = vanilla.findClass(obfuscatedName); - assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName; - - for (Field f : cf.getFields()) - { - an = f.getAnnotations(); - - if (an == null || an.find(DeobAnnotations.EXPORT) == null) - { - continue; // not an exported field - } - - Annotation exportAnnotation = an.find(DeobAnnotations.EXPORT); - String exportedName = exportAnnotation.getElement().getString(); - - obfuscatedName = DeobAnnotations.getObfuscatedName(an); - - Annotation getterAnnotation = an.find(DeobAnnotations.OBFUSCATED_GETTER); - Number getter = null; - if (getterAnnotation != null) - { - getter = (Number) getterAnnotation.getElement().getValue(); - } - // the ob jar is the same as the vanilla so this field must exist in this class. - - Type obType = getFieldType(f); - Field otherf = other.findField(obfuscatedName, obType); - assert otherf != null; - - assert f.isStatic() == otherf.isStatic(); - - ClassFile targetClass = f.isStatic() ? vanilla.findClass("client") : other; // target class for getter - java.lang.Class targetApiClass = f.isStatic() ? CLIENT_CLASS : implementingClass; // target api class for getter - if (targetApiClass == null) - { - assert !f.isStatic(); - - // non static field exported on non exported interface - // logger.debug("Non static exported field {} on non exported interface", exportedName); - continue; - } - - java.lang.reflect.Method apiMethod = findImportMethodOnApi(targetApiClass, exportedName, true); - if (apiMethod != null) - { - Number setter = null; - if (getter != null) - { - setter = DMath.modInverse(getter); // inverse getter to get the setter - } - - setters.injectSetter(targetClass, targetApiClass, otherf, exportedName, setter); - } - - apiMethod = findImportMethodOnApi(targetApiClass, exportedName, false); - if (apiMethod == null) - { - //logger.debug("Unable to find import method on api class {} with imported name {}, not injecting getter", targetApiClass, exportedName); - continue; - } - - // check that otherf is converable to apiMethod's - // return type - Type fieldType = otherf.getType(); - Type returnType = classToType(apiMethod.getReturnType()); - if (!validateTypeIsConvertibleTo(fieldType, returnType)) - { - throw new InjectionException("Type " + fieldType + " is not convertable to " + returnType + " for getter " + apiMethod); - } - - getters.injectGetter(targetClass, apiMethod, otherf, getter); - } - - for (Method m : cf.getMethods()) - { - hookMethod.process(m); - invokes.process(m, other, implementingClass); - } - } - - logger.info("Injected {} getters, {} setters, {} invokers", - getters.getInjectedGetters(), - setters.getInjectedSetters(), invokes.getInjectedInvokers()); - - new DrawAfterWidgets(this).inject(); - new ScriptVM(this).inject(); - new ClearColorBuffer(this).inject(); - new RenderDraw(this).inject(); - // new DrawMenu(this).inject(); - new Occluder(this).inject(); - new HidePlayerAttacks(this).inject(); - } - - private java.lang.Class injectInterface(ClassFile cf, ClassFile other) - { - Annotations an = cf.getAnnotations(); - if (an == null) - { - return null; - } - - Annotation a = an.find(DeobAnnotations.IMPLEMENTS); - if (a == null) - { - return null; - } - - String ifaceName = API_PACKAGE_BASE + a.getElement().getString(); - java.lang.Class apiClass; - - try - { - apiClass = java.lang.Class.forName(ifaceName); - } - catch (ClassNotFoundException ex) - { - logger.trace("Class {} implements nonexistent interface {}, skipping interface injection", - cf.getName(), - ifaceName); - return null; - } - - String ifaceNameInternal = ifaceName.replace('.', '/'); // to internal name - Class clazz = new Class(ifaceNameInternal); - - Interfaces interfaces = other.getInterfaces(); - interfaces.addInterface(clazz); - - return apiClass; - } - - public java.lang.reflect.Method findImportMethodOnApi(java.lang.Class clazz, String name, Boolean setter) - { - for (java.lang.reflect.Method method : clazz.getDeclaredMethods()) - { - if (method.isSynthetic()) - { - /* - * If you override an interface method in another interface - * with a return type that is a child of the overriden methods - * return type, both methods end up in the interface, and both - * are *annotated*. But the base one is synthetic. - */ - continue; - } - - Import i = method.getAnnotation(Import.class); - - if (i == null || !name.equals(i.value()) || (setter != null && (method.getParameterCount() > 0) != setter)) - { - continue; - } - - return method; - } - - return null; - } - - /** - * create a load instruction for a variable of type from a given index - * - * @param instructions - * @param type - * @param index - * @return - */ - public Instruction createLoadForTypeIndex(Instructions instructions, Type type, int index) - { - if (type.getDimensions() > 0 || !type.isPrimitive()) - { - return new ALoad(instructions, index); - } - - switch (type.toString()) - { - case "B": - case "C": - case "I": - case "S": - case "Z": - return new ILoad(instructions, index); - case "D": - return new DLoad(instructions, index); - case "F": - return new FLoad(instructions, index); - case "J": - return new LLoad(instructions, index); - default: - throw new RuntimeException("Unknown type"); - } - } - - ClassFile toDeobClass(ClassFile obClass) - { - for (ClassFile cf : deobfuscated.getClasses()) - { - String obfuscatedName = DeobAnnotations.getObfuscatedName(cf.getAnnotations()); - - if (obClass.getName().equalsIgnoreCase(obfuscatedName)) - { - return cf; - } - } - - return null; - } - - Type deobfuscatedTypeToApiType(Type type) throws InjectionException - { - if (type.isPrimitive()) - { - return type; - } - - ClassFile cf = deobfuscated.findClass(type.getInternalName()); - if (cf == null) - { - return type; // not my type - } - - java.lang.Class rsApiType; - try - { - rsApiType = java.lang.Class.forName(API_PACKAGE_BASE + cf.getName().replace("/", ".")); - } - catch (ClassNotFoundException ex) - { - throw new InjectionException("Deobfuscated type " + type.getInternalName() + " has no API type", ex); - } - - java.lang.Class rlApiType = null; - - for (java.lang.Class inter : rsApiType.getInterfaces()) - { - if (inter.getName().startsWith(RL_API_PACKAGE_BASE)) - { - rlApiType = inter; - } - } - - // if (rlApiType == null) - // { - // throw new InjectionException("RS API type " + rsApiType + " does not extend RL API interface"); - // } - - final java.lang.Class finalType = rlApiType == null ? rsApiType : rlApiType; - - return Type.getType("L" + finalType.getName().replace('.', '/') + ";", type.getDimensions()); - } - - Type apiTypeToDeobfuscatedType(Type type) - { - if (type.isPrimitive()) - { - return type; - } - - String internalName = type.getInternalName().replace('/', '.'); - if (!internalName.startsWith(API_PACKAGE_BASE)) - { - return type; // not an rs api type - } - - return Type.getType("L" + type.getInternalName().substring(API_PACKAGE_BASE.length()) + ";", type.getDimensions()); - } - - ClassFile findVanillaForInterface(java.lang.Class clazz) - { - String className = clazz.getName().replace('.', '/'); - for (ClassFile cf : getVanilla().getClasses()) - { - for (net.runelite.asm.pool.Class cl : cf.getInterfaces().getInterfaces()) - { - if (cl.getName().equals(className)) - { - return cf; - } - } - } - return null; - } - - private boolean validateTypeIsConvertibleTo(Type from, Type to) throws InjectionException - { - if (from.getDimensions() != to.getDimensions()) - { - throw new InjectionException("Array dimension mismatch"); - } - - if (from.isPrimitive()) - { - return true; - } - - ClassFile vanillaClass = vanilla.findClass(from.getInternalName()); - if (vanillaClass == null) - { - return true; - } - - boolean okay = false; - for (Class inter : vanillaClass.getInterfaces().getInterfaces()) - { - java.lang.Class c; - - try - { - c = java.lang.Class.forName(inter.getName().replace('/', '.')); - } - catch (ClassNotFoundException ex) - { - continue; - } - - okay |= check(c, to); - } - - return okay; - } - - private boolean check(java.lang.Class c, Type type) - { - String s = type.getInternalName() - .replace('/', '.'); - - if (c.getName().equals(s)) - { - return true; - } - - for (java.lang.Class c2 : c.getInterfaces()) - { - if (check(c2, type)) - { - return true; - } - } - return false; - } - - public final ClassGroup getDeobfuscated() - { - return deobfuscated; - } - - public final ClassGroup getVanilla() - { - return vanilla; - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java b/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java deleted file mode 100644 index 8a87451da6..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.Instructions; -import net.runelite.asm.attributes.code.instructions.CheckCast; -import net.runelite.asm.attributes.code.instructions.Dup; -import net.runelite.asm.attributes.code.instructions.InvokeSpecial; -import net.runelite.asm.attributes.code.instructions.New; -import net.runelite.asm.attributes.code.instructions.Return; -import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; -import net.runelite.mapping.Construct; -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class InjectConstruct -{ - private static final Logger logger = LoggerFactory.getLogger(InjectConstruct.class); - - private final Inject inject; - - InjectConstruct(Inject inject) - { - this.inject = inject; - } - - public void inject(Map implemented) throws InjectionException - { - for (Entry entry : implemented.entrySet()) - { - Class clazz = entry.getValue(); - ClassFile cf = entry.getKey(); - - if (clazz == null) - { - continue; - } - - for (java.lang.reflect.Method method : clazz.getDeclaredMethods()) - { - if (method.isSynthetic()) - { - continue; - } - - Construct construct = method.getAnnotation(Construct.class); - if (construct == null) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(cf.getAnnotations()); - if (obfuscatedName == null) - { - obfuscatedName = cf.getName(); - } - - ClassGroup vanilla = inject.getVanilla(); - ClassFile other = vanilla.findClass(obfuscatedName); - assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName; - - injectConstruct(other, method); - } - } - } - - void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException - { - logger.info("Injecting construct for {}", apiMethod); - - assert targetClass.findMethod(apiMethod.getName()) == null; - - Class typeToConstruct = apiMethod.getReturnType(); - ClassFile vanillaClass = inject.findVanillaForInterface(typeToConstruct); - if (vanillaClass == null) - { - throw new InjectionException("Unable to find vanilla class which implements interface " + typeToConstruct); - } - - Signature sig = inject.javaMethodToSignature(apiMethod); - - Signature constructorSig = new Signature.Builder() - .addArguments(Stream.of(apiMethod.getParameterTypes()) - .map(arg -> - { - ClassFile vanilla = inject.findVanillaForInterface(arg); - if (vanilla != null) - { - return new Type("L" + vanilla.getName() + ";"); - } - return Inject.classToType(arg); - }) - .collect(Collectors.toList())) - .setReturnType(Type.VOID) - .build(); - Method vanillaConstructor = vanillaClass.findMethod("", constructorSig); - if (vanillaConstructor == null) - { - throw new InjectionException("Unable to find constructor for " + vanillaClass.getName() + "." + constructorSig); - } - - Method setterMethod = new Method(targetClass, apiMethod.getName(), sig); - setterMethod.setAccessFlags(ACC_PUBLIC); - targetClass.addMethod(setterMethod); - - Code code = new Code(setterMethod); - setterMethod.setCode(code); - - Instructions instructions = code.getInstructions(); - List ins = instructions.getInstructions(); - - ins.add(new New(instructions, vanillaClass.getPoolClass())); - ins.add(new Dup(instructions)); - int idx = 1; - int parameter = 0; - for (Type type : vanillaConstructor.getDescriptor().getArguments()) - { - Instruction load = inject.createLoadForTypeIndex(instructions, type, idx); - idx += type.getSize(); - ins.add(load); - - Type paramType = sig.getTypeOfArg(parameter); - if (!type.equals(paramType)) - { - CheckCast checkCast = new CheckCast(instructions); - checkCast.setType(type); - ins.add(checkCast); - } - - ++parameter; - } - ins.add(new InvokeSpecial(instructions, vanillaConstructor.getPoolMethod())); - ins.add(new Return(instructions)); - - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java b/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java deleted file mode 100644 index cd94ee80d8..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.util.List; -import net.runelite.asm.ClassFile; -import net.runelite.asm.Field; -import net.runelite.asm.Method; -import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.InstructionType; -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.attributes.code.instructions.Return; -import net.runelite.asm.signature.Signature; -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class InjectGetter -{ - private static final Logger logger = LoggerFactory.getLogger(InjectGetter.class); - - private final Inject inject; - - private int injectedGetters; - - InjectGetter(Inject inject) - { - this.inject = inject; - } - - void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter) - { - // clazz = class file we're injecting the method into. - // method = api method (java reflect) that we're overriding - // field = field we're getting. might not be in this class if static. - // getter = encryption getter - - assert clazz.findMethod(method.getName()) == null; - assert field.isStatic() || field.getClassFile() == clazz; - - Signature sig = new Signature.Builder() - .setReturnType(Inject.classToType(method.getReturnType())) - .build(); - Method getterMethod = new Method(clazz, method.getName(), sig); - getterMethod.setAccessFlags(ACC_PUBLIC); - - // create code - Code code = new Code(getterMethod); - getterMethod.setCode(code); - - Instructions instructions = code.getInstructions(); - List ins = instructions.getInstructions(); - - if (field.isStatic()) - { - code.setMaxStack(1); - - ins.add(new GetStatic(instructions, field.getPoolField())); - } - else - { - code.setMaxStack(2); - - ins.add(new ALoad(instructions, 0)); - ins.add(new GetField(instructions, field.getPoolField())); - } - - if (getter != null) - { - code.setMaxStack(2); - - assert getter instanceof Integer || getter instanceof Long; - - if (getter instanceof Integer) - { - ins.add(new LDC(instructions, (int) getter)); - ins.add(new IMul(instructions)); - } - else - { - ins.add(new LDC(instructions, (long) getter)); - ins.add(new LMul(instructions)); - } - } - - InstructionType returnType; - if (field.getType().isPrimitive() && field.getType().getDimensions() == 0) - { - switch (field.getType().toString()) - { - case "B": - case "C": - case "I": - case "S": - case "Z": - returnType = InstructionType.IRETURN; - break; - case "D": - returnType = InstructionType.DRETURN; - break; - case "F": - returnType = InstructionType.FRETURN; - break; - case "J": - returnType = InstructionType.LRETURN; - break; - default: - throw new RuntimeException("Unknown type"); - } - } - else - { - returnType = InstructionType.ARETURN; - } - - ins.add(new Return(instructions, returnType)); - - clazz.addMethod(getterMethod); - ++injectedGetters; - } - - int getInjectedGetters() - { - return injectedGetters; - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java b/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java deleted file mode 100644 index 19ae3a3df6..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import com.google.common.collect.Lists; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import net.runelite.asm.Field; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.InstructionType; -import net.runelite.asm.attributes.code.Instructions; -import net.runelite.asm.attributes.code.instruction.types.DupInstruction; -import net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction; -import net.runelite.asm.attributes.code.instructions.ArrayStore; -import net.runelite.asm.attributes.code.instructions.CheckCast; -import net.runelite.asm.attributes.code.instructions.Dup; -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.LMul; -import net.runelite.asm.attributes.code.instructions.PutField; -import net.runelite.asm.attributes.code.instructions.Swap; -import net.runelite.asm.execution.Execution; -import net.runelite.asm.execution.InstructionContext; -import net.runelite.asm.execution.StackContext; -import net.runelite.asm.signature.Signature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class InjectHook -{ - private static final Logger logger = LoggerFactory.getLogger(InjectHook.class); - private static final String HOOK_METHOD_SIGNATURE = "(I)V"; - private static final String CLINIT = ""; - private final Inject inject; - private final Map hooked = new HashMap<>(); - private int injectedHooks; - - InjectHook(Inject inject) - { - this.inject = inject; - } - - void hook(Field field, HookInfo hookInfo) - { - hooked.put(field, hookInfo); - } - - void run() - { - Execution e = new Execution(inject.getVanilla()); - e.populateInitialMethods(); - - Set done = new HashSet<>(); - Set doneIh = new HashSet<>(); - - e.addExecutionVisitor((InstructionContext ic) -> - { - Instruction i = ic.getInstruction(); - Instructions ins = i.getInstructions(); - Code code = ins.getCode(); - Method method = code.getMethod(); - - if (method.getName().equals(CLINIT)) - { - return; - } - - if (!(i instanceof SetFieldInstruction)) - { - return; - } - - if (!done.add(i)) - { - return; - } - - SetFieldInstruction sfi = (SetFieldInstruction) i; - Field fieldBeingSet = sfi.getMyField(); - - if (fieldBeingSet == null) - { - return; - } - - HookInfo hookInfo = hooked.get(fieldBeingSet); - if (hookInfo == null) - { - return; - } - - String hookName = hookInfo.fieldName; - assert hookName != null; - - logger.trace("Found injection location for hook {} at instruction {}", hookName, sfi); - ++injectedHooks; - - StackContext value = ic.getPops().get(0); - - StackContext objectStackContext = null; - if (sfi instanceof PutField) - { - objectStackContext = ic.getPops().get(1); - } - - int idx = ins.getInstructions().indexOf(sfi); - assert idx != -1; - - try - { - if (hookInfo.before) - { - injectCallbackBefore(ins, idx, hookInfo, null, objectStackContext, value); - } - else - { - // idx + 1 to insert after the set - injectCallback(ins, idx + 1, hookInfo, null, objectStackContext); - } - } - catch (InjectionException ex) - { - throw new RuntimeException(ex); - } - }); - - // these look like: - // getfield - // iload_0 - // iconst_0 - // iastore - e.addExecutionVisitor((InstructionContext ic) -> - { - Instruction i = ic.getInstruction(); - Instructions ins = i.getInstructions(); - Code code = ins.getCode(); - Method method = code.getMethod(); - - if (method.getName().equals(CLINIT)) - { - return; - } - - if (!(i instanceof ArrayStore)) - { - return; - } - - if (!doneIh.add(i)) - { - return; - } - - ArrayStore as = (ArrayStore) i; - - Field fieldBeingSet = as.getMyField(ic); - if (fieldBeingSet == null) - { - return; - } - - HookInfo hookInfo = hooked.get(fieldBeingSet); - if (hookInfo == null) - { - return; - } - - String hookName = hookInfo.fieldName; - - StackContext value = ic.getPops().get(0); - StackContext index = ic.getPops().get(1); - - StackContext arrayReference = ic.getPops().get(2); - InstructionContext arrayReferencePushed = arrayReference.getPushed(); - - StackContext objectStackContext = null; - if (arrayReferencePushed.getInstruction().getType() == InstructionType.GETFIELD) - { - objectStackContext = arrayReferencePushed.getPops().get(0); - } - - // inject hook after 'i' - logger.info("Found array injection location for hook {} at instruction {}", hookName, i); - ++injectedHooks; - - int idx = ins.getInstructions().indexOf(i); - assert idx != -1; - - try - { - if (hookInfo.before) - { - injectCallbackBefore(ins, idx, hookInfo, index, objectStackContext, value); - } - else - { - injectCallback(ins, idx + 1, hookInfo, index, objectStackContext); - } - } - catch (InjectionException ex) - { - throw new RuntimeException(ex); - } - }); - - e.run(); - } - - private void injectCallbackBefore(Instructions ins, int idx, HookInfo hookInfo, StackContext index, StackContext object, StackContext value) throws InjectionException - { - Signature signature = hookInfo.method.getDescriptor(); - Type methodArgumentType = signature.getTypeOfArg(0); - - if (!hookInfo.method.isStatic()) - { - if (object == null) - { - throw new InjectionException("null object"); - } - - ins.getInstructions().add(idx++, new Dup(ins)); // dup value - idx = recursivelyPush(ins, idx, object); - ins.getInstructions().add(idx++, new Swap(ins)); - if (hookInfo.getter != null) - { - assert hookInfo.getter instanceof Integer || hookInfo.getter instanceof Long; - - if (hookInfo.getter instanceof Integer) - { - ins.getInstructions().add(idx++, new LDC(ins, (int) hookInfo.getter)); - ins.getInstructions().add(idx++, new IMul(ins)); - } - else - { - ins.getInstructions().add(idx++, new LDC(ins, (long) hookInfo.getter)); - ins.getInstructions().add(idx++, new LMul(ins)); - } - } - if (!value.type.equals(methodArgumentType)) - { - CheckCast checkCast = new CheckCast(ins); - checkCast.setType(methodArgumentType); - ins.getInstructions().add(idx++, checkCast); - } - if (index != null) - { - idx = recursivelyPush(ins, idx, index); - } - - InvokeVirtual invoke = new InvokeVirtual(ins, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(hookInfo.clazz), - hookInfo.method.getName(), - signature - ) - ); - ins.getInstructions().add(idx++, invoke); - } - else - { - ins.getInstructions().add(idx++, new Dup(ins)); // dup value - if (!value.type.equals(methodArgumentType)) - { - CheckCast checkCast = new CheckCast(ins); - checkCast.setType(methodArgumentType); - ins.getInstructions().add(idx++, checkCast); - } - if (index != null) - { - idx = recursivelyPush(ins, idx, index); - } - - InvokeStatic invoke = new InvokeStatic(ins, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(hookInfo.clazz), - hookInfo.method.getName(), - signature - ) - ); - ins.getInstructions().add(idx++, invoke); - } - } - - private int recursivelyPush(Instructions ins, int idx, StackContext sctx) - { - InstructionContext ctx = sctx.getPushed(); - if (ctx.getInstruction() instanceof DupInstruction) - { - DupInstruction dupInstruction = (DupInstruction) ctx.getInstruction(); - sctx = dupInstruction.getOriginal(sctx); - ctx = sctx.getPushed(); - } - - for (StackContext s : Lists.reverse(ctx.getPops())) - { - idx = recursivelyPush(ins, idx, s); - } - - ins.getInstructions().add(idx++, ctx.getInstruction().clone()); - return idx; - } - - private void injectCallback(Instructions ins, int idx, HookInfo hookInfo, StackContext index, StackContext objectPusher) throws InjectionException - { - if (!hookInfo.method.isStatic()) - { - if (objectPusher == null) - { - throw new InjectionException("Null object pusher"); - } - - idx = recursivelyPush(ins, idx, objectPusher); - if (index != null) - { - idx = recursivelyPush(ins, idx, index); - } - else - { - ins.getInstructions().add(idx++, new LDC(ins, -1)); - } - - InvokeVirtual invoke = new InvokeVirtual(ins, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(hookInfo.clazz), - hookInfo.method.getName(), - new Signature(HOOK_METHOD_SIGNATURE) - ) - ); - ins.getInstructions().add(idx++, invoke); - - } - else - { - if (index != null) - { - idx = recursivelyPush(ins, idx, index); - } - else - { - ins.getInstructions().add(idx++, new LDC(ins, -1)); - } - - InvokeStatic invoke = new InvokeStatic(ins, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(hookInfo.clazz), - hookInfo.method.getName(), - new Signature(HOOK_METHOD_SIGNATURE) - ) - ); - ins.getInstructions().add(idx++, invoke); - } - } - - int getInjectedHooks() - { - return injectedHooks; - } - - static class HookInfo - { - String fieldName; - String clazz; - Method method; - boolean before; - Number getter; - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java b/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java deleted file mode 100644 index 3c304807be..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Annotations; -import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.annotation.Annotation; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.InstructionType; -import net.runelite.asm.attributes.code.Instructions; -import net.runelite.asm.attributes.code.instruction.types.InvokeInstruction; -import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction; -import net.runelite.asm.attributes.code.instructions.ALoad; -import net.runelite.asm.attributes.code.instructions.InvokeStatic; -import net.runelite.asm.attributes.code.instructions.InvokeVirtual; -import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class InjectHookMethod -{ - public static final String HOOKS = "net/runelite/client/callback/Hooks"; - private static final Logger logger = LoggerFactory.getLogger(InjectHookMethod.class); - private final Inject inject; - - InjectHookMethod(Inject inject) - { - this.inject = inject; - } - - void process(Method method) throws InjectionException - { - Annotations an = method.getAnnotations(); - if (an == null) - { - return; - } - - Annotation a = an.find(DeobAnnotations.HOOK); - if (a == null) - { - return; - } - - String hookName = a.getElement().getString(); - boolean end = a.getElements().size() == 2 && a.getElements().get(1).getValue().equals(true); - - inject(null, method, hookName, end, true); - } - - public void inject(Method hookMethod, Method method, String name, boolean end, boolean useHooks) throws InjectionException - { - Annotations an = method.getAnnotations(); - - // Method is hooked - // Find equivalent method in vanilla, and insert callback at the beginning - ClassFile cf = method.getClassFile(); - String obfuscatedMethodName = DeobAnnotations.getObfuscatedName(an), - obfuscatedClassName = DeobAnnotations.getObfuscatedName(cf.getAnnotations()); - - // might be a constructor - if (obfuscatedMethodName == null) - { - obfuscatedMethodName = method.getName(); - } - - assert obfuscatedClassName != null : "hook on method in class with no obfuscated name"; - assert obfuscatedMethodName != null : "hook on method with no obfuscated name"; - - Signature obfuscatedSignature = inject.getMethodSignature(method); - - ClassGroup vanilla = inject.getVanilla(); - ClassFile vanillaClass = vanilla.findClass(obfuscatedClassName); - Method vanillaMethod = vanillaClass.findMethod(obfuscatedMethodName, obfuscatedSignature); - assert method.isStatic() == vanillaMethod.isStatic(); - - // Insert instructions at beginning of method - injectHookMethod(hookMethod, name, end, method, vanillaMethod, useHooks); - } - - private void injectHookMethod(Method hookMethod, String hookName, boolean end, Method deobMethod, Method vanillaMethod, boolean useHooks) throws InjectionException - { - Code code = vanillaMethod.getCode(); - if (code == null) - { - logger.warn(vanillaMethod + " code is null"); - } - Instructions instructions = code.getInstructions(); - - Signature.Builder builder = new Signature.Builder() - .setReturnType(Type.VOID); // Hooks always return void - - for (Type type : deobMethod.getDescriptor().getArguments()) - { - builder.addArgument(inject.deobfuscatedTypeToApiType(type)); - } - - assert deobMethod.isStatic() == vanillaMethod.isStatic(); - - boolean modifiedSignature = false; - if (!deobMethod.isStatic() && useHooks) - { - // Add variable to signature - builder.addArgument(0, inject.deobfuscatedTypeToApiType(new Type(deobMethod.getClassFile().getName()))); - modifiedSignature = true; - } - - Signature signature = builder.build(); - - List insertIndexes = findHookLocations(hookName, end, vanillaMethod); - insertIndexes.sort((a, b) -> Integer.compare(b, a)); - - for (int insertPos : insertIndexes) - { - if (!deobMethod.isStatic()) - { - instructions.addInstruction(insertPos++, new ALoad(instructions, 0)); - } - - int signatureStart = modifiedSignature ? 1 : 0; - int index = deobMethod.isStatic() ? 0 : 1; // current variable index - - for (int i = signatureStart; i < signature.size(); ++i) - { - Type type = signature.getTypeOfArg(i); - - Instruction load = inject.createLoadForTypeIndex(instructions, type, index); - instructions.addInstruction(insertPos++, load); - - index += type.getSize(); - } - - InvokeInstruction invoke; - - // use old Hooks callback - if (useHooks) - { - // Invoke callback - invoke = new InvokeStatic(instructions, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(HOOKS), - hookName, - signature - ) - ); - } - else - { - // Invoke methodhook - assert hookMethod != null; - - if (vanillaMethod.isStatic()) - { - invoke = new InvokeStatic(instructions, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class("client"), // Static methods are in client - hookMethod.getName(), - signature - ) - ); - } - else - { - // otherwise invoke member function - //instructions.addInstruction(insertPos++, new ALoad(instructions, 0)); - invoke = new InvokeVirtual(instructions, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(vanillaMethod.getClassFile().getName()), - hookMethod.getName(), - hookMethod.getDescriptor() - ) - ); - } - } - - instructions.addInstruction(insertPos++, (Instruction) invoke); - } - - logger.info("Injected method hook {} in {} with {} args: {}", - hookName, vanillaMethod, signature.size(), - signature.getArguments()); - } - - private List findHookLocations(String hookName, boolean end, Method vanillaMethod) throws InjectionException - { - Instructions instructions = vanillaMethod.getCode().getInstructions(); - - if (end) - { - // find return - List returns = instructions.getInstructions().stream() - .filter(i -> i instanceof ReturnInstruction) - .collect(Collectors.toList()); - List indexes = new ArrayList<>(); - - for (Instruction ret : returns) - { - int idx = instructions.getInstructions().indexOf(ret); - assert idx != -1; - indexes.add(idx); - } - - return indexes; - } - - if (!vanillaMethod.getName().equals("")) - { - return Arrays.asList(0); - } - - // Find index after invokespecial - for (int i = 0; i < instructions.getInstructions().size(); ++i) - { - Instruction in = instructions.getInstructions().get(i); - - if (in.getType() == InstructionType.INVOKESPECIAL) - { - return Arrays.asList(i + 1); // one after - } - } - - throw new IllegalStateException("constructor with no invokespecial"); - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java b/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java deleted file mode 100644 index 3367b26c7a..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.util.List; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Annotations; -import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.InstructionType; -import net.runelite.asm.attributes.code.Instructions; -import net.runelite.asm.attributes.code.instructions.ALoad; -import net.runelite.asm.attributes.code.instructions.BiPush; -import net.runelite.asm.attributes.code.instructions.CheckCast; -import net.runelite.asm.attributes.code.instructions.DLoad; -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.Return; -import net.runelite.asm.attributes.code.instructions.SiPush; -import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; -import static net.runelite.deob.DeobAnnotations.EXPORT; -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class InjectInvoker -{ - private static final Logger logger = LoggerFactory.getLogger(InjectInvoker.class); - - private final Inject inject; - - private int injectedInvokers; - - InjectInvoker(Inject inject) - { - this.inject = inject; - } - - /** - * Inject an invoker for a method - * - * @param m Method in the deobfuscated client to inject an invoker for - * @param other Class in the vanilla client of the same class m is a - * member of - * @param implementingClass Java class for the API interface the class - * will implement - */ - void process(Method m, ClassFile other, java.lang.Class implementingClass) - { - Annotations an = m.getAnnotations(); - - if (an == null || an.find(EXPORT) == null) - { - return; // not an exported method - } - - String exportedName = DeobAnnotations.getExportedName(an); - String obfuscatedName = DeobAnnotations.getObfuscatedName(an); - - if (obfuscatedName == null) - { - obfuscatedName = m.getName(); - } - - String garbage = DeobAnnotations.getDecoder(m); - Method otherm = other.findMethod(obfuscatedName, inject.getMethodSignature(m)); - - assert otherm != null; - assert m.isStatic() == otherm.isStatic(); - - ClassGroup vanilla = inject.getVanilla(); - - ClassFile targetClass = m.isStatic() ? vanilla.findClass("client") : other; - - // Place into implementing class, unless the method is static - java.lang.Class targetClassJava = m.isStatic() ? Inject.CLIENT_CLASS : implementingClass; - - if (targetClassJava == null) - { - assert !m.isStatic(); - - // non static exported method on non exported interface, weird. - // logger.debug("Non static exported method {} on non exported interface", exportedName); - return; - } - - java.lang.reflect.Method apiMethod = inject.findImportMethodOnApi(targetClassJava, exportedName, null); // api method to invoke 'otherm' - if (apiMethod == null) - { - // logger.debug("Unable to find api method on {} with imported name {}, not injecting invoker", targetClassJava, exportedName); - return; - } - - injectInvoker(targetClass, apiMethod, m, otherm, garbage); - ++injectedInvokers; - } - - private void injectInvoker(ClassFile clazz, java.lang.reflect.Method method, Method deobfuscatedMethod, Method invokeMethod, String garbage) - { - // clazz = clazz to add invoker to - // method = api method to override - // deobfuscatedMethod = deobfuscated method, used to get the deobfuscated signature - // invokeMethod = method to invoke, obfuscated - - if (clazz.findMethod(method.getName(), deobfuscatedMethod.getDescriptor()) != null) - { - logger.warn("Not injecting method {} because it already exists!", method); - return; // this can happen from exporting a field and method with the same name - } - - assert invokeMethod.isStatic() == deobfuscatedMethod.isStatic(); - assert invokeMethod.isStatic() || invokeMethod.getClassFile() == clazz; - - Type lastGarbageArgumentType = null; - - if (deobfuscatedMethod.getDescriptor().getArguments().size() != invokeMethod.getDescriptor().getArguments().size()) - { - // allow for obfuscated method to have a single bogus signature at the end - assert deobfuscatedMethod.getDescriptor().size() + 1 == invokeMethod.getDescriptor().size(); - - List arguments = invokeMethod.getDescriptor().getArguments(); - lastGarbageArgumentType = arguments.get(arguments.size() - 1); - } - - // Injected method signature is always the same as the API - Signature apiSignature = inject.javaMethodToSignature(method); - Method invokerMethodSignature = new Method(clazz, method.getName(), apiSignature); - invokerMethodSignature.setAccessFlags(ACC_PUBLIC); - - // create code attribute - Code code = new Code(invokerMethodSignature); - invokerMethodSignature.setCode(code); - - Instructions instructions = code.getInstructions(); - List ins = instructions.getInstructions(); - - code.setMaxStack(1 + invokeMethod.getDescriptor().size()); // this + arguments - - // load function arguments onto the stack. - int index = 0; - if (!invokeMethod.isStatic()) - { - ins.add(new ALoad(instructions, index++)); // this - } - else - { - ++index; // this method is always non static - } - for (int i = 0; i < deobfuscatedMethod.getDescriptor().size(); ++i) - { - Type type = deobfuscatedMethod.getDescriptor().getTypeOfArg(i); - - Instruction loadInstruction = inject.createLoadForTypeIndex(instructions, type, index); - ins.add(loadInstruction); - - Signature invokeDesc = invokeMethod.getDescriptor(); - Type obType = invokeDesc.getTypeOfArg(i); - if (!type.equals(obType)) - { - CheckCast checkCast = new CheckCast(instructions); - checkCast.setType(obType); - ins.add(checkCast); - } - - if (loadInstruction instanceof DLoad || loadInstruction instanceof LLoad) - { - index += 2; - } - else - { - index += 1; - } - } - - if (lastGarbageArgumentType != null) - { - // function requires garbage value - - // if garbage is null here it might just be an unused parameter, not part of the obfuscation - if (garbage == null) - { - garbage = "0"; - } - - switch (lastGarbageArgumentType.toString()) - { - case "Z": - case "B": - case "C": - ins.add(new BiPush(instructions, Byte.parseByte(garbage))); - break; - case "S": - ins.add(new SiPush(instructions, Short.parseShort(garbage))); - break; - case "I": - ins.add(new LDC(instructions, Integer.parseInt(garbage))); - break; - case "D": - ins.add(new LDC(instructions, Double.parseDouble(garbage))); - break; - case "F": - ins.add(new LDC(instructions, Float.parseFloat(garbage))); - break; - case "J": - ins.add(new LDC(instructions, Long.parseLong(garbage))); - break; - default: - throw new RuntimeException("Unknown type"); - } - } - - if (invokeMethod.isStatic()) - { - ins.add(new InvokeStatic(instructions, invokeMethod.getPoolMethod())); - } - else - { - ins.add(new InvokeVirtual(instructions, invokeMethod.getPoolMethod())); - } - - Type returnValue = invokeMethod.getDescriptor().getReturnValue(); - InstructionType returnType; - - if (returnValue.isPrimitive() && returnValue.getDimensions() == 0) - { - switch (returnValue.toString()) - { - case "Z": - case "I": - returnType = InstructionType.IRETURN; - break; - case "J": - returnType = InstructionType.LRETURN; - break; - case "F": - returnType = InstructionType.FRETURN; - break; - case "D": - returnType = InstructionType.DRETURN; - break; - case "V": - returnType = InstructionType.RETURN; - break; - default: - assert false; - return; - } - } - else - { - returnType = InstructionType.ARETURN; - } - - ins.add(new Return(instructions, returnType)); - - clazz.addMethod(invokerMethodSignature); - } - - int getInjectedInvokers() - { - return injectedInvokers; - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java b/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java deleted file mode 100644 index b7c22194fe..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.deob.clientver.ClientVersion; -import net.runelite.deob.util.JarUtil; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.logging.Log; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; - -@Mojo( - name = "runelite-injector", - defaultPhase = LifecyclePhase.GENERATE_RESOURCES -) -public class InjectMojo extends AbstractMojo -{ - private final Log log = getLog(); - @Parameter(defaultValue = "${project.build.outputDirectory}") - private File outputDirectory; - @Parameter(defaultValue = "./runescape-client/target/rs-client-${project.version}.jar", readonly = true, required = true) - private String rsClientPath; - @Parameter(defaultValue = "${net.runelite.rs:vanilla:jar}", readonly = true, required = true) - private String vanillaPath; - - @Override - public void execute() throws MojoExecutionException, MojoFailureException - { - ClientVersion ver = new ClientVersion(new File(vanillaPath)); - int version; - try - { - version = ver.getVersion(); - } - catch (IOException ex) - { - throw new MojoExecutionException("Unable to read vanilla client version", ex); - } - - log.info("Vanilla client version " + version); - - ClassGroup rs; - ClassGroup vanilla; - - try - { - rs = JarUtil.loadJar(new File(rsClientPath)); - vanilla = JarUtil.loadJar(new File(vanillaPath)); - } - catch (IOException ex) - { - throw new MojoExecutionException("Unable to load dependency jars", ex); - } - - Injector injector = new Injector(rs, vanilla); - try - { - injector.inject(); - } - catch (InjectionException ex) - { - throw new MojoExecutionException("Error injecting client", ex); - } - - InjectorValidator iv = new InjectorValidator(vanilla); - iv.validate(); - - if (iv.getError() > 0) - { - throw new MojoExecutionException("Error building injected jar"); - } - - if (iv.getMissing() > 0) - { - throw new MojoExecutionException("Unable to inject all methods"); - } - - try - { - writeClasses(vanilla, outputDirectory); - } - catch (IOException ex) - { - throw new MojoExecutionException("Unable to write classes", ex); - } - - log.info("Injector wrote " + vanilla.getClasses().size() + " classes, " + iv.getOkay() + " injected methods"); - } - - private void writeClasses(ClassGroup group, File outputDirectory) throws IOException - { - for (ClassFile cf : group.getClasses()) - { - File classFile = getClassFile(outputDirectory, cf); - byte[] classData = JarUtil.writeClass(group, cf); - - try (FileOutputStream fout = new FileOutputStream(classFile, false)) - { - fout.write(classData); - } - } - } - - private File getClassFile(File base, ClassFile cf) - { - File f = base; - - String[] parts = cf.getName().split("/"); - for (int i = 0; i < parts.length - 1; ++i) - { - String part = parts[i]; - - f = new File(f, part); - } - - f.mkdirs(); - f = new File(f, parts[parts.length - 1] + ".class"); - - return f; - } - -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java b/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java deleted file mode 100644 index 58c225fa87..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.util.List; -import net.runelite.asm.ClassFile; -import net.runelite.asm.Field; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Code; -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.LMul; -import net.runelite.asm.attributes.code.instructions.PutField; -import net.runelite.asm.attributes.code.instructions.PutStatic; -import net.runelite.asm.attributes.code.instructions.VReturn; -import net.runelite.asm.signature.Signature; -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class InjectSetter -{ - private static final Logger logger = LoggerFactory.getLogger(InjectSetter.class); - - private final Inject inject; - - private int injectedSetters; - - InjectSetter(Inject inject) - { - this.inject = inject; - } - - /** - * inject a setter into the vanilla classgroup - * - * @param targetClass Class where to inject the setter (field's class, - * or client) - * @param targetApiClass API targetClass implements, which may have the - * setter declared - * @param field Field of vanilla that will be set - * @param exportedName exported name of field - */ - void injectSetter(ClassFile targetClass, Class targetApiClass, Field field, String exportedName, Number setter) - { - java.lang.reflect.Method method = inject.findImportMethodOnApi(targetApiClass, exportedName, true); - if (method == null) - { - logger.warn("Setter injection for field {} but an API method was not found on {}", exportedName, targetApiClass); - return; - } - - if (method.getParameterCount() != 1) - { - logger.warn("Setter {} with not parameter count != 1?", exportedName); - return; - } - - logger.info("Injecting setter for {} on {}", exportedName, targetApiClass); - - assert targetClass.findMethod(method.getName()) == null; - assert field.isStatic() || field.getClassFile() == targetClass; - - Signature sig = new Signature.Builder() - .setReturnType(Type.VOID) - .addArgument(Inject.classToType(method.getParameterTypes()[0])) - .build(); - - Method setterMethod = new Method(targetClass, method.getName(), sig); - setterMethod.setAccessFlags(ACC_PUBLIC); - targetClass.addMethod(setterMethod); - ++injectedSetters; - - Code code = new Code(setterMethod); - setterMethod.setCode(code); - - Instructions instructions = code.getInstructions(); - List ins = instructions.getInstructions(); - - // load this - if (!field.isStatic()) - { - ins.add(new ALoad(instructions, 0)); - } - - // load argument - Type argumentType = sig.getTypeOfArg(0); - ins.add(inject.createLoadForTypeIndex(instructions, argumentType, 1)); - - // cast argument to field type - Type fieldType = field.getType(); - if (!argumentType.equals(fieldType)) - { - CheckCast checkCast = new CheckCast(instructions); - checkCast.setType(fieldType); - ins.add(checkCast); - } - - if (setter != null) - { - assert setter instanceof Integer || setter instanceof Long; - - if (setter instanceof Integer) - { - ins.add(new LDC(instructions, (int) setter)); - ins.add(new IMul(instructions)); - } - else - { - ins.add(new LDC(instructions, (long) setter)); - ins.add(new LMul(instructions)); - } - } - - if (field.isStatic()) - { - ins.add(new PutStatic(instructions, field)); - } - else - { - ins.add(new PutField(instructions, field)); - } - - ins.add(new VReturn(instructions)); - } - - int getInjectedSetters() - { - return injectedSetters; - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java b/injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java deleted file mode 100644 index 2292b349ab..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java +++ /dev/null @@ -1,281 +0,0 @@ -package net.runelite.injector; - -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.asm.Field; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.annotation.Annotation; -import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; - -public class InjectUtil -{ - public static ClassFile toObClass(final ClassGroup vanilla, final ClassFile deobCf) throws InjectionException - { - final String obfuscatedName = DeobAnnotations.getObfuscatedName(deobCf.getAnnotations()); - final ClassFile obCf = vanilla.findClass(obfuscatedName); - - if (obCf == null) - { - throw new InjectionException(String.format("ClassFile \"%s\" could not be found.", obfuscatedName)); - } - - return obCf; - } - - public static Field toObField(final ClassGroup vanilla, final Field field) throws InjectionException - { - String obfuscatedClassName = DeobAnnotations.getObfuscatedName(field.getClassFile().getAnnotations()); - String obfuscatedFieldName = DeobAnnotations.getObfuscatedName(field.getAnnotations()); // obfuscated name of field - Type type = getFieldType(field); - - ClassFile obfuscatedClass = vanilla.findClass(obfuscatedClassName); - if (obfuscatedClass == null) - { - throw new InjectionException(String.format("ClassFile \"%s\" could not be found.", obfuscatedClassName)); - } - - Field obfuscatedField = obfuscatedClass.findFieldDeep(obfuscatedFieldName, type); - if (obfuscatedField == null) - { - throw new InjectionException(String.format("Field \"%s\" could not be found.", obfuscatedFieldName)); - } - - return obfuscatedField; - } - - public static ClassFile toDeobClass(final ClassFile obCf, final ClassGroup deob) throws InjectionException - { - final ClassFile wowThatWasQuick = deob.findObfuscatedName(obCf.getName()); - if (wowThatWasQuick == null) - { - throw new InjectionException("It wasn't obfscated enough, or a bit too much. Whatever it was it, wasn't in deob"); - } - return wowThatWasQuick; - } - - public static Type getFieldType(final Field f) - { - Type type = f.getType(); - - Annotation obfSignature = f.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE); - if (obfSignature != null) - { - //Annotation exists. Type was updated by us during deobfuscation - type = DeobAnnotations.getObfuscatedType(f); - } - - return type; - } - - /** - * Find a static method in ClassGroup group. Check the class with name hint first. - * (useful for static methods which are in the class they belong to) - */ - public static Method findStaticMethod(final ClassGroup group, final String name, final String hint) throws InjectionException - { - final ClassFile cf = group.findClass(hint); - - if (cf == null) - { - throw new InjectionException(String.format("ClassFile \"%s\" could not be found.", hint)); - } - - Method m = cf.findStaticMethod(name); - - if (m == null) - { - m = group.findStaticMethod(name); - } - - return m; - } - - /** - * Find a static method in ClassGroup group. Throws exception if not found. - */ - public static Method findStaticMethod(final ClassGroup group, final String name) throws InjectionException - { - Method m = group.findStaticMethod(name); - - if (m == null) - { - throw new InjectionException(String.format("Static method \"%s\" could not be found.", name)); - } - - return m; - } - - /** - * Find a static method in ClassGroup group. Throws exception if not found. - */ - public static Method findStaticMethod(final ClassGroup group, final String name, Signature sig) throws InjectionException - { - Method m = group.findStaticMethod(name, sig); - - if (m == null) - { - throw new InjectionException(String.format("Static method \"%s\" could not be found.", name)); - } - - return m; - } - - public static Method findMethod(Inject inject, String name) throws InjectionException - { - return findMethod(inject, name, null); - } - - public static Method findMethod(Inject inject, String name, String hint) throws InjectionException - { - if (hint != null) - { - ClassFile c = inject.getDeobfuscated().findClass(hint); - - if (c == null) - { - throw new InjectionException("Class " + hint + " doesn't exist. (check capitalization)"); - } - - Method deob = c.findMethod(name); - - if (deob != null) - { - String obfuscatedName = DeobAnnotations.getObfuscatedName(deob.getAnnotations()); - Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(deob); - - ClassFile ob = toObClass(inject.getVanilla(), c); - - return ob.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : deob.getDescriptor()); - } - } - - for (ClassFile c : inject.getDeobfuscated().getClasses()) - { - for (Method m : c.getMethods()) - { - if (!m.getName().equals(name)) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations()); - Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m); - - ClassFile c2 = toObClass(inject.getVanilla(), c); - - return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor()); - } - } - - throw new InjectionException("Couldn't find method " + name); - } - - public static Method findStaticMethod(Inject inject, String name) throws InjectionException - { - for (ClassFile c : inject.getDeobfuscated().getClasses()) - { - for (Method m : c.getMethods()) - { - if (!m.isStatic() || !m.getName().equals(name)) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations()); - Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m); - - ClassFile c2 = toObClass(inject.getVanilla(), c); - - return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor()); - } - } - - throw new InjectionException("Couldn't find static method " + name); - } - - - public static Field findObField(Inject inject, String name) throws InjectionException - { - for (ClassFile c : inject.getVanilla().getClasses()) - { - for (Field f : c.getFields()) - { - if (!f.getName().equals(name)) - { - continue; - } - return f; - } - } - - throw new InjectionException(String.format("Field \"%s\" could not be found.", name)); - } - - public static Field findDeobField(Inject inject, String name) throws InjectionException - { - return findDeobField(inject, name, null); - } - - public static Field findDeobField(Inject inject, String name, String hint) throws InjectionException - { - if (hint != null) - { - ClassFile c = inject.getDeobfuscated().findClass(hint); - if (c == null) - { - throw new InjectionException("Class " + hint + " doesn't exist. (check capitalization)"); - } - - for (Field f : c.getFields()) - { - if (!f.getName().equals(name)) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(f.getAnnotations()); - - ClassFile c2 = toObClass(inject.getVanilla(), c); - return c2.findField(obfuscatedName); - } - } - - for (ClassFile c : inject.getDeobfuscated().getClasses()) - { - for (Field f : c.getFields()) - { - if (!f.getName().equals(name)) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(f.getAnnotations()); - - ClassFile c2 = toObClass(inject.getVanilla(), c); - return c2.findField(obfuscatedName); - } - } - - throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name)); - } - - public static Field findDeobFieldButUseless(Inject inject, String name) throws InjectionException - { - for (ClassFile c : inject.getDeobfuscated().getClasses()) - { - for (Field f : c.getFields()) - { - if (!f.getName().equals(name)) - { - continue; - } - - return f; - } - } - - throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name)); - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectionException.java b/injector-plugin/src/main/java/net/runelite/injector/InjectionException.java deleted file mode 100644 index 7881ba739e..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectionException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -public class InjectionException extends Exception -{ - public InjectionException(String message) - { - super(message); - } - - public InjectionException(Throwable cause) - { - super(cause); - } - - public InjectionException(String message, Throwable cause) - { - super(message, cause); - } - -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/Injector.java b/injector-plugin/src/main/java/net/runelite/injector/Injector.java deleted file mode 100644 index 4543ed5b46..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/Injector.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2016-2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.io.File; -import java.io.IOException; - -import com.google.common.io.Files; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.deob.util.JarUtil; - -public class Injector -{ - private final ClassGroup deobfuscated, vanilla; - - public Injector(ClassGroup deobfuscated, ClassGroup vanilla) - { - this.deobfuscated = deobfuscated; - this.vanilla = vanilla; - } - - public static void main(String[] args) throws IOException, InjectionException - { - if (args.length < 3) - { - System.exit(-1); - } - - ClassGroup deobfuscated = JarUtil.loadJar(new File(args[0])); - ClassGroup vanilla = JarUtil.loadJar(new File(args[1])); - - Injector u = new Injector( - deobfuscated, - vanilla - ); - u.inject(); - - InjectorValidator iv = new InjectorValidator(vanilla); - iv.validate(); - - u.save(new File(args[2])); - } - - public void inject() throws InjectionException - { - Inject instance = new Inject(deobfuscated, vanilla); - instance.run(); - } - - private void save(File out) throws IOException - { - out.mkdirs(); - for (ClassFile cf : vanilla.getClasses()) - { - File f = new File(out, cf.getClassName() + ".class"); - byte[] data = JarUtil.writeClass(vanilla, cf); - Files.write(data, f); - } - } - - -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java b/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java deleted file mode 100644 index a49df63a3a..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import net.runelite.asm.ClassFile; -import net.runelite.asm.ClassGroup; -import net.runelite.asm.signature.Signature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Verifies the injected jar is valid - * - * @author Adam - */ -class InjectorValidator -{ - private static final Logger logger = LoggerFactory.getLogger(InjectorValidator.class); - - private static final String API_PACKAGE_BASE = "net/runelite/rs/api/"; - - private final ClassGroup group; - - private int error, missing, okay; - - InjectorValidator(ClassGroup group) - { - this.group = group; - } - - void validate() - { - for (ClassFile cf : group.getClasses()) - { - validate(cf); - } - - logger.info("{} overridden methods, {} missing", okay, missing); - } - - private void validate(ClassFile cf) - { - // find methods of the interface not implemented in the class - for (net.runelite.asm.pool.Class clazz : cf.getInterfaces().getInterfaces()) - { - if (!clazz.getName().startsWith(API_PACKAGE_BASE)) - { - continue; - } - - Class c; - try - { - c = Class.forName(clazz.getName().replace('/', '.')); - } - catch (ClassNotFoundException ex) - { - logger.warn(null, ex); - continue; - } - - if (cf.isAbstract()) - { - // Abstract classes don't have to implement anything - continue; - } - - for (Method method : c.getMethods()) - { - if (method.isSynthetic() || method.isDefault()) - { - continue; - } - - // could check method signature here too but it is - // annoying to deal with both runelite api and java - // reflection api - if (cf.findMethodDeep(method.getName()) == null) - { - logger.warn("Class {} implements interface {} but not does implement method {}", - cf.getName(), c.getSimpleName(), method); - ++missing; - } - else - { - ++okay; - } - } - } - - Set signatures = new HashSet<>(); - - for (net.runelite.asm.Method method : cf.getMethods()) - { - NameAndSignature nas = new NameAndSignature(method.getName(), method.getDescriptor()); - - if (signatures.contains(nas)) - { - logger.error("Class {} has duplicate method with same name and signature {} {}", - cf.getName(), method.getName(), method.getDescriptor()); - ++error; - } - - signatures.add(nas); - } - } - - int getError() - { - return error; - } - - int getMissing() - { - return missing; - } - - int getOkay() - { - return okay; - } - - static final class NameAndSignature - { - String name; - Signature signature; - - NameAndSignature(String name, Signature signature) - { - this.name = name; - this.signature = signature; - } - - @Override - public int hashCode() - { - int hash = 3; - hash = 67 * hash + Objects.hashCode(this.name); - hash = 67 * hash + Objects.hashCode(this.signature); - return hash; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (getClass() != obj.getClass()) - { - return false; - } - final NameAndSignature other = (NameAndSignature) obj; - if (!Objects.equals(this.name, other.name)) - { - return false; - } - if (!Objects.equals(this.signature, other.signature)) - { - return false; - } - return true; - } - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java b/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java deleted file mode 100644 index bf4627c785..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java +++ /dev/null @@ -1,998 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector; - -import com.google.common.reflect.ClassPath; -import com.google.common.reflect.ClassPath.ClassInfo; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import net.runelite.api.mixins.Mixin; -import net.runelite.asm.ClassFile; -import net.runelite.asm.Field; -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.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.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.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; -import net.runelite.asm.attributes.code.instructions.InvokeSpecial; -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.asm.visitors.ClassFileVisitor; -import net.runelite.deob.DeobAnnotations; -import static net.runelite.injector.InjectUtil.findStaticMethod; -import static net.runelite.injector.InjectUtil.toDeobClass; -import static net.runelite.injector.InjectUtil.toObClass; -import static net.runelite.injector.InjectUtil.toObField; -import org.objectweb.asm.ClassReader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MixinInjector -{ - private static final Logger logger = LoggerFactory.getLogger(MixinInjector.class); - - private static final Type INJECT = new Type("Lnet/runelite/api/mixins/Inject;"); - private static final Type SHADOW = new Type("Lnet/runelite/api/mixins/Shadow;"); - private static final Type COPY = new Type("Lnet/runelite/api/mixins/Copy;"); - private static final Type REPLACE = new Type("Lnet/runelite/api/mixins/Replace;"); - private static final Type FIELDHOOK = new Type("Lnet/runelite/api/mixins/FieldHook;"); - private static final Type METHODHOOK = new Type("Lnet/runelite/api/mixins/MethodHook;"); - private static final Type JAVAX_INJECT = new Type("Ljavax/inject/Inject;"); - private static final Type NAMED = new Type("Ljavax/inject/Named;"); - - private static final String MIXIN_BASE = "net.runelite.mixins"; - private static final String ASSERTION_FIELD = "$assertionsDisabled"; - - private final Inject inject; - - // field name -> Field of injected fields - private final Map injectedFields = new HashMap<>(); - // Use net.runelite.asm.pool.Field instead of Field because the pool version has hashcode implemented - private final Map shadowFields = new HashMap<>(); - - MixinInjector(Inject inject) - { - this.inject = inject; - } - - public void inject() throws InjectionException - { - ClassPath classPath; - - try - { - classPath = ClassPath.from(this.getClass().getClassLoader()); - } - catch (IOException ex) - { - throw new InjectionException(ex); - } - - // key: mixin class - // value: mixin targets - Map, List> mixinClasses = new HashMap<>(); - - // Find mixins and populate mixinClasses - for (ClassInfo classInfo : classPath.getTopLevelClasses(MIXIN_BASE)) - { - Class mixinClass = classInfo.load(); - List mixinTargets = new ArrayList<>(); - - for (Mixin mixin : mixinClass.getAnnotationsByType(Mixin.class)) - { - Class implementInto = mixin.value(); - - ClassFile targetCf = inject.findVanillaForInterface(implementInto); - - if (targetCf == null) - { - throw new InjectionException("No class implements " + implementInto + " for mixin " + mixinClass); - } - - mixinTargets.add(targetCf); - } - - mixinClasses.put(mixinClass, mixinTargets); - } - - inject(mixinClasses); - } - - public void inject(Map, List> mixinClasses) throws InjectionException - { - injectFields(mixinClasses); - findShadowFields(mixinClasses); - - for (Class mixinClass : mixinClasses.keySet()) - { - try - { - for (ClassFile cf : mixinClasses.get(mixinClass)) - { - // Make a new mixin ClassFile copy every time, - // so they don't share Code references - ClassFile mixinCf = loadClass(mixinClass); - - injectMethods(mixinCf, cf, shadowFields); - } - } - catch (IOException ex) - { - throw new InjectionException(ex); - } - } - - injectFieldHooks(mixinClasses); - injectMethodHooks(mixinClasses); - } - - /** - * Finds fields that are marked @Inject and inject them into the target - */ - private void injectFields(Map, List> mixinClasses) throws InjectionException - { - // Inject fields, and put them in injectedFields if they can be used by other mixins - for (Class mixinClass : mixinClasses.keySet()) - { - ClassFile mixinCf; - - try - { - mixinCf = loadClass(mixinClass); - } - catch (IOException ex) - { - throw new InjectionException(ex); - } - - List targetCfs = mixinClasses.get(mixinClass); - - for (ClassFile cf : targetCfs) - { - for (Field field : mixinCf.getFields()) - { - // Always inject $assertionsEnabled if its missing. - if (ASSERTION_FIELD.equals(field.getName())) - { - if (cf.findField(ASSERTION_FIELD, Type.BOOLEAN) != null) - { - continue; - } - } - else - { - Annotation inject = field.getAnnotations().find(INJECT); - - if (inject == null) - { - continue; - } - } - - Field copy = new Field(cf, field.getName(), field.getType()); - copy.setAccessFlags(field.getAccessFlags()); - copy.setPublic(); - copy.setValue(field.getValue()); - - Annotation jInject = field.getAnnotations().find(JAVAX_INJECT); - if (jInject != null) - { - copy.getAnnotations().addAnnotation(jInject); - logger.info("Added javax inject to {}.{}", cf.getClassName(), copy.getName()); - - Annotation named = field.getAnnotations().find(NAMED); - if (named != null) - { - copy.getAnnotations().addAnnotation(named); - logger.info("Added javax named to {}.{}", cf.getClassName(), copy.getName()); - } - } - - cf.addField(copy); - - if (injectedFields.containsKey(field.getName()) && !field.getName().equals(ASSERTION_FIELD)) - { - java.util.logging.Logger.getAnonymousLogger().severe("Duplicate field : " + field.getName()); - throw new InjectionException("Injected field names must be globally unique"); - } - - injectedFields.put(field.getName(), copy); - } - } - - } - } - - /** - * Find fields which are marked @Shadow, and what they shadow - */ - private void findShadowFields(Map, List> mixinClasses) throws InjectionException - { - // Find shadow fields - // Injected static fields take precedence when looking up shadowed fields - for (Class mixinClass : mixinClasses.keySet()) - { - ClassFile mixinCf; - - try - { - mixinCf = loadClass(mixinClass); - } - catch (IOException ex) - { - throw new InjectionException(ex); - } - - for (Field field : mixinCf.getFields()) - { - Annotation shadow = field.getAnnotations().find(SHADOW); - if (shadow != null) - { - if (!field.isStatic()) - { - throw new InjectionException("Can only shadow static fields"); - } - - String shadowName = shadow.getElement().getString(); // shadow this field - - Field injectedField = injectedFields.get(shadowName); - if (injectedField != null) - { - // Shadow a field injected by a mixin - shadowFields.put(field.getPoolField(), injectedField); - } - else - { - // Shadow a field already in the gamepack - Field shadowField = InjectUtil.findDeobFieldButUseless(inject, shadowName); - - if (shadowField == null) - { - throw new InjectionException("Shadow of nonexistent field " + shadowName); - } - - Field obShadow = toObField(inject.getVanilla(), shadowField); - assert obShadow != null; - shadowFields.put(field.getPoolField(), obShadow); - } - } - } - } - } - - private ClassFile loadClass(Class clazz) throws IOException - { - try (InputStream is = clazz.getClassLoader().getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) - { - ClassReader reader = new ClassReader(is); - ClassFileVisitor cv = new ClassFileVisitor(); - - reader.accept(cv, 0); - - return cv.getClassFile(); - } - } - - private void injectMethods(ClassFile mixinCf, ClassFile cf, Map shadowFields) - throws InjectionException - { - // Keeps mappings between methods annotated with @Copy -> the copied method within the vanilla pack - Map copiedMethods = new HashMap<>(); - - // Handle the copy mixins first, so all other mixins know of the copies - for (Method method : mixinCf.getMethods()) - { - Annotation copyAnnotation = method.getAnnotations().find(COPY); - - if (copyAnnotation == null) - { - continue; - } - - String deobMethodName = (String) copyAnnotation.getElement().getValue(); - Method deobMethod; - if (method.isStatic()) - { - deobMethod = findStaticMethod(inject.getDeobfuscated(), deobMethodName, method.getDescriptor().rsApiToRsClient()); - } - else - { - ClassFile deobCf = toDeobClass(cf, inject.getDeobfuscated()); - deobMethod = deobCf.findMethod(deobMethodName, method.getDescriptor().rsApiToRsClient()); - } - - - if (deobMethod == null) - { - throw new InjectionException("Failed to find the deob method " + deobMethodName + " for mixin " + mixinCf); - } - - if (method.isStatic() != deobMethod.isStatic()) - { - throw new InjectionException("Mixin method " + method + " should be " + (deobMethod.isStatic() ? "static" : "non-static")); - } - - // Find the vanilla class where the method to copy is in - String obClassName = DeobAnnotations.getObfuscatedName(deobMethod.getClassFile().getAnnotations()); - ClassFile obCf = inject.getVanilla().findClass(obClassName); - assert obCf != null : "unable to find vanilla class from obfuscated name " + obClassName; - - String obMethodName = DeobAnnotations.getObfuscatedName(deobMethod.getAnnotations()); - Signature obMethodSignature = DeobAnnotations.getObfuscatedSignature(deobMethod); - - if (obMethodName == null) - { - obMethodName = deobMethod.getName(); - } - if (obMethodSignature == null) - { - obMethodSignature = deobMethod.getDescriptor(); - } - - Method obMethod = obCf.findMethod(obMethodName, obMethodSignature); - if (obMethod == null) - { - throw new InjectionException("Failed to find the ob method " + obMethodName + " for mixin " + mixinCf); - } - - if (method.getDescriptor().size() > obMethod.getDescriptor().size()) - { - throw new InjectionException("Mixin methods cannot have more parameters than their corresponding ob method"); - } - - Method copy = new Method(cf, "copy$" + deobMethodName, obMethodSignature); - moveCode(copy, obMethod.getCode()); - copy.setAccessFlags(obMethod.getAccessFlags()); - copy.setPublic(); - copy.getExceptions().getExceptions().addAll(obMethod.getExceptions().getExceptions()); - copy.getAnnotations().getAnnotations().addAll(obMethod.getAnnotations().getAnnotations()); - cf.addMethod(copy); - - /* - If the desc for the mixin method and the desc for the ob method - are the same in length, assume that the mixin method is taking - care of the garbage parameter itself. - */ - boolean hasGarbageValue = method.getDescriptor().size() != obMethod.getDescriptor().size() - && deobMethod.getDescriptor().size() < obMethodSignature.size(); - copiedMethods.put(method.getPoolMethod(), new CopiedMethod(copy, hasGarbageValue)); - - logger.debug("Injected copy of {} to {}", obMethod, copy); - } - - // Handle the rest of the mixin types - for (Method method : mixinCf.getMethods()) - { - boolean isClinit = "".equals(method.getName()); - boolean isInit = "".equals(method.getName()); - boolean hasInject = method.getAnnotations().find(INJECT) != null; - - // You can't annotate clinit, so its always injected - if ((hasInject && isInit) || isClinit) - { - if (!"()V".equals(method.getDescriptor().toString())) - { - throw new InjectionException("Injected constructors cannot have arguments"); - } - - Method[] originalMethods = cf.getMethods().stream() - .filter(n -> n.getName().equals(method.getName())) - .toArray(Method[]::new); - // If there isn't a already just inject ours, otherwise rename it - // This is always true for - String name = method.getName(); - if (originalMethods.length > 0) - { - name = "rl$$" + (isInit ? "init" : "clinit"); - } - String numberlessName = name; - for (int i = 1; cf.findMethod(name, method.getDescriptor()) != null; i++) - { - name = numberlessName + i; - } - - Method copy = new Method(cf, name, method.getDescriptor()); - moveCode(copy, method.getCode()); - copy.setAccessFlags(method.getAccessFlags()); - copy.setPrivate(); - assert method.getExceptions().getExceptions().isEmpty(); - - // Remove the call to the superclass's ctor - if (isInit) - { - Instructions instructions = copy.getCode().getInstructions(); - ListIterator listIter = instructions.getInstructions().listIterator(); - for (; listIter.hasNext(); ) - { - Instruction instr = listIter.next(); - if (instr instanceof InvokeSpecial) - { - InvokeSpecial invoke = (InvokeSpecial) instr; - assert invoke.getMethod().getName().equals(""); - listIter.remove(); - int pops = invoke.getMethod().getType().getArguments().size() + 1; - for (int i = 0; i < pops; i++) - { - listIter.add(new Pop(instructions)); - } - break; - } - } - } - - setOwnersToTargetClass(mixinCf, cf, copy, shadowFields, copiedMethods); - cf.addMethod(copy); - - // Call our method at the return point of the matching method(s) - for (Method om : originalMethods) - { - Instructions instructions = om.getCode().getInstructions(); - ListIterator listIter = instructions.getInstructions().listIterator(); - for (; listIter.hasNext(); ) - { - Instruction instr = listIter.next(); - if (instr instanceof ReturnInstruction) - { - listIter.previous(); - if (isInit) - { - listIter.add(new ALoad(instructions, 0)); - listIter.add(new InvokeSpecial(instructions, copy.getPoolMethod())); - } - else if (isClinit) - { - listIter.add(new InvokeStatic(instructions, copy.getPoolMethod())); - } - listIter.next(); - } - } - } - - logger.debug("Injected mixin method {} to {}", copy, cf); - } - else if (hasInject) - { - // Make sure the method doesn't invoke copied methods - for (Instruction i : method.getCode().getInstructions().getInstructions()) - { - if (i instanceof InvokeInstruction) - { - InvokeInstruction ii = (InvokeInstruction) i; - - if (copiedMethods.containsKey(ii.getMethod())) - { - throw new InjectionException("Injected methods cannot invoke copied methods"); - } - } - } - - Method copy = new Method(cf, method.getName(), method.getDescriptor()); - moveCode(copy, method.getCode()); - copy.setAccessFlags(method.getAccessFlags()); - copy.setPublic(); - assert method.getExceptions().getExceptions().isEmpty(); - - setOwnersToTargetClass(mixinCf, cf, copy, shadowFields, copiedMethods); - - cf.addMethod(copy); - - logger.debug("Injected mixin method {} to {}", copy, cf); - } - else if (method.getAnnotations().find(REPLACE) != null) - { - Annotation replaceAnnotation = method.getAnnotations().find(REPLACE); - String deobMethodName = (String) replaceAnnotation.getElement().getValue(); - - ClassFile deobCf = inject.toDeobClass(cf); - Method deobMethod = findDeobMethod(deobCf, deobMethodName, method.getDescriptor()); - - if (deobMethod == null) - { - throw new InjectionException("Failed to find the deob method " + deobMethodName + " for mixin " + mixinCf); - } - - if (method.isStatic() != deobMethod.isStatic()) - { - throw new InjectionException("Mixin method " + method + " should be " - + (deobMethod.isStatic() ? "static" : "non-static")); - } - - String obMethodName = DeobAnnotations.getObfuscatedName(deobMethod.getAnnotations()); - Signature obMethodSignature = DeobAnnotations.getObfuscatedSignature(deobMethod); - - // Deob signature is the same as ob signature - if (obMethodName == null) - { - obMethodName = deobMethod.getName(); - } - if (obMethodSignature == null) - { - obMethodSignature = deobMethod.getDescriptor(); - } - - // Find the vanilla class where the method to copy is in - String obClassName = DeobAnnotations.getObfuscatedName(deobMethod.getClassFile().getAnnotations()); - ClassFile obCf = inject.getVanilla().findClass(obClassName); - - Method obMethod = obCf.findMethod(obMethodName, obMethodSignature); - assert obMethod != null : "obfuscated method " + obMethodName + obMethodSignature + " does not exist"; - - if (method.getDescriptor().size() > obMethod.getDescriptor().size()) - { - throw new InjectionException("Mixin methods cannot have more parameters than their corresponding ob method"); - } - - Type returnType = method.getDescriptor().getReturnValue(); - Type deobReturnType = inject.apiTypeToDeobfuscatedType(returnType); - if (!returnType.equals(deobReturnType)) - { - ClassFile deobReturnTypeClassFile = inject.getDeobfuscated() - .findClass(deobReturnType.getInternalName()); - if (deobReturnTypeClassFile != null) - { - ClassFile obReturnTypeClass = toObClass(inject.getVanilla(), deobReturnTypeClassFile); - - Instructions instructions = method.getCode().getInstructions(); - ListIterator listIter = instructions.getInstructions().listIterator(); - for (; 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, method.getCode()); - - boolean hasGarbageValue = method.getDescriptor().size() != obMethod.getDescriptor().size() - && deobMethod.getDescriptor().size() < obMethodSignature.size(); - - if (hasGarbageValue) - { - int garbageIndex = obMethod.isStatic() - ? obMethod.getDescriptor().size() - 1 - : obMethod.getDescriptor().size(); - - /* - If the mixin method doesn't have the garbage parameter, - the compiler will have produced code that uses the garbage - parameter's local variable index for other things, - so we'll have to add 1 to all loads/stores to indices - that are >= garbageIndex. - */ - shiftLocalIndices(obMethod.getCode().getInstructions(), garbageIndex); - } - - setOwnersToTargetClass(mixinCf, cf, obMethod, shadowFields, copiedMethods); - - logger.debug("Replaced method {} with mixin method {}", obMethod, method); - } - } - } - - private void moveCode(Method method, Code code) - { - Code newCode = new Code(method); - newCode.setMaxStack(code.getMaxStack()); - newCode.getInstructions().getInstructions().addAll(code.getInstructions().getInstructions()); - // Update instructions for each instruction - for (Instruction i : newCode.getInstructions().getInstructions()) - { - i.setInstructions(newCode.getInstructions()); - } - newCode.getExceptions().getExceptions().addAll(code.getExceptions().getExceptions()); - for (net.runelite.asm.attributes.code.Exception e : newCode.getExceptions().getExceptions()) - { - e.setExceptions(newCode.getExceptions()); - } - method.setCode(newCode); - } - - private void setOwnersToTargetClass(ClassFile mixinCf, ClassFile cf, Method method, - Map shadowFields, - Map copiedMethods) - throws InjectionException - { - ListIterator iterator = method.getCode().getInstructions().getInstructions().listIterator(); - - while (iterator.hasNext()) - { - Instruction i = iterator.next(); - - if (i instanceof ANewArray) - { - Type type = ((ANewArray) i).getType_(); - ClassFile deobCf = inject.getDeobfuscated().findClass(type.toString().replace("Lnet/runelite/rs/api/RS", "").replace(";", "")); - - if (deobCf != null) - { - ClassFile obReturnTypeClass = toObClass(inject.getVanilla(), deobCf); - Type newType = new Type("L" + obReturnTypeClass.getName() + ";"); - - ((ANewArray) i).setType(newType); - logger.info("Replaced {} type {} with type {}", i, type, newType); - } - } - - if (i instanceof InvokeInstruction) - { - InvokeInstruction ii = (InvokeInstruction) i; - - CopiedMethod copiedMethod = copiedMethods.get(ii.getMethod()); - if (copiedMethod != null) - { - ii.setMethod(copiedMethod.obMethod.getPoolMethod()); - - // Pass through garbage value if the method has one - if (copiedMethod.hasGarbageValue) - { - int garbageIndex = copiedMethod.obMethod.isStatic() - ? copiedMethod.obMethod.getDescriptor().size() - 1 - : copiedMethod.obMethod.getDescriptor().size(); - - iterator.previous(); - iterator.add(new ILoad(method.getCode().getInstructions(), garbageIndex)); - iterator.next(); - } - } - else if (ii.getMethod().getClazz().getName().equals(mixinCf.getName())) - { - ii.setMethod(new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(cf.getName()), - ii.getMethod().getName(), - ii.getMethod().getType() - )); - } - } - else if (i instanceof FieldInstruction) - { - FieldInstruction fi = (FieldInstruction) i; - - Field shadowed = shadowFields.get(fi.getField()); - if (shadowed != null) - { - fi.setField(shadowed.getPoolField()); - } - else if (fi.getField().getClazz().getName().equals(mixinCf.getName())) - { - fi.setField(new net.runelite.asm.pool.Field( - new net.runelite.asm.pool.Class(cf.getName()), - fi.getField().getName(), - fi.getField().getType() - )); - } - } - else if (i instanceof PushConstantInstruction) - { - PushConstantInstruction pi = (PushConstantInstruction) i; - if (mixinCf.getPoolClass().equals(pi.getConstant())) - { - pi.setConstant(cf.getPoolClass()); - } - } - - verify(mixinCf, i); - } - } - - private void shiftLocalIndices(Instructions instructions, int startIdx) - { - for (Instruction i : instructions.getInstructions()) - { - if (i instanceof LVTInstruction) - { - LVTInstruction lvti = (LVTInstruction) i; - - if (lvti.getVariableIndex() >= startIdx) - { - lvti.setVariableIndex(lvti.getVariableIndex() + 1); - } - } - } - } - - private Method findDeobMethod(ClassFile deobCf, String deobMethodName, Signature descriptor) - throws InjectionException - { - List matchingMethods = new ArrayList<>(); - - for (Method m : deobCf.getMethods()) - { - if (!deobMethodName.equals(m.getName())) - { - continue; - } - - Type returnType = inject.apiTypeToDeobfuscatedType(descriptor.getReturnValue()); - Type returnType2 = m.getDescriptor().getReturnValue(); - - if (!returnType.equals(returnType2)) - { - continue; - } - - List args = descriptor.getArguments(); - List args2 = m.getDescriptor().getArguments(); - - if (args.size() > args2.size()) - { - continue; - } - - boolean matchingArgs = true; - - for (int i = 0; i < args.size(); i++) - { - Type type = inject.apiTypeToDeobfuscatedType(args.get(i)); - Type type2 = args2.get(i); - - if (!type.equals(type2)) - { - matchingArgs = false; - break; - } - } - - if (!matchingArgs) - { - continue; - } - - matchingMethods.add(m); - } - - if (matchingMethods.size() > 1) - { - // this happens when it has found several deob methods for some mixin method, - // to get rid of the error, refine your search by making your mixin method have more parameters - throw new InjectionException("There are several matching methods when there should only be one"); - } - else if (matchingMethods.size() == 1) - { - return matchingMethods.get(0); - } - - Method method = deobCf.findMethod(deobMethodName); - - if (method == null) - { - // Look for static methods if an instance method couldn't be found - for (ClassFile deobCf2 : inject.getDeobfuscated().getClasses()) - { - if (deobCf2 != deobCf) - { - method = deobCf2.findMethod(deobMethodName); - - if (method != null) - { - break; - } - } - } - } - - return method; - } - - private void verify(ClassFile mixinCf, Instruction i) throws InjectionException - { - if (i instanceof FieldInstruction) - { - FieldInstruction fi = (FieldInstruction) i; - - if (fi.getField().getClazz().getName().equals(mixinCf.getName())) - { - if (i instanceof PutField || i instanceof GetField) - { - throw new InjectionException("Access to non static member field of mixin"); - } - - Field field = fi.getMyField(); - if (field != null && !field.isPublic()) - { - throw new InjectionException("Static access to non public field " + field); - } - } - } - else if (i instanceof InvokeStatic) - { - InvokeStatic is = (InvokeStatic) i; - - if (is.getMethod().getClazz() != mixinCf.getPoolClass() - && is.getMethod().getClazz().getName().startsWith(MIXIN_BASE.replace(".", "/"))) - { - throw new InjectionException("Invoking static methods of other mixins is not supported"); - } - } - else if (i instanceof InvokeDynamic) - { - // RS classes don't verify under java 7+ due to the - // super() invokespecial being inside of a try{} - throw new InjectionException("Injected bytecode must be Java 6 compatible"); - } - } - - private void injectFieldHooks(Map, List> mixinClasses) throws InjectionException - { - InjectHook injectHook = new InjectHook(inject); - - for (Class mixinClass : mixinClasses.keySet()) - { - ClassFile mixinCf; - - try - { - mixinCf = loadClass(mixinClass); - } - catch (IOException ex) - { - throw new InjectionException(ex); - } - - List targetCfs = mixinClasses.get(mixinClass); - - for (ClassFile cf : targetCfs) - { - for (Method method : mixinCf.getMethods()) - { - Annotation fieldHook = method.getAnnotations().find(FIELDHOOK); - if (fieldHook != null) - { - String hookName = fieldHook.getElement().getString(); - boolean before = fieldHook.getElements().size() == 2 && fieldHook.getElements().get(1).getValue().equals(true); - ClassFile deobCf = inject.toDeobClass(cf); - Field targetField = deobCf.findField(hookName); - if (targetField == null) - { - // first try non static fields, then static - targetField = InjectUtil.findDeobFieldButUseless(inject, hookName); - } - - if (targetField == null) - { - throw new InjectionException("Field hook for nonexistent field " + hookName + " on " + method); - } - - Annotation an = targetField.getAnnotations().find(DeobAnnotations.OBFUSCATED_GETTER); - Number getter = null; - if (an != null) - { - getter = (Number) an.getElement().getValue(); - } - - Field obField = toObField(inject.getVanilla(), targetField); - - if (method.isStatic() != targetField.isStatic()) - { - throw new InjectionException("Field hook method static flag must match target field"); - } - - // cf is the target class to invoke - InjectHook.HookInfo hookInfo = new InjectHook.HookInfo(); - hookInfo.clazz = cf.getName(); - hookInfo.fieldName = hookName; - hookInfo.method = method; - hookInfo.before = before; - hookInfo.getter = getter; - injectHook.hook(obField, hookInfo); - } - } - } - } - - injectHook.run(); - - logger.info("Injected {} field hooks", injectHook.getInjectedHooks()); - } - - private void injectMethodHooks(Map, List> mixinClasses) throws InjectionException - { - InjectHookMethod injectHookMethod = new InjectHookMethod(inject); - - for (Class mixinClass : mixinClasses.keySet()) - { - ClassFile mixinCf; - - try - { - mixinCf = loadClass(mixinClass); - } - catch (IOException ex) - { - throw new InjectionException(ex); - } - - List targetCfs = mixinClasses.get(mixinClass); - - for (ClassFile cf : targetCfs) - { - for (Method method : mixinCf.getMethods()) - { - Annotation methodHook = method.getAnnotations().find(METHODHOOK); - - if (methodHook == null) - { - continue; - } - - String hookName = methodHook.getElement().getString(); - boolean end = methodHook.getElements().size() == 2 && methodHook.getElements().get(1).getValue().equals(true); - ClassFile deobCf = inject.toDeobClass(cf); - Method targetMethod = findDeobMethod(deobCf, hookName, method.getDescriptor()); - - if (targetMethod == null) - { - throw new InjectionException("Method hook for nonexistent method " + hookName + " on " + method); - } - - if (method.isStatic() != targetMethod.isStatic()) - { - throw new InjectionException("Method hook static flag must match target - " + hookName); - } - - injectHookMethod.inject(method, targetMethod, hookName, end, false); - } - } - } - } - - private static class CopiedMethod - { - private Method obMethod; - private boolean hasGarbageValue; - - private CopiedMethod(Method obMethod, boolean hasGarbageValue) - { - this.obMethod = obMethod; - this.hasGarbageValue = hasGarbageValue; - } - } -} diff --git a/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java b/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java deleted file mode 100644 index f4de5d056e..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java +++ /dev/null @@ -1,124 +0,0 @@ -package net.runelite.injector.raw; - -import java.util.ListIterator; -import net.runelite.asm.ClassFile; -import net.runelite.asm.Method; -import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.Instructions; -import net.runelite.asm.attributes.code.instructions.ILoad; -import net.runelite.asm.attributes.code.instructions.InvokeStatic; -import net.runelite.asm.attributes.code.instructions.LDC; -import net.runelite.asm.pool.Class; -import net.runelite.asm.signature.Signature; -import net.runelite.injector.Inject; -import net.runelite.injector.InjectUtil; -import net.runelite.injector.InjectionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ClearColorBuffer -{ - private static final Logger log = LoggerFactory.getLogger(ClearColorBuffer.class); - private static final net.runelite.asm.pool.Method clearBuffer = new net.runelite.asm.pool.Method( - new Class("net.runelite.client.callback.Hooks"), - "clearColorBuffer", - new Signature("(IIIII)V") - ); - private final Inject inject; - - public ClearColorBuffer(Inject inject) - { - this.inject = inject; - } - - public void inject() throws InjectionException - { - injectColorBufferHooks(); - } - - private void injectColorBufferHooks() throws InjectionException - { - net.runelite.asm.pool.Method fillRectangle = InjectUtil.findStaticMethod(inject, "Rasterizer2D_fillRectangle").getPoolMethod(); - - int count = 0; - int replaced = 0; - - for (ClassFile cf : inject.getVanilla().getClasses()) - { - for (Method m : cf.getMethods()) - { - if (!m.isStatic()) - { - continue; - } - - Code c = m.getCode(); - if (c == null) - { - continue; - } - - Instructions ins = c.getInstructions(); - ListIterator it = ins.getInstructions().listIterator(); - - for (; it.hasNext(); ) - { - Instruction i = it.next(); - if (!(i instanceof InvokeStatic)) - { - continue; - } - - if (!((InvokeStatic) i).getMethod().equals(fillRectangle)) - { - continue; - } - - int indexToReturnTo = it.nextIndex(); - count++; - it.previous(); - Instruction current = it.previous(); - if (current instanceof LDC && ((LDC) current).getConstantAsInt() == 0) - { - int varIdx = 0; - for (; ; ) - { - current = it.previous(); - if (current instanceof ILoad && ((ILoad) current).getVariableIndex() == 3 - varIdx) - { - varIdx++; - log.debug(varIdx + " we can count yay"); - continue; - } - - break; - } - - if (varIdx == 4) - { - for (; !(current instanceof InvokeStatic); ) - { - current = it.next(); - } - assert it.nextIndex() == indexToReturnTo; - - it.set(new InvokeStatic(ins, clearBuffer)); - replaced++; - log.debug("Found drawRectangle at {}. Found: {}, replaced {}", m.getName(), count, replaced); - } - else - { - log.debug("Welp, guess this wasn't it chief " + m); - } - } - - while (it.nextIndex() != indexToReturnTo) - { - it.next(); - } - } - } - } - } -} \ No newline at end of file diff --git a/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java b/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java deleted file mode 100644 index 5b6f6fbd50..0000000000 --- a/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2018, Lotto - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.injector.raw; - -import java.util.HashSet; -import java.util.ListIterator; -import java.util.Set; -import net.runelite.asm.ClassFile; -import net.runelite.asm.Method; -import net.runelite.asm.attributes.code.Instruction; -import net.runelite.asm.attributes.code.Instructions; -import net.runelite.asm.attributes.code.Label; -import net.runelite.asm.attributes.code.instruction.types.JumpingInstruction; -import net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction; -import net.runelite.asm.attributes.code.instructions.GetStatic; -import net.runelite.asm.attributes.code.instructions.IMul; -import net.runelite.asm.attributes.code.instructions.InvokeStatic; -import net.runelite.asm.signature.Signature; -import net.runelite.injector.Inject; -import static net.runelite.injector.InjectHookMethod.HOOKS; -import static net.runelite.injector.InjectUtil.findStaticMethod; -import net.runelite.injector.InjectionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DrawAfterWidgets -{ - private static final Logger logger = LoggerFactory.getLogger(DrawAfterWidgets.class); - - private final Inject inject; - - public DrawAfterWidgets(Inject inject) - { - this.inject = inject; - } - - public void inject() throws InjectionException - { - injectDrawAfterWidgets(); - } - - private void injectDrawAfterWidgets() throws InjectionException - { - /* - This call has to be injected using raw injection because the - drawWidgets method gets inlined in some revisions. If it wouldn't be, - mixins would be used to add the call to the end of drawWidgets. - - --> This hook depends on the positions of "if (535573958 * kl != -1)" and "jz.db();". - - - Revision 180 - client.gs(): - ______________________________________________________ - - @Export("drawLoggedIn") - final void drawLoggedIn() { - if(rootInterface != -1) { - ClientPreferences.method1809(rootInterface); - } - - int var1; - for(var1 = 0; var1 < rootWidgetCount; ++var1) { - if(__client_od[var1]) { - __client_ot[var1] = true; - } - - __client_oq[var1] = __client_od[var1]; - __client_od[var1] = false; - } - - __client_oo = cycle; - __client_lq = -1; - __client_ln = -1; - UserComparator6.__fg_jh = null; - if(rootInterface != -1) { - rootWidgetCount = 0; - Interpreter.method1977(rootInterface, 0, 0, SoundCache.canvasWidth, Huffman.canvasHeight, 0, 0, -1); - } - - < -- here appearantly - - Rasterizer2D.Rasterizer2D_resetClip(); - ______________________________________________________ - */ - - boolean injected = false; - - Method noClip = findStaticMethod(inject, "Rasterizer2D_resetClip"); // !!!!! - - if (noClip == null) - { - throw new InjectionException("Mapped method \"Rasterizer2D_resetClip\" could not be found."); - } - - net.runelite.asm.pool.Method poolNoClip = noClip.getPoolMethod(); - - for (ClassFile c : inject.getVanilla().getClasses()) - { - for (Method m : c.getMethods()) - { - if (m.getCode() == null) - { - continue; - } - - Instructions instructions = m.getCode().getInstructions(); - - Set