diff --git a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/Transformers.kt b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/Transformers.kt index b6e35ef..de77804 100644 --- a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/Transformers.kt +++ b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/Transformers.kt @@ -16,7 +16,7 @@ object Transformers : Collection by mutableListOf( TrashClassTransformer, StringEncryptTransformer, NumberEncryptTransformer, - InitializerRedirectTransformer, + //InitializerRedirectTransformer, DISABLED StringEqualsRedirectTransformer, FieldRedirectTransformer, NativeCandidateTransformer, diff --git a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ClassDumper.kt b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ClassDumper.kt index aa47f10..c65f06d 100644 --- a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ClassDumper.kt +++ b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ClassDumper.kt @@ -10,16 +10,16 @@ class ClassDumper( useComputeMax: Boolean = false ) : ClassWriter(if (useComputeMax) COMPUTE_MAXS else COMPUTE_FRAMES) { - override fun getCommonSuperClass(type1: String, type2: String): String? { - val clazz1 = resourceCache.getClassNode(type1) ?: return null - val clazz2 = resourceCache.getClassNode(type2) ?: return null + override fun getCommonSuperClass(type1: String, type2: String): String { + val clazz1 = resourceCache.getClassNode(type1) ?: return "java/lang/Object" + val clazz2 = resourceCache.getClassNode(type2) ?: return "java/lang/Object" return when { type1 == "java/lang/Object" -> type1 type2 == "java/lang/Object" -> type2 clazz1.isInterface && clazz2.isInterface -> "java/lang/Object" hierarchy.isSubType(type1, type2) -> type2 hierarchy.isSubType(type2, type1) -> type1 - else -> return null + else -> return "java/lang/Object" } } diff --git a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ResourceCache.kt b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ResourceCache.kt index e4ae8eb..af3d606 100644 --- a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ResourceCache.kt +++ b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/resource/ResourceCache.kt @@ -89,9 +89,14 @@ class ResourceCache(private val input: String, private val libs: List) { }.toByteArray() } catch (ignore: Exception) { Logger.error("Failed to dump class ${classNode.name}. Force use COMPUTE_MAXS") - ClassDumper(this@ResourceCache, hierarchy, false).apply { - classNode.accept(this) - }.toByteArray() + try { + ClassDumper(this@ResourceCache, hierarchy, false).apply { + classNode.accept(this) + }.toByteArray() + } catch (exception: Exception) { + exception.printStackTrace() + ByteArray(0) + } } putNextEntry(ZipEntry(classNode.name + ".class")) write(byteArray) diff --git a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/minecraft/MixinFieldRenameTransformer.kt b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/minecraft/MixinFieldRenameTransformer.kt index 68ed3dd..045d633 100644 --- a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/minecraft/MixinFieldRenameTransformer.kt +++ b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/minecraft/MixinFieldRenameTransformer.kt @@ -5,11 +5,12 @@ import net.spartanb312.grunt.process.Transformer import net.spartanb312.grunt.process.hierarchy.FastHierarchy import net.spartanb312.grunt.process.resource.NameGenerator import net.spartanb312.grunt.process.resource.ResourceCache -import net.spartanb312.grunt.process.transformers.rename.FieldRenameTransformer.isPrimeField import net.spartanb312.grunt.utils.extensions.isAnnotation import net.spartanb312.grunt.utils.isExcludedIn import net.spartanb312.grunt.utils.isNotExcludedIn import net.spartanb312.grunt.utils.logging.Logger +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.FieldNode import kotlin.system.measureTimeMillis /** @@ -65,6 +66,16 @@ object MixinFieldRenameTransformer : Transformer("MixinFieldRename", Category.Mi Logger.info(" Renamed ${mappings.size} mixin fields") } + fun FastHierarchy.isPrimeField(owner: ClassNode, field: FieldNode): Boolean { + val ownerInfo = getHierarchyInfo(owner) + if (ownerInfo.missingDependencies) return false + return ownerInfo.parents.none { p -> + if (p is FastHierarchy.HierarchyInfo) { + p.classNode.fields.any { it.name == field.name && it.desc == field.desc } + } else true//Missing dependencies + } + } + private val annotations = mutableListOf( "Lorg/spongepowered/asm/mixin/gen/Accessor", "Lorg/spongepowered/asm/mixin/gen/Invoker", diff --git a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/FieldRenameTransformer.kt b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/FieldRenameTransformer.kt index 7be26b8..4be135a 100644 --- a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/FieldRenameTransformer.kt +++ b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/FieldRenameTransformer.kt @@ -36,53 +36,44 @@ object FieldRenameTransformer : Transformer("FiledRename", Category.Renaming) { override fun ResourceCache.transform() { Logger.info(" - Renaming fields...") - Logger.info(" Building hierarchy graph...") - val hierarchy = FastHierarchy(this) - val buildTime = measureTimeMillis { - hierarchy.build() - } - Logger.info(" Took ${buildTime}ms to build ${hierarchy.size} hierarchies") - val mappings = HashMap() - nonExcluded.asSequence() - .filter { !it.isAnnotation && it.name.isNotExcludedIn(exclusion) } - .forEach { classNode -> - val dictionary = NameGenerator.getByName(dictionary) - val info = hierarchy.getHierarchyInfo(classNode) - if (!info.missingDependencies) { - for (fieldNode in classNode.fields) { - if (fieldNode.name.isExcludedIn(excludedName)) continue - if (hierarchy.isPrimeField(classNode, fieldNode)) { - val key = classNode.name + "." + fieldNode.name - val newName = malPrefix + dictionary.nextName() - mappings[key] = newName - // Apply for children - info.children.forEach { c -> - if (c is FastHierarchy.HierarchyInfo) { - val childKey = c.classNode.name + "." + fieldNode.name - mappings[childKey] = newName - } - } - } else continue + val fields: MutableList = ArrayList() + nonExcluded.forEach { fields.addAll(it.fields) } + fields.shuffle() + + val dictionaries = ConcurrentHashMap() + val count = count { + for (fieldNode in fields) { + if (fieldNode.name.isExcludedIn(excludedName)) continue + val c = getOwner(fieldNode, classes) + val dic = dictionaries.getOrPut(c) { NameGenerator.getByName(dictionary) } + val name = malPrefix + dic.nextName() + val stack: Stack = Stack() + stack.add(c) + while (stack.size > 0) { + val classNode = stack.pop() + val key = classNode.name + "." + fieldNode.name + if (key.isNotExcludedIn(exclusion)) { + mappings[key] = name + } + classes.values.forEach { + if (it.superName == classNode.name || it.interfaces.contains(classNode.name)) + stack.add(it) } } + add() } - + }.get() Logger.info(" Applying remapping for fields...") applyRemap("fields", mappings) - Logger.info(" Renamed ${mappings.size} fields") + Logger.info(" Renamed $count fields") } - fun FastHierarchy.isPrimeField(owner: ClassNode, field: FieldNode): Boolean { - val ownerInfo = getHierarchyInfo(owner) - if (ownerInfo.missingDependencies) return false - return ownerInfo.parents.none { p -> - if (p is FastHierarchy.HierarchyInfo) { - p.classNode.fields.any { it.name == field.name && it.desc == field.desc } - } else true//Missing dependencies - } + private fun getOwner(f: FieldNode, classNodes: MutableMap): ClassNode? { + for (c in classNodes.values) if (c.fields.contains(f)) return c + return null } } \ No newline at end of file diff --git a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/MethodRenameTransformer.kt b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/MethodRenameTransformer.kt index 72aa5ca..b45b5b3 100644 --- a/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/MethodRenameTransformer.kt +++ b/grunt-main/src/main/kotlin/net/spartanb312/grunt/process/transformers/rename/MethodRenameTransformer.kt @@ -1,19 +1,21 @@ package net.spartanb312.grunt.process.transformers.rename -import net.spartanb312.grunt.config.Configs import net.spartanb312.grunt.config.value -import net.spartanb312.grunt.process.resource.NameGenerator import net.spartanb312.grunt.process.Transformer import net.spartanb312.grunt.process.hierarchy.FastHierarchy +import net.spartanb312.grunt.process.resource.NameGenerator import net.spartanb312.grunt.process.resource.ResourceCache -import net.spartanb312.grunt.utils.* +import net.spartanb312.grunt.utils.count import net.spartanb312.grunt.utils.extensions.isAnnotation +import net.spartanb312.grunt.utils.extensions.isEnum import net.spartanb312.grunt.utils.extensions.isNative +import net.spartanb312.grunt.utils.isExcludedIn +import net.spartanb312.grunt.utils.isNotExcludedIn import net.spartanb312.grunt.utils.logging.Logger +import net.spartanb312.grunt.utils.nextBadKeyword import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.MethodNode import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.CountDownLatch import kotlin.system.measureTimeMillis /** @@ -37,7 +39,7 @@ object MethodRenameTransformer : Transformer("MethodRename", Category.Renaming) Logger.info(" - Renaming methods...") Logger.info(" Building hierarchy graph...") - val hierarchy = FastHierarchy(this) + val hierarchy = FastHierarchy(this, true) val buildTime = measureTimeMillis { hierarchy.build() } @@ -47,46 +49,55 @@ object MethodRenameTransformer : Transformer("MethodRename", Category.Renaming) val mappings = ConcurrentHashMap() val count = count { // Generate names and apply to children - val tasks = mutableListOf() nonExcluded.asSequence() - .filter { !it.isAnnotation && it.name.isNotExcludedIn(exclusion) } + .filter { !it.isEnum && !it.isAnnotation && it.name.isNotExcludedIn(exclusion) } .forEach { classNode -> - val task = Runnable { - val info = hierarchy.getHierarchyInfo(classNode) - if (!info.missingDependencies) { - for (methodNode in classNode.methods) { - if (methodNode.name.startsWith("<")) continue - if (methodNode.name == "main") continue - if (methodNode.name.isExcludedIn(excludedName)) continue - if (methodNode.isNative) continue - if (hierarchy.isPrimeMethod(classNode, methodNode)) { - val newName = (if (randomKeywordPrefix) "$nextBadKeyword " else "") + - prefix + dic.nextName(heavyOverloads, methodNode.desc) - mappings[combine(classNode.name, methodNode.name, methodNode.desc)] = newName - // Apply to children - info.children.forEach { c -> - if (c is FastHierarchy.HierarchyInfo) { - val childKey = combine(c.classNode.name, methodNode.name, methodNode.desc) - mappings[childKey] = newName + val info = hierarchy.getHierarchyInfo(classNode) + if (!info.missingDependencies) { + for (methodNode in classNode.methods) { + if (methodNode.name.startsWith("<")) continue + if (methodNode.name == "main") continue + if (methodNode.name.isExcludedIn(excludedName)) continue + if (methodNode.isNative) continue + if (hierarchy.isPrimeMethod(classNode, methodNode)) { + val readyToApply = mutableMapOf() + var shouldApply = true + val newName = (if (randomKeywordPrefix) "$nextBadKeyword " else "") + + prefix + dic.nextName(heavyOverloads, methodNode.desc) + readyToApply[combine(classNode.name, methodNode.name, methodNode.desc)] = newName + // Check children + info.children.forEach { c -> + if (c is FastHierarchy.HierarchyInfo) { + // Check its origin + for (parent in c.parents) { + if (parent.missingDependencies) shouldApply = false + if (parent is FastHierarchy.HierarchyInfo) { + val flag1 = !hierarchy.isSubType(parent.classNode.name, classNode.name) + val flag2 = !hierarchy.isSubType(classNode.name, parent.classNode.name) + if (parent.classNode.name != classNode.name && (flag1 && flag2)) { + parent.classNode.methods.forEach { check -> + if (check.name == methodNode.name && check.desc == methodNode.desc) { + // Skip multi origin methods + shouldApply = false + //Logger.debug("Multi Origin ${methodNode.name}${methodNode.desc} in ${classNode.name} and ${parent.classNode.name}") + } + } + } + } } + + val childKey = combine(c.classNode.name, methodNode.name, methodNode.desc) + readyToApply[childKey] = newName } - add() - } else continue - } + } + // Apply mappings + if (shouldApply) readyToApply.forEach { (key, value) -> mappings[key] = value } + add() + } else continue } } - if (Configs.Settings.parallel) tasks.add(task) else task.run() - } - if (Configs.Settings.parallel) { - val cdl = CountDownLatch(tasks.size) - tasks.forEach { - Thread { - it.run() - cdl.countDown() - }.start() + } - cdl.await() - } }.get() Logger.info(" Applying remapping for methods...")