mirror of
https://github.com/ReVanced/revanced-patcher.git
synced 2026-01-21 10:13:57 +00:00
feat: add MethodWalker
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
package app.revanced.patcher
|
package app.revanced.patcher
|
||||||
|
|
||||||
|
import app.revanced.patcher.methodWalker.MethodWalker
|
||||||
import app.revanced.patcher.patch.Patch
|
import app.revanced.patcher.patch.Patch
|
||||||
import app.revanced.patcher.proxy.ClassProxy
|
import app.revanced.patcher.proxy.ClassProxy
|
||||||
import app.revanced.patcher.signature.SignatureResolverResult
|
import app.revanced.patcher.signature.SignatureResolverResult
|
||||||
import org.jf.dexlib2.iface.ClassDef
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
|
import org.jf.dexlib2.iface.Method
|
||||||
|
|
||||||
class PatcherData(
|
class PatcherData(
|
||||||
internal val classes: MutableList<ClassDef>,
|
internal val classes: MutableList<ClassDef>,
|
||||||
@@ -61,6 +63,10 @@ internal inline fun <reified T> Iterable<T>.find(predicate: (T) -> Boolean): T?
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PatcherData.toMethodWalker(startMethod: Method): MethodWalker {
|
||||||
|
return MethodWalker(this, startMethod)
|
||||||
|
}
|
||||||
|
|
||||||
internal inline fun <T> Iterable<T>.findIndexed(predicate: (T) -> Boolean): Pair<T, Int>? {
|
internal inline fun <T> Iterable<T>.findIndexed(predicate: (T) -> Boolean): Pair<T, Int>? {
|
||||||
for ((index, element) in this.withIndex()) {
|
for ((index, element) in this.withIndex()) {
|
||||||
if (predicate(element)) {
|
if (predicate(element)) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package app.revanced.patcher.methodWalker
|
||||||
|
|
||||||
|
import app.revanced.patcher.MethodNotFoundException
|
||||||
|
import app.revanced.patcher.PatcherData
|
||||||
|
import app.revanced.patcher.proxy.mutableTypes.MutableMethod
|
||||||
|
import org.jf.dexlib2.Format
|
||||||
|
import org.jf.dexlib2.iface.Method
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodReference
|
||||||
|
import org.jf.dexlib2.util.Preconditions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a method from another method via instruction offsets.
|
||||||
|
* @param patcherData The patcherData to use when resolving the next method reference.
|
||||||
|
* @param currentMethod The method to start from.
|
||||||
|
*/
|
||||||
|
class MethodWalker internal constructor(
|
||||||
|
private val patcherData: PatcherData,
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
fun getMethod(): Method {
|
||||||
|
return currentMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walk to a method defined at the offset in the instruction list of the current method.
|
||||||
|
* @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.
|
||||||
|
* The current method will be mutable.
|
||||||
|
*/
|
||||||
|
fun walk(offset: Int, walkMutable: Boolean = false): MethodWalker {
|
||||||
|
currentMethod.implementation?.instructions?.let { instructions ->
|
||||||
|
val instruction = instructions.elementAt(offset)
|
||||||
|
|
||||||
|
Preconditions.checkFormat(instruction.opcode, Format.Format35c)
|
||||||
|
|
||||||
|
val newMethodRef = (instruction as Instruction35c).reference as MethodReference
|
||||||
|
val proxy = patcherData.findClass(newMethodRef.definingClass)!!
|
||||||
|
|
||||||
|
val methods = if (walkMutable) proxy.resolve().methods else proxy.immutableClass.methods
|
||||||
|
currentMethod = methods.first { it.name == newMethodRef.name }
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
throw MethodNotFoundException("This method can not be walked at offset $offset inside the method ${currentMethod.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user