From 78db7d31790078fe0ccbc05b7ea4e55417d1189a Mon Sep 17 00:00:00 2001 From: Graham Date: Sat, 7 Mar 2020 13:47:39 +0000 Subject: [PATCH] Account for inheritance in StaticScramblingTransformer GETSTATIC, PUTSTATIC and INVOKESTATIC (strangely) use the same field and method resolution algorithms as their non-static equivalents. While this doesn't cause problems for 550, as the *STATIC instructions seem to always refer to the class containing the static definition, Major reports that OSRS clients sometimes change the owner to a subclass. This broke the old transformer. This commit fixes it by applying the old to new owner mapping to an entire disjoint set at a time. Signed-off-by: Graham --- .../transform/StaticScramblingTransformer.kt | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/deob/src/main/java/dev/openrs2/deob/transform/StaticScramblingTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/StaticScramblingTransformer.kt index ebf4b774..1a440cc3 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/StaticScramblingTransformer.kt +++ b/deob/src/main/java/dev/openrs2/deob/transform/StaticScramblingTransformer.kt @@ -6,6 +6,7 @@ import dev.openrs2.asm.MemberRef import dev.openrs2.asm.classpath.ClassPath import dev.openrs2.asm.classpath.Library import dev.openrs2.asm.transform.Transformer +import dev.openrs2.common.collect.DisjointSet import dev.openrs2.deob.remap.TypedRemapper import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.ClassNode @@ -27,9 +28,11 @@ class StaticScramblingTransformer : Transformer() { ?.mapTo(mutableSetOf(), ::MemberRef) ?: emptySet() } + private lateinit var inheritedFieldSets: DisjointSet + private lateinit var inheritedMethodSets: DisjointSet private val fieldSets = mutableMapOf() - private val fieldClasses = mutableMapOf() - private val methodClasses = mutableMapOf() + private val fieldClasses = mutableMapOf, String>() + private val methodClasses = mutableMapOf, String>() private var nextStaticClass: ClassNode? = null private var nextClinit: MethodNode? = null private val staticClasses = mutableListOf() @@ -115,12 +118,14 @@ class StaticScramblingTransformer : Transformer() { } for (field in fieldSet.fields) { - val ref = MemberRef(fieldSet.owner, field) - fieldClasses[ref] = staticClass.name + val partition = inheritedFieldSets[MemberRef(fieldSet.owner, field)]!! + fieldClasses[partition] = staticClass.name } } override fun preTransform(classPath: ClassPath) { + inheritedFieldSets = classPath.createInheritedFieldSets() + inheritedMethodSets = classPath.createInheritedMethodSets() fieldSets.clear() fieldClasses.clear() methodClasses.clear() @@ -166,7 +171,8 @@ class StaticScramblingTransformer : Transformer() { staticClass.methods.add(method) staticClass.version = ClassVersionUtils.maxVersion(staticClass.version, clazz.version) - methodClasses[MemberRef(clazz, method)] = staticClass.name + val partition = inheritedMethodSets[MemberRef(clazz, method)]!! + methodClasses[partition] = staticClass.name return@removeIf true } } @@ -182,8 +188,18 @@ class StaticScramblingTransformer : Transformer() { override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { for (insn in method.instructions) { when (insn) { - is FieldInsnNode -> insn.owner = fieldClasses.getOrDefault(MemberRef(insn), insn.owner) - is MethodInsnNode -> insn.owner = methodClasses.getOrDefault(MemberRef(insn), insn.owner) + is FieldInsnNode -> { + val partition = inheritedFieldSets[MemberRef(insn)] + if (partition != null) { + insn.owner = fieldClasses.getOrDefault(partition, insn.owner) + } + } + is MethodInsnNode -> { + val partition = inheritedMethodSets[MemberRef(insn)] + if (partition != null) { + insn.owner = methodClasses.getOrDefault(partition, insn.owner) + } + } } }