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 --- .../cuchaz/enigma/bytecode/CheckCastIterator.java | 117 +++++ .../cuchaz/enigma/bytecode/ClassProtectifier.java | 51 ++ .../cuchaz/enigma/bytecode/ClassPublifier.java | 51 ++ .../java/cuchaz/enigma/bytecode/ClassRenamer.java | 514 +++++++++++++++++++++ .../cuchaz/enigma/bytecode/ClassTranslator.java | 151 ++++++ .../cuchaz/enigma/bytecode/ConstPoolEditor.java | 263 +++++++++++ src/main/java/cuchaz/enigma/bytecode/InfoType.java | 301 ++++++++++++ .../cuchaz/enigma/bytecode/InnerClassWriter.java | 132 ++++++ .../enigma/bytecode/LocalVariableRenamer.java | 119 +++++ .../enigma/bytecode/MethodParameterWriter.java | 66 +++ .../enigma/bytecode/MethodParametersAttribute.java | 86 ++++ .../bytecode/accessors/ClassInfoAccessor.java | 55 +++ .../bytecode/accessors/ConstInfoAccessor.java | 151 ++++++ .../accessors/InvokeDynamicInfoAccessor.java | 74 +++ .../bytecode/accessors/MemberRefInfoAccessor.java | 74 +++ .../accessors/MethodHandleInfoAccessor.java | 74 +++ .../bytecode/accessors/MethodTypeInfoAccessor.java | 55 +++ .../accessors/NameAndTypeInfoAccessor.java | 74 +++ .../bytecode/accessors/StringInfoAccessor.java | 55 +++ .../bytecode/accessors/Utf8InfoAccessor.java | 28 ++ 20 files changed, 2491 insertions(+) create mode 100644 src/main/java/cuchaz/enigma/bytecode/CheckCastIterator.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/InfoType.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/MethodParameterWriter.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java create mode 100644 src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java (limited to 'src/main/java/cuchaz/enigma/bytecode') diff --git a/src/main/java/cuchaz/enigma/bytecode/CheckCastIterator.java b/src/main/java/cuchaz/enigma/bytecode/CheckCastIterator.java new file mode 100644 index 0000000..8058d0e --- /dev/null +++ b/src/main/java/cuchaz/enigma/bytecode/CheckCastIterator.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * 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.util.Iterator;
+
+import cuchaz.enigma.bytecode.CheckCastIterator.CheckCast;
+import cuchaz.enigma.mapping.ClassEntry;
+import cuchaz.enigma.mapping.MethodEntry;
+import cuchaz.enigma.mapping.Signature;
+import javassist.bytecode.*;
+
+public class CheckCastIterator implements Iterator
+ * Contributors:
+ * Jeff Martin - initial API and implementation
+ ******************************************************************************/
+package cuchaz.enigma.bytecode;
+
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.InnerClassesAttribute;
+
+
+public class ClassProtectifier {
+
+ public static CtClass protectify(CtClass c) {
+
+ // protectify all the fields
+ for (CtField field : c.getDeclaredFields()) {
+ field.setModifiers(protectify(field.getModifiers()));
+ }
+
+ // protectify all the methods and constructors
+ for (CtBehavior behavior : c.getDeclaredBehaviors()) {
+ behavior.setModifiers(protectify(behavior.getModifiers()));
+ }
+
+ // 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)));
+ }
+ }
+
+ return c;
+ }
+
+ private static int protectify(int flags) {
+ if (AccessFlag.isPrivate(flags)) {
+ flags = AccessFlag.setProtected(flags);
+ }
+ return flags;
+ }
+}
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java b/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java
new file mode 100644
index 0000000..da86b2b
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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 javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.InnerClassesAttribute;
+
+
+public class ClassPublifier {
+
+ public static CtClass publify(CtClass c) {
+
+ // publify all the fields
+ for (CtField field : c.getDeclaredFields()) {
+ field.setModifiers(publify(field.getModifiers()));
+ }
+
+ // publify all the methods and constructors
+ for (CtBehavior behavior : c.getDeclaredBehaviors()) {
+ behavior.setModifiers(publify(behavior.getModifiers()));
+ }
+
+ // 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)));
+ }
+ }
+
+ return c;
+ }
+
+ private static int publify(int flags) {
+ if (AccessFlag.isPrivate(flags) || AccessFlag.isProtected(flags)) {
+ flags = AccessFlag.setPublic(flags);
+ }
+ return flags;
+ }
+}
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java
new file mode 100644
index 0000000..548bea7
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java
@@ -0,0 +1,514 @@
+/*******************************************************************************
+ * 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 cuchaz.enigma.mapping.ClassEntry;
+import cuchaz.enigma.mapping.ClassNameReplacer;
+import cuchaz.enigma.mapping.Translator;
+import javassist.CtClass;
+import javassist.bytecode.*;
+import javassist.bytecode.SignatureAttribute.*;
+
+public class ClassRenamer {
+
+ private 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
+ * Contributors:
+ * Jeff Martin - initial API and implementation
+ ******************************************************************************/
+package cuchaz.enigma.bytecode;
+
+import cuchaz.enigma.mapping.*;
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.bytecode.ConstPool;
+import javassist.bytecode.Descriptor;
+import javassist.bytecode.EnclosingMethodAttribute;
+import javassist.bytecode.SourceFileAttribute;
+
+public class ClassTranslator {
+
+ private Translator m_translator;
+
+ public ClassTranslator(Translator translator) {
+ m_translator = translator;
+ }
+
+ public void translate(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 = m_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 = m_translator.translateEntry(entry);
+ if (!entry.equals(translatedEntry)) {
+ editor.changeMemberrefNameAndType(i, translatedEntry.getName(), translatedEntry.getSignature().toString());
+ }
+ }
+ break;
+ }
+ }
+
+ ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName()));
+
+ // translate all the fields
+ for (CtField field : c.getDeclaredFields()) {
+
+ // translate the name
+ FieldEntry entry = EntryFactory.getFieldEntry(field);
+ String translatedName = m_translator.translate(entry);
+ if (translatedName != null) {
+ field.setName(translatedName);
+ }
+
+ // translate the type
+ Type translatedType = m_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);
+
+ if (behavior instanceof CtMethod) {
+ CtMethod method = (CtMethod) behavior;
+
+ // translate the name
+ String translatedName = m_translator.translate(entry);
+ if (translatedName != null) {
+ method.setName(translatedName);
+ }
+ }
+
+ if (entry.getSignature() != null) {
+ // translate the signature
+ Signature translatedSignature = m_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 = m_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 = m_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, m_translator);
+
+ // translate the source file attribute too
+ ClassEntry deobfClassEntry = m_translator.translateEntry(classEntry);
+ if (deobfClassEntry != null) {
+ String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassEntry().getSimpleName()) + ".java";
+ c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile));
+ }
+ }
+}
diff --git a/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java b/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java
new file mode 100644
index 0000000..0082a72
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * 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.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;
+
+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;
+
+public class ConstPoolEditor {
+
+ private static Method m_getItem;
+ private static Method m_addItem;
+ private static Method m_addItem0;
+ private static Field m_items;
+ private static Field m_cache;
+ private static Field m_numItems;
+ private static Field m_objects;
+ private static Field m_elements;
+ private static Method m_methodWritePool;
+ private static Constructor
+ * Contributors:
+ * Jeff Martin - initial API and implementation
+ ******************************************************************************/
+package cuchaz.enigma.bytecode;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import cuchaz.enigma.bytecode.accessors.*;
+
+public enum InfoType {
+
+ Utf8Info(1, 0),
+ IntegerInfo(3, 0),
+ FloatInfo(4, 0),
+ LongInfo(5, 0),
+ DoubleInfo(6, 0),
+ ClassInfo(7, 1) {
+ @Override
+ public void gatherIndexTree(Collection
+ * Contributors:
+ * Jeff Martin - initial API and implementation
+ ******************************************************************************/
+package cuchaz.enigma.bytecode;
+
+import com.google.common.collect.Lists;
+
+import java.util.Collection;
+import java.util.List;
+
+import cuchaz.enigma.analysis.JarIndex;
+import cuchaz.enigma.mapping.BehaviorEntry;
+import cuchaz.enigma.mapping.ClassEntry;
+import cuchaz.enigma.mapping.EntryFactory;
+import javassist.CtClass;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.ConstPool;
+import javassist.bytecode.EnclosingMethodAttribute;
+import javassist.bytecode.InnerClassesAttribute;
+
+public class InnerClassWriter {
+
+ private JarIndex m_index;
+
+ public InnerClassWriter(JarIndex index) {
+ m_index = index;
+ }
+
+ public void write(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;
+
+import cuchaz.enigma.mapping.ArgumentEntry;
+import cuchaz.enigma.mapping.BehaviorEntry;
+import cuchaz.enigma.mapping.EntryFactory;
+import cuchaz.enigma.mapping.Translator;
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.bytecode.*;
+
+
+public class LocalVariableRenamer {
+
+ private Translator m_translator;
+
+ public LocalVariableRenamer(Translator translator) {
+ m_translator = translator;
+ }
+
+ public void rename(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(behaviorEntry, constants, table);
+ }
+
+ LocalVariableTypeAttribute typeTable = (LocalVariableTypeAttribute) codeAttribute.getAttribute(LocalVariableAttribute.typeTag);
+ if (typeTable != null) {
+ renameLVTT(typeTable, table);
+ }
+ }
+ }
+
+ // DEBUG
+ @SuppressWarnings("unused")
+ private 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 void renameLVT(BehaviorEntry behaviorEntry, ConstPool constants, LocalVariableAttribute table) {
+
+ // 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 = 1;
+ }
+
+ // rename method arguments first
+ int numArgs = 0;
+ if (behaviorEntry.getSignature() != null) {
+ numArgs = behaviorEntry.getSignature().getArgumentTypes().size();
+ for (int i = starti; i < starti + numArgs && i < table.tableLength(); i++) {
+ int argi = i - starti;
+ String argName = m_translator.translate(new ArgumentEntry(behaviorEntry, argi, ""));
+ if (argName == null) {
+ argName = "a" + (argi + 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 = table.index(starti + numArgs);
+ renameVariable(table, i, constants.addUtf8Info("v" + (table.index(i) - firstIndex + 1)));
+ }
+ }
+
+ private 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 void renameVariable(LocalVariableAttribute table, int i, int stringId) {
+ // based off of LocalVariableAttribute.nameIndex()
+ ByteArray.write16bit(stringId, table.get(), i * 10 + 6);
+ }
+
+ private 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/MethodParameterWriter.java b/src/main/java/cuchaz/enigma/bytecode/MethodParameterWriter.java
new file mode 100644
index 0000000..e53e8e7
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/MethodParameterWriter.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.util.ArrayList;
+import java.util.List;
+
+import cuchaz.enigma.mapping.*;
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.bytecode.CodeAttribute;
+import javassist.bytecode.LocalVariableAttribute;
+
+public class MethodParameterWriter {
+
+ private Translator m_translator;
+
+ public MethodParameterWriter(Translator translator) {
+ m_translator = translator;
+ }
+
+ public void writeMethodArguments(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;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javassist.bytecode.AttributeInfo;
+import javassist.bytecode.ConstPool;
+import javassist.bytecode.MethodInfo;
+
+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> m_class;
+ private static Field m_nameIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.ClassInfo");
+ m_nameIndex = m_class.getDeclaredField("name");
+ m_nameIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public ClassInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getNameIndex() {
+ try {
+ return (Integer) m_nameIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setNameIndex(int val) {
+ try {
+ m_nameIndex.set(m_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
new file mode 100644
index 0000000..2692c06
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * 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.io.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import cuchaz.enigma.bytecode.InfoType;
+
+public class ConstInfoAccessor {
+
+ private static Class> m_class;
+ private static Field m_index;
+ private static Method m_getTag;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.ConstInfo");
+ m_index = m_class.getDeclaredField("index");
+ m_index.setAccessible(true);
+ m_getTag = m_class.getMethod("getTag");
+ m_getTag.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ private Object m_item;
+
+ public ConstInfoAccessor(Object item) {
+ if (item == null) {
+ throw new IllegalArgumentException("item cannot be null!");
+ }
+ m_item = item;
+ }
+
+ public ConstInfoAccessor(DataInputStream in) throws IOException {
+ try {
+ // read the entry
+ String className = in.readUTF();
+ int oldIndex = in.readInt();
+
+ // NOTE: ConstInfo instances write a type id (a "tag"), but they don't read it back
+ // so we have to read it here
+ in.readByte();
+
+ Constructor> constructor = Class.forName(className).getConstructor(DataInputStream.class, int.class);
+ constructor.setAccessible(true);
+ m_item = constructor.newInstance(in, oldIndex);
+ } catch (IOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public Object getItem() {
+ return m_item;
+ }
+
+ public int getIndex() {
+ try {
+ return (Integer) m_index.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setIndex(int val) {
+ try {
+ m_index.set(m_item, val);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public int getTag() {
+ try {
+ return (Integer) m_getTag.invoke(m_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(m_item.getClass().getName());
+ out.writeInt(getIndex());
+
+ Method method = m_item.getClass().getMethod("write", DataOutputStream.class);
+ method.setAccessible(true);
+ method.invoke(m_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(buf);
+ Method print = m_item.getClass().getMethod("print", PrintWriter.class);
+ print.setAccessible(true);
+ print.invoke(m_item, out);
+ out.close();
+ return buf.toString().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
new file mode 100644
index 0000000..0ca82b7
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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> m_class;
+ private static Field m_bootstrapIndex;
+ private static Field m_nameAndTypeIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.InvokeDynamicInfo");
+ m_bootstrapIndex = m_class.getDeclaredField("bootstrap");
+ m_bootstrapIndex.setAccessible(true);
+ m_nameAndTypeIndex = m_class.getDeclaredField("nameAndType");
+ m_nameAndTypeIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public InvokeDynamicInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getBootstrapIndex() {
+ try {
+ return (Integer) m_bootstrapIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setBootstrapIndex(int val) {
+ try {
+ m_bootstrapIndex.set(m_item, val);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public int getNameAndTypeIndex() {
+ try {
+ return (Integer) m_nameAndTypeIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setNameAndTypeIndex(int val) {
+ try {
+ m_nameAndTypeIndex.set(m_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
new file mode 100644
index 0000000..bb9d16b
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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> m_class;
+ private static Field m_classIndex;
+ private static Field m_nameAndTypeIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.MemberrefInfo");
+ m_classIndex = m_class.getDeclaredField("classIndex");
+ m_classIndex.setAccessible(true);
+ m_nameAndTypeIndex = m_class.getDeclaredField("nameAndTypeIndex");
+ m_nameAndTypeIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public MemberRefInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getClassIndex() {
+ try {
+ return (Integer) m_classIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setClassIndex(int val) {
+ try {
+ m_classIndex.set(m_item, val);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public int getNameAndTypeIndex() {
+ try {
+ return (Integer) m_nameAndTypeIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setNameAndTypeIndex(int val) {
+ try {
+ m_nameAndTypeIndex.set(m_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
new file mode 100644
index 0000000..88e42f4
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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> m_class;
+ private static Field m_kindIndex;
+ private static Field m_indexIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.MethodHandleInfo");
+ m_kindIndex = m_class.getDeclaredField("refKind");
+ m_kindIndex.setAccessible(true);
+ m_indexIndex = m_class.getDeclaredField("refIndex");
+ m_indexIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public MethodHandleInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getTypeIndex() {
+ try {
+ return (Integer) m_kindIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setTypeIndex(int val) {
+ try {
+ m_kindIndex.set(m_item, val);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public int getMethodRefIndex() {
+ try {
+ return (Integer) m_indexIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setMethodRefIndex(int val) {
+ try {
+ m_indexIndex.set(m_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
new file mode 100644
index 0000000..1d039f6
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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> m_class;
+ private static Field m_descriptorIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.MethodTypeInfo");
+ m_descriptorIndex = m_class.getDeclaredField("descriptor");
+ m_descriptorIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public MethodTypeInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getTypeIndex() {
+ try {
+ return (Integer) m_descriptorIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setTypeIndex(int val) {
+ try {
+ m_descriptorIndex.set(m_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
new file mode 100644
index 0000000..acba779
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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> m_class;
+ private static Field m_nameIndex;
+ private static Field m_typeIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.NameAndTypeInfo");
+ m_nameIndex = m_class.getDeclaredField("memberName");
+ m_nameIndex.setAccessible(true);
+ m_typeIndex = m_class.getDeclaredField("typeDescriptor");
+ m_typeIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public NameAndTypeInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getNameIndex() {
+ try {
+ return (Integer) m_nameIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setNameIndex(int val) {
+ try {
+ m_nameIndex.set(m_item, val);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public int getTypeIndex() {
+ try {
+ return (Integer) m_typeIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setTypeIndex(int val) {
+ try {
+ m_typeIndex.set(m_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
new file mode 100644
index 0000000..b40e0eb
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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> m_class;
+ private static Field m_stringIndex;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.StringInfo");
+ m_stringIndex = m_class.getDeclaredField("string");
+ m_stringIndex.setAccessible(true);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+
+ private Object m_item;
+
+ public StringInfoAccessor(Object item) {
+ m_item = item;
+ }
+
+ public int getStringIndex() {
+ try {
+ return (Integer) m_stringIndex.get(m_item);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public void setStringIndex(int val) {
+ try {
+ m_stringIndex.set(m_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
new file mode 100644
index 0000000..9303b41
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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> m_class;
+
+ static {
+ try {
+ m_class = Class.forName("javassist.bytecode.Utf8Info");
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ public static boolean isType(ConstInfoAccessor accessor) {
+ return m_class.isAssignableFrom(accessor.getItem().getClass());
+ }
+}
--
cgit v1.2.3