mirror of
https://github.com/ReVanced/revanced-patcher.git
synced 2026-01-24 19:51:03 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6dcd88495 | ||
|
|
a925650044 | ||
|
|
77bbf6be1f | ||
|
|
bd053b7e99 | ||
|
|
fd742eba63 | ||
|
|
ba9d998681 |
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,3 +1,24 @@
|
|||||||
|
# [6.2.0](https://github.com/revanced/revanced-patcher/compare/v6.1.1...v6.2.0) (2022-12-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* merge classes on addition ([#127](https://github.com/revanced/revanced-patcher/issues/127)) ([a925650](https://github.com/revanced/revanced-patcher/commit/a9256500440f9b4117f1b8813ba0097dafee4ebb))
|
||||||
|
|
||||||
|
## [6.1.1](https://github.com/revanced/revanced-patcher/compare/v6.1.0...v6.1.1) (2022-11-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use `MethodUtil.methodSignaturesMatch` instead of `Method.softCompareTo` ([bd053b7](https://github.com/revanced/revanced-patcher/commit/bd053b7e9974c0282d56e6762459db7070452e4a))
|
||||||
|
|
||||||
|
# [6.1.0](https://github.com/revanced/revanced-patcher/compare/v6.0.2...v6.1.0) (2022-11-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* apply changes from ReVanced Patcher ([ba9d998](https://github.com/revanced/revanced-patcher/commit/ba9d99868103406fe36b9aa0cfaa0ed5023edfab))
|
||||||
|
|
||||||
## [6.0.2](https://github.com/revanced/revanced-patcher/compare/v6.0.1...v6.0.2) (2022-11-18)
|
## [6.0.2](https://github.com/revanced/revanced-patcher/compare/v6.0.1...v6.0.2) (2022-11-18)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 6.0.2
|
version = 6.2.0
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ package app.revanced.patcher
|
|||||||
import app.revanced.patcher.data.Context
|
import app.revanced.patcher.data.Context
|
||||||
import app.revanced.patcher.data.findIndexed
|
import app.revanced.patcher.data.findIndexed
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.dependencies
|
import app.revanced.patcher.extensions.PatchExtensions.dependencies
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.deprecated
|
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||||
import app.revanced.patcher.extensions.nullOutputStream
|
import app.revanced.patcher.extensions.nullOutputStream
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
import app.revanced.patcher.patch.*
|
import app.revanced.patcher.patch.*
|
||||||
import app.revanced.patcher.util.VersionReader
|
import app.revanced.patcher.util.VersionReader
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass.Companion.toMutable
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import brut.androlib.Androlib
|
import brut.androlib.Androlib
|
||||||
import brut.androlib.meta.UsesFramework
|
import brut.androlib.meta.UsesFramework
|
||||||
import brut.androlib.options.BuildOptions
|
import brut.androlib.options.BuildOptions
|
||||||
@@ -23,7 +26,9 @@ import lanchon.multidexlib2.BasicDexFileNamer
|
|||||||
import lanchon.multidexlib2.DexIO
|
import lanchon.multidexlib2.DexIO
|
||||||
import lanchon.multidexlib2.MultiDexIO
|
import lanchon.multidexlib2.MultiDexIO
|
||||||
import org.jf.dexlib2.Opcodes
|
import org.jf.dexlib2.Opcodes
|
||||||
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
import org.jf.dexlib2.iface.DexFile
|
import org.jf.dexlib2.iface.DexFile
|
||||||
|
import org.jf.dexlib2.util.MethodUtil
|
||||||
import org.jf.dexlib2.writer.io.MemoryDataStore
|
import org.jf.dexlib2.writer.io.MemoryDataStore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
@@ -66,40 +71,85 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
/**
|
/**
|
||||||
* Add additional dex file container to the patcher.
|
* Add additional dex file container to the patcher.
|
||||||
* @param files The dex file containers to add to the patcher.
|
* @param files The dex file containers to add to the patcher.
|
||||||
* @param allowedOverwrites A list of class types that are allowed to be overwritten.
|
* @param process The callback for [files] which are being added.
|
||||||
* @param throwOnDuplicates If this is set to true, the patcher will throw an exception if a duplicate class has been found.
|
|
||||||
*/
|
*/
|
||||||
fun addFiles(
|
fun addFiles(
|
||||||
files: List<File>,
|
files: List<File>,
|
||||||
allowedOverwrites: Iterable<String> = emptyList(),
|
process: (File) -> Unit
|
||||||
throwOnDuplicates: Boolean = false,
|
|
||||||
callback: (File) -> Unit
|
|
||||||
) {
|
) {
|
||||||
for (file in files) {
|
with(context.bytecodeContext.classes) {
|
||||||
var modified = false
|
for (file in files) {
|
||||||
for (classDef in MultiDexIO.readDexFile(true, file, NAMER, null, null).classes) {
|
process(file)
|
||||||
val type = classDef.type
|
for (classDef in MultiDexIO.readDexFile(true, file, NAMER, null, null).classes) {
|
||||||
|
val type = classDef.type
|
||||||
|
|
||||||
val existingClass = context.bytecodeContext.classes.classes.findIndexed { it.type == type }
|
val result = classes.findIndexed { it.type == type }
|
||||||
if (existingClass == null) {
|
if (result == null) {
|
||||||
if (throwOnDuplicates) throw Exception("Class $type has already been added to the patcher")
|
logger.trace("Merging type $type")
|
||||||
|
classes.add(classDef)
|
||||||
|
} else {
|
||||||
|
val (existingClass, existingClassIndex) = result
|
||||||
|
|
||||||
logger.trace("Merging $type")
|
logger.trace("Type $type exists. Adding missing methods and fields.")
|
||||||
context.bytecodeContext.classes.classes.add(classDef)
|
|
||||||
modified = true
|
|
||||||
|
|
||||||
continue
|
/**
|
||||||
|
* Add missing fields and methods from [from].
|
||||||
|
*
|
||||||
|
* @param from The class to add methods and fields from.
|
||||||
|
*/
|
||||||
|
fun ClassDef.addMissingFrom(from: ClassDef) {
|
||||||
|
var changed = false
|
||||||
|
fun <T> ClassDef.transformClass(transform: (MutableClass) -> T): T {
|
||||||
|
fun toMutableClass() =
|
||||||
|
if (this@transformClass is MutableClass) this else this.toMutable()
|
||||||
|
return transform(toMutableClass())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ClassDef.addMissingMethods(): ClassDef {
|
||||||
|
fun getMissingMethods() = from.methods.filterNot {
|
||||||
|
this@addMissingMethods.methods.any { original ->
|
||||||
|
MethodUtil.methodSignaturesMatch(original, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getMissingMethods()
|
||||||
|
.apply {
|
||||||
|
if (isEmpty()) return@addMissingMethods this@addMissingMethods else changed =
|
||||||
|
true
|
||||||
|
}
|
||||||
|
.map { it.toMutable() }
|
||||||
|
.let { missingMethods ->
|
||||||
|
this@addMissingMethods.transformClass { classDef ->
|
||||||
|
classDef.apply { methods.addAll(missingMethods) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ClassDef.addMissingFields(): ClassDef {
|
||||||
|
fun getMissingFields() = from.fields.filterNot {
|
||||||
|
this@addMissingFields.fields.any { original -> original.name == it.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
return getMissingFields()
|
||||||
|
.apply {
|
||||||
|
if (isEmpty()) return@addMissingFields this@addMissingFields else changed = true
|
||||||
|
}
|
||||||
|
.map { it.toMutable() }
|
||||||
|
.let { missingFields ->
|
||||||
|
this@addMissingFields.transformClass { classDef ->
|
||||||
|
classDef.apply { fields.addAll(missingFields) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classes[existingClassIndex] = addMissingMethods().addMissingFields()
|
||||||
|
.apply { if (!changed) return }
|
||||||
|
}
|
||||||
|
|
||||||
|
existingClass.addMissingFrom(classDef)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allowedOverwrites.contains(type)) continue
|
|
||||||
|
|
||||||
logger.trace("Overwriting $type")
|
|
||||||
|
|
||||||
val index = existingClass.second
|
|
||||||
context.bytecodeContext.classes.classes[index] = classDef
|
|
||||||
modified = true
|
|
||||||
}
|
}
|
||||||
if (modified) callback(file)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +205,7 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
cacheDirectory.close()
|
cacheDirectory.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> logger.info("Not compiling resources because resource patching is not required")
|
else -> logger.info("Not compiling resources because resource patching is not required")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,6 +292,7 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceDecodingMode.MANIFEST_ONLY -> {
|
ResourceDecodingMode.MANIFEST_ONLY -> {
|
||||||
logger.info("Decoding AndroidManifest.xml only, because resources are not needed")
|
logger.info("Decoding AndroidManifest.xml only, because resources are not needed")
|
||||||
|
|
||||||
@@ -316,11 +368,6 @@ class Patcher(private val options: PatcherOptions) {
|
|||||||
return PatchResultError("'$patchName' depends on '${dependency.patchName}' but the following error was raised: $errorMessage")
|
return PatchResultError("'$patchName' depends on '${dependency.patchName}' but the following error was raised: $errorMessage")
|
||||||
}
|
}
|
||||||
|
|
||||||
patchClass.deprecated?.let { (reason, replacement) ->
|
|
||||||
logger.warn("'$patchName' is deprecated, reason: $reason")
|
|
||||||
if (replacement != null) logger.warn("Use '${replacement.java.patchName}' instead")
|
|
||||||
}
|
|
||||||
|
|
||||||
val isResourcePatch = ResourcePatch::class.java.isAssignableFrom(patchClass)
|
val isResourcePatch = ResourcePatch::class.java.isAssignableFrom(patchClass)
|
||||||
val patchInstance = patchClass.getDeclaredConstructor().newInstance()
|
val patchInstance = patchClass.getDeclaredConstructor().newInstance()
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package app.revanced.patcher.annotation
|
package app.revanced.patcher.annotation
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.patch.Patch
|
import app.revanced.patcher.patch.Patch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to constrain a [Patch] or [MethodFingerprint] to compatible packages.
|
* Annotation to constrain a [Patch] to compatible packages.
|
||||||
* @param compatiblePackages A list of packages a [Patch] or [MethodFingerprint] is compatible with.
|
* @param compatiblePackages A list of packages a [Patch] is compatible with.
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@@ -17,7 +16,7 @@ annotation class Compatibility(
|
|||||||
/**
|
/**
|
||||||
* Annotation to represent packages a patch can be compatible with.
|
* Annotation to represent packages a patch can be compatible with.
|
||||||
* @param name The package identifier name.
|
* @param name The package identifier name.
|
||||||
* @param versions The versions of the package the [Patch] or [MethodFingerprint]is compatible with.
|
* @param versions The versions of the package the [Patch] is compatible with.
|
||||||
*/
|
*/
|
||||||
@Target()
|
@Target()
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package app.revanced.patcher.annotation
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.Context
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declares a [Patch] deprecated for removal.
|
|
||||||
* @param reason The reason why the patch is deprecated.
|
|
||||||
* @param replacement The replacement for the deprecated patch, if any.
|
|
||||||
*/
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class PatchDeprecated(
|
|
||||||
val reason: String,
|
|
||||||
val replacement: KClass<out Patch<Context>> = Patch::class
|
|
||||||
// Values cannot be nullable in annotations, so this will have to do.
|
|
||||||
)
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
package app.revanced.patcher.annotation
|
package app.revanced.patcher.annotation
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.patch.Patch
|
import app.revanced.patcher.patch.Patch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to name a [Patch] or [MethodFingerprint].
|
* Annotation to name a [Patch].
|
||||||
* @param name A suggestive name for the [Patch] or [MethodFingerprint].
|
* @param name A suggestive name for the [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@@ -15,8 +14,8 @@ annotation class Name(
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to describe a [Patch] or [MethodFingerprint].
|
* Annotation to describe a [Patch].
|
||||||
* @param description A description for the [Patch] or [MethodFingerprint].
|
* @param description A description for the [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@@ -27,8 +26,8 @@ annotation class Description(
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to version a [Patch] or [MethodFingerprint].
|
* Annotation to version a [Patch].
|
||||||
* @param version The version of a [Patch] or [MethodFingerprint].
|
* @param version The version of a [Patch].
|
||||||
*/
|
*/
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
|||||||
@@ -65,24 +65,11 @@ object PatchExtensions {
|
|||||||
(it as? OptionsContainer)?.options
|
(it as? OptionsContainer)?.options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val Class<out Patch<Context>>.deprecated: Pair<String, KClass<out Patch<Context>>?>?
|
|
||||||
get() = findAnnotationRecursively(PatchDeprecated::class)?.let {
|
|
||||||
it.reason to it.replacement.let { cl ->
|
|
||||||
if (cl == Patch::class) null else cl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object MethodFingerprintExtensions {
|
object MethodFingerprintExtensions {
|
||||||
val MethodFingerprint.name: String
|
val MethodFingerprint.name: String
|
||||||
get() = javaClass.findAnnotationRecursively(Name::class)?.name ?: this.javaClass.simpleName
|
get() = this.javaClass.simpleName
|
||||||
|
|
||||||
val MethodFingerprint.version
|
|
||||||
get() = javaClass.findAnnotationRecursively(Version::class)?.version ?: "0.0.1"
|
|
||||||
|
|
||||||
val MethodFingerprint.description
|
|
||||||
get() = javaClass.findAnnotationRecursively(Description::class)?.description
|
|
||||||
|
|
||||||
val MethodFingerprint.fuzzyPatternScanMethod
|
val MethodFingerprint.fuzzyPatternScanMethod
|
||||||
get() = javaClass.findAnnotationRecursively(FuzzyPatternScanMethod::class)
|
get() = javaClass.findAnnotationRecursively(FuzzyPatternScanMethod::class)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.jf.dexlib2.builder.MutableMethodImplementation
|
|||||||
import org.jf.dexlib2.builder.instruction.*
|
import org.jf.dexlib2.builder.instruction.*
|
||||||
import org.jf.dexlib2.iface.Method
|
import org.jf.dexlib2.iface.Method
|
||||||
import org.jf.dexlib2.iface.instruction.Instruction
|
import org.jf.dexlib2.iface.instruction.Instruction
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference
|
|
||||||
import org.jf.dexlib2.immutable.ImmutableMethod
|
import org.jf.dexlib2.immutable.ImmutableMethod
|
||||||
import org.jf.dexlib2.immutable.ImmutableMethodImplementation
|
import org.jf.dexlib2.immutable.ImmutableMethodImplementation
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
@@ -45,17 +44,6 @@ fun MutableMethodImplementation.removeInstructions(index: Int, count: Int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare a method to another, considering name and parameters.
|
|
||||||
* @param otherMethod The method to compare against.
|
|
||||||
* @return True if the methods match given the conditions.
|
|
||||||
*/
|
|
||||||
fun Method.softCompareTo(otherMethod: MethodReference): Boolean {
|
|
||||||
return this.name == otherMethod.name && parametersEqual(
|
|
||||||
this.parameterTypes, otherMethod.parameterTypes
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones the method.
|
* Clones the method.
|
||||||
* @param registerCount This parameter allows you to change the register count of the method.
|
* @param registerCount This parameter allows you to change the register count of the method.
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import app.revanced.patcher.data.BytecodeContext
|
|||||||
import app.revanced.patcher.extensions.MethodFingerprintExtensions.fuzzyPatternScanMethod
|
import app.revanced.patcher.extensions.MethodFingerprintExtensions.fuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.extensions.MethodFingerprintExtensions.fuzzyScanThreshold
|
import app.revanced.patcher.extensions.MethodFingerprintExtensions.fuzzyScanThreshold
|
||||||
import app.revanced.patcher.extensions.parametersEqual
|
import app.revanced.patcher.extensions.parametersEqual
|
||||||
import app.revanced.patcher.extensions.softCompareTo
|
|
||||||
import app.revanced.patcher.fingerprint.Fingerprint
|
import app.revanced.patcher.fingerprint.Fingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.util.proxy.ClassProxy
|
import app.revanced.patcher.util.proxy.ClassProxy
|
||||||
@@ -14,6 +13,7 @@ import org.jf.dexlib2.iface.Method
|
|||||||
import org.jf.dexlib2.iface.instruction.Instruction
|
import org.jf.dexlib2.iface.instruction.Instruction
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import org.jf.dexlib2.iface.reference.StringReference
|
import org.jf.dexlib2.iface.reference.StringReference
|
||||||
|
import org.jf.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the [MethodFingerprint] for a method.
|
* Represents the [MethodFingerprint] for a method.
|
||||||
@@ -297,7 +297,7 @@ data class MethodFingerprintResult(
|
|||||||
*/
|
*/
|
||||||
val mutableMethod by lazy {
|
val mutableMethod by lazy {
|
||||||
mutableClass.methods.first {
|
mutableClass.methods.first {
|
||||||
it.softCompareTo(this.method)
|
MethodUtil.methodSignaturesMatch(it, this.method)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package app.revanced.patcher.util.method
|
package app.revanced.patcher.util.method
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.softCompareTo
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import org.jf.dexlib2.iface.Method
|
import org.jf.dexlib2.iface.Method
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference
|
import org.jf.dexlib2.iface.reference.MethodReference
|
||||||
|
import org.jf.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a method from another method via instruction offsets.
|
* Find a method from another method via instruction offsets.
|
||||||
@@ -44,8 +44,8 @@ class MethodWalker internal constructor(
|
|||||||
val proxy = bytecodeContext.findClass(newMethod.definingClass)!!
|
val proxy = bytecodeContext.findClass(newMethod.definingClass)!!
|
||||||
|
|
||||||
val methods = if (walkMutable) proxy.mutableClass.methods else proxy.immutableClass.methods
|
val methods = if (walkMutable) proxy.mutableClass.methods else proxy.immutableClass.methods
|
||||||
currentMethod = methods.first { it ->
|
currentMethod = methods.first {
|
||||||
return@first it.softCompareTo(newMethod)
|
return@first MethodUtil.methodSignaturesMatch(it, newMethod)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
package app.revanced.patcher.usage.bytecode
|
package app.revanced.patcher.usage.bytecode
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("example-fingerprint")
|
|
||||||
@FuzzyPatternScanMethod(2)
|
@FuzzyPatternScanMethod(2)
|
||||||
@ExampleBytecodeCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object ExampleFingerprint : MethodFingerprint(
|
object ExampleFingerprint : MethodFingerprint(
|
||||||
"V",
|
"V",
|
||||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
|||||||
Reference in New Issue
Block a user