docs: Document important parts of the code

This commit is contained in:
oSumAtrIX 2022-03-31 19:25:46 +02:00
parent 1dd3394ea3
commit 650bf71124
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
5 changed files with 49 additions and 2 deletions

View File

@ -5,17 +5,24 @@ import app.revanced.patcher.patch.Patch
import app.revanced.patcher.resolver.SignatureResolver
import app.revanced.patcher.signature.MethodSignature
import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.DexIO
import lanchon.multidexlib2.MultiDexIO
import org.jf.dexlib2.Opcodes
import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.DexFile
import java.io.File
/**
* ReVanced Patcher.
* @param input The input file (an apk or any other multi dex container).
* @param output The output folder.
* @param signatures An array of method signatures for the patches
*
*/
class Patcher(
input: File,
private val output: File,
signatures: Array<MethodSignature>,
) {
private val cache: Cache
private val patches = mutableSetOf<Patch>()
@ -25,6 +32,9 @@ class Patcher(
cache = Cache(dexFile.classes, SignatureResolver(dexFile.classes, signatures).resolve())
}
/**
* Save the patched dex file.
*/
fun save() {
val newDexFile = object : DexFile {
override fun getClasses(): Set<ClassDef> {
@ -45,13 +55,21 @@ class Patcher(
}
// TODO: we should use the multithreading capable overload for writeDexFile
MultiDexIO.writeDexFile(true, output, BasicDexFileNamer(), newDexFile, 50000, null)
MultiDexIO.writeDexFile(true, output, BasicDexFileNamer(), newDexFile, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null)
}
/**
* Add a patch to the patcher.
* @param patches The patches to add.
*/
fun addPatches(vararg patches: Patch) {
this.patches.addAll(patches)
}
/**
* Apply patches loaded into the patcher.
* @param stopOnError If true, the patches will stop on the first error.
*/
fun applyPatches(stopOnError: Boolean = false): Map<String, Result<Nothing?>> {
return buildMap {
// TODO: after each patch execution we could clear left overs like proxied classes to safe memory

View File

@ -13,6 +13,10 @@ class Cache(
// if the class proxy already exists in the cached proxy list below
internal val classProxy = mutableSetOf<ClassProxy>()
/**
* Find a class by a given predicate
* @return A proxy for the first class that matches the predicate
*/
fun findClass(predicate: (ClassDef) -> Boolean): ClassProxy? {
// if we already proxied the class matching the predicate,
val proxiedClass = classProxy.singleOrNull { classProxy -> predicate(classProxy.immutableClass) }

View File

@ -3,6 +3,13 @@ package app.revanced.patcher.proxy
import app.revanced.patcher.proxy.mutableTypes.MutableClass
import org.jf.dexlib2.iface.ClassDef
/**
* A proxy class for a [ClassDef]
* A class proxy simply holds a reference to the original class
* and creates a mutable clone for the original class if needed.
* @param immutableClass The class to proxy
* @param originalIndex The original index of the class in the list of classes
*/
class ClassProxy(
val immutableClass: ClassDef,
val originalIndex: Int,
@ -10,6 +17,10 @@ class ClassProxy(
internal var proxyUsed = false
internal lateinit var mutatedClass: MutableClass
/**
* Creates and returns a mutable clone of the original class
* A patch should always use the original immutable class reference to avoid unnucessary allocations for the mutable class
*/
fun resolve(): MutableClass {
if (!proxyUsed) {
proxyUsed = true

View File

@ -2,6 +2,14 @@ package app.revanced.patcher.signature
import org.jf.dexlib2.Opcode
/**
* Represents a method signature.
* @param name A suggestive name for the method which the signature was created for.
* @param returnType The return type of the method.
* @param methodParameters The parameters of the method.
* @param opcodes A list of opcodes of the method.
* @param accessFlags The access flags of the method.
*/
@Suppress("ArrayInDataClass")
data class MethodSignature(
val name: String,

View File

@ -3,6 +3,12 @@ package app.revanced.patcher.signature
import app.revanced.patcher.proxy.ClassProxy
import app.revanced.patcher.resolver.SignatureResolver
/**
* Represents the result of a [SignatureResolver].
* @param definingClassProxy The [ClassProxy] that the matching method was found in.
* @param resolvedMethodName The name of the actual matching method.
* @param scanData OpCodes pattern scan result.
*/
data class SignatureResolverResult(
val definingClassProxy: ClassProxy,
val resolvedMethodName: String,