summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/bytecode
diff options
context:
space:
mode:
authorGravatar asiekierka2016-08-17 18:35:12 +0200
committerGravatar asiekierka2016-08-17 18:35:12 +0200
commit5540c815de36e316d0749ce2163f12c61895b327 (patch)
tree2b30d5ae98735ee7cba7d1c0087c51d68ed3ebf9 /src/main/java/cuchaz/enigma/bytecode
parentRevert "Removed util" (diff)
downloadenigma-fork-5540c815de36e316d0749ce2163f12c61895b327.tar.gz
enigma-fork-5540c815de36e316d0749ce2163f12c61895b327.tar.xz
enigma-fork-5540c815de36e316d0749ce2163f12c61895b327.zip
Revert "Removed unused methods"
This reverts commit 1742190f784d0d62e7cc869eebafdfe1927e448f.
Diffstat (limited to 'src/main/java/cuchaz/enigma/bytecode')
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/CheckCastIterator.java117
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java10
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java122
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java42
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java4
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java28
12 files changed, 347 insertions, 0 deletions
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..19c39d3
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/CheckCastIterator.java
@@ -0,0 +1,117 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import java.util.Iterator;
14
15import cuchaz.enigma.bytecode.CheckCastIterator.CheckCast;
16import cuchaz.enigma.mapping.ClassEntry;
17import cuchaz.enigma.mapping.MethodEntry;
18import cuchaz.enigma.mapping.Signature;
19import javassist.bytecode.*;
20
21public class CheckCastIterator implements Iterator<CheckCast> {
22
23 public static class CheckCast {
24
25 public String className;
26 public MethodEntry prevMethodEntry;
27
28 public CheckCast(String className, MethodEntry prevMethodEntry) {
29 this.className = className;
30 this.prevMethodEntry = prevMethodEntry;
31 }
32 }
33
34 private ConstPool constants;
35 private CodeAttribute attribute;
36 private CodeIterator iter;
37 private CheckCast next;
38
39 public CheckCastIterator(CodeAttribute codeAttribute) throws BadBytecode {
40 this.constants = codeAttribute.getConstPool();
41 this.attribute = codeAttribute;
42 this.iter = this.attribute.iterator();
43
44 this.next = getNext();
45 }
46
47 @Override
48 public boolean hasNext() {
49 return this.next != null;
50 }
51
52 @Override
53 public CheckCast next() {
54 CheckCast out = this.next;
55 try {
56 this.next = getNext();
57 } catch (BadBytecode ex) {
58 throw new Error(ex);
59 }
60 return out;
61 }
62
63 @Override
64 public void remove() {
65 throw new UnsupportedOperationException();
66 }
67
68 private CheckCast getNext() throws BadBytecode {
69 int prevPos = 0;
70 while (this.iter.hasNext()) {
71 int pos = this.iter.next();
72 int opcode = this.iter.byteAt(pos);
73 switch (opcode) {
74 case Opcode.CHECKCAST:
75
76 // get the type of this op code (next two bytes are a classinfo index)
77 MethodEntry prevMethodEntry = getMethodEntry(prevPos);
78 if (prevMethodEntry != null) {
79 return new CheckCast(this.constants.getClassInfo(this.iter.s16bitAt(pos + 1)), prevMethodEntry);
80 }
81 break;
82 }
83 prevPos = pos;
84 }
85 return null;
86 }
87
88 private MethodEntry getMethodEntry(int pos) {
89 switch (this.iter.byteAt(pos)) {
90 case Opcode.INVOKEVIRTUAL:
91 case Opcode.INVOKESTATIC:
92 case Opcode.INVOKEDYNAMIC:
93 case Opcode.INVOKESPECIAL: {
94 int index = this.iter.s16bitAt(pos + 1);
95 return new MethodEntry(
96 new ClassEntry(Descriptor.toJvmName(this.constants.getMethodrefClassName(index))),
97 this.constants.getMethodrefName(index),
98 new Signature(this.constants.getMethodrefType(index))
99 );
100 }
101
102 case Opcode.INVOKEINTERFACE: {
103 int index = this.iter.s16bitAt(pos + 1);
104 return new MethodEntry(
105 new ClassEntry(Descriptor.toJvmName(this.constants.getInterfaceMethodrefClassName(index))),
106 this.constants.getInterfaceMethodrefName(index),
107 new Signature(this.constants.getInterfaceMethodrefType(index))
108 );
109 }
110 }
111 return null;
112 }
113
114 public Iterable<CheckCast> casts() {
115 return () -> CheckCastIterator.this;
116 }
117}
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java
index 4a77eec..c13aae4 100644
--- a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java
+++ b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java
@@ -90,6 +90,16 @@ public class ClassRenamer {
90 }); 90 });
91 } 91 }
92 92
93 public static void moveAllClassesIntoDefaultPackage(CtClass c, final String oldPackageName) {
94 renameClasses(c, className -> {
95 ClassEntry entry = new ClassEntry(className);
96 if (entry.getPackageName().equals(oldPackageName)) {
97 return entry.getSimpleName();
98 }
99 return null;
100 });
101 }
102
93 @SuppressWarnings("unchecked") 103 @SuppressWarnings("unchecked")
94 public static void renameClasses(CtClass c, ClassNameReplacer replacer) { 104 public static void renameClasses(CtClass c, ClassNameReplacer replacer) {
95 105
diff --git a/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java b/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java
index af8c79a..256df61 100644
--- a/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/ConstPoolEditor.java
@@ -17,6 +17,7 @@ import java.lang.reflect.Field;
17import java.lang.reflect.Method; 17import java.lang.reflect.Method;
18import java.util.HashMap; 18import java.util.HashMap;
19 19
20import cuchaz.enigma.bytecode.accessors.ClassInfoAccessor;
20import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor; 21import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor;
21import cuchaz.enigma.bytecode.accessors.MemberRefInfoAccessor; 22import cuchaz.enigma.bytecode.accessors.MemberRefInfoAccessor;
22import javassist.bytecode.ConstPool; 23import javassist.bytecode.ConstPool;
@@ -77,6 +78,22 @@ public class ConstPoolEditor {
77 this.pool = pool; 78 this.pool = pool;
78 } 79 }
79 80
81 public void writePool(DataOutputStream out) {
82 try {
83 methodWritePool.invoke(this.pool, out);
84 } catch (Exception ex) {
85 throw new Error(ex);
86 }
87 }
88
89 public static ConstPool readPool(DataInputStream in) {
90 try {
91 return constructorPool.newInstance(in);
92 } catch (Exception ex) {
93 throw new Error(ex);
94 }
95 }
96
80 public String getMemberrefClassname(int memberrefIndex) { 97 public String getMemberrefClassname(int memberrefIndex) {
81 return Descriptor.toJvmName(this.pool.getClassInfo(this.pool.getMemberClass(memberrefIndex))); 98 return Descriptor.toJvmName(this.pool.getClassInfo(this.pool.getMemberClass(memberrefIndex)));
82 } 99 }
@@ -101,6 +118,48 @@ public class ConstPoolEditor {
101 } 118 }
102 } 119 }
103 120
121 public int addItem(Object item) {
122 try {
123 return (Integer) addItem.invoke(this.pool, item);
124 } catch (Exception ex) {
125 throw new Error(ex);
126 }
127 }
128
129 public int addItemForceNew(Object item) {
130 try {
131 return (Integer) addItem0.invoke(this.pool, item);
132 } catch (Exception ex) {
133 throw new Error(ex);
134 }
135 }
136
137 @SuppressWarnings("rawtypes")
138 public void removeLastItem() {
139 try {
140 // remove the item from the cache
141 HashMap cache = getCache();
142 if (cache != null) {
143 Object item = getItem(this.pool.getSize() - 1);
144 cache.remove(item);
145 }
146
147 // remove the actual item
148 // based off of LongVector.addElement()
149 Object item = items.get(this.pool);
150 Object[][] object = (Object[][]) objects.get(items);
151 int numElements = (Integer) elements.get(items) - 1;
152 int nth = numElements >> 7;
153 int offset = numElements & (128 - 1);
154 object[nth][offset] = null;
155
156 // decrement the number of items
157 elements.set(item, numElements);
158 numItems.set(this.pool, (Integer) numItems.get(this.pool) - 1);
159 } catch (Exception ex) {
160 throw new Error(ex);
161 }
162 }
104 163
105 @SuppressWarnings("rawtypes") 164 @SuppressWarnings("rawtypes")
106 public HashMap getCache() { 165 public HashMap getCache() {
@@ -138,4 +197,67 @@ public class ConstPoolEditor {
138 assert (newName.equals(getMemberrefName(memberrefIndex))); 197 assert (newName.equals(getMemberrefName(memberrefIndex)));
139 assert (newType.equals(getMemberrefType(memberrefIndex))); 198 assert (newType.equals(getMemberrefType(memberrefIndex)));
140 } 199 }
200
201 @SuppressWarnings({"rawtypes", "unchecked"})
202 public void changeClassName(int classNameIndex, String newName) {
203 // NOTE: when changing values, we always need to copy-on-write
204 try {
205 // get the class item
206 Object item = getItem(classNameIndex).getItem();
207
208 // update the cache
209 HashMap cache = getCache();
210 if (cache != null) {
211 cache.remove(item);
212 }
213
214 // add the new name and repoint the name-and-type to it
215 new ClassInfoAccessor(item).setNameIndex(this.pool.addUtf8Info(newName));
216
217 // update the cache
218 if (cache != null) {
219 cache.put(item, item);
220 }
221 } catch (Exception ex) {
222 throw new Error(ex);
223 }
224 }
225
226 public static ConstPool newConstPool() {
227 // const pool expects the name of a class to initialize itself
228 // but we want an empty pool
229 // so give it a bogus name, and then clear the entries afterwards
230 ConstPool pool = new ConstPool("a");
231
232 ConstPoolEditor editor = new ConstPoolEditor(pool);
233 int size = pool.getSize();
234 for (int i = 0; i < size - 1; i++) {
235 editor.removeLastItem();
236 }
237
238 // make sure the pool is actually empty
239 // although, in this case "empty" means one thing in it
240 // the JVM spec says index 0 should be reserved
241 assert (pool.getSize() == 1);
242 assert (editor.getItem(0) == null);
243 assert (editor.getItem(1) == null);
244 assert (editor.getItem(2) == null);
245 assert (editor.getItem(3) == null);
246
247 // also, clear the cache
248 editor.getCache().clear();
249
250 return pool;
251 }
252
253 public String dump() {
254 StringBuilder buf = new StringBuilder();
255 for (int i = 1; i < this.pool.getSize(); i++) {
256 buf.append(String.format("%4d", i));
257 buf.append(" ");
258 buf.append(getItem(i).toString());
259 buf.append("\n");
260 }
261 return buf.toString();
262 }
141} 263}
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java
index 316bb5e..66f2283 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/ClassInfoAccessor.java
@@ -39,6 +39,10 @@ public class ClassInfoAccessor {
39 } 39 }
40 } 40 }
41 41
42 public static boolean isType(ConstInfoAccessor accessor) {
43 return clazz.isAssignableFrom(accessor.getItem().getClass());
44 }
45
42 static { 46 static {
43 try { 47 try {
44 clazz = Class.forName("javassist.bytecode.ClassInfo"); 48 clazz = Class.forName("javassist.bytecode.ClassInfo");
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java
index 474a3ef..bc7af87 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/ConstInfoAccessor.java
@@ -10,8 +10,12 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.bytecode.accessors; 11package cuchaz.enigma.bytecode.accessors;
12 12
13import java.io.ByteArrayInputStream;
13import java.io.ByteArrayOutputStream; 14import java.io.ByteArrayOutputStream;
15import java.io.DataInputStream;
16import java.io.DataOutputStream;
14import java.io.FileOutputStream; 17import java.io.FileOutputStream;
18import java.io.IOException;
15import java.io.OutputStreamWriter; 19import java.io.OutputStreamWriter;
16import java.io.PrintWriter; 20import java.io.PrintWriter;
17import java.lang.reflect.Field; 21import java.lang.reflect.Field;
@@ -55,6 +59,44 @@ public class ConstInfoAccessor {
55 } 59 }
56 } 60 }
57 61
62 public ConstInfoAccessor copy() {
63 return new ConstInfoAccessor(copyItem());
64 }
65
66 public Object copyItem() {
67 // I don't know of a simpler way to copy one of these silly things...
68 try {
69 // serialize the item
70 ByteArrayOutputStream buf = new ByteArrayOutputStream();
71 DataOutputStream out = new DataOutputStream(buf);
72 write(out);
73
74 // deserialize the item
75 DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf.toByteArray()));
76 Object item = new ConstInfoAccessor(in).getItem();
77 in.close();
78
79 return item;
80 } catch (Exception ex) {
81 throw new Error(ex);
82 }
83 }
84
85 public void write(DataOutputStream out) throws IOException {
86 try {
87 out.writeUTF(this.item.getClass().getName());
88 out.writeInt(getIndex());
89
90 Method method = this.item.getClass().getMethod("write", DataOutputStream.class);
91 method.setAccessible(true);
92 method.invoke(this.item, out);
93 } catch (IOException ex) {
94 throw ex;
95 } catch (Exception ex) {
96 throw new Error(ex);
97 }
98 }
99
58 @Override 100 @Override
59 public String toString() { 101 public String toString() {
60 try { 102 try {
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java
index a158394..69aee16 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/InvokeDynamicInfoAccessor.java
@@ -57,6 +57,10 @@ public class InvokeDynamicInfoAccessor {
57 } 57 }
58 } 58 }
59 59
60 public static boolean isType(ConstInfoAccessor accessor) {
61 return clazz.isAssignableFrom(accessor.getItem().getClass());
62 }
63
60 static { 64 static {
61 try { 65 try {
62 clazz = Class.forName("javassist.bytecode.InvokeDynamicInfo"); 66 clazz = Class.forName("javassist.bytecode.InvokeDynamicInfo");
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java
index 2835508..0e0297b 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/MemberRefInfoAccessor.java
@@ -56,6 +56,10 @@ public class MemberRefInfoAccessor {
56 } 56 }
57 } 57 }
58 58
59 public static boolean isType(ConstInfoAccessor accessor) {
60 return clazz.isAssignableFrom(accessor.getItem().getClass());
61 }
62
59 static { 63 static {
60 try { 64 try {
61 clazz = Class.forName("javassist.bytecode.MemberrefInfo"); 65 clazz = Class.forName("javassist.bytecode.MemberrefInfo");
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java
index a203b43..9a7dd69 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodHandleInfoAccessor.java
@@ -56,6 +56,10 @@ public class MethodHandleInfoAccessor {
56 } 56 }
57 } 57 }
58 58
59 public static boolean isType(ConstInfoAccessor accessor) {
60 return clazz.isAssignableFrom(accessor.getItem().getClass());
61 }
62
59 static { 63 static {
60 try { 64 try {
61 clazz = Class.forName("javassist.bytecode.MethodHandleInfo"); 65 clazz = Class.forName("javassist.bytecode.MethodHandleInfo");
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java
index 993c79b..5ec9c3b 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/MethodTypeInfoAccessor.java
@@ -39,6 +39,10 @@ public class MethodTypeInfoAccessor {
39 } 39 }
40 } 40 }
41 41
42 public static boolean isType(ConstInfoAccessor accessor) {
43 return clazz.isAssignableFrom(accessor.getItem().getClass());
44 }
45
42 static { 46 static {
43 try { 47 try {
44 clazz = Class.forName("javassist.bytecode.MethodTypeInfo"); 48 clazz = Class.forName("javassist.bytecode.MethodTypeInfo");
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java
index d6c2531..95df37c 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/NameAndTypeInfoAccessor.java
@@ -56,6 +56,10 @@ public class NameAndTypeInfoAccessor {
56 } 56 }
57 } 57 }
58 58
59 public static boolean isType(ConstInfoAccessor accessor) {
60 return clazz.isAssignableFrom(accessor.getItem().getClass());
61 }
62
59 static { 63 static {
60 try { 64 try {
61 clazz = Class.forName("javassist.bytecode.NameAndTypeInfo"); 65 clazz = Class.forName("javassist.bytecode.NameAndTypeInfo");
diff --git a/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java b/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java
index e211381..1c55a44 100644
--- a/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/StringInfoAccessor.java
@@ -39,6 +39,10 @@ public class StringInfoAccessor {
39 } 39 }
40 } 40 }
41 41
42 public static boolean isType(ConstInfoAccessor accessor) {
43 return clazz.isAssignableFrom(accessor.getItem().getClass());
44 }
45
42 static { 46 static {
43 try { 47 try {
44 clazz = Class.forName("javassist.bytecode.StringInfo"); 48 clazz = Class.forName("javassist.bytecode.StringInfo");
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..7a2cb66
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/accessors/Utf8InfoAccessor.java
@@ -0,0 +1,28 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode.accessors;
12
13public class Utf8InfoAccessor {
14
15 private static Class<?> clazz;
16
17 static {
18 try {
19 clazz = Class.forName("javassist.bytecode.Utf8Info");
20 } catch (Exception ex) {
21 throw new Error(ex);
22 }
23 }
24
25 public static boolean isType(ConstInfoAccessor accessor) {
26 return clazz.isAssignableFrom(accessor.getItem().getClass());
27 }
28}