From 4c6f6b07cf3d94f7369c182bcd084c7dcd3aaf4d Mon Sep 17 00:00:00 2001 From: Graham Date: Fri, 3 Jul 2020 20:16:37 +0100 Subject: [PATCH] Store mapped local variable names in the OriginalPcTable We could use LocalVariableTable in theory, but it's more complicated as we'd need to do live variable analysis and type inference. It's much easier to leave that for the decompiler. Signed-off-by: Graham --- .../java/dev/openrs2/deob/OriginalPcTable.kt | 13 ++++- .../transform/OriginalPcRestoreTransformer.kt | 47 ++++++++++++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/deob/src/main/java/dev/openrs2/deob/OriginalPcTable.kt b/deob/src/main/java/dev/openrs2/deob/OriginalPcTable.kt index 91c094d9..fe8abfed 100644 --- a/deob/src/main/java/dev/openrs2/deob/OriginalPcTable.kt +++ b/deob/src/main/java/dev/openrs2/deob/OriginalPcTable.kt @@ -6,7 +6,10 @@ import org.objectweb.asm.ClassWriter import org.objectweb.asm.Label import org.objectweb.asm.tree.LabelNode -class OriginalPcTable(private val pcs: Map) : Attribute("OriginalPcTable") { +class OriginalPcTable( + private val pcs: Map, + private val names: Map +) : Attribute("OriginalPcTable") { override fun isCodeAttribute(): Boolean { return true } @@ -27,11 +30,19 @@ class OriginalPcTable(private val pcs: Map) : Attribute("Origina maxLocals: Int ): ByteVector { val buf = ByteVector() + buf.putShort(pcs.size) for ((label, pc) in pcs) { buf.putShort(label.label.offset) buf.putShort(pc) } + + buf.putShort(names.size) + for ((pc, name) in names) { + buf.putShort(pc) + buf.putShort(classWriter.newUTF8(name)) + } + return buf } } diff --git a/deob/src/main/java/dev/openrs2/deob/transform/OriginalPcRestoreTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/OriginalPcRestoreTransformer.kt index 5984566a..aee51515 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/OriginalPcRestoreTransformer.kt +++ b/deob/src/main/java/dev/openrs2/deob/transform/OriginalPcRestoreTransformer.kt @@ -1,18 +1,23 @@ package dev.openrs2.deob.transform import com.github.michaelbull.logging.InlineLogger +import dev.openrs2.asm.MemberRef import dev.openrs2.asm.classpath.ClassPath import dev.openrs2.asm.classpath.Library import dev.openrs2.asm.removeDeadCode import dev.openrs2.asm.transform.Transformer import dev.openrs2.deob.OriginalPcTable +import dev.openrs2.deob.annotation.OriginalMember +import dev.openrs2.deob.util.map.NameMap +import org.objectweb.asm.Type import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.LabelNode import org.objectweb.asm.tree.MethodNode +import javax.inject.Inject import javax.inject.Singleton @Singleton -class OriginalPcRestoreTransformer : Transformer() { +class OriginalPcRestoreTransformer @Inject constructor(private val nameMap: NameMap) : Transformer() { private var originalPcsRestored = 0 override fun preTransform(classPath: ClassPath) { @@ -39,10 +44,17 @@ class OriginalPcRestoreTransformer : Transformer() { originalPcsRestored++ } + val originalMember = method.getOriginalMember() + val names: Map = if (originalMember != null) { + nameMap.methods[originalMember]?.locals ?: emptyMap() + } else { + emptyMap() + } + if (method.attrs == null) { method.attrs = mutableListOf() } - method.attrs.add(OriginalPcTable(pcs)) + method.attrs.add(OriginalPcTable(pcs, names)) return false } @@ -51,6 +63,37 @@ class OriginalPcRestoreTransformer : Transformer() { logger.info { "Restored $originalPcsRestored original instruction indexes" } } + private fun MethodNode.getOriginalMember(): MemberRef? { + if (invisibleAnnotations == null) { + return null + } + + for (annotation in invisibleAnnotations) { + if (annotation.desc != Type.getDescriptor(OriginalMember::class.java)) { + continue + } + + var owner: String? = null + var name: String? = null + var desc: String? = null + for ((key, value) in annotation.values.windowed(2, 2)) { + when (key) { + "owner" -> owner = value as String + "name" -> name = value as String + "descriptor" -> desc = value as String + } + } + + check(owner != null) { "Failed to extract owner from OriginalMember" } + check(name != null) { "Failed to extract name from OriginalMember" } + check(desc != null) { "Failed to extract descriptor from OriginalMember" } + + return MemberRef(owner, name, desc) + } + + return null + } + private companion object { private val logger = InlineLogger() }