mirror of
https://github.com/ReVanced/revanced-patcher.git
synced 2024-11-10 01:02:22 +01:00
fix: fix classes having multiple method instances
This commit is contained in:
parent
d18a3b6a28
commit
398239dc10
6 changed files with 54 additions and 34 deletions
|
@ -29,7 +29,7 @@ class Patcher(
|
|||
|
||||
init {
|
||||
val dexFile = MultiDexIO.readDexFile(true, input, BasicDexFileNamer(), null, null)
|
||||
cache = Cache(dexFile.classes, SignatureResolver(dexFile.classes, signatures).resolve())
|
||||
cache = Cache(dexFile.classes.toMutableSet(), SignatureResolver(dexFile.classes, signatures).resolve())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,13 +39,13 @@ class Patcher(
|
|||
val newDexFile = object : DexFile {
|
||||
override fun getClasses(): Set<ClassDef> {
|
||||
// this is a slow workaround for now
|
||||
val classes = cache.classes.toMutableSet()
|
||||
cache.classProxy
|
||||
.filter { it.proxyUsed }.forEach { proxy ->
|
||||
classes.remove(classes.elementAt(proxy.originalIndex))
|
||||
classes.add(proxy.mutatedClass)
|
||||
cache.classes.remove(cache.classes.elementAt(proxy.originalIndex))
|
||||
cache.classes.add(proxy.mutatedClass)
|
||||
}
|
||||
return classes
|
||||
|
||||
return setOf(cache.classProxy.first().mutatedClass)
|
||||
}
|
||||
|
||||
override fun getOpcodes(): Opcodes {
|
||||
|
|
|
@ -5,7 +5,7 @@ import app.revanced.patcher.signature.SignatureResolverResult
|
|||
import org.jf.dexlib2.iface.ClassDef
|
||||
|
||||
class Cache(
|
||||
internal val classes: Set<ClassDef>,
|
||||
internal val classes: MutableSet<ClassDef>,
|
||||
val resolvedMethods: MethodMap
|
||||
) {
|
||||
// TODO: currently we create ClassProxies at multiple places, which is why we could have merge conflicts
|
||||
|
|
|
@ -3,8 +3,10 @@ package app.revanced.patcher.proxy.mutableTypes
|
|||
import app.revanced.patcher.proxy.mutableTypes.MutableAnnotation.Companion.toMutable
|
||||
import app.revanced.patcher.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import com.google.common.collect.Iterables
|
||||
import org.jf.dexlib2.base.reference.BaseTypeReference
|
||||
import org.jf.dexlib2.iface.ClassDef
|
||||
import org.jf.dexlib2.util.MethodUtil
|
||||
|
||||
class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
|
||||
// Class
|
||||
|
@ -14,17 +16,23 @@ class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
|
|||
private var superclass = classDef.superclass
|
||||
|
||||
private val _interfaces by lazy { classDef.interfaces.toMutableList() }
|
||||
private val _annotations by lazy { classDef.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() }
|
||||
private val _annotations by lazy {
|
||||
classDef.annotations.map { annotation -> annotation.toMutable() }.toMutableSet()
|
||||
}
|
||||
|
||||
// Methods
|
||||
private val _methods by lazy { classDef.methods.map { method -> method.toMutable() }.toMutableSet() }
|
||||
private val _directMethods by lazy { classDef.directMethods.map { directMethod -> directMethod.toMutable() }.toMutableSet() }
|
||||
private val _virtualMethods by lazy { classDef.virtualMethods.map { virtualMethod -> virtualMethod.toMutable() }.toMutableSet() }
|
||||
private val _directMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_DIRECT).toMutableSet() }
|
||||
private val _virtualMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_VIRTUAL).toMutableSet() }
|
||||
|
||||
// Fields
|
||||
private val _fields by lazy { classDef.fields.map { field -> field.toMutable() }.toMutableSet() }
|
||||
private val _staticFields by lazy { classDef.staticFields.map { staticField -> staticField.toMutable() }.toMutableSet() }
|
||||
private val _instanceFields by lazy { classDef.instanceFields.map { instanceFields -> instanceFields.toMutable() }.toMutableSet() }
|
||||
private val _staticFields by lazy {
|
||||
classDef.staticFields.map { staticField -> staticField.toMutable() }.toMutableSet()
|
||||
}
|
||||
private val _instanceFields by lazy {
|
||||
classDef.instanceFields.map { instanceFields -> instanceFields.toMutable() }.toMutableSet()
|
||||
}
|
||||
|
||||
fun setType(type: String) {
|
||||
this.type = type
|
||||
|
|
|
@ -9,7 +9,9 @@ class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, Base
|
|||
private var type = parameter.type
|
||||
private var name = parameter.name
|
||||
private var signature = parameter.signature
|
||||
private val _annotations by lazy { parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() }
|
||||
private val _annotations by lazy {
|
||||
parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet()
|
||||
}
|
||||
|
||||
override fun getType(): String {
|
||||
return type
|
||||
|
|
|
@ -5,7 +5,6 @@ import org.antlr.runtime.TokenSource
|
|||
import org.antlr.runtime.tree.CommonTreeNodeStream
|
||||
import org.jf.dexlib2.Opcodes
|
||||
import org.jf.dexlib2.builder.BuilderInstruction
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.writer.builder.DexBuilder
|
||||
import org.jf.smali.LexerErrorInterface
|
||||
import org.jf.smali.smaliFlexLexer
|
||||
|
|
|
@ -11,6 +11,7 @@ import app.revanced.patcher.signature.MethodSignature
|
|||
import app.revanced.patcher.smali.asInstruction
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
@ -51,12 +52,12 @@ fun main() {
|
|||
it.name.contains("HideReel")
|
||||
}!!
|
||||
|
||||
val instructions = hideReelMethod.implementation!!
|
||||
val implementation = hideReelMethod.implementation!!
|
||||
|
||||
val readInsn =
|
||||
val readSettingsInstructionCompiled =
|
||||
"invoke-static { }, Lfi/razerman/youtube/XGlobals;->ReadSettings()V"
|
||||
.asInstruction() as BuilderInstruction35c
|
||||
val testInsn = BuilderInstruction35c(
|
||||
val readSettingsInstructionAssembled = BuilderInstruction35c(
|
||||
Opcode.INVOKE_STATIC,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
ImmutableMethodReference(
|
||||
|
@ -67,30 +68,40 @@ fun main() {
|
|||
)
|
||||
)
|
||||
|
||||
assertEquals(testInsn.opcode, readInsn.opcode)
|
||||
assertEquals(testInsn.referenceType, readInsn.referenceType)
|
||||
assertEquals(testInsn.registerCount, readInsn.registerCount)
|
||||
assertEquals(testInsn.registerC, readInsn.registerC)
|
||||
assertEquals(testInsn.registerD, readInsn.registerD)
|
||||
assertEquals(testInsn.registerE, readInsn.registerE)
|
||||
assertEquals(testInsn.registerF, readInsn.registerF)
|
||||
assertEquals(testInsn.registerG, readInsn.registerG)
|
||||
assertEquals(readSettingsInstructionAssembled.opcode, readSettingsInstructionCompiled.opcode)
|
||||
assertEquals(
|
||||
readSettingsInstructionAssembled.referenceType,
|
||||
readSettingsInstructionCompiled.referenceType
|
||||
)
|
||||
assertEquals(
|
||||
readSettingsInstructionAssembled.registerCount,
|
||||
readSettingsInstructionCompiled.registerCount
|
||||
)
|
||||
assertEquals(readSettingsInstructionAssembled.registerC, readSettingsInstructionCompiled.registerC)
|
||||
assertEquals(readSettingsInstructionAssembled.registerD, readSettingsInstructionCompiled.registerD)
|
||||
assertEquals(readSettingsInstructionAssembled.registerE, readSettingsInstructionCompiled.registerE)
|
||||
assertEquals(readSettingsInstructionAssembled.registerF, readSettingsInstructionCompiled.registerF)
|
||||
assertEquals(readSettingsInstructionAssembled.registerG, readSettingsInstructionCompiled.registerG)
|
||||
run {
|
||||
val tref = testInsn.reference as MethodReference
|
||||
val rref = readInsn.reference as MethodReference
|
||||
val compiledRef = readSettingsInstructionCompiled.reference as MethodReference
|
||||
val assembledRef = readSettingsInstructionAssembled.reference as MethodReference
|
||||
|
||||
assertEquals(tref.name, rref.name)
|
||||
assertEquals(tref.definingClass, rref.definingClass)
|
||||
assertEquals(tref.returnType, rref.returnType)
|
||||
assertContentEquals(tref.parameterTypes, rref.parameterTypes)
|
||||
assertEquals(assembledRef.name, compiledRef.name)
|
||||
assertEquals(assembledRef.definingClass, compiledRef.definingClass)
|
||||
assertEquals(assembledRef.returnType, compiledRef.returnType)
|
||||
assertContentEquals(assembledRef.parameterTypes, compiledRef.parameterTypes)
|
||||
}
|
||||
|
||||
// TODO: figure out control flow
|
||||
// otherwise the we would still jump over to the original instruction at index 21 instead to our new one
|
||||
instructions.addInstruction(
|
||||
implementation.addInstruction(
|
||||
21,
|
||||
readInsn
|
||||
readSettingsInstructionCompiled
|
||||
)
|
||||
|
||||
// fix labels
|
||||
// create a new label for the instruction we want to jump to
|
||||
val newLabel = implementation.newLabelForIndex(21)
|
||||
// replace all instances of the old label with the new one
|
||||
implementation.replaceInstruction(4, BuilderInstruction21t(Opcode.IF_NEZ, 0, newLabel))
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue