refactor: Improve SignatureResolver

This commit is contained in:
oSumAtrIX 2022-04-06 01:25:45 +02:00
parent 2777117da2
commit a16c8cabf2
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
2 changed files with 26 additions and 65 deletions

View File

@ -1,7 +0,0 @@
package app.revanced.patcher.resolver
internal data class PatternScanData(
val found: Boolean,
val startIndex: Int? = 0,
val endIndex: Int? = 0
)

View File

@ -8,6 +8,7 @@ import app.revanced.patcher.signature.SignatureResolverResult
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.ClassDef import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.Instruction
// TODO: add logger back // TODO: add logger back
internal class SignatureResolver( internal class SignatureResolver(
@ -24,21 +25,14 @@ internal class SignatureResolver(
} }
for (method in classDef.methods) { for (method in classDef.methods) {
val (isMatch, patternScanData) = compareSignatureToMethod(signature, method) val patternScanData = compareSignatureToMethod(signature, method) ?: continue
if (!isMatch || patternScanData == null) {
continue
}
// create class proxy, in case a patch needs mutability // create class proxy, in case a patch needs mutability
val classProxy = ClassProxy(classDef, index) val classProxy = ClassProxy(classDef, index)
methodMap[signature.name] = SignatureResolverResult( methodMap[signature.name] = SignatureResolverResult(
classProxy, classProxy,
method.name, method.name,
PatternScanResult( patternScanData
patternScanData.startIndex!!,
patternScanData.endIndex!!
)
) )
} }
} }
@ -56,12 +50,11 @@ internal class SignatureResolver(
companion object { companion object {
fun resolveFromProxy(classProxy: ClassProxy, signature: MethodSignature): SignatureResolverResult? { fun resolveFromProxy(classProxy: ClassProxy, signature: MethodSignature): SignatureResolverResult? {
for (method in classProxy.immutableClass.methods) { for (method in classProxy.immutableClass.methods) {
val (r, sr) = compareSignatureToMethod(signature, method) val result = compareSignatureToMethod(signature, method) ?: continue
if (!r || sr == null) continue
return SignatureResolverResult( return SignatureResolverResult(
classProxy, classProxy,
method.name, method.name,
null result
) )
} }
return null return null
@ -70,33 +63,29 @@ internal class SignatureResolver(
private fun compareSignatureToMethod( private fun compareSignatureToMethod(
signature: MethodSignature, signature: MethodSignature,
method: Method method: Method
): Pair<Boolean, PatternScanData?> { ): PatternScanResult? {
// TODO: compare as generic object if not primitive
signature.returnType?.let { _ -> signature.returnType?.let { _ ->
if (signature.returnType != method.returnType) { if (!method.returnType.startsWith(signature.returnType)) return@compareSignatureToMethod null
return@compareSignatureToMethod false to null
}
} }
signature.accessFlags?.let { _ -> signature.accessFlags?.let { _ ->
if (signature.accessFlags != method.accessFlags) { if (signature.accessFlags != method.accessFlags) {
return@compareSignatureToMethod false to null return@compareSignatureToMethod null
} }
} }
// TODO: compare as generic object if the parameter is not primitive
signature.methodParameters?.let { _ -> signature.methodParameters?.let { _ ->
if (signature.methodParameters != method.parameters) { if (signature.methodParameters.all { signatureMethodParameter ->
return@compareSignatureToMethod false to null method.parameterTypes.any { methodParameter ->
methodParameter.startsWith(signatureMethodParameter)
}
}) {
return@compareSignatureToMethod null
} }
} }
signature.opcodes?.let { _ -> return if (signature.opcodes == null) null
val result = method.implementation?.instructions?.scanFor(signature.opcodes) else method.implementation?.instructions?.scanFor(signature.opcodes)!!
return@compareSignatureToMethod if (result != null && result.found) true to result else false to null
}
return true to PatternScanData(true)
} }
} }
} }
@ -104,38 +93,17 @@ internal class SignatureResolver(
private operator fun ClassDef.component1() = this private operator fun ClassDef.component1() = this
private operator fun ClassDef.component2() = this.methods private operator fun ClassDef.component2() = this.methods
private fun <T> MutableIterable<T>.scanFor(pattern: Array<Opcode>): PatternScanData { private fun MutableIterable<Instruction>.scanFor(pattern: Array<Opcode>): PatternScanResult? {
// TODO: create var for count? // TODO: create var for count?
for (i in 0 until this.count()) { for (instructionIndex in 0 until this.count()) {
var occurrence = 0 var patternIndex = 0
while (i + occurrence < this.count()) { while (instructionIndex + patternIndex < this.count()) {
val n = this.elementAt(i + occurrence) if (this.elementAt(instructionIndex + patternIndex).opcode != pattern[patternIndex]) break
if (!n.shouldSkip() && n != pattern[occurrence]) break if (++patternIndex < pattern.size) continue
if (++occurrence >= pattern.size) {
val current = i + occurrence return PatternScanResult(instructionIndex, instructionIndex + patternIndex)
return PatternScanData(true, current - pattern.size, current)
}
} }
} }
return PatternScanData(false) return null
} }
// TODO: extend Opcode type, not T (requires a cast to Opcode)
private fun <T> T.shouldSkip(): Boolean {
return this == Opcode.GOTO // TODO: and: this == AbstractInsnNode.LINE
}
// TODO: use this somehow to compare types as generic objects if not primitive
// private fun Type.convertObject(): Type {
// return when (this.sort) {
// Type.OBJECT -> ExtraTypes.Any
// Type.ARRAY -> ExtraTypes.ArrayAny
// else -> this
// }
// }
//
// private fun Array<Type>.convertObjects(): Array<Type> {
// return this.map { it.convertObject() }.toTypedArray()
// }