package org.openrs2.deob.bytecode import com.github.michaelbull.logging.InlineLogger import org.objectweb.asm.Type import org.objectweb.asm.tree.LdcInsnNode import org.objectweb.asm.tree.MethodNode import org.openrs2.asm.InsnMatcher import org.openrs2.asm.classpath.Library public object SignedClassUtils { private val logger = InlineLogger() private val LOAD_SIGNED_CLASS_MATCHER = InsnMatcher.compile("LDC INVOKESTATIC ASTORE ALOAD GETFIELD ALOAD INVOKEVIRTUAL ALOAD INVOKEVIRTUAL POP") public fun move(loader: Library, client: Library, signLink: Library) { // find signed classes val signedClasses = findSignedClasses(loader) logger.info { "Identified signed classes $signedClasses" } val dependencies = findDependencies(loader, signedClasses) logger.info { "Identified signed class dependencies $dependencies" } // delete original signed classes (these have no dependencies) for (name in signedClasses) { client.remove(name) } // move loader signed classes to signlink for (name in signedClasses union dependencies) { signLink.add(loader.remove(name)!!) } } private fun findSignedClasses(loader: Library): Set { val clazz = loader["loader"] ?: throw IllegalArgumentException("Failed to find loader class") val method = clazz.methods.find { it.name == "run" && it.desc == "()V" } ?: throw IllegalArgumentException("Failed to find loader.run() method") return findSignedClasses(method) } private fun findSignedClasses(method: MethodNode): Set { val classes = mutableSetOf() for (match in LOAD_SIGNED_CLASS_MATCHER.match(method)) { val ldc = match[0] as LdcInsnNode val cst = ldc.cst if (cst is String && cst != "unpack") { classes.add(cst) } } return classes } private fun findDependencies(loader: Library, signedClasses: Set): Set { val dependencies = mutableSetOf() for (signedClass in signedClasses) { val clazz = loader[signedClass]!! for (field in clazz.fields) { val type = Type.getType(field.desc) if (type.sort != Type.OBJECT) { continue } val name = type.className if (name in loader && name !in signedClasses) { dependencies.add(name) } } } return dependencies } }