summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java')
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java111
1 files changed, 56 insertions, 55 deletions
diff --git a/src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java b/src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java
index bace3a0..3f819ab 100644
--- a/src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java
+++ b/src/main/java/cuchaz/enigma/bytecode/MethodParametersAttribute.java
@@ -8,79 +8,80 @@
8 * Contributors: 8 * Contributors:
9 * Jeff Martin - initial API and implementation 9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/ 10 ******************************************************************************/
11
11package cuchaz.enigma.bytecode; 12package cuchaz.enigma.bytecode;
12 13
14import javassist.bytecode.AttributeInfo;
15import javassist.bytecode.ConstPool;
16import javassist.bytecode.MethodInfo;
17
13import java.io.ByteArrayOutputStream; 18import java.io.ByteArrayOutputStream;
14import java.io.DataOutputStream; 19import java.io.DataOutputStream;
15import java.io.IOException; 20import java.io.IOException;
16import java.util.ArrayList; 21import java.util.ArrayList;
17import java.util.List; 22import java.util.List;
18 23
19import javassist.bytecode.AttributeInfo;
20import javassist.bytecode.ConstPool;
21import javassist.bytecode.MethodInfo;
22
23public class MethodParametersAttribute extends AttributeInfo { 24public class MethodParametersAttribute extends AttributeInfo {
24 25
25 private MethodParametersAttribute(ConstPool pool, List<Integer> parameterNameIndices) { 26 private MethodParametersAttribute(ConstPool pool, List<Integer> parameterNameIndices) {
26 super(pool, "MethodParameters", writeStruct(parameterNameIndices)); 27 super(pool, "MethodParameters", writeStruct(parameterNameIndices));
27 } 28 }
28 29
29 public static void updateClass(MethodInfo info, List<String> names) { 30 public static void updateClass(MethodInfo info, List<String> names) {
30 31
31 // add the names to the class const pool 32 // add the names to the class const pool
32 ConstPool constPool = info.getConstPool(); 33 ConstPool constPool = info.getConstPool();
33 List<Integer> parameterNameIndices = new ArrayList<>(); 34 List<Integer> parameterNameIndices = new ArrayList<>();
34 for (String name : names) { 35 for (String name : names) {
35 if (name != null) { 36 if (name != null) {
36 parameterNameIndices.add(constPool.addUtf8Info(name)); 37 parameterNameIndices.add(constPool.addUtf8Info(name));
37 } else { 38 } else {
38 parameterNameIndices.add(0); 39 parameterNameIndices.add(0);
39 } 40 }
40 } 41 }
41 42
42 // add the attribute to the method 43 // add the attribute to the method
43 info.addAttribute(new MethodParametersAttribute(constPool, parameterNameIndices)); 44 info.addAttribute(new MethodParametersAttribute(constPool, parameterNameIndices));
44 } 45 }
45 46
46 private static byte[] writeStruct(List<Integer> parameterNameIndices) { 47 private static byte[] writeStruct(List<Integer> parameterNameIndices) {
47 // JVM 8 Spec says the struct looks like this: 48 // JVM 8 Spec says the struct looks like this:
48 // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24 49 // http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24
49 // uint8 num_params 50 // uint8 num_params
50 // for each param: 51 // for each param:
51 // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry 52 // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry
52 // uint16 access_flags -> don't care, just set to 0 53 // uint16 access_flags -> don't care, just set to 0
53 54
54 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 55 ByteArrayOutputStream buf = new ByteArrayOutputStream();
55 DataOutputStream out = new DataOutputStream(buf); 56 DataOutputStream out = new DataOutputStream(buf);
56 57
57 // NOTE: java hates unsigned integers, so we have to be careful here 58 // NOTE: java hates unsigned integers, so we have to be careful here
58 // the writeShort(), writeByte() methods will read 16,8 low-order bits from the int argument 59 // the writeShort(), writeByte() methods will read 16,8 low-order bits from the int argument
59 // as long as the int argument is in range of the unsigned short/byte type, it will be written as an unsigned short/byte 60 // as long as the int argument is in range of the unsigned short/byte type, it will be written as an unsigned short/byte
60 // if the int is out of range, the byte stream won't look the way we want and weird things will happen 61 // if the int is out of range, the byte stream won't look the way we want and weird things will happen
61 final int SIZEOF_UINT8 = 1; 62 final int SIZEOF_UINT8 = 1;
62 final int SIZEOF_UINT16 = 2; 63 final int SIZEOF_UINT16 = 2;
63 final int MAX_UINT8 = (1 << 8) - 1; 64 final int MAX_UINT8 = (1 << 8) - 1;
64 final int MAX_UINT16 = (1 << 16) - 1; 65 final int MAX_UINT16 = (1 << 16) - 1;
65 66
66 try { 67 try {
67 assert (parameterNameIndices.size() >= 0 && parameterNameIndices.size() <= MAX_UINT8); 68 assert (parameterNameIndices.size() >= 0 && parameterNameIndices.size() <= MAX_UINT8);
68 out.writeByte(parameterNameIndices.size()); 69 out.writeByte(parameterNameIndices.size());
69 70
70 for (Integer index : parameterNameIndices) { 71 for (Integer index : parameterNameIndices) {
71 assert (index >= 0 && index <= MAX_UINT16); 72 assert (index >= 0 && index <= MAX_UINT16);
72 out.writeShort(index); 73 out.writeShort(index);
73 74
74 // just write 0 for the access flags 75 // just write 0 for the access flags
75 out.writeShort(0); 76 out.writeShort(0);
76 } 77 }
77 78
78 out.close(); 79 out.close();
79 byte[] data = buf.toByteArray(); 80 byte[] data = buf.toByteArray();
80 assert (data.length == SIZEOF_UINT8 + parameterNameIndices.size() * (SIZEOF_UINT16 + SIZEOF_UINT16)); 81 assert (data.length == SIZEOF_UINT8 + parameterNameIndices.size() * (SIZEOF_UINT16 + SIZEOF_UINT16));
81 return data; 82 return data;
82 } catch (IOException ex) { 83 } catch (IOException ex) {
83 throw new Error(ex); 84 throw new Error(ex);
84 } 85 }
85 } 86 }
86} 87}