From 3cc62555961f527b40af4531ab0b1396656fd29d Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 19 Mar 2016 12:45:56 -0400 Subject: [PATCH] Rebuild pool when writing instrutions to fix previous corruption with the newarray stuff. Run classes through ow2 asm to generate stack maps (and maxs for fun) since I don't want to generate my own stackmaps. --- pom.xml | 10 +-- .../java/net/runelite/deob/asm/AsmUtils.java | 22 ++++++ .../deob/asm/NonloadingClassWriter.java | 67 +++++++++++++++++++ .../deob/attributes/code/Instructions.java | 4 +- .../code/instructions/ANewArray.java | 5 +- .../code/instructions/MultiANewArray.java | 5 +- .../java/net/runelite/deob/util/JarUtil.java | 9 ++- 7 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 src/main/java/net/runelite/deob/asm/AsmUtils.java create mode 100644 src/main/java/net/runelite/deob/asm/NonloadingClassWriter.java diff --git a/pom.xml b/pom.xml index e9fd898944..cd9bc692a1 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,11 @@ asm-all 5.0.4 + + net.runelite.rs + api + 1.0-SNAPSHOT + org.slf4j @@ -47,11 +52,6 @@ 4.12 test - - net.runelite.rs - api - 1.0-SNAPSHOT - diff --git a/src/main/java/net/runelite/deob/asm/AsmUtils.java b/src/main/java/net/runelite/deob/asm/AsmUtils.java new file mode 100644 index 0000000000..a2cfed4671 --- /dev/null +++ b/src/main/java/net/runelite/deob/asm/AsmUtils.java @@ -0,0 +1,22 @@ +package net.runelite.deob.asm; + +import java.io.IOException; +import java.io.InputStream; +import net.runelite.deob.ClassGroup; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +public class AsmUtils +{ + public static byte[] rebuildWithStackmaps(ClassGroup group, InputStream is) throws IOException + { + // I don't want to write my own stack map builder. + + ClassReader r = new ClassReader(is); + ClassWriter writer = new NonloadingClassWriter(group, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + r.accept(writer, ClassReader.SKIP_FRAMES); + + return writer.toByteArray(); + } +} diff --git a/src/main/java/net/runelite/deob/asm/NonloadingClassWriter.java b/src/main/java/net/runelite/deob/asm/NonloadingClassWriter.java new file mode 100644 index 0000000000..4a3ba0c260 --- /dev/null +++ b/src/main/java/net/runelite/deob/asm/NonloadingClassWriter.java @@ -0,0 +1,67 @@ +package net.runelite.deob.asm; + +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; +import org.objectweb.asm.ClassWriter; + +class NonloadingClassWriter extends ClassWriter +{ + private final ClassGroup group; + + public NonloadingClassWriter(ClassGroup group, int flags) + { + super(flags); + + this.group = group; + } + + @Override + protected String getCommonSuperClass(String type1, String type2) + { + ClassFile cf1 = group.findClass(type1), + cf2 = group.findClass(type2); + + if (cf1 == null && cf2 == null) + { + // not mine + return super.getCommonSuperClass(type1, type2); + } + + if (cf1 != null && cf2 != null) + { + for (ClassFile c = cf1; c != null; c = c.getParent()) + for (ClassFile c2 = cf2; c2 != null; c2 = c2.getParent()) + if (c == c2) + return c.getName(); + + throw new RuntimeException("No common base"); + } + + ClassFile found; + String other; + + if (cf1 == null) + { + found = cf2; + other = type1; + } + else + { + assert cf2 == null; + found = cf1; + other = type2; + } + + ClassFile prev = null; + + for (ClassFile c = found; c != null; c = c.getParent()) + { + prev = c; + + if (c.getName().equals(other)) + return other; + } + + return super.getCommonSuperClass(prev.getSuperName(), other); + } +} diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index 468cb86e0c..5555b026c1 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -82,7 +82,9 @@ public class Instructions public void write(DataOutputStream out) throws IOException { - // trnaslate instructions to specific + this.regeneratePool(); + + // translate instructions to specific this.buildJumpGraph(); for (Instruction i : new ArrayList<>(instructions)) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java index 2261843eaa..5245daa395 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java @@ -82,7 +82,10 @@ public class ANewArray extends Instruction StringBuffer sb = new StringBuffer(); for (int i = 0; i < this.dimensions; ++i) sb.append('['); - sb.append("L" + myClass.getName() + ";"); + if (this.dimensions > 0) + sb.append("L" + myClass.getName() + ";"); + else + sb.append(myClass.getName()); clazz = new Class(sb.toString()); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java b/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java index 53e0b897d4..d0b1b26884 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java @@ -87,7 +87,10 @@ public class MultiANewArray extends Instruction StringBuffer sb = new StringBuffer(); for (int i = 0; i < this.dimensions; ++i) sb.append('['); - sb.append("L" + myClass.getName() + ";"); + if (this.dimensions > 0) + sb.append("L" + myClass.getName() + ";"); + else + sb.append(myClass.getName()); clazz = new Class(sb.toString()); } } diff --git a/src/main/java/net/runelite/deob/util/JarUtil.java b/src/main/java/net/runelite/deob/util/JarUtil.java index bd97fd6ae9..c10a858bb0 100644 --- a/src/main/java/net/runelite/deob/util/JarUtil.java +++ b/src/main/java/net/runelite/deob/util/JarUtil.java @@ -1,5 +1,6 @@ package net.runelite.deob.util; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -14,6 +15,8 @@ import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import net.runelite.deob.ClassFile; import net.runelite.deob.ClassGroup; +import net.runelite.deob.asm.AsmUtils; +import org.objectweb.asm.ClassReader; public class JarUtil { @@ -51,7 +54,11 @@ public class JarUtil ByteArrayOutputStream bout = new ByteArrayOutputStream(); cf.write(new DataOutputStream(bout)); - jout.write(bout.toByteArray()); + + // run through asm to generate stackmaps + byte[] b = AsmUtils.rebuildWithStackmaps(group, new ByteArrayInputStream(bout.toByteArray())); + + jout.write(b); jout.closeEntry(); }