From 76be350b3c54ea88cc1a95b5cf0d1db153f2edb3 Mon Sep 17 00:00:00 2001 From: jeff Date: Sun, 3 Aug 2014 11:16:33 -0400 Subject: fixed bugs with saving mappings got argument renaming to work --- .../enigma/bytecode/MethodParameterWriter.java | 26 +++++++++++- .../enigma/bytecode/MethodParametersAttribute.java | 46 +++++++++++++++------- 2 files changed, 55 insertions(+), 17 deletions(-) (limited to 'src/cuchaz/enigma/bytecode') 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 @@ ******************************************************************************/ package cuchaz.enigma.bytecode; +import java.util.ArrayList; +import java.util.List; + import javassist.CtBehavior; import javassist.CtClass; -import javassist.bytecode.AttributeInfo; +import javassist.bytecode.Descriptor; +import cuchaz.enigma.mapping.ArgumentEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.MethodEntry; import cuchaz.enigma.mapping.Translator; public class MethodParameterWriter @@ -27,9 +33,25 @@ public class MethodParameterWriter public void writeMethodArguments( CtClass c ) { // Procyon will read method arguments from the "MethodParameters" attribute, so write those + ClassEntry classEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); for( CtBehavior behavior : c.getDeclaredBehaviors() ) { - AttributeInfo attribute = behavior.getMethodInfo().getAttribute( "MethodParameter" ); + int numParams = Descriptor.numOfParameters( behavior.getMethodInfo().getDescriptor() ); + if( numParams <= 0 ) + { + continue; + } + + // get the list of parameter names + MethodEntry methodEntry = new MethodEntry( classEntry, behavior.getMethodInfo().getName(), behavior.getSignature() ); + List names = new ArrayList( numParams ); + for( int i=0; i parameterNameIndices ) + private MethodParametersAttribute( ConstPool pool, List parameterNameIndices ) { - super( pool, "MethodParameters", writeStruct( attributeNameIndex, parameterNameIndices ) ); + super( pool, "MethodParameters", writeStruct( parameterNameIndices ) ); } - private static byte[] writeStruct( int attributeNameIndex, List parameterNameIndices ) + public static void updateClass( MethodInfo info, List names ) { - // JVM Spec says the struct looks like this: + // add the names to the class const pool + ConstPool constPool = info.getConstPool(); + List parameterNameIndices = new ArrayList(); + for( String name : names ) + { + if( name != null ) + { + parameterNameIndices.add( constPool.addUtf8Info( name ) ); + } + else + { + parameterNameIndices.add( 0 ); + } + } + + // add the attribute to the method + info.addAttribute( new MethodParametersAttribute( constPool, parameterNameIndices ) ); + } + + private static byte[] writeStruct( List parameterNameIndices ) + { + // JVM 8 Spec says the struct looks like this: // http://cr.openjdk.java.net/~mr/se/8/java-se-8-fr-spec-01/java-se-8-jvms-fr-diffs.pdf - // uint16 name_index -> points to UTF8 entry in constant pool that says "MethodParameters" - // uint32 length -> length of this struct, minus 6 bytes (ie, length of num_params and parameter array) // uint8 num_params // for each param: // uint16 name_index -> points to UTF8 entry in constant pool, or 0 for no entry @@ -43,20 +64,13 @@ public class MethodParametersAttribute extends AttributeInfo // the writeShort(), writeByte() methods will read 16,8 low-order bits from the int argument // as long as the int argument is in range of the unsigned short/byte type, it will be written as an unsigned short/byte // if the int is out of range, the byte stream won't look the way we want and weird things will happen + final int SIZEOF_UINT8 = 1; final int SIZEOF_UINT16 = 2; final int MAX_UINT8 = ( 1 << 8 ) - 1; final int MAX_UINT16 = ( 1 << 16 ) - 1; - final long MAX_UINT32 = ( 1 << 32 ) - 1; try { - assert( attributeNameIndex >= 0 && attributeNameIndex <= MAX_UINT16 ); - out.writeShort( attributeNameIndex ); - - long length = SIZEOF_UINT16 + parameterNameIndices.size()*( SIZEOF_UINT16 + SIZEOF_UINT16 ); - assert( length >= 0 && length <= MAX_UINT32 ); - out.writeInt( (int)length ); - assert( parameterNameIndices.size() >= 0 && parameterNameIndices.size() <= MAX_UINT8 ); out.writeByte( parameterNameIndices.size() ); @@ -70,7 +84,9 @@ public class MethodParametersAttribute extends AttributeInfo } out.close(); - return buf.toByteArray(); + byte[] data = buf.toByteArray(); + assert( data.length == SIZEOF_UINT8 + parameterNameIndices.size()*( SIZEOF_UINT16 + SIZEOF_UINT16 ) ); + return data; } catch( IOException ex ) { -- cgit v1.2.3