forked from openrs2/openrs2
This improves deobfuscation of a static field initializer in the 667 client that looks like: a = b = new X() This transformer translates it to two separate expressions: b = new X(); a = b This allows the StaticFieldUnscrambler to move both fields independently, rather than them both being forced to remain in their scrambled class. Signed-off-by: Graham <gpe@openrs2.org>
parent
6a7a29c85c
commit
223c451f2d
@ -0,0 +1,57 @@ |
|||||||
|
package org.openrs2.deob.bytecode.transform |
||||||
|
|
||||||
|
import com.github.michaelbull.logging.InlineLogger |
||||||
|
import jakarta.inject.Singleton |
||||||
|
import org.objectweb.asm.Opcodes |
||||||
|
import org.objectweb.asm.tree.ClassNode |
||||||
|
import org.objectweb.asm.tree.FieldInsnNode |
||||||
|
import org.objectweb.asm.tree.MethodNode |
||||||
|
import org.openrs2.asm.InsnMatcher |
||||||
|
import org.openrs2.asm.classpath.ClassPath |
||||||
|
import org.openrs2.asm.classpath.Library |
||||||
|
import org.openrs2.asm.transform.Transformer |
||||||
|
import org.openrs2.deob.bytecode.remap.StaticFieldUnscrambler |
||||||
|
|
||||||
|
/** |
||||||
|
* A [Transformer] that splits multiple assignments to static fields in a |
||||||
|
* single expression in `<clinit>` methods. For example, `a = b = new X()` is |
||||||
|
* translated to `b = new X(); a = b`. This allows [StaticFieldUnscrambler] to |
||||||
|
* move the fields independently. |
||||||
|
*/ |
||||||
|
@Singleton |
||||||
|
public class MultipleAssignmentTransformer : Transformer() { |
||||||
|
private var assignments = 0 |
||||||
|
|
||||||
|
override fun preTransform(classPath: ClassPath) { |
||||||
|
assignments = 0 |
||||||
|
} |
||||||
|
|
||||||
|
override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { |
||||||
|
if (method.name != "<clinit>") { |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
for (match in MATCHER.match(method)) { |
||||||
|
for (i in 0 until match.size - 1 step 2) { |
||||||
|
val dup = match[i] |
||||||
|
val putstatic = match[i + 1] as FieldInsnNode |
||||||
|
|
||||||
|
method.instructions.remove(dup) |
||||||
|
method.instructions.insert(putstatic, FieldInsnNode(Opcodes.GETSTATIC, putstatic.owner, putstatic.name, putstatic.desc)) |
||||||
|
|
||||||
|
assignments++ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
override fun postTransform(classPath: ClassPath) { |
||||||
|
logger.info { "Split $assignments multiple assignment expressions into separate expressions" } |
||||||
|
} |
||||||
|
|
||||||
|
private companion object { |
||||||
|
private val logger = InlineLogger() |
||||||
|
private val MATCHER = InsnMatcher.compile("(DUP PUTSTATIC)+ PUTSTATIC") |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue