mirror of
https://github.com/revanced/revanced-patcher.git
synced 2025-05-03 14:14:26 +02:00
56 lines
2.2 KiB
Kotlin
56 lines
2.2 KiB
Kotlin
package app.revanced.patcher.util.method
|
|
|
|
import app.revanced.patcher.data.BytecodeContext
|
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|
import org.jf.dexlib2.iface.Method
|
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
|
import org.jf.dexlib2.iface.reference.MethodReference
|
|
import org.jf.dexlib2.util.MethodUtil
|
|
|
|
/**
|
|
* Find a method from another method via instruction offsets.
|
|
* @param bytecodeContext The context to use when resolving the next method reference.
|
|
* @param currentMethod The method to start from.
|
|
*/
|
|
class MethodWalker internal constructor(
|
|
private val bytecodeContext: BytecodeContext,
|
|
private var currentMethod: Method
|
|
) {
|
|
/**
|
|
* Get the method which was walked last.
|
|
*
|
|
* It is possible to cast this method to a [MutableMethod], if the method has been walked mutably.
|
|
*
|
|
* @return The method which was walked last.
|
|
*/
|
|
fun getMethod(): Method {
|
|
return currentMethod
|
|
}
|
|
|
|
/**
|
|
* Walk to a method defined at the offset in the instruction list of the current method.
|
|
*
|
|
* The current method will be mutable.
|
|
*
|
|
* @param offset The offset of the instruction. This instruction must be of format 35c.
|
|
* @param walkMutable If this is true, the class of the method will be resolved mutably.
|
|
* @return The same [MethodWalker] instance with the method at [offset].
|
|
*/
|
|
fun nextMethod(offset: Int, walkMutable: Boolean = false): MethodWalker {
|
|
currentMethod.implementation?.instructions?.let { instructions ->
|
|
val instruction = instructions.elementAt(offset)
|
|
|
|
val newMethod = (instruction as ReferenceInstruction).reference as MethodReference
|
|
val proxy = bytecodeContext.findClass(newMethod.definingClass)!!
|
|
|
|
val methods = if (walkMutable) proxy.mutableClass.methods else proxy.immutableClass.methods
|
|
currentMethod = methods.first {
|
|
return@first MethodUtil.methodSignaturesMatch(it, newMethod)
|
|
}
|
|
return this
|
|
}
|
|
throw MethodNotFoundException("This method can not be walked at offset $offset inside the method ${currentMethod.name}")
|
|
}
|
|
|
|
internal class MethodNotFoundException(exception: String) : Exception(exception)
|
|
} |