diff --git a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.kt b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.kt index 9e4a477ec3..a05492801a 100644 --- a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.kt +++ b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.kt @@ -19,6 +19,7 @@ import dev.openrs2.deob.transform.DummyLocalTransformer import dev.openrs2.deob.transform.ExceptionTracingTransformer import dev.openrs2.deob.transform.FieldOrderTransformer import dev.openrs2.deob.transform.FinalTransformer +import dev.openrs2.deob.transform.InvokeSpecialTransformer import dev.openrs2.deob.transform.OpaquePredicateTransformer import dev.openrs2.deob.transform.OriginalNameTransformer import dev.openrs2.deob.transform.OverrideTransformer @@ -164,6 +165,7 @@ class Deobfuscator(private val input: Path, private val output: Path) { ResetTransformer(), FinalTransformer(), ClassLiteralTransformer(), + InvokeSpecialTransformer(), VisibilityTransformer(), OverrideTransformer() ) diff --git a/deob/src/main/java/dev/openrs2/deob/transform/InvokeSpecialTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/InvokeSpecialTransformer.kt new file mode 100644 index 0000000000..3d7bc15089 --- /dev/null +++ b/deob/src/main/java/dev/openrs2/deob/transform/InvokeSpecialTransformer.kt @@ -0,0 +1,48 @@ +package dev.openrs2.deob.transform + +import com.github.michaelbull.logging.InlineLogger +import dev.openrs2.asm.classpath.ClassPath +import dev.openrs2.asm.classpath.Library +import dev.openrs2.asm.transform.Transformer +import org.objectweb.asm.Opcodes +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.MethodInsnNode +import org.objectweb.asm.tree.MethodNode + +class InvokeSpecialTransformer : Transformer() { + private var invokeSpecialsReplaced = 0 + + override fun preTransform(classPath: ClassPath) { + invokeSpecialsReplaced = 0 + } + + override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { + for (insn in method.instructions) { + if (insn !is MethodInsnNode || insn.opcode != Opcodes.INVOKESPECIAL) { + continue + } else if (insn.name == "") { + continue + } else if (insn.owner != clazz.name) { + continue + } + + val owner = classPath.getNode(insn.owner)!! + if ((owner.access and Opcodes.ACC_FINAL) == 0) { + continue + } + + insn.opcode = Opcodes.INVOKEVIRTUAL + invokeSpecialsReplaced++ + } + + return false + } + + override fun postTransform(classPath: ClassPath) { + logger.info { "Replaced $invokeSpecialsReplaced INVOKESPECIALs with INVOKEVIRTUAL" } + } + + companion object { + private val logger = InlineLogger() + } +}