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 <gpe@openrs2.dev>
pull/132/head
Graham 4 years ago
parent f291b121bc
commit 4c6f6b07cf
  1. 13
      deob/src/main/java/dev/openrs2/deob/OriginalPcTable.kt
  2. 47
      deob/src/main/java/dev/openrs2/deob/transform/OriginalPcRestoreTransformer.kt

@ -6,7 +6,10 @@ import org.objectweb.asm.ClassWriter
import org.objectweb.asm.Label import org.objectweb.asm.Label
import org.objectweb.asm.tree.LabelNode import org.objectweb.asm.tree.LabelNode
class OriginalPcTable(private val pcs: Map<LabelNode, Int>) : Attribute("OriginalPcTable") { class OriginalPcTable(
private val pcs: Map<LabelNode, Int>,
private val names: Map<Int, String>
) : Attribute("OriginalPcTable") {
override fun isCodeAttribute(): Boolean { override fun isCodeAttribute(): Boolean {
return true return true
} }
@ -27,11 +30,19 @@ class OriginalPcTable(private val pcs: Map<LabelNode, Int>) : Attribute("Origina
maxLocals: Int maxLocals: Int
): ByteVector { ): ByteVector {
val buf = ByteVector() val buf = ByteVector()
buf.putShort(pcs.size) buf.putShort(pcs.size)
for ((label, pc) in pcs) { for ((label, pc) in pcs) {
buf.putShort(label.label.offset) buf.putShort(label.label.offset)
buf.putShort(pc) buf.putShort(pc)
} }
buf.putShort(names.size)
for ((pc, name) in names) {
buf.putShort(pc)
buf.putShort(classWriter.newUTF8(name))
}
return buf return buf
} }
} }

@ -1,18 +1,23 @@
package dev.openrs2.deob.transform package dev.openrs2.deob.transform
import com.github.michaelbull.logging.InlineLogger import com.github.michaelbull.logging.InlineLogger
import dev.openrs2.asm.MemberRef
import dev.openrs2.asm.classpath.ClassPath import dev.openrs2.asm.classpath.ClassPath
import dev.openrs2.asm.classpath.Library import dev.openrs2.asm.classpath.Library
import dev.openrs2.asm.removeDeadCode import dev.openrs2.asm.removeDeadCode
import dev.openrs2.asm.transform.Transformer import dev.openrs2.asm.transform.Transformer
import dev.openrs2.deob.OriginalPcTable 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.ClassNode
import org.objectweb.asm.tree.LabelNode import org.objectweb.asm.tree.LabelNode
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class OriginalPcRestoreTransformer : Transformer() { class OriginalPcRestoreTransformer @Inject constructor(private val nameMap: NameMap) : Transformer() {
private var originalPcsRestored = 0 private var originalPcsRestored = 0
override fun preTransform(classPath: ClassPath) { override fun preTransform(classPath: ClassPath) {
@ -39,10 +44,17 @@ class OriginalPcRestoreTransformer : Transformer() {
originalPcsRestored++ originalPcsRestored++
} }
val originalMember = method.getOriginalMember()
val names: Map<Int, String> = if (originalMember != null) {
nameMap.methods[originalMember]?.locals ?: emptyMap()
} else {
emptyMap()
}
if (method.attrs == null) { if (method.attrs == null) {
method.attrs = mutableListOf() method.attrs = mutableListOf()
} }
method.attrs.add(OriginalPcTable(pcs)) method.attrs.add(OriginalPcTable(pcs, names))
return false return false
} }
@ -51,6 +63,37 @@ class OriginalPcRestoreTransformer : Transformer() {
logger.info { "Restored $originalPcsRestored original instruction indexes" } 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 companion object {
private val logger = InlineLogger() private val logger = InlineLogger()
} }

Loading…
Cancel
Save