From 4be005617b3b8c3578cca07c5d085d12916f0d1d Mon Sep 17 00:00:00 2001 From: lclc98 Date: Thu, 30 Jun 2016 00:49:21 +1000 Subject: Json format (#2) * Added new format * Fixed bug * Updated Version --- src/cuchaz/enigma/bytecode/ClassRenamer.java | 544 --------------------------- 1 file changed, 544 deletions(-) delete mode 100644 src/cuchaz/enigma/bytecode/ClassRenamer.java (limited to 'src/cuchaz/enigma/bytecode/ClassRenamer.java') diff --git a/src/cuchaz/enigma/bytecode/ClassRenamer.java b/src/cuchaz/enigma/bytecode/ClassRenamer.java deleted file mode 100644 index 509877a..0000000 --- a/src/cuchaz/enigma/bytecode/ClassRenamer.java +++ /dev/null @@ -1,544 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - * - * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.bytecode; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javassist.CtClass; -import javassist.bytecode.AttributeInfo; -import javassist.bytecode.BadBytecode; -import javassist.bytecode.ByteArray; -import javassist.bytecode.ClassFile; -import javassist.bytecode.CodeAttribute; -import javassist.bytecode.ConstPool; -import javassist.bytecode.Descriptor; -import javassist.bytecode.FieldInfo; -import javassist.bytecode.InnerClassesAttribute; -import javassist.bytecode.LocalVariableTypeAttribute; -import javassist.bytecode.MethodInfo; -import javassist.bytecode.SignatureAttribute; -import javassist.bytecode.SignatureAttribute.ArrayType; -import javassist.bytecode.SignatureAttribute.BaseType; -import javassist.bytecode.SignatureAttribute.ClassSignature; -import javassist.bytecode.SignatureAttribute.ClassType; -import javassist.bytecode.SignatureAttribute.MethodSignature; -import javassist.bytecode.SignatureAttribute.NestedClassType; -import javassist.bytecode.SignatureAttribute.ObjectType; -import javassist.bytecode.SignatureAttribute.Type; -import javassist.bytecode.SignatureAttribute.TypeArgument; -import javassist.bytecode.SignatureAttribute.TypeParameter; -import javassist.bytecode.SignatureAttribute.TypeVariable; -import cuchaz.enigma.mapping.ClassEntry; -import cuchaz.enigma.mapping.ClassNameReplacer; -import cuchaz.enigma.mapping.Translator; - -public class ClassRenamer { - - private static enum SignatureType { - Class { - - @Override - public String rename(String signature, ReplacerClassMap map) { - return renameClassSignature(signature, map); - } - }, - Field { - - @Override - public String rename(String signature, ReplacerClassMap map) { - return renameFieldSignature(signature, map); - } - }, - Method { - - @Override - public String rename(String signature, ReplacerClassMap map) { - return renameMethodSignature(signature, map); - } - }; - - public abstract String rename(String signature, ReplacerClassMap map); - } - - private static class ReplacerClassMap extends HashMap { - - private static final long serialVersionUID = 317915213205066168L; - - private ClassNameReplacer m_replacer; - - public ReplacerClassMap(ClassNameReplacer replacer) { - m_replacer = replacer; - } - - @Override - public String get(Object obj) { - if (obj instanceof String) { - return get((String)obj); - } - return null; - } - - public String get(String className) { - return m_replacer.replace(className); - } - } - - public static void renameClasses(CtClass c, final Translator translator) { - renameClasses(c, new ClassNameReplacer() { - @Override - public String replace(String className) { - ClassEntry entry = translator.translateEntry(new ClassEntry(className)); - if (entry != null) { - return entry.getName(); - } - return null; - } - }); - } - - public static void moveAllClassesOutOfDefaultPackage(CtClass c, final String newPackageName) { - renameClasses(c, new ClassNameReplacer() { - @Override - public String replace(String className) { - ClassEntry entry = new ClassEntry(className); - if (entry.isInDefaultPackage()) { - return newPackageName + "/" + entry.getName(); - } - return null; - } - }); - } - - public static void moveAllClassesIntoDefaultPackage(CtClass c, final String oldPackageName) { - renameClasses(c, new ClassNameReplacer() { - @Override - public String replace(String className) { - ClassEntry entry = new ClassEntry(className); - if (entry.getPackageName().equals(oldPackageName)) { - return entry.getSimpleName(); - } - return null; - } - }); - } - - @SuppressWarnings("unchecked") - public static void renameClasses(CtClass c, ClassNameReplacer replacer) { - - // sadly, we can't use CtClass.renameClass() because SignatureAttribute.renameClass() is extremely buggy =( - - ReplacerClassMap map = new ReplacerClassMap(replacer); - ClassFile classFile = c.getClassFile(); - - // rename the constant pool (covers ClassInfo, MethodTypeInfo, and NameAndTypeInfo) - ConstPool constPool = c.getClassFile().getConstPool(); - constPool.renameClass(map); - - // rename class attributes - renameAttributes(classFile.getAttributes(), map, SignatureType.Class); - - // rename methods - for (MethodInfo methodInfo : (List)classFile.getMethods()) { - methodInfo.setDescriptor(Descriptor.rename(methodInfo.getDescriptor(), map)); - renameAttributes(methodInfo.getAttributes(), map, SignatureType.Method); - } - - // rename fields - for (FieldInfo fieldInfo : (List)classFile.getFields()) { - fieldInfo.setDescriptor(Descriptor.rename(fieldInfo.getDescriptor(), map)); - renameAttributes(fieldInfo.getAttributes(), map, SignatureType.Field); - } - - // rename the class name itself last - // NOTE: don't use the map here, because setName() calls the buggy SignatureAttribute.renameClass() - // we only want to replace exactly this class name - String newName = renameClassName(c.getName(), map); - if (newName != null) { - c.setName(newName); - } - - // replace simple names in the InnerClasses attribute too - InnerClassesAttribute attr = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag); - if (attr != null) { - for (int i = 0; i < attr.tableLength(); i++) { - - // get the inner class full name (which has already been translated) - ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i))); - - if (attr.innerNameIndex(i) != 0) { - // update the inner name - attr.setInnerNameIndex(i, constPool.addUtf8Info(classEntry.getInnermostClassName())); - } - - /* DEBUG - System.out.println(String.format("\tDEOBF: %s-> ATTR: %s,%s,%s", classEntry, attr.outerClass(i), attr.innerClass(i), attr.innerName(i))); - */ - } - } - } - - @SuppressWarnings("unchecked") - private static void renameAttributes(List attributes, ReplacerClassMap map, SignatureType type) { - try { - - // make the rename class method accessible - Method renameClassMethod = AttributeInfo.class.getDeclaredMethod("renameClass", Map.class); - renameClassMethod.setAccessible(true); - - for (AttributeInfo attribute : attributes) { - if (attribute instanceof SignatureAttribute) { - // this has to be handled specially because SignatureAttribute.renameClass() is buggy as hell - SignatureAttribute signatureAttribute = (SignatureAttribute)attribute; - String newSignature = type.rename(signatureAttribute.getSignature(), map); - if (newSignature != null) { - signatureAttribute.setSignature(newSignature); - } - } else if (attribute instanceof CodeAttribute) { - // code attributes have signature attributes too (indirectly) - CodeAttribute codeAttribute = (CodeAttribute)attribute; - renameAttributes(codeAttribute.getAttributes(), map, type); - } else if (attribute instanceof LocalVariableTypeAttribute) { - // lvt attributes have signature attributes too - LocalVariableTypeAttribute localVariableAttribute = (LocalVariableTypeAttribute)attribute; - renameLocalVariableTypeAttribute(localVariableAttribute, map); - } else { - renameClassMethod.invoke(attribute, map); - } - } - - } catch(NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Error("Unable to call javassist methods by reflection!", ex); - } - } - - private static void renameLocalVariableTypeAttribute(LocalVariableTypeAttribute attribute, ReplacerClassMap map) { - - // adapted from LocalVariableAttribute.renameClass() - ConstPool cp = attribute.getConstPool(); - int n = attribute.tableLength(); - byte[] info = attribute.get(); - for (int i = 0; i < n; ++i) { - int pos = i * 10 + 2; - int index = ByteArray.readU16bit(info, pos + 6); - if (index != 0) { - String signature = cp.getUtf8Info(index); - String newSignature = renameLocalVariableSignature(signature, map); - if (newSignature != null) { - ByteArray.write16bit(cp.addUtf8Info(newSignature), info, pos + 6); - } - } - } - } - - private static String renameLocalVariableSignature(String signature, ReplacerClassMap map) { - - // for some reason, signatures with . in them don't count as field signatures - // looks like anonymous classes delimit with . in stead of $ - // convert the . to $, but keep track of how many we replace - // we need to put them back after we translate - int start = signature.lastIndexOf('$') + 1; - int numConverted = 0; - StringBuilder buf = new StringBuilder(signature); - for (int i=buf.length()-1; i>=start; i--) { - char c = buf.charAt(i); - if (c == '.') { - buf.setCharAt(i, '$'); - numConverted++; - } - } - signature = buf.toString(); - - // translate - String newSignature = renameFieldSignature(signature, map); - if (newSignature != null) { - - // put the delimiters back - buf = new StringBuilder(newSignature); - for (int i=buf.length()-1; i>=0 && numConverted > 0; i--) { - char c = buf.charAt(i); - if (c == '$') { - buf.setCharAt(i, '.'); - numConverted--; - } - } - assert(numConverted == 0); - newSignature = buf.toString(); - - return newSignature; - } - - return null; - } - - private static String renameClassSignature(String signature, ReplacerClassMap map) { - try { - ClassSignature type = renameType(SignatureAttribute.toClassSignature(signature), map); - if (type != null) { - return type.encode(); - } - return null; - } catch (BadBytecode ex) { - throw new Error("Can't parse field signature: " + signature); - } - } - - private static String renameFieldSignature(String signature, ReplacerClassMap map) { - try { - ObjectType type = renameType(SignatureAttribute.toFieldSignature(signature), map); - if (type != null) { - return type.encode(); - } - return null; - } catch (BadBytecode ex) { - throw new Error("Can't parse class signature: " + signature); - } - } - - private static String renameMethodSignature(String signature, ReplacerClassMap map) { - try { - MethodSignature type = renameType(SignatureAttribute.toMethodSignature(signature), map); - if (type != null) { - return type.encode(); - } - return null; - } catch (BadBytecode ex) { - throw new Error("Can't parse method signature: " + signature); - } - } - - private static ClassSignature renameType(ClassSignature type, ReplacerClassMap map) { - - TypeParameter[] typeParamTypes = type.getParameters(); - if (typeParamTypes != null) { - typeParamTypes = Arrays.copyOf(typeParamTypes, typeParamTypes.length); - for (int i=0; i