summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/bytecode/MethodParametersAttribute.java')
-rw-r--r--src/cuchaz/enigma/bytecode/MethodParametersAttribute.java80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java b/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java
new file mode 100644
index 0000000..0b29403
--- /dev/null
+++ b/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java
@@ -0,0 +1,80 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import java.io.ByteArrayOutputStream;
14import java.io.DataOutputStream;
15import java.io.IOException;
16import java.util.List;
17
18import javassist.bytecode.AttributeInfo;
19import javassist.bytecode.ConstPool;
20
21public class MethodParametersAttribute extends AttributeInfo
22{
23 public MethodParametersAttribute( ConstPool pool, int attributeNameIndex, List<Integer> parameterNameIndices )
24 {
25 super( pool, "MethodParameters", writeStruct( attributeNameIndex, parameterNameIndices ) );
26 }
27
28 private static byte[] writeStruct( int attributeNameIndex, List<Integer> parameterNameIndices )
29 {
30 // JVM Spec says the struct looks like this:
31 // http://cr.openjdk.java.net/~mr/se/8/java-se-8-fr-spec-01/java-se-8-jvms-fr-diffs.pdf
32 // uint16 name_index -> points to UTF8 entry in constant pool that says "MethodParameters"
33 // uint32 length -> length of this struct, minus 6 bytes (ie, length of num_params and parameter array)
34 // uint8 num_params
35 // for each param:
36 // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry
37 // uint16 access_flags -> don't care, just set to 0
38
39 ByteArrayOutputStream buf = new ByteArrayOutputStream();
40 DataOutputStream out = new DataOutputStream( buf );
41
42 // NOTE: java hates unsigned integers, so we have to be careful here
43 // the writeShort(), writeByte() methods will read 16,8 low-order bits from the int argument
44 // as long as the int argument is in range of the unsigned short/byte type, it will be written as an unsigned short/byte
45 // if the int is out of range, the byte stream won't look the way we want and weird things will happen
46 final int SIZEOF_UINT16 = 2;
47 final int MAX_UINT8 = ( 1 << 8 ) - 1;
48 final int MAX_UINT16 = ( 1 << 16 ) - 1;
49 final long MAX_UINT32 = ( 1 << 32 ) - 1;
50
51 try
52 {
53 assert( attributeNameIndex >= 0 && attributeNameIndex <= MAX_UINT16 );
54 out.writeShort( attributeNameIndex );
55
56 long length = SIZEOF_UINT16 + parameterNameIndices.size()*( SIZEOF_UINT16 + SIZEOF_UINT16 );
57 assert( length >= 0 && length <= MAX_UINT32 );
58 out.writeInt( (int)length );
59
60 assert( parameterNameIndices.size() >= 0 && parameterNameIndices.size() <= MAX_UINT8 );
61 out.writeByte( parameterNameIndices.size() );
62
63 for( Integer index : parameterNameIndices )
64 {
65 assert( index >= 0 && index <= MAX_UINT16 );
66 out.writeShort( index );
67
68 // just write 0 for the access flags
69 out.writeShort( 0 );
70 }
71
72 out.close();
73 return buf.toByteArray();
74 }
75 catch( IOException ex )
76 {
77 throw new Error( ex );
78 }
79 }
80}