public Java.Attributes.Code End(Java.ConstantPool pool) { Java.Attributes.Code result = new Java.Attributes.Code(); result.CodeBytes = Link(pool); StackSimulator.SimulateStack(pool, result); return(result); }
private void GenerateBaseByRefType(JavaPrimitiveType type) { if ((baseTypesGenerated & (1 << (int)type)) != 0) { return; } Java.Class javaClass = new Java.Class(); javaClass.AccessFlag = Java.ClassAccessFlag.Abstract | Java.ClassAccessFlag.Public | Java.ClassAccessFlag.Super; javaClass.ThisClass = TypeNameToJava(new JavaByRefType(ByRefPlace.Unknown, type).ToString()); javaClass.SuperClass = TypeNameToJava(ClassNames.JavaObject); Java.Method ctor = new Java.Method(); ctor.AccessFlags = Java.MethodAccessFlags.Public; ctor.Name = ClassNames.JavaConstructorMethodName; ctor.Descriptor = "()V"; JavaBytecodeWriter ctorCodeGenerator = new JavaBytecodeWriter(); ctorCodeGenerator .AddLocalVarInstruction(LocalVarInstruction.Load, JavaPrimitiveType.Ref, 0, null) .AddInstruction(new JavaInstruction(Java.OpCodes.invokespecial, ClassNames.JavaObjectCtorMethodRef)) .AddReturn(JavaPrimitiveType.Void, null); Java.Attributes.Code ctorCode = new Java.Attributes.Code(); ctorCode.CodeBytes = ctorCodeGenerator.Link(javaClass.ConstantPool); ctorCode.MaxLocals = 1; ctorCode.MaxStack = 1; ctor.Attributes.Add(ctorCode); javaClass.Methods.Add(ctor); Java.Method getValue = new Java.Method(); getValue.AccessFlags = Java.MethodAccessFlags.Abstract | Java.MethodAccessFlags.Public; getValue.Name = ClassNames.ByRef.GetValueMethodName; getValue.Descriptor = GetByRefGetValueDescriptor(type); javaClass.Methods.Add(getValue); Java.Method setValue = new Java.Method(); setValue.AccessFlags = Java.MethodAccessFlags.Abstract | Java.MethodAccessFlags.Public; setValue.Name = ClassNames.ByRef.SetValueMethodName; setValue.Descriptor = GetByRefSetValueDescriptor(type); javaClass.Methods.Add(setValue); WriteClass(javaClass); baseTypesGenerated |= (1 << (int)type); }
public static void SimulateStack(Java.ConstantPool Pool, Java.Attributes.Code resultCode) { List <int> SimulatedInstructions = new List <int>(); Dictionary <int, int> Branches = new Dictionary <int, int>(); StackImitator Stack = new StackImitator(); Branches.Add(0, 0); foreach (Java.Attributes.Code.Exception E in resultCode.ExceptionTable) { Branches.Add(E.HandlerPC, 1); } byte[] Code = resultCode.CodeBytes; int CodeLength = Code.Length; bool LastWide = false; int LocalVarCount = 0; while (Branches.Count > 0) { KeyValuePair <int, int> Branch = Branches.First(); Branches.Remove(Branch.Key); Stack.Value = Branch.Value; int Position = Branch.Key; while (Position < CodeLength) { if (SimulatedInstructions.Contains(Position)) { break; } SimulatedInstructions.Add(Position); Java.OpCodes OpCode = (Java.OpCodes)Code[Position]; if (OpCode == Java.OpCodes.wide) { LastWide = true; Position++; continue; } ByteCode.JavaInstructionDescption Desc = ByteCode.JavaInstructions[OpCode]; int Size = Desc.Size; if (LastWide) { Size = (Size - 1) * 2 + 1; LastWide = false; } int Operand = 0; if ((Desc.OpType != ByteCode.JavaOperandType.None) && (Desc.OpType != ByteCode.JavaOperandType.Special)) { Operand = BitConverterBE.ReadAsInt32(Code, Position + 1, Size - 1); } if (OpCodeToVarIndex.ContainsKey(OpCode)) { int varIndex = OpCodeToVarIndex[OpCode]; if (varIndex < 0) { varIndex = Operand; } if (Array.IndexOf(DoubleSizeVars, OpCode) >= 0) { varIndex++; } LocalVarCount = Math.Max(LocalVarCount, varIndex + 1); } if (Desc.OpType == ByteCode.JavaOperandType.Special) { if (OpCode == Java.OpCodes.invokeinterface) { Operand = BitConverterBE.ReadAsInt32(Code, Position + 1, Size - 1); uint tmp = ((uint)((Operand & 0xffff0000) >> 16) | (uint)((Operand & 0xffff) << 16)); Operand = unchecked ((int)tmp); } } if (Desc.PopAction != null) { Stack.Pop(Desc.PopAction(Operand, Pool)); } if (Desc.PushAction != null) { Stack.Push(Desc.PushAction(Operand, Pool)); } if (Desc.BranchType == ByteCode.JavaBranchType.Break) { break; } else if (Desc.BranchType == ByteCode.JavaBranchType.Conditional) { if ((OpCode == Java.OpCodes.jsr) || (OpCode == Java.OpCodes.jsr_w)) { Stack.Push(1); } int NextPosition = Position + Operand; if (!Branches.ContainsKey(NextPosition)) { Branches.Add(NextPosition, Stack.Value); } if ((OpCode == Java.OpCodes.jsr) || (OpCode == Java.OpCodes.jsr_w)) { Stack.Pop(0); } Position += Size; } else if (Desc.BranchType == ByteCode.JavaBranchType.Switch) { int PaddingLength = (4 - ((Position + 1) % 4)) % 4; int SwitchArrayStart = Position + PaddingLength + 1; int NextPosition = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart, 4); if (OpCode == Java.OpCodes.lookupswitch) { int Count = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 4, 4); for (int i = 0; i < Count; i++) { int Offset = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 8 + (i * 8) + 4, 4); int NextPos = Position + Offset; if (!Branches.ContainsKey(NextPos)) { Branches.Add(Position + Offset, Stack.Value); } } } else if (OpCode == Java.OpCodes.tableswitch) { int low = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 4, 4); int hight = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 8, 4); for (int i = 0; i < hight - low + 1; i++) { int Offset = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 12 + (i * 4), 4); int NextPos = Position + Offset; if (!Branches.ContainsKey(NextPos)) { Branches.Add(Position + Offset, Stack.Value); } } } Position += NextPosition; } else if (Desc.BranchType == ByteCode.JavaBranchType.Goto) { Position += Operand; } else if (Desc.BranchType == ByteCode.JavaBranchType.Next) { Position += Size; } } } resultCode.MaxStack = (ushort)Stack.MaxValue; resultCode.MaxLocals = (ushort)LocalVarCount; }
public void Compile() { MethodDefinition methodDef = thisMethod.Body.Method; Messages.Verbose(" Generating IL graph..."); ILAstBuilder builder = new ILAstBuilder(); ilBody = new ILBlock(); DecompilerContext context = new DecompilerContext(methodDef.Module) { CurrentType = methodDef.DeclaringType, CurrentMethod = methodDef }; Utils.SetDecompillerSettings(context.Settings); ilBody.Body = builder.Build(methodDef, true, context); new ILAstOptimizer().Optimize(context, ilBody); FillVars(builder.Parameters); Messages.Verbose(" Preprocess IL graph..."); RunPreprocessor(); Messages.Verbose(" Compiling IL graph to java bytecode..."); CompileNode(ilBody, ExpectType.None); //Checking for deleted last ret if (ilBody.Body.Count > 0) { ILNode lastNode = ilBody.Body.Last(); if ((lastNode is ILExpression) && (((ILExpression)lastNode).Code != ILCode.Ret) && (((ILExpression)lastNode).Code != ILCode.Throw)) { CompileRet(null, ExpectType.None); } else if (thisMethod.ReturnParameter.Type.PrimitiveType == PrimitiveType.Void) { CompileRet(null, ExpectType.None); } } else { CompileRet(null, ExpectType.None); } oldCodeGenerator = codeGenerator; byte[] prolog = GenerateMethodProlog(); codeGenerator = oldCodeGenerator; Messages.Verbose(" Linking java bytecode..."); codeGenerator.StartOffset = prolog.Length; byte[] codeBytes = codeGenerator.Link(constsPool); GenerateJavaExceptionTable(); resultCode = new Java.Attributes.Code(); resultCode.CodeBytes = prolog.Concat(codeBytes).ToArray(); WriteJavaExceptionTable(prolog.Length); Messages.Verbose(" Simulating stack to calculate MaxStack and MaxLocals..."); StackSimulator.SimulateStack(constsPool, resultCode); resultCode.MaxLocals = (ushort)nextVarIndex; if (Program.Debug) { GenerateDebugInfo(prolog.Length); } }
public static Attribute ReadAttribute(BinaryReader Reader, ConstantPool Pool) { string Name = ((Constants.Utf8)Pool[Reader.ReadUInt16BE()]).Value; uint Length = Reader.ReadUInt32BE(); long Next = (long)Reader.BaseStream.Position - (long)(Length - 6); Attribute Result = null; if (Name == "AnnotationDefault") { Result = new Attributes.AnnotationDefault(); } else if (Name == "Code") { Result = new Attributes.Code(); } else if (Name == "ConstantValue") { Result = new Attributes.ConstantValue(); } else if (Name == "Deprecated") { Result = new Attributes.Deprecated(); } else if (Name == "Exceptions") { Result = new Attributes.Exceptions(); } else if (Name == "InnerClasses") { Result = new Attributes.InnerClasses(); } else if (Name == "LineNumberTable") { Result = new Attributes.LineNumberTable(); } else if (Name == "LocalVariableTable") { Result = new Attributes.LocalVariableTable(); } else if (Name == "RuntimeVisibleAnnotations") { Result = new Attributes.RuntimeVisibleAnnotations(); } else if (Name == "RuntimeInvisibleAnnotations") { Result = new Attributes.RuntimeInvisibleAnnotations(); } else if (Name == "RuntimeVisibleParameterAnnotations") { Result = new Attributes.RuntimeVisibleParameterAnnotations(Reader.ReadByte()); } else if (Name == "RuntimeInvisibleParameterAnnotations") { Result = new Attributes.RuntimeInvisibleParameterAnnotations(Reader.ReadByte()); } else if (Name == "Signature") { Result = new Attributes.Signature(); } else if (Name == "SourceFile") { Result = new Attributes.SourceFile(); } else if (Name == "Synthetic") { Result = new Attributes.Synthetic(); } else { Result = new Attributes.RawAttribute(); Result.Name = Name; } Result.Read(Length, Reader, Pool); return(Result); }
private static void Disasm(Attributes.Code codeAttr, ConstantPool pool, CountingStreamWriter writer, string[] sourceFile) { byte[] code = codeAttr.CodeBytes; int i = 0; bool lastWide = false; Attributes.LineNumberTable lnt = codeAttr.Attributes.Where(A => A is Attributes.LineNumberTable).FirstOrDefault() as Attributes.LineNumberTable; Attributes.LineNumberTable newLnt = new Attributes.LineNumberTable(); int lastLine = 0; while (i < code.Length) { if ((lnt != null) && (sourceFile != null)) { try { var lns = lnt.Table.Where(ln => ln.StartPC <= i); if (lns.Count() > 0) { int currLine = lns.Aggregate((i1, i2) => i1.StartPC > i2.StartPC ? i1 : i2).LineNumberInFile; if (lastLine != currLine) { writer.WriteLine(" ## {0}", sourceFile[currLine]); } lastLine = currLine; } } catch (Exception) { } } newLnt.Table.Add(new Attributes.LineNumberTable.LineNumber((ushort)i, (ushort)writer.CurrLine)); OpCodes op = (OpCodes)code[i]; if (!lastWide) { writer.Write(" {0,4:X} : ", i); } if (op == OpCodes.wide) { writer.Write("wide "); i++; lastWide = true; continue; } string opStr = op.ToString(); string operandStr = ""; if (opStr[0] == '_') { opStr = opStr.Substring(1); } writer.Write(opStr); ByteCode.JavaInstructionDescption descr = ByteCode.JavaInstructions[op]; int operandSize = descr.Size - 1; if (lastWide) { operandSize *= 2; lastWide = false; } switch (descr.OpType) { case ByteCode.JavaOperandType.ConstPool: ushort index = (ushort)BitConverterBE.ReadAsInt32(code, i + 1, operandSize); operandStr = pool[index].ToString(); break; case ByteCode.JavaOperandType.ConstValue: case ByteCode.JavaOperandType.LocalVar: operandStr = BitConverterBE.ReadAsInt32(code, i + 1, operandSize).ToString(); break; case ByteCode.JavaOperandType.Offset: short offset = (short)BitConverterBE.ReadAsInt32(code, i + 1, operandSize); operandStr = String.Format("{0,4:X}", (i + offset)); break; case ByteCode.JavaOperandType.Special: switch (op) { case OpCodes.iinc: int op1 = BitConverterBE.ReadAsInt32(code, i + 1, operandSize / 2); int op2 = BitConverterBE.ReadAsInt32(code, i + 1 + operandSize / 2, operandSize / 2); operandStr = String.Format("{0}, {1}", op1, op2); break; case OpCodes.lookupswitch: int paddingLength = (4 - ((i + 1) % 4)) % 4; int _default = BitConverterBE.ReadAsInt32(code, i + paddingLength + 1, 4); int npairs = BitConverterBE.ReadAsInt32(code, i + paddingLength + 5, 4); int pairsStart = i + paddingLength + 9; operandSize = npairs * 8 + 8 + paddingLength; writer.WriteLine(" default: {0,4:X}, npairs: {1}", _default, npairs); for (int pair = 0; pair < npairs; pair++) { int pairValue = BitConverterBE.ReadAsInt32(code, pairsStart + (pair * 8), 4); int pairOffset = BitConverterBE.ReadAsInt32(code, pairsStart + (pair * 8) + 4, 4); writer.WriteLine(" {0,4:X} : {1}", pairOffset, pairValue); } break; case OpCodes.tableswitch: paddingLength = (4 - ((i + 1) % 4)) % 4; _default = BitConverterBE.ReadAsInt32(code, i + paddingLength + 1, 4); int low = BitConverterBE.ReadAsInt32(code, i + paddingLength + 5, 4); int hight = BitConverterBE.ReadAsInt32(code, i + paddingLength + 9, 4); writer.WriteLine(" default: {0,4:X}, low: {1}, hight: {2}", _default, low, hight); int jmpCount = hight - low + 1; int jmpStart = i + paddingLength + 13; operandSize = jmpCount * 4 + 13 + paddingLength; for (int jmp = 0; jmp < jmpCount; jmp++) { writer.WriteLine(" {0,4:X} : {1}", BitConverterBE.ReadAsInt32(code, jmpStart + jmp * 4, 4), low + jmp); } break; case OpCodes.invokeinterface: case OpCodes.invokedynamic: index = (ushort)BitConverterBE.ReadAsInt32(code, i + 1, 2); operandStr = pool[index].ToString(); break; case OpCodes.newarray: operandStr = ArrayTypes[code[i + 1]]; break; case OpCodes.multianewarray: index = (ushort)BitConverterBE.ReadAsInt32(code, i + 1, 2); byte dismensions = code[i + 3]; operandStr = String.Format("{0}, {1}", dismensions, pool[index].ToString()); break; } ; break; } writer.WriteLine(" {0}", operandStr); i += 1 + operandSize; } if (Program.DebugBytecode) { if (lnt != null) { codeAttr.Attributes.Remove(lnt); } codeAttr.Attributes.Add(newLnt); } }
public static void Dump(Java.Class value, Stream output) { string[] sourceFile = null; CountingStreamWriter writer = new CountingStreamWriter(output); writer.WriteLine("Class file version: {0}.{1}", value.MajorVersion, value.MinorVersion); writer.WriteLine("class {0} extends {1}", value.ThisClass, value.SuperClass); writer.WriteLine("Access Flags: {0}", value.AccessFlag.ToString()); writer.WriteLine("Interfaces (count: {0}):", value.Interfaces.Count); foreach (string iface in value.Interfaces) { writer.WriteLine(" " + iface); } writer.WriteLine("Attributes (count: {0}):", value.Attributes.Count); for (int i = 0; i < value.Attributes.Count; i++) { writer.WriteLine("{0,6:G}: {1}", i, value.Attributes[i].Name); value.Attributes[i].Dump(writer, " "); if ((value.Attributes[i] is Attributes.SourceFile) && (Program.FullPathInSourceFileName)) { using (StreamReader r = new StreamReader(((Attributes.SourceFile)value.Attributes[i]).Value)) sourceFile = r.ReadAllLines(); } } writer.WriteLine("Fields (count: {0}):", value.Fields.Count); for (int i = 0; i < value.Fields.Count; i++) { writer.WriteLine("{0,6:G}: Name: {1}", i, value.Fields[i].Name); writer.WriteLine(" Descriptor: {0}", value.Fields[i].Descriptor); writer.WriteLine(" Access Flags: {0}", value.Fields[i].AccessFlags.ToString()); writer.WriteLine(" Attributes (count: {0}):", value.Fields[i].Attributes.Count); for (int j = 0; j < value.Fields[i].Attributes.Count; j++) { writer.WriteLine(" {0,6:G}: {1}", j, value.Fields[i].Attributes[j].Name); value.Fields[i].Attributes[j].Dump(writer, " "); } writer.WriteLine(); } writer.WriteLine("Methods (count: {0}):", value.Methods.Count); for (int i = 0; i < value.Methods.Count; i++) { writer.WriteLine("{0,6:G}: Name: {1}", i, value.Methods[i].Name); writer.WriteLine(" Descriptor: {0}", value.Methods[i].Descriptor); writer.WriteLine(" Access Flags: {0}", value.Methods[i].AccessFlags.ToString()); Attributes.Code code = null; writer.WriteLine(" Attributes (count: {0}):", value.Attributes.Count); for (int j = 0; j < value.Methods[i].Attributes.Count; j++) { writer.WriteLine(" {0,6:G}: {1}", j, value.Methods[i].Attributes[j].Name); value.Methods[i].Attributes[j].Dump(writer, " "); if (value.Methods[i].Attributes[j] is Attributes.Code) { code = (Attributes.Code)value.Methods[i].Attributes[j]; } } if (code != null) { writer.WriteLine(); Disasm(code, value.ConstantPool, writer, sourceFile); } ; writer.WriteLine(); } writer.Close(); }