Пример #1
0
 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);
 }
Пример #2
0
        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);
        }
Пример #3
0
        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;
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        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();
        }