diff options
| author | 2014-08-03 11:16:33 -0400 | |
|---|---|---|
| committer | 2014-08-03 11:16:33 -0400 | |
| commit | 76be350b3c54ea88cc1a95b5cf0d1db153f2edb3 (patch) | |
| tree | 91baffda41c4fcdcc69c646287e98d6d2a0f80d6 /src/cuchaz/enigma/bytecode | |
| parent | started working on method parameter renaming (diff) | |
| download | enigma-fork-76be350b3c54ea88cc1a95b5cf0d1db153f2edb3.tar.gz enigma-fork-76be350b3c54ea88cc1a95b5cf0d1db153f2edb3.tar.xz enigma-fork-76be350b3c54ea88cc1a95b5cf0d1db153f2edb3.zip | |
fixed bugs with saving mappings
got argument renaming to work
Diffstat (limited to 'src/cuchaz/enigma/bytecode')
| -rw-r--r-- | src/cuchaz/enigma/bytecode/MethodParameterWriter.java | 26 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/MethodParametersAttribute.java | 46 |
2 files changed, 55 insertions, 17 deletions
diff --git a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java index 1e5d1f0..a8d3983 100644 --- a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java +++ b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java | |||
| @@ -10,9 +10,15 @@ | |||
| 10 | ******************************************************************************/ | 10 | ******************************************************************************/ |
| 11 | package cuchaz.enigma.bytecode; | 11 | package cuchaz.enigma.bytecode; |
| 12 | 12 | ||
| 13 | import java.util.ArrayList; | ||
| 14 | import java.util.List; | ||
| 15 | |||
| 13 | import javassist.CtBehavior; | 16 | import javassist.CtBehavior; |
| 14 | import javassist.CtClass; | 17 | import javassist.CtClass; |
| 15 | import javassist.bytecode.AttributeInfo; | 18 | import javassist.bytecode.Descriptor; |
| 19 | import cuchaz.enigma.mapping.ArgumentEntry; | ||
| 20 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 21 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 16 | import cuchaz.enigma.mapping.Translator; | 22 | import cuchaz.enigma.mapping.Translator; |
| 17 | 23 | ||
| 18 | public class MethodParameterWriter | 24 | public class MethodParameterWriter |
| @@ -27,9 +33,25 @@ public class MethodParameterWriter | |||
| 27 | public void writeMethodArguments( CtClass c ) | 33 | public void writeMethodArguments( CtClass c ) |
| 28 | { | 34 | { |
| 29 | // Procyon will read method arguments from the "MethodParameters" attribute, so write those | 35 | // Procyon will read method arguments from the "MethodParameters" attribute, so write those |
| 36 | ClassEntry classEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); | ||
| 30 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) | 37 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) |
| 31 | { | 38 | { |
| 32 | AttributeInfo attribute = behavior.getMethodInfo().getAttribute( "MethodParameter" ); | 39 | int numParams = Descriptor.numOfParameters( behavior.getMethodInfo().getDescriptor() ); |
| 40 | if( numParams <= 0 ) | ||
| 41 | { | ||
| 42 | continue; | ||
| 43 | } | ||
| 44 | |||
| 45 | // get the list of parameter names | ||
| 46 | MethodEntry methodEntry = new MethodEntry( classEntry, behavior.getMethodInfo().getName(), behavior.getSignature() ); | ||
| 47 | List<String> names = new ArrayList<String>( numParams ); | ||
| 48 | for( int i=0; i<numParams; i++ ) | ||
| 49 | { | ||
| 50 | names.add( m_translator.translate( new ArgumentEntry( methodEntry, i, "" ) ) ); | ||
| 51 | } | ||
| 52 | |||
| 53 | // save the mappings to the class | ||
| 54 | MethodParametersAttribute.updateClass( behavior.getMethodInfo(), names ); | ||
| 33 | } | 55 | } |
| 34 | } | 56 | } |
| 35 | } | 57 | } |
diff --git a/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java b/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java index 0b29403..baf1ac1 100644 --- a/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java +++ b/src/cuchaz/enigma/bytecode/MethodParametersAttribute.java | |||
| @@ -13,24 +13,45 @@ package cuchaz.enigma.bytecode; | |||
| 13 | import java.io.ByteArrayOutputStream; | 13 | import java.io.ByteArrayOutputStream; |
| 14 | import java.io.DataOutputStream; | 14 | import java.io.DataOutputStream; |
| 15 | import java.io.IOException; | 15 | import java.io.IOException; |
| 16 | import java.util.ArrayList; | ||
| 16 | import java.util.List; | 17 | import java.util.List; |
| 17 | 18 | ||
| 18 | import javassist.bytecode.AttributeInfo; | 19 | import javassist.bytecode.AttributeInfo; |
| 19 | import javassist.bytecode.ConstPool; | 20 | import javassist.bytecode.ConstPool; |
| 21 | import javassist.bytecode.MethodInfo; | ||
| 20 | 22 | ||
| 21 | public class MethodParametersAttribute extends AttributeInfo | 23 | public class MethodParametersAttribute extends AttributeInfo |
| 22 | { | 24 | { |
| 23 | public MethodParametersAttribute( ConstPool pool, int attributeNameIndex, List<Integer> parameterNameIndices ) | 25 | private MethodParametersAttribute( ConstPool pool, List<Integer> parameterNameIndices ) |
| 24 | { | 26 | { |
| 25 | super( pool, "MethodParameters", writeStruct( attributeNameIndex, parameterNameIndices ) ); | 27 | super( pool, "MethodParameters", writeStruct( parameterNameIndices ) ); |
| 26 | } | 28 | } |
| 27 | 29 | ||
| 28 | private static byte[] writeStruct( int attributeNameIndex, List<Integer> parameterNameIndices ) | 30 | public static void updateClass( MethodInfo info, List<String> names ) |
| 29 | { | 31 | { |
| 30 | // JVM Spec says the struct looks like this: | 32 | // add the names to the class const pool |
| 33 | ConstPool constPool = info.getConstPool(); | ||
| 34 | List<Integer> parameterNameIndices = new ArrayList<Integer>(); | ||
| 35 | for( String name : names ) | ||
| 36 | { | ||
| 37 | if( name != null ) | ||
| 38 | { | ||
| 39 | parameterNameIndices.add( constPool.addUtf8Info( name ) ); | ||
| 40 | } | ||
| 41 | else | ||
| 42 | { | ||
| 43 | parameterNameIndices.add( 0 ); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | // add the attribute to the method | ||
| 48 | info.addAttribute( new MethodParametersAttribute( constPool, parameterNameIndices ) ); | ||
| 49 | } | ||
| 50 | |||
| 51 | private static byte[] writeStruct( List<Integer> parameterNameIndices ) | ||
| 52 | { | ||
| 53 | // JVM 8 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 | 54 | // 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 | 55 | // uint8 num_params |
| 35 | // for each param: | 56 | // for each param: |
| 36 | // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry | 57 | // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry |
| @@ -43,20 +64,13 @@ public class MethodParametersAttribute extends AttributeInfo | |||
| 43 | // the writeShort(), writeByte() methods will read 16,8 low-order bits from the int argument | 64 | // 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 | 65 | // 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 | 66 | // if the int is out of range, the byte stream won't look the way we want and weird things will happen |
| 67 | final int SIZEOF_UINT8 = 1; | ||
| 46 | final int SIZEOF_UINT16 = 2; | 68 | final int SIZEOF_UINT16 = 2; |
| 47 | final int MAX_UINT8 = ( 1 << 8 ) - 1; | 69 | final int MAX_UINT8 = ( 1 << 8 ) - 1; |
| 48 | final int MAX_UINT16 = ( 1 << 16 ) - 1; | 70 | final int MAX_UINT16 = ( 1 << 16 ) - 1; |
| 49 | final long MAX_UINT32 = ( 1 << 32 ) - 1; | ||
| 50 | 71 | ||
| 51 | try | 72 | try |
| 52 | { | 73 | { |
| 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 ); | 74 | assert( parameterNameIndices.size() >= 0 && parameterNameIndices.size() <= MAX_UINT8 ); |
| 61 | out.writeByte( parameterNameIndices.size() ); | 75 | out.writeByte( parameterNameIndices.size() ); |
| 62 | 76 | ||
| @@ -70,7 +84,9 @@ public class MethodParametersAttribute extends AttributeInfo | |||
| 70 | } | 84 | } |
| 71 | 85 | ||
| 72 | out.close(); | 86 | out.close(); |
| 73 | return buf.toByteArray(); | 87 | byte[] data = buf.toByteArray(); |
| 88 | assert( data.length == SIZEOF_UINT8 + parameterNameIndices.size()*( SIZEOF_UINT16 + SIZEOF_UINT16 ) ); | ||
| 89 | return data; | ||
| 74 | } | 90 | } |
| 75 | catch( IOException ex ) | 91 | catch( IOException ex ) |
| 76 | { | 92 | { |