From 2b2249e873c4adfd2dd6e8f1f2489ccd9f6aa021 Mon Sep 17 00:00:00 2001 From: gegy1000 Date: Sat, 19 May 2018 17:02:46 +0200 Subject: Initial port to ASM --- .../java/cuchaz/enigma/bytecode/AccessFlags.java | 79 +++ .../cuchaz/enigma/bytecode/ClassProtectifier.java | 54 +-- .../cuchaz/enigma/bytecode/ClassPublifier.java | 58 +-- .../java/cuchaz/enigma/bytecode/ClassRenamer.java | 539 --------------------- .../cuchaz/enigma/bytecode/ConstPoolEditor.java | 264 ---------- src/main/java/cuchaz/enigma/bytecode/InfoType.java | 266 ---------- .../enigma/bytecode/MethodParametersAttribute.java | 87 ---- .../bytecode/accessors/ClassInfoAccessor.java | 56 --- .../bytecode/accessors/ConstInfoAccessor.java | 124 ----- .../accessors/InvokeDynamicInfoAccessor.java | 75 --- .../bytecode/accessors/MemberRefInfoAccessor.java | 75 --- .../accessors/MethodHandleInfoAccessor.java | 75 --- .../bytecode/accessors/MethodTypeInfoAccessor.java | 57 --- .../accessors/NameAndTypeInfoAccessor.java | 75 --- .../bytecode/accessors/StringInfoAccessor.java | 56 --- .../bytecode/accessors/Utf8InfoAccessor.java | 29 -- .../bytecode/translators/ClassTranslator.java | 161 ------ .../bytecode/translators/InnerClassWriter.java | 144 ------ .../translators/LocalVariableTranslator.java | 142 ------ .../translators/MethodParameterTranslator.java | 62 --- .../translators/TranslationClassVisitor.java | 106 ++++ .../translators/TranslationMethodVisitor.java | 82 ++++ 22 files changed, 324 insertions(+), 2342 deletions(-) create mode 100644 src/main/java/cuchaz/enigma/bytecode/AccessFlags.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/InfoType.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/ClassTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/InnerClassWriter.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/MethodParameterTranslator.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java (limited to 'src/main/java/cuchaz/enigma/bytecode') diff --git a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java new file mode 100644 index 0000000..0999abf --- /dev/null +++ b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java @@ -0,0 +1,79 @@ +package cuchaz.enigma.bytecode; + +import org.objectweb.asm.Opcodes; + +import java.lang.reflect.Modifier; + +public class AccessFlags { + private static final int SYNTHETIC_FLAG = 0x00001000; + private static final int BRIDGED_FLAG = 0x00000040; + + private int flags; + + public AccessFlags(int flags) { + this.flags = flags; + } + + public boolean isPrivate() { + return Modifier.isPrivate(this.flags); + } + + public boolean isProtected() { + return Modifier.isProtected(this.flags); + } + + public boolean isPublic() { + return Modifier.isPublic(this.flags); + } + + public boolean isSynthetic() { + return (this.flags & SYNTHETIC_FLAG) != 0; + } + + public boolean isStatic() { + return Modifier.isStatic(this.flags); + } + + public AccessFlags setPrivate() { + this.setVisibility(Opcodes.ACC_PRIVATE); + return this; + } + + public AccessFlags setProtected() { + this.setVisibility(Opcodes.ACC_PROTECTED); + return this; + } + + public AccessFlags setPublic() { + this.setVisibility(Opcodes.ACC_PUBLIC); + return this; + } + + public AccessFlags setBridged() { + this.setVisibility(BRIDGED_FLAG); + return this; + } + + public void setVisibility(int visibility) { + this.resetVisibility(); + this.flags |= visibility; + } + + private void resetVisibility() { + this.flags &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC); + } + + public int getFlags() { + return this.flags; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof AccessFlags && ((AccessFlags) obj).flags == flags; + } + + @Override + public int hashCode() { + return flags; + } +} diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java b/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java index 6ec576e..9ed6db9 100644 --- a/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java +++ b/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java @@ -11,41 +11,39 @@ package cuchaz.enigma.bytecode; -import javassist.CtBehavior; -import javassist.CtClass; -import javassist.CtField; -import javassist.bytecode.AccessFlag; -import javassist.bytecode.InnerClassesAttribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; -public class ClassProtectifier { +public class ClassProtectifier extends ClassVisitor { - public static CtClass protectify(CtClass c) { - - // protectify all the fields - for (CtField field : c.getDeclaredFields()) { - field.setModifiers(protectify(field.getModifiers())); - } + public ClassProtectifier(int api, ClassVisitor cv) { + super(api, cv); + } - // protectify all the methods and constructors - for (CtBehavior behavior : c.getDeclaredBehaviors()) { - behavior.setModifiers(protectify(behavior.getModifiers())); - } + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + access = protectify(access); + return super.visitMethod(access, name, desc, signature, exceptions); + } - // protectify all the inner classes - InnerClassesAttribute attr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag); - if (attr != null) { - for (int i = 0; i < attr.tableLength(); i++) { - attr.setAccessFlags(i, protectify(attr.accessFlags(i))); - } - } + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { + access = protectify(access); + return super.visitField(access, name, desc, signature, value); + } - return c; + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + access = protectify(access); + super.visitInnerClass(name, outerName, innerName, access); } - private static int protectify(int flags) { - if (AccessFlag.isPrivate(flags)) { - flags = AccessFlag.setProtected(flags); + private static int protectify(int access) { + AccessFlags accessFlags = new AccessFlags(access); + if (accessFlags.isPrivate()) { + accessFlags.setProtected(); } - return flags; + return accessFlags.getFlags(); } } diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java b/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java index d627fe9..64de788 100644 --- a/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java +++ b/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java @@ -11,41 +11,45 @@ package cuchaz.enigma.bytecode; -import javassist.CtBehavior; -import javassist.CtClass; -import javassist.CtField; -import javassist.bytecode.AccessFlag; -import javassist.bytecode.InnerClassesAttribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; -public class ClassPublifier { +public class ClassPublifier extends ClassVisitor { - public static CtClass publify(CtClass c) { + public ClassPublifier(int api, ClassVisitor cv) { + super(api, cv); + } - // publify all the fields - for (CtField field : c.getDeclaredFields()) { - field.setModifiers(publify(field.getModifiers())); - } + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + access = publify(access); + super.visit(version, access, name, signature, superName, interfaces); + } - // publify all the methods and constructors - for (CtBehavior behavior : c.getDeclaredBehaviors()) { - behavior.setModifiers(publify(behavior.getModifiers())); - } + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { + access = publify(access); + return super.visitField(access, name, desc, signature, value); + } - // publify all the inner classes - InnerClassesAttribute attr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag); - if (attr != null) { - for (int i = 0; i < attr.tableLength(); i++) { - attr.setAccessFlags(i, publify(attr.accessFlags(i))); - } - } + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + access = publify(access); + return super.visitMethod(access, name, desc, signature, exceptions); + } - return c; + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + access = publify(access); + super.visitInnerClass(name, outerName, innerName, access); } - private static int publify(int flags) { - if (!AccessFlag.isPublic(flags)) { - flags = AccessFlag.setPublic(flags); + private static int publify(int access) { + AccessFlags accessFlags = new AccessFlags(access); + if (!accessFlags.isPublic()) { + accessFlags.setPublic(); } - return flags; + return accessFlags.getFlags(); } } diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java deleted file mode 100644 index 62a838d..0000000 --- a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java +++ /dev/null @@ -1,539 +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 cuchaz.enigma.mapping.ClassEntry;
-import cuchaz.enigma.mapping.ClassNameReplacer;
-import cuchaz.enigma.mapping.Mappings;
-import cuchaz.enigma.mapping.Translator;
-import javassist.CtBehavior;
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.Modifier;
-import javassist.bytecode.*;
-import javassist.bytecode.SignatureAttribute.*;
-
-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;
-
-public class ClassRenamer {
-
- public static void applyModifier(Object obj, Mappings.EntryModifier modifier) {
- int mod = -1;
- if (obj instanceof CtField)
- mod = ((CtField) obj).getModifiers();
- else if (obj instanceof CtBehavior)
- mod = ((CtBehavior) obj).getModifiers();
- else if (obj instanceof CtClass)
- mod = ((CtClass) obj).getModifiers();
-
- if (mod != -1) {
- switch (modifier) {
- case PRIVATE:
- mod = Modifier.setPrivate(mod);
- break;
- case PROTECTED:
- mod = Modifier.setProtected(mod);
- break;
- case PUBLIC:
- mod = Modifier.setPublic(mod);
- break;
- default:
- break;
- }
- if (obj instanceof CtField)
- ((CtField) obj).setModifiers(mod);
- else if (obj instanceof CtBehavior)
- ((CtBehavior) obj).setModifiers(mod);
- else
- ((CtClass) obj).setModifiers(mod);
- }
- }
-
- public static void renameClasses(CtClass c, final Translator translator) {
- renameClasses(c, 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, 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, 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
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.bytecode;
-
-import cuchaz.enigma.bytecode.accessors.ClassInfoAccessor;
-import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor;
-import cuchaz.enigma.bytecode.accessors.MemberRefInfoAccessor;
-import javassist.bytecode.ConstPool;
-import javassist.bytecode.Descriptor;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-
-public class ConstPoolEditor {
-
- private static Method getItem;
- private static Method addItem;
- private static Method addItem0;
- private static Field items;
- private static Field cache;
- private static Field numItems;
- private static Field objects;
- private static Field elements;
- private static Method methodWritePool;
- private static Constructor
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.bytecode;
-
-import com.google.common.collect.Maps;
-import cuchaz.enigma.bytecode.accessors.*;
-
-import java.util.Collection;
-import java.util.Map;
-
-public enum InfoType {
-
- Utf8Info(1),
- IntegerInfo(3),
- FloatInfo(4),
- LongInfo(5),
- DoubleInfo(6),
- ClassInfo(7) {
- @Override
- public void gatherIndexTree(Collection
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.bytecode;
-
-import javassist.bytecode.AttributeInfo;
-import javassist.bytecode.ConstPool;
-import javassist.bytecode.MethodInfo;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MethodParametersAttribute extends AttributeInfo {
-
- private MethodParametersAttribute(ConstPool pool, List
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.bytecode.accessors;
-
-import java.lang.reflect.Field;
-
-public class ClassInfoAccessor {
-
- private static Class> clazz;
- private static Field nameIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.ClassInfo");
- nameIndex = clazz.getDeclaredField("name");
- nameIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public ClassInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getNameIndex() {
- try {
- return (Integer) nameIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setNameIndex(int val) {
- try {
- nameIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java
deleted file mode 100644
index 27d991a..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java
+++ /dev/null
@@ -1,124 +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.accessors;
-
-import com.google.common.base.Charsets;
-import cuchaz.enigma.bytecode.InfoType;
-
-import java.io.*;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-public class ConstInfoAccessor {
-
- private static Class> clazz;
- private static Field index;
- private static Method getTag;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.ConstInfo");
- index = clazz.getDeclaredField("index");
- index.setAccessible(true);
- getTag = clazz.getMethod("getTag");
- getTag.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public ConstInfoAccessor(Object item) {
- if (item == null) {
- throw new IllegalArgumentException("item cannot be null!");
- }
- this.item = item;
- }
-
- public Object getItem() {
- return this.item;
- }
-
- public int getIndex() {
- try {
- return (Integer) index.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public int getTag() {
- try {
- return (Integer) getTag.invoke(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public ConstInfoAccessor copy() {
- return new ConstInfoAccessor(copyItem());
- }
-
- public Object copyItem() {
- // I don't know of a simpler way to copy one of these silly things...
- try {
- // serialize the item
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- DataOutputStream out = new DataOutputStream(buf);
- write(out);
-
- // deserialize the item
- DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf.toByteArray()));
- Object item = new ConstInfoAccessor(in).getItem();
- in.close();
-
- return item;
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void write(DataOutputStream out) throws IOException {
- try {
- out.writeUTF(this.item.getClass().getName());
- out.writeInt(getIndex());
-
- Method method = this.item.getClass().getMethod("write", DataOutputStream.class);
- method.setAccessible(true);
- method.invoke(this.item, out);
- } catch (IOException ex) {
- throw ex;
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- @Override
- public String toString() {
- try {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- PrintWriter out = new PrintWriter(new OutputStreamWriter(buf, Charsets.UTF_8));
- Method print = this.item.getClass().getMethod("print", PrintWriter.class);
- print.setAccessible(true);
- print.invoke(this.item, out);
- out.close();
- return buf.toString("UTF-8").replace("\n", "");
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public InfoType getType() {
- return InfoType.getByTag(getTag());
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java
deleted file mode 100644
index aef3532..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java
+++ /dev/null
@@ -1,75 +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.accessors;
-
-import java.lang.reflect.Field;
-
-public class InvokeDynamicInfoAccessor {
-
- private static Class> clazz;
- private static Field bootstrapIndex;
- private static Field nameAndTypeIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.InvokeDynamicInfo");
- bootstrapIndex = clazz.getDeclaredField("bootstrap");
- bootstrapIndex.setAccessible(true);
- nameAndTypeIndex = clazz.getDeclaredField("nameAndType");
- nameAndTypeIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public InvokeDynamicInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getBootstrapIndex() {
- try {
- return (Integer) bootstrapIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setBootstrapIndex(int val) {
- try {
- bootstrapIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public int getNameAndTypeIndex() {
- try {
- return (Integer) nameAndTypeIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setNameAndTypeIndex(int val) {
- try {
- nameAndTypeIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java
deleted file mode 100644
index 058bb45..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java
+++ /dev/null
@@ -1,75 +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.accessors;
-
-import java.lang.reflect.Field;
-
-public class MemberRefInfoAccessor {
-
- private static Class> clazz;
- private static Field classIndex;
- private static Field nameAndTypeIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.MemberrefInfo");
- classIndex = clazz.getDeclaredField("classIndex");
- classIndex.setAccessible(true);
- nameAndTypeIndex = clazz.getDeclaredField("nameAndTypeIndex");
- nameAndTypeIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public MemberRefInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getClassIndex() {
- try {
- return (Integer) classIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setClassIndex(int val) {
- try {
- classIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public int getNameAndTypeIndex() {
- try {
- return (Integer) nameAndTypeIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setNameAndTypeIndex(int val) {
- try {
- nameAndTypeIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java
deleted file mode 100644
index 985e792..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java
+++ /dev/null
@@ -1,75 +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.accessors;
-
-import java.lang.reflect.Field;
-
-public class MethodHandleInfoAccessor {
-
- private static Class> clazz;
- private static Field kindIndex;
- private static Field indexIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.MethodHandleInfo");
- kindIndex = clazz.getDeclaredField("refKind");
- kindIndex.setAccessible(true);
- indexIndex = clazz.getDeclaredField("refIndex");
- indexIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public MethodHandleInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getTypeIndex() {
- try {
- return (Integer) kindIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setTypeIndex(int val) {
- try {
- kindIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public int getMethodRefIndex() {
- try {
- return (Integer) indexIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setMethodRefIndex(int val) {
- try {
- indexIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java
deleted file mode 100644
index 10b0cb0..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java
+++ /dev/null
@@ -1,57 +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.accessors;
-
-import java.lang.reflect.Field;
-
-public class MethodTypeInfoAccessor {
-
- private static Class> clazz;
- private static Field descriptorIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.MethodTypeInfo");
- descriptorIndex = clazz.getDeclaredField("descriptor");
- descriptorIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public MethodTypeInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getTypeIndex() {
- try {
- return (Integer) descriptorIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setTypeIndex(int val) {
- try {
- descriptorIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java
deleted file mode 100644
index cc7fdbe..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java
+++ /dev/null
@@ -1,75 +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.accessors;
-
-import java.lang.reflect.Field;
-
-public class NameAndTypeInfoAccessor {
-
- private static Class> clazz;
- private static Field nameIndex;
- private static Field typeIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.NameAndTypeInfo");
- nameIndex = clazz.getDeclaredField("memberName");
- nameIndex.setAccessible(true);
- typeIndex = clazz.getDeclaredField("typeDescriptor");
- typeIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public NameAndTypeInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getNameIndex() {
- try {
- return (Integer) nameIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setNameIndex(int val) {
- try {
- nameIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public int getTypeIndex() {
- try {
- return (Integer) typeIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setTypeIndex(int val) {
- try {
- typeIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java
deleted file mode 100644
index 5c68d4a..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java
+++ /dev/null
@@ -1,56 +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.accessors;
-
-import java.lang.reflect.Field;
-
-public class StringInfoAccessor {
-
- private static Class> clazz;
- private static Field stringIndex;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.StringInfo");
- stringIndex = clazz.getDeclaredField("string");
- stringIndex.setAccessible(true);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- private Object item;
-
- public StringInfoAccessor(Object item) {
- this.item = item;
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-
- public int getStringIndex() {
- try {
- return (Integer) stringIndex.get(this.item);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public void setStringIndex(int val) {
- try {
- stringIndex.set(this.item, val);
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java
deleted file mode 100644
index cc3b41b..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java
+++ /dev/null
@@ -1,29 +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.accessors;
-
-public class Utf8InfoAccessor {
-
- private static Class> clazz;
-
- static {
- try {
- clazz = Class.forName("javassist.bytecode.Utf8Info");
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- public static boolean isType(ConstInfoAccessor accessor) {
- return clazz.isAssignableFrom(accessor.getItem().getClass());
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/ClassTranslator.java b/src/main/java/cuchaz/enigma/bytecode/translators/ClassTranslator.java
deleted file mode 100644
index 4ac5a8b..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/translators/ClassTranslator.java
+++ /dev/null
@@ -1,161 +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.translators;
-
-import cuchaz.enigma.bytecode.ClassRenamer;
-import cuchaz.enigma.bytecode.ConstPoolEditor;
-import cuchaz.enigma.mapping.*;
-import javassist.CtBehavior;
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.CtMethod;
-import javassist.bytecode.*;
-
-public class ClassTranslator {
-
- public static void translate(Translator translator, CtClass c) {
-
- // NOTE: the order of these translations is very important
-
- // translate all the field and method references in the code by editing the constant pool
- ConstPool constants = c.getClassFile().getConstPool();
- ConstPoolEditor editor = new ConstPoolEditor(constants);
- for (int i = 1; i < constants.getSize(); i++) {
- switch (constants.getTag(i)) {
-
- case ConstPool.CONST_Fieldref: {
-
- // translate the name and type
- FieldEntry entry = EntryFactory.getFieldEntry(
- Descriptor.toJvmName(constants.getFieldrefClassName(i)),
- constants.getFieldrefName(i),
- constants.getFieldrefType(i)
- );
- FieldEntry translatedEntry = translator.translateEntry(entry);
- if (!entry.equals(translatedEntry)) {
- editor.changeMemberrefNameAndType(i, translatedEntry.getName(), translatedEntry.getType().toString());
- }
- }
- break;
-
- case ConstPool.CONST_Methodref:
- case ConstPool.CONST_InterfaceMethodref: {
-
- // translate the name and type (ie signature)
- BehaviorEntry entry = EntryFactory.getBehaviorEntry(
- Descriptor.toJvmName(editor.getMemberrefClassname(i)),
- editor.getMemberrefName(i),
- editor.getMemberrefType(i)
- );
- BehaviorEntry translatedEntry = translator.translateEntry(entry);
- if (!entry.equals(translatedEntry)) {
- editor.changeMemberrefNameAndType(i, translatedEntry.getName(), translatedEntry.getSignature().toString());
- }
- }
- break;
- default:
- break;
- }
- }
-
- ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName()));
- Mappings.EntryModifier modifier = translator.getModifier(classEntry);
- if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED)
- ClassRenamer.applyModifier(c, modifier);
-
- // translate all the fields
- for (CtField field : c.getDeclaredFields()) {
-
- // translate the name
- FieldEntry entry = EntryFactory.getFieldEntry(field);
- String translatedName = translator.translate(entry);
- modifier = translator.getModifier(entry);
- if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED)
- ClassRenamer.applyModifier(field, modifier);
-
- if (translatedName != null) {
- field.setName(translatedName);
- }
-
- // translate the type
- Type translatedType = translator.translateType(entry.getType());
- field.getFieldInfo().setDescriptor(translatedType.toString());
- }
-
- // translate all the methods and constructors
- for (CtBehavior behavior : c.getDeclaredBehaviors()) {
-
- BehaviorEntry entry = EntryFactory.getBehaviorEntry(behavior);
-
- modifier = translator.getModifier(entry);
- if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED)
- ClassRenamer.applyModifier(behavior, modifier);
-
- if (behavior instanceof CtMethod) {
- CtMethod method = (CtMethod) behavior;
-
- // translate the name
- String translatedName = translator.translate(entry);
- if (translatedName != null) {
- method.setName(translatedName);
- }
- }
-
- if (entry.getSignature() != null) {
- // translate the signature
- Signature translatedSignature = translator.translateSignature(entry.getSignature());
- behavior.getMethodInfo().setDescriptor(translatedSignature.toString());
- }
- }
-
- // translate the EnclosingMethod attribute
- EnclosingMethodAttribute enclosingMethodAttr = (EnclosingMethodAttribute) c.getClassFile().getAttribute(EnclosingMethodAttribute.tag);
- if (enclosingMethodAttr != null) {
-
- if (enclosingMethodAttr.methodIndex() == 0) {
- BehaviorEntry obfBehaviorEntry = EntryFactory.getBehaviorEntry(Descriptor.toJvmName(enclosingMethodAttr.className()));
- BehaviorEntry deobfBehaviorEntry = translator.translateEntry(obfBehaviorEntry);
- c.getClassFile().addAttribute(new EnclosingMethodAttribute(
- constants,
- deobfBehaviorEntry.getClassName()
- ));
- } else {
- BehaviorEntry obfBehaviorEntry = EntryFactory.getBehaviorEntry(
- Descriptor.toJvmName(enclosingMethodAttr.className()),
- enclosingMethodAttr.methodName(),
- enclosingMethodAttr.methodDescriptor()
- );
- BehaviorEntry deobfBehaviorEntry = translator.translateEntry(obfBehaviorEntry);
- c.getClassFile().addAttribute(new EnclosingMethodAttribute(
- constants,
- deobfBehaviorEntry.getClassName(),
- deobfBehaviorEntry.getName(),
- deobfBehaviorEntry.getSignature().toString()
- ));
- }
- }
-
- // translate all the class names referenced in the code
- // the above code only changed method/field/reference names and types, but not the rest of the class references
- ClassRenamer.renameClasses(c, translator);
-
- // translate the source file attribute too
- ClassEntry deobfClassEntry = translator.translateEntry(classEntry);
- if (deobfClassEntry != null) {
- String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassEntry().getSimpleName()) + ".java";
- c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile));
- }
- InnerClassesAttribute attr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag);
- if (attr != null)
- InnerClassWriter.changeModifier(c, attr, translator);
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/InnerClassWriter.java b/src/main/java/cuchaz/enigma/bytecode/translators/InnerClassWriter.java
deleted file mode 100644
index 0e35938..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/translators/InnerClassWriter.java
+++ /dev/null
@@ -1,144 +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.translators;
-
-import com.google.common.collect.Lists;
-import cuchaz.enigma.analysis.JarIndex;
-import cuchaz.enigma.bytecode.ClassRenamer;
-import cuchaz.enigma.mapping.*;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.NotFoundException;
-import javassist.bytecode.*;
-
-import java.util.Collection;
-import java.util.List;
-
-public class InnerClassWriter {
-
- // FIXME: modifier is not applied to inner class
- public static void changeModifier(CtClass c, InnerClassesAttribute attr, Translator translator) {
- ClassPool pool = c.getClassPool();
- for (int i = 0; i < attr.tableLength(); i++) {
-
- String innerName = attr.innerClass(i);
- // get the inner class full name (which has already been translated)
- ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(innerName));
- try {
- CtClass innerClass = pool.get(innerName);
- Mappings.EntryModifier modifier = translator.getModifier(classEntry);
- if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED)
- ClassRenamer.applyModifier(innerClass, modifier);
- } catch (NotFoundException e) {
- // This shouldn't be possible in theory
- //e.printStackTrace();
- }
- }
- }
-
- public static void write(JarIndex index, CtClass c) {
-
- // don't change anything if there's already an attribute there
- InnerClassesAttribute oldAttr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag);
- if (oldAttr != null) {
- // bail!
- return;
- }
-
- ClassEntry obfClassEntry = EntryFactory.getClassEntry(c);
- List
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.bytecode.translators;
-
-import cuchaz.enigma.mapping.*;
-import javassist.CtBehavior;
-import javassist.CtClass;
-import javassist.bytecode.*;
-
-public class LocalVariableTranslator {
-
- public static void translate(Translator translator, CtClass c) {
- for (CtBehavior behavior : c.getDeclaredBehaviors()) {
-
- // if there's a local variable table, just rename everything to v1, v2, v3, ... for now
- CodeAttribute codeAttribute = behavior.getMethodInfo().getCodeAttribute();
- if (codeAttribute == null) {
- continue;
- }
-
- BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior);
- ConstPool constants = c.getClassFile().getConstPool();
-
- LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
- if (table != null) {
- renameLVT(translator, behaviorEntry, constants, table, c);
- }
-
- LocalVariableTypeAttribute typeTable = (LocalVariableTypeAttribute) codeAttribute.getAttribute(LocalVariableAttribute.typeTag);
- if (typeTable != null) {
- renameLVTT(typeTable, table);
- }
- }
- }
-
- // DEBUG
- @SuppressWarnings("unused")
- private static void dumpTable(LocalVariableAttribute table) {
- for (int i = 0; i < table.tableLength(); i++) {
- System.out.println(String.format("\t%d (%d): %s %s",
- i, table.index(i), table.variableName(i), table.descriptor(i)
- ));
- }
- }
-
- private static void renameLVT(Translator translator, BehaviorEntry behaviorEntry, ConstPool constants, LocalVariableAttribute table, CtClass ctClass) {
-
- // skip empty tables
- if (table.tableLength() <= 0) {
- return;
- }
-
- // where do we start counting variables?
- int starti = 0;
- if (table.variableName(0).equals("this")) {
- // skip the "this" variable
- starti++;
- }
-
- // rename method arguments first
- int numArgs = 0;
- if (behaviorEntry.getSignature() != null) {
- numArgs = behaviorEntry.getSignature().getArgumentTypes().size();
- boolean isNestedClassConstructor = false;
-
- // If the behavior is a constructor and if it have more than one arg, it's probably from a nested!
- if (behaviorEntry instanceof ConstructorEntry && behaviorEntry.getClassEntry() != null && behaviorEntry.getClassEntry().isInnerClass() && numArgs >= 1) {
- // Get the first arg type
- Type firstArg = behaviorEntry.getSignature().getArgumentTypes().get(0);
-
- // If the arg is a class and if the class name match the outer class name of the constructor, it's definitely a constructor of a nested class
- if (firstArg.isClass() && firstArg.getClassEntry().equals(behaviorEntry.getClassEntry().getOuterClassEntry())) {
- isNestedClassConstructor = true;
- numArgs--;
- }
- }
-
- for (int i = starti; i < starti + numArgs && i < table.tableLength(); i++) {
- int argi = i - starti;
- if (ctClass.isEnum())
- argi += 2;
- String argName = translator.translate(new ArgumentEntry(behaviorEntry, argi, ""));
- if (argName == null) {
- int argIndex = isNestedClassConstructor ? argi + 1 : argi;
- if (ctClass.isEnum())
- argIndex -= 2;
- Type argType = behaviorEntry.getSignature().getArgumentTypes().get(argIndex);
- // Unfortunately each of these have different name getters, so they have different code paths
- if (argType.isPrimitive()) {
- Type.Primitive argCls = argType.getPrimitive();
- argName = "a" + argCls.name() + (argIndex + 1);
- } else if (argType.isArray()) {
- // List types would require this whole block again, so just go with aListx
- argName = "aList" + (argIndex + 1);
- } else if (argType.isClass()) {
- ClassEntry argClsTrans = translator.translateEntry(argType.getClassEntry());
- argName = "a" + argClsTrans.getSimpleName().replace("$", "") + (argIndex + 1);
- } else {
- argName = "a" + (argIndex + 1);
- }
- }
- renameVariable(table, i, constants.addUtf8Info(argName));
- }
- }
-
- // then rename the rest of the args, if any
- for (int i = starti + numArgs; i < table.tableLength(); i++) {
- int firstIndex = Math.min(table.index(starti + numArgs), table.index(i));
- renameVariable(table, i, constants.addUtf8Info("v" + (table.index(i) - firstIndex + 1)));
- }
- }
-
- private static void renameLVTT(LocalVariableTypeAttribute typeTable, LocalVariableAttribute table) {
- // rename args to the same names as in the LVT
- for (int i = 0; i < typeTable.tableLength(); i++) {
- renameVariable(typeTable, i, getNameIndex(table, typeTable.index(i)));
- }
- }
-
- private static void renameVariable(LocalVariableAttribute table, int i, int stringId) {
- // based off of LocalVariableAttribute.nameIndex()
- ByteArray.write16bit(stringId, table.get(), i * 10 + 6);
- }
-
- private static int getNameIndex(LocalVariableAttribute table, int index) {
- for (int i = 0; i < table.tableLength(); i++) {
- if (table.index(i) == index) {
- return table.nameIndex(i);
- }
- }
- return 0;
- }
-}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/MethodParameterTranslator.java b/src/main/java/cuchaz/enigma/bytecode/translators/MethodParameterTranslator.java
deleted file mode 100644
index 4e632b9..0000000
--- a/src/main/java/cuchaz/enigma/bytecode/translators/MethodParameterTranslator.java
+++ /dev/null
@@ -1,62 +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.translators;
-
-import cuchaz.enigma.bytecode.MethodParametersAttribute;
-import cuchaz.enigma.mapping.*;
-import javassist.CtBehavior;
-import javassist.CtClass;
-import javassist.bytecode.CodeAttribute;
-import javassist.bytecode.LocalVariableAttribute;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MethodParameterTranslator {
-
- public static void translate(Translator translator, CtClass c) {
-
- // Procyon will read method arguments from the "MethodParameters" attribute, so write those
- for (CtBehavior behavior : c.getDeclaredBehaviors()) {
-
- // if there's a local variable table here, don't write a MethodParameters attribute
- // let the local variable writer deal with it instead
- // procyon starts doing really weird things if we give it both attributes
- CodeAttribute codeAttribute = behavior.getMethodInfo().getCodeAttribute();
- if (codeAttribute != null && codeAttribute.getAttribute(LocalVariableAttribute.tag) != null) {
- continue;
- }
-
- BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior);
-
- // get the number of arguments
- Signature signature = behaviorEntry.getSignature();
- if (signature == null) {
- // static initializers have no signatures, or arguments
- continue;
- }
- int numParams = signature.getArgumentTypes().size();
- if (numParams <= 0) {
- continue;
- }
-
- // get the list of argument names
- List
+ * Contributors:
+ * Jeff Martin - initial API and implementation
+ ******************************************************************************/
+
+package cuchaz.enigma.bytecode.translators;
+
+import cuchaz.enigma.analysis.JarIndex;
+import cuchaz.enigma.bytecode.AccessFlags;
+import cuchaz.enigma.mapping.*;
+import org.objectweb.asm.*;
+
+import java.util.regex.Pattern;
+
+public class TranslationClassVisitor extends ClassVisitor {
+ private static final Pattern OBJECT_PATTERN = Pattern.compile(".*:Ljava/lang/Object;:.*");
+
+ private final Translator translator;
+ private final JarIndex jarIndex;
+ private final ReferencedEntryPool entryPool;
+
+ private ClassDefEntry obfClassEntry;
+
+ public TranslationClassVisitor(Translator translator, JarIndex jarIndex, ReferencedEntryPool entryPool, int api, ClassVisitor cv) {
+ super(api, cv);
+ this.translator = translator;
+ this.jarIndex = jarIndex;
+ this.entryPool = entryPool;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ if (signature != null && OBJECT_PATTERN.matcher(signature).matches()) {
+ signature = signature.replaceAll(":Ljava/lang/Object;:", "::");
+ }
+ obfClassEntry = new ClassDefEntry(name, new AccessFlags(access));
+ ClassDefEntry entry = translator.getTranslatedClassDef(obfClassEntry);
+ ClassEntry superEntry = translator.getTranslatedClass(entryPool.getClass(superName));
+ String[] translatedInterfaces = new String[interfaces.length];
+ for (int i = 0; i < interfaces.length; i++) {
+ translatedInterfaces[i] = translator.getTranslatedClass(entryPool.getClass(interfaces[i])).getName();
+ }
+ super.visit(version, entry.getAccess().getFlags(), entry.getName(), signature, superEntry.getName(), translatedInterfaces);
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+ FieldDefEntry entry = new FieldDefEntry(obfClassEntry, name, new TypeDescriptor(desc), new AccessFlags(access));
+ FieldDefEntry translatedEntry = translator.getTranslatedFieldDef(entry);
+ return super.visitField(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), signature, value);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ MethodDefEntry entry = new MethodDefEntry(obfClassEntry, name, new MethodDescriptor(desc), new AccessFlags(access));
+ MethodDefEntry translatedEntry = translator.getTranslatedMethodDef(entry);
+ if (jarIndex.getBridgedMethod(entry) != null) {
+ translatedEntry.getAccess().setBridged();
+ }
+ MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), name, desc, signature, exceptions);
+ return new TranslationMethodVisitor(translator, translatedEntry, api, mv);
+ }
+
+ @Override
+ public void visitOuterClass(String owner, String name, String desc) {
+ if (name != null) {
+ ClassEntry ownerEntry = translator.getTranslatedClass(entryPool.getClass(owner));
+ ClassEntry entry = translator.getTranslatedClass(entryPool.getClass(name));
+ String translatedDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc)).toString();
+ super.visitOuterClass(ownerEntry.getName(), entry.getName(), translatedDesc);
+ } else {
+ super.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // TODO: Implement
+ return super.visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
+ // TODO: Implement
+ return super.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ // If this is not an anonymous class
+ if (innerName != null && outerName != null) {
+ ClassDefEntry translatedEntry = translator.getTranslatedClassDef(new ClassDefEntry(innerName, new AccessFlags(access)));
+ ClassEntry outerEntry = translator.getTranslatedClass(entryPool.getClass(outerName));
+ ClassEntry innerEntry = translator.getTranslatedClass(entryPool.getClass(innerName));
+ super.visitInnerClass(translatedEntry.getName(), outerEntry.getName(), innerEntry.getName(), translatedEntry.getAccess().getFlags());
+ } else {
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
new file mode 100644
index 0000000..e40becc
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -0,0 +1,82 @@
+package cuchaz.enigma.bytecode.translators;
+
+import cuchaz.enigma.mapping.*;
+import org.objectweb.asm.*;
+
+import java.util.Locale;
+
+public class TranslationMethodVisitor extends MethodVisitor {
+ private final MethodDefEntry methodEntry;
+ private final Translator translator;
+
+ public TranslationMethodVisitor(Translator translator, MethodDefEntry methodEntry, int api, MethodVisitor mv) {
+ super(api, mv);
+ this.translator = translator;
+ this.methodEntry = methodEntry;
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ FieldEntry entry = new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc));
+ FieldEntry translatedEntry = translator.getTranslatedField(entry);
+ if (translatedEntry != null) {
+ super.visitFieldInsn(opcode, translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString());
+ } else {
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+ MethodEntry entry = new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc));
+ MethodEntry translatedEntry = translator.getTranslatedMethod(entry);
+ if (translatedEntry != null) {
+ super.visitMethodInsn(opcode, translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString(), itf);
+ } else {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ }
+
+ @Override
+ public void visitAttribute(Attribute attr) {
+ // TODO: Implement
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // TODO: Implement
+ return super.visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
+ LocalVariableDefEntry entry = new LocalVariableDefEntry(methodEntry, index, name, new TypeDescriptor(desc));
+ LocalVariableDefEntry translatedEntry = translator.getTranslatedVariableDef(entry);
+ String translatedName = translatedEntry.getName();
+ // TODO: Better name inference
+ if (translatedName.equals(entry.getName())) {
+ TypeDescriptor argDesc = translatedEntry.getDesc();
+ int nameIndex = translatedEntry.getNamedIndex() + 1;
+ String prefix = translatedEntry.getNamedIndex() < methodEntry.getDesc().getArgumentDescs().size() ? "a" : "v";
+ StringBuilder nameBuilder = new StringBuilder(prefix);
+ // Unfortunately each of these have different name getters, so they have different code paths
+ if (argDesc.isPrimitive()) {
+ TypeDescriptor.Primitive argCls = argDesc.getPrimitive();
+ nameBuilder.append(argCls.name());
+ } else if (argDesc.isArray()) {
+ // List types would require this whole block again, so just go with aListx
+ nameBuilder.append(nameIndex);
+ } else if (argDesc.isType()) {
+ String typeName = argDesc.getOwnerEntry().getSimpleName().replace("$", "");
+ typeName = typeName.substring(0, 1).toUpperCase(Locale.ROOT) + typeName.substring(1);
+ nameBuilder.append(typeName);
+ }
+ if (methodEntry.getDesc().getArgumentDescs().size() > 1) {
+ nameBuilder.append(nameIndex);
+ }
+ translatedName = nameBuilder.toString();
+ }
+ super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), signature, start, end, index);
+ }
+}
--
cgit v1.2.3
From 406b9a89318473571d27de60b8aa1b51f84af245 Mon Sep 17 00:00:00 2001
From: gegy1000
Date: Sat, 19 May 2018 17:06:26 +0200
Subject: Package updates
---
.../java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java | 1 +
.../cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java | 1 +
2 files changed, 2 insertions(+)
(limited to 'src/main/java/cuchaz/enigma/bytecode')
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
index 24bfe24..3f61c29 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
@@ -14,6 +14,7 @@ package cuchaz.enigma.bytecode.translators;
import cuchaz.enigma.analysis.JarIndex;
import cuchaz.enigma.bytecode.AccessFlags;
import cuchaz.enigma.mapping.*;
+import cuchaz.enigma.mapping.entry.*;
import org.objectweb.asm.*;
import java.util.regex.Pattern;
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
index e40becc..b2192e4 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -1,6 +1,7 @@
package cuchaz.enigma.bytecode.translators;
import cuchaz.enigma.mapping.*;
+import cuchaz.enigma.mapping.entry.*;
import org.objectweb.asm.*;
import java.util.Locale;
--
cgit v1.2.3
From 8e7453727ff059c8f1db7f89f6793d22cbd5e6fc Mon Sep 17 00:00:00 2001
From: gegy1000
Date: Sat, 19 May 2018 18:02:29 +0200
Subject: Annotation + inner class translation
---
.../java/cuchaz/enigma/bytecode/AccessFlags.java | 3 ++
.../translators/TranslationAnnotationVisitor.java | 45 ++++++++++++++++++++++
.../translators/TranslationClassVisitor.java | 31 ++++++++++-----
.../translators/TranslationFieldVisitor.java | 33 ++++++++++++++++
.../translators/TranslationMethodVisitor.java | 16 ++++----
5 files changed, 111 insertions(+), 17 deletions(-)
create mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java
create mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java
(limited to 'src/main/java/cuchaz/enigma/bytecode')
diff --git a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
index 0999abf..152f462 100644
--- a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
+++ b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
@@ -5,6 +5,9 @@ import org.objectweb.asm.Opcodes;
import java.lang.reflect.Modifier;
public class AccessFlags {
+ public static final AccessFlags PUBLIC = new AccessFlags(Modifier.PUBLIC);
+ public static final AccessFlags PUBLIC_STATIC_FINAL = new AccessFlags(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
+
private static final int SYNTHETIC_FLAG = 0x00001000;
private static final int BRIDGED_FLAG = 0x00000040;
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java
new file mode 100644
index 0000000..177691b
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java
@@ -0,0 +1,45 @@
+package cuchaz.enigma.bytecode.translators;
+
+import cuchaz.enigma.bytecode.AccessFlags;
+import cuchaz.enigma.mapping.Translator;
+import cuchaz.enigma.mapping.TypeDescriptor;
+import cuchaz.enigma.mapping.entry.ClassEntry;
+import cuchaz.enigma.mapping.entry.FieldDefEntry;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+
+public class TranslationAnnotationVisitor extends AnnotationVisitor {
+ private final Translator translator;
+ private final ClassEntry annotationEntry;
+
+ public TranslationAnnotationVisitor(Translator translator, ClassEntry annotationEntry, int api, AnnotationVisitor av) {
+ super(api, av);
+ this.translator = translator;
+ this.annotationEntry = annotationEntry;
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ if (value instanceof Type) {
+ Type type = (Type) value;
+ super.visit(name, translator.getTranslatedType(type));
+ } else {
+ super.visit(name, value);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ TypeDescriptor type = new TypeDescriptor(desc);
+ FieldDefEntry annotationField = translator.getTranslatedFieldDef(new FieldDefEntry(annotationEntry, name, type, AccessFlags.PUBLIC));
+ return super.visitAnnotation(annotationField.getName(), annotationField.getDesc().toString());
+ }
+
+ @Override
+ public void visitEnum(String name, String desc, String value) {
+ TypeDescriptor type = new TypeDescriptor(desc);
+ FieldDefEntry annotationField = translator.getTranslatedFieldDef(new FieldDefEntry(annotationEntry, name, type, AccessFlags.PUBLIC));
+ FieldDefEntry enumField = translator.getTranslatedFieldDef(new FieldDefEntry(type.getTypeEntry(), value, type, AccessFlags.PUBLIC_STATIC_FINAL));
+ super.visitEnum(annotationField.getName(), annotationField.getDesc().toString(), enumField.getName());
+ }
+}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
index 3f61c29..5fdfaf1 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
@@ -54,7 +54,8 @@ public class TranslationClassVisitor extends ClassVisitor {
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
FieldDefEntry entry = new FieldDefEntry(obfClassEntry, name, new TypeDescriptor(desc), new AccessFlags(access));
FieldDefEntry translatedEntry = translator.getTranslatedFieldDef(entry);
- return super.visitField(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), signature, value);
+ FieldVisitor fv = super.visitField(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), signature, value);
+ return new TranslationFieldVisitor(translator, translatedEntry, api, fv);
}
@Override
@@ -64,32 +65,38 @@ public class TranslationClassVisitor extends ClassVisitor {
if (jarIndex.getBridgedMethod(entry) != null) {
translatedEntry.getAccess().setBridged();
}
- MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), name, desc, signature, exceptions);
+ String[] translatedExceptions = new String[exceptions.length];
+ for (int i = 0; i < exceptions.length; i++) {
+ translatedExceptions[i] = translator.getTranslatedClass(entryPool.getClass(exceptions[i])).getName();
+ }
+ MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), signature, translatedExceptions);
return new TranslationMethodVisitor(translator, translatedEntry, api, mv);
}
@Override
public void visitOuterClass(String owner, String name, String desc) {
+ ClassEntry ownerEntry = translator.getTranslatedClass(entryPool.getClass(owner));
+ String translatedDesc = desc != null ? translator.getTranslatedTypeDesc(new TypeDescriptor(desc)).toString() : desc;
if (name != null) {
- ClassEntry ownerEntry = translator.getTranslatedClass(entryPool.getClass(owner));
ClassEntry entry = translator.getTranslatedClass(entryPool.getClass(name));
- String translatedDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc)).toString();
super.visitOuterClass(ownerEntry.getName(), entry.getName(), translatedDesc);
} else {
- super.visitOuterClass(owner, name, desc);
+ super.visitOuterClass(ownerEntry.getName(), name, translatedDesc);
}
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // TODO: Implement
- return super.visitAnnotation(desc, visible);
+ TypeDescriptor translatedDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitAnnotation(translatedDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, translatedDesc.getTypeEntry(), api, av);
}
@Override
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
- // TODO: Implement
- return super.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ TypeDescriptor translatedDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, translatedDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, translatedDesc.getTypeEntry(), api, av);
}
@Override
@@ -101,7 +108,11 @@ public class TranslationClassVisitor extends ClassVisitor {
ClassEntry innerEntry = translator.getTranslatedClass(entryPool.getClass(innerName));
super.visitInnerClass(translatedEntry.getName(), outerEntry.getName(), innerEntry.getName(), translatedEntry.getAccess().getFlags());
} else {
- super.visitInnerClass(name, outerName, innerName, access);
+ int separatorIndex = name.lastIndexOf("$");
+ String parentName = name.substring(0, separatorIndex);
+ String childName = name.substring(separatorIndex + 1);
+ ClassEntry outerEntry = translator.getTranslatedClass(entryPool.getClass(parentName));
+ super.visitInnerClass(outerEntry.getName() + "$" + childName, outerName, innerName, access);
}
}
}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java
new file mode 100644
index 0000000..e4695fb
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java
@@ -0,0 +1,33 @@
+package cuchaz.enigma.bytecode.translators;
+
+import cuchaz.enigma.mapping.Translator;
+import cuchaz.enigma.mapping.TypeDescriptor;
+import cuchaz.enigma.mapping.entry.FieldDefEntry;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.TypePath;
+
+public class TranslationFieldVisitor extends FieldVisitor {
+ private final FieldDefEntry fieldEntry;
+ private final Translator translator;
+
+ public TranslationFieldVisitor(Translator translator, FieldDefEntry fieldEntry, int api, FieldVisitor fv) {
+ super(api, fv);
+ this.translator = translator;
+ this.fieldEntry = fieldEntry;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ TypeDescriptor typeDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
+ TypeDescriptor typeDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av);
+ }
+}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
index b2192e4..c729962 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -39,15 +39,17 @@ public class TranslationMethodVisitor extends MethodVisitor {
}
@Override
- public void visitAttribute(Attribute attr) {
- // TODO: Implement
- super.visitAttribute(attr);
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ TypeDescriptor typeDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av);
}
@Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // TODO: Implement
- return super.visitAnnotation(desc, visible);
+ public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
+ TypeDescriptor typeDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av);
}
@Override
@@ -69,7 +71,7 @@ public class TranslationMethodVisitor extends MethodVisitor {
// List types would require this whole block again, so just go with aListx
nameBuilder.append(nameIndex);
} else if (argDesc.isType()) {
- String typeName = argDesc.getOwnerEntry().getSimpleName().replace("$", "");
+ String typeName = argDesc.getTypeEntry().getSimpleName().replace("$", "");
typeName = typeName.substring(0, 1).toUpperCase(Locale.ROOT) + typeName.substring(1);
nameBuilder.append(typeName);
}
--
cgit v1.2.3
From 93c771a890f0f73b8caebafa4667e0535703cfa2 Mon Sep 17 00:00:00 2001
From: gegy1000
Date: Sat, 19 May 2018 19:00:56 +0200
Subject: Fix inner class mapping
---
.../translators/TranslationClassVisitor.java | 25 ++++++++++------------
1 file changed, 11 insertions(+), 14 deletions(-)
(limited to 'src/main/java/cuchaz/enigma/bytecode')
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
index 5fdfaf1..dcc221e 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
@@ -13,7 +13,9 @@ package cuchaz.enigma.bytecode.translators;
import cuchaz.enigma.analysis.JarIndex;
import cuchaz.enigma.bytecode.AccessFlags;
-import cuchaz.enigma.mapping.*;
+import cuchaz.enigma.mapping.MethodDescriptor;
+import cuchaz.enigma.mapping.Translator;
+import cuchaz.enigma.mapping.TypeDescriptor;
import cuchaz.enigma.mapping.entry.*;
import org.objectweb.asm.*;
@@ -101,18 +103,13 @@ public class TranslationClassVisitor extends ClassVisitor {
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
- // If this is not an anonymous class
- if (innerName != null && outerName != null) {
- ClassDefEntry translatedEntry = translator.getTranslatedClassDef(new ClassDefEntry(innerName, new AccessFlags(access)));
- ClassEntry outerEntry = translator.getTranslatedClass(entryPool.getClass(outerName));
- ClassEntry innerEntry = translator.getTranslatedClass(entryPool.getClass(innerName));
- super.visitInnerClass(translatedEntry.getName(), outerEntry.getName(), innerEntry.getName(), translatedEntry.getAccess().getFlags());
- } else {
- int separatorIndex = name.lastIndexOf("$");
- String parentName = name.substring(0, separatorIndex);
- String childName = name.substring(separatorIndex + 1);
- ClassEntry outerEntry = translator.getTranslatedClass(entryPool.getClass(parentName));
- super.visitInnerClass(outerEntry.getName() + "$" + childName, outerName, innerName, access);
- }
+ ClassDefEntry translatedEntry = translator.getTranslatedClassDef(new ClassDefEntry(name, new AccessFlags(access)));
+ String translatedName = translatedEntry.getName();
+ int separatorIndex = translatedName.lastIndexOf("$");
+ String parentName = translatedName.substring(0, separatorIndex);
+ String childName = translatedName.substring(separatorIndex + 1);
+
+ ClassEntry outerEntry = translator.getTranslatedClass(entryPool.getClass(parentName));
+ super.visitInnerClass(translatedName, outerEntry.getName(), childName, translatedEntry.getAccess().getFlags());
}
}
--
cgit v1.2.3
From 227ccb35a48529724ecf28c94a9156af2f699481 Mon Sep 17 00:00:00 2001
From: gegy1000
Date: Sat, 19 May 2018 20:00:12 +0200
Subject: More bytecode translation
---
.../translators/TranslationAnnotationVisitor.java | 13 +--
.../translators/TranslationClassVisitor.java | 26 ++---
.../translators/TranslationMethodVisitor.java | 81 ++++++++++++--
.../translators/TranslationSignatureVisitor.java | 122 +++++++++++++++++++++
4 files changed, 208 insertions(+), 34 deletions(-)
create mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java
(limited to 'src/main/java/cuchaz/enigma/bytecode')
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java
index 177691b..7cc3771 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java
@@ -6,7 +6,6 @@ import cuchaz.enigma.mapping.TypeDescriptor;
import cuchaz.enigma.mapping.entry.ClassEntry;
import cuchaz.enigma.mapping.entry.FieldDefEntry;
import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Type;
public class TranslationAnnotationVisitor extends AnnotationVisitor {
private final Translator translator;
@@ -20,12 +19,12 @@ public class TranslationAnnotationVisitor extends AnnotationVisitor {
@Override
public void visit(String name, Object value) {
- if (value instanceof Type) {
- Type type = (Type) value;
- super.visit(name, translator.getTranslatedType(type));
- } else {
- super.visit(name, value);
- }
+ super.visit(name, translator.getTranslatedValue(value));
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ return this;
}
@Override
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
index dcc221e..89772db 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
@@ -19,11 +19,7 @@ import cuchaz.enigma.mapping.TypeDescriptor;
import cuchaz.enigma.mapping.entry.*;
import org.objectweb.asm.*;
-import java.util.regex.Pattern;
-
public class TranslationClassVisitor extends ClassVisitor {
- private static final Pattern OBJECT_PATTERN = Pattern.compile(".*:Ljava/lang/Object;:.*");
-
private final Translator translator;
private final JarIndex jarIndex;
private final ReferencedEntryPool entryPool;
@@ -39,9 +35,6 @@ public class TranslationClassVisitor extends ClassVisitor {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- if (signature != null && OBJECT_PATTERN.matcher(signature).matches()) {
- signature = signature.replaceAll(":Ljava/lang/Object;:", "::");
- }
obfClassEntry = new ClassDefEntry(name, new AccessFlags(access));
ClassDefEntry entry = translator.getTranslatedClassDef(obfClassEntry);
ClassEntry superEntry = translator.getTranslatedClass(entryPool.getClass(superName));
@@ -49,14 +42,16 @@ public class TranslationClassVisitor extends ClassVisitor {
for (int i = 0; i < interfaces.length; i++) {
translatedInterfaces[i] = translator.getTranslatedClass(entryPool.getClass(interfaces[i])).getName();
}
- super.visit(version, entry.getAccess().getFlags(), entry.getName(), signature, superEntry.getName(), translatedInterfaces);
+ String translatedSignature = translator.getTranslatedSignature(signature, false, api);
+ super.visit(version, entry.getAccess().getFlags(), entry.getName(), translatedSignature, superEntry.getName(), translatedInterfaces);
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
FieldDefEntry entry = new FieldDefEntry(obfClassEntry, name, new TypeDescriptor(desc), new AccessFlags(access));
FieldDefEntry translatedEntry = translator.getTranslatedFieldDef(entry);
- FieldVisitor fv = super.visitField(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), signature, value);
+ String translatedSignature = translator.getTranslatedSignature(signature, true, api);
+ FieldVisitor fv = super.visitField(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), translatedSignature, value);
return new TranslationFieldVisitor(translator, translatedEntry, api, fv);
}
@@ -71,19 +66,18 @@ public class TranslationClassVisitor extends ClassVisitor {
for (int i = 0; i < exceptions.length; i++) {
translatedExceptions[i] = translator.getTranslatedClass(entryPool.getClass(exceptions[i])).getName();
}
- MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), signature, translatedExceptions);
+ String translatedSignature = translator.getTranslatedSignature(signature, false, api);
+ MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), translatedSignature, translatedExceptions);
return new TranslationMethodVisitor(translator, translatedEntry, api, mv);
}
@Override
public void visitOuterClass(String owner, String name, String desc) {
- ClassEntry ownerEntry = translator.getTranslatedClass(entryPool.getClass(owner));
- String translatedDesc = desc != null ? translator.getTranslatedTypeDesc(new TypeDescriptor(desc)).toString() : desc;
- if (name != null) {
- ClassEntry entry = translator.getTranslatedClass(entryPool.getClass(name));
- super.visitOuterClass(ownerEntry.getName(), entry.getName(), translatedDesc);
+ if (desc != null) {
+ MethodEntry translatedEntry = translator.getTranslatedMethod(new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc)));
+ super.visitOuterClass(translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString());
} else {
- super.visitOuterClass(ownerEntry.getName(), name, translatedDesc);
+ super.visitOuterClass(owner, name, desc);
}
}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
index c729962..cce91db 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -1,6 +1,8 @@
package cuchaz.enigma.bytecode.translators;
-import cuchaz.enigma.mapping.*;
+import cuchaz.enigma.mapping.MethodDescriptor;
+import cuchaz.enigma.mapping.Translator;
+import cuchaz.enigma.mapping.TypeDescriptor;
import cuchaz.enigma.mapping.entry.*;
import org.objectweb.asm.*;
@@ -20,22 +22,35 @@ public class TranslationMethodVisitor extends MethodVisitor {
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
FieldEntry entry = new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc));
FieldEntry translatedEntry = translator.getTranslatedField(entry);
- if (translatedEntry != null) {
- super.visitFieldInsn(opcode, translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString());
- } else {
- super.visitFieldInsn(opcode, owner, name, desc);
- }
+ super.visitFieldInsn(opcode, translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString());
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
MethodEntry entry = new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc));
MethodEntry translatedEntry = translator.getTranslatedMethod(entry);
- if (translatedEntry != null) {
- super.visitMethodInsn(opcode, translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString(), itf);
- } else {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
+ super.visitMethodInsn(opcode, translatedEntry.getClassName(), translatedEntry.getName(), translatedEntry.getDesc().toString(), itf);
+ }
+
+ @Override
+ public void visitFrame(int type, int localCount, Object[] locals, int stackCount, Object[] stack) {
+ Object[] translatedLocals = this.getTranslatedFrame(locals, localCount);
+ Object[] translatedStack = this.getTranslatedFrame(stack, stackCount);
+ super.visitFrame(type, localCount, translatedLocals, stackCount, translatedStack);
+ }
+
+ private Object[] getTranslatedFrame(Object[] array, int count) {
+ if (array == null) {
+ return null;
}
+ for (int i = 0; i < count; i++) {
+ Object object = array[i];
+ if (object instanceof String) {
+ ClassEntry entry = new ClassEntry((String) object);
+ array[i] = translator.getTranslatedClass(entry).getName();
+ }
+ }
+ return array;
}
@Override
@@ -45,6 +60,13 @@ public class TranslationMethodVisitor extends MethodVisitor {
return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av);
}
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
+ TypeDescriptor typeDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
+ AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible);
+ return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av);
+ }
+
@Override
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
TypeDescriptor typeDesc = translator.getTranslatedTypeDesc(new TypeDescriptor(desc));
@@ -80,6 +102,43 @@ public class TranslationMethodVisitor extends MethodVisitor {
}
translatedName = nameBuilder.toString();
}
- super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), signature, start, end, index);
+ String translatedSignature = translator.getTranslatedSignature(signature, true, api);
+ super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), translatedSignature, start, end, index);
+ }
+
+ @Override
+ public void visitTypeInsn(int opcode, String type) {
+ ClassEntry translatedEntry = translator.getTranslatedClass(new ClassEntry(type));
+ super.visitTypeInsn(opcode, translatedEntry.getName());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+ MethodDescriptor translatedMethodDesc = translator.getTranslatedMethodDesc(new MethodDescriptor(desc));
+ Object[] translatedBsmArgs = new Object[bsmArgs.length];
+ for (int i = 0; i < bsmArgs.length; i++) {
+ translatedBsmArgs[i] = translator.getTranslatedValue(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(name, translatedMethodDesc.toString(), translator.getTranslatedHandle(bsm), translatedBsmArgs);
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ super.visitLdcInsn(translator.getTranslatedValue(cst));
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ super.visitMultiANewArrayInsn(translator.getTranslatedTypeDesc(new TypeDescriptor(desc)).toString(), dims);
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ if (type != null) {
+ ClassEntry translatedEntry = translator.getTranslatedClass(new ClassEntry(type));
+ super.visitTryCatchBlock(start, end, handler, translatedEntry.getName());
+ } else {
+ super.visitTryCatchBlock(start, end, handler, type);
+ }
}
}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java
new file mode 100644
index 0000000..e1dcea5
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java
@@ -0,0 +1,122 @@
+package cuchaz.enigma.bytecode.translators;
+
+import cuchaz.enigma.mapping.Translator;
+import cuchaz.enigma.mapping.entry.ClassEntry;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+import java.util.Stack;
+
+public class TranslationSignatureVisitor extends SignatureVisitor {
+ private final Translator translator;
+
+ private final SignatureVisitor sv;
+ private final Stack