Beispiel #1
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Add(v=vs.110).aspx
         * Description : Adds two values and pushes the result onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 2)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 2");
            }

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();

            var size = Math.Max(Helper.GetTypeSize(itemA.OperandType, Config.TargetPlatform),
                                Helper.GetTypeSize(itemB.OperandType, Config.TargetPlatform));

            /* The stack transitional behavior, in sequential order, is:
             * value1 is pushed onto the stack.
             * value2 is pushed onto the stack.
             * value2 and value1 are popped from the stack; value1 is added to value2.
             * The result is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (itemA.IsFloat || itemB.IsFloat || size > 4)
                {
                    throw new Exception(string.Format("UnImplemented '{0}'", msIL));
                }

                if (!itemA.SystemStack || !itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Add {
                    DestinationReg = Register.ESP, SourceReg = Register.EAX, DestinationIndirect = true
                };

                Optimizer.vStack.Push(new StackItem(itemA.OperandType));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #2
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Conv_I1(v=vs.110).aspx
         * Description : Converts the value on top of the evaluation stack to native int
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var item = Optimizer.vStack.Pop();
            var size = Helper.GetTypeSize(item.OperandType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * value is pushed onto the stack.
             * value is popped from the stack and the conversion operation is attempted.
             * If the conversion is successful, the resulting value is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (item.IsFloat || size > 4)
                {
                    throw new Exception(string.Format("UnImplemented '{0}'", msIL));
                }

                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Movsx {
                    DestinationReg = Register.EAX, SourceReg = Register.AL, Size = 8
                };
                new Push {
                    DestinationReg = Register.EAX
                };

                Optimizer.vStack.Push(new StackItem(typeof(int)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #3
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Switch(v=vs.110).aspx
         * Description : Implements a jump table.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var branches = ((OpSwitch)xOp).Value;

            /* The stack transitional behavior, in sequential order, is:
             * A value is pushed onto the stack.
             * The value is popped off the stack and execution is transferred to the instruction at the offset indexed by the value, where the value is less than N.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                for (int i = 0; i < branches.Length; i++)
                {
                    new Cmp {
                        DestinationReg = Register.EAX, SourceRef = "0x" + i.ToString("X")
                    };
                    new Jmp {
                        Condition = ConditionalJump.JE, DestinationRef = Helper.GetLabel(branches[i])
                    };
                    Optimizer.SaveStack(branches[i]);
                }

                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #4
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stelem_Ref(v=vs.110).aspx
         * Description : Replaces the array element at a given index with the object ref value (type O) on the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 3)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 3");
            }

            /* The stack transitional behavior, in sequential order, is:
             * An object reference to an array, array, is pushed onto the stack.
             * An index value, index, to an element in array is pushed onto the stack.
             * A value of the type specified in the instruction is pushed onto the stack.
             * The value, the index, and the array reference are popped from the stack; the value is put into the array element at the given index.
             */

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();
            var itemC = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!itemA.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                if (!itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                if (!itemC.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                Stelem_il.Executex86(4);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #5
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Dup(v=vs.110).aspx
         * Description : Copies the current topmost value on the evaluation stack, and then pushes the copy onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var item = Optimizer.vStack.Peek();
            var size = Helper.GetTypeSize(item.OperandType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * value is pushed onto the stack.
             * value is popped off of the stack for duplication.
             * value is pushed back onto the stack.
             * A duplicate value is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (size > 4)
                {
                    throw new Exception(string.Format("UnImplemented '{0}'", msIL));
                }

                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Push {
                    DestinationReg = Register.ESP, DestinationIndirect = true
                };

                Optimizer.vStack.Push(new StackItem(item.OperandType));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #6
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldelem_U4(v=vs.110).aspx
         * Description : Loads the element with type unsigned int32 at a specified array index onto the top of the evaluation stack as an int32.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 2)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 2");
            }

            /* The stack transitional behavior, in sequential order, is:
             * An object reference array is pushed onto the stack.
             * An index value index is pushed onto the stack.
             * index and array are popped from the stack; the value stored at position index in array is looked up.
             * The value is pushed onto the stack.
             */

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!itemA.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                if (!itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                Ldelem_il.Executex86(4, false);
                Optimizer.vStack.Push(new StackItem(typeof(uint)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #7
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldlen(v=vs.110).aspx
         * Description : Pushes the number of elements of a zero-based, one-dimensional array onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            /* The stack transitional behavior, in sequential order, is:
             * An object reference to an array is pushed onto the stack.
             * The array reference is popped from the stack and the length is computed.
             * The length is pushed onto the stack.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Push {
                    DestinationReg = Register.EAX, DestinationDisplacement = 8, DestinationIndirect = true
                };

                Optimizer.vStack.Push(new StackItem(typeof(uint)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #8
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldflda(v=vs.110).aspx
         * Description : Finds the address of a field in the object whose reference is currently on the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var field  = ((OpField)xOp).Value;
            var offset = Helper.GetFieldOffset(field.DeclaringType, field, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * An object reference (or pointer) is pushed onto the stack.
             * The object reference (or pointer) is popped from the stack; the address of the specified field in the object is found.
             * The address of the specified field is pushed onto the stack.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Add {
                    DestinationReg = Register.ESP, DestinationIndirect = true, SourceRef = "0x" + offset.ToString("X")
                };
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.vStack.Push(new StackItem(typeof(uint)));
            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #9
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stind_R8(v=vs.110).aspx
         * Description : Stores a value of type float64 at a supplied address.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 2)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 2");
            }

            /* The stack transitional behavior, in sequential order, is:
             * An address is pushed onto the stack.
             * A value is pushed onto the stack.
             * The value and the address are popped from the stack; the value is stored at the address.
             */

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!itemA.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                if (!itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                Stind_I_il.Executex86(8);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #10
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldnull(v=vs.110).aspx
         * Description : Pushes a null reference (type O) onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            /* The stack transitional behavior, in sequential order, is:
             * A null object reference is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                new Push {
                    DestinationRef = "0x0"
                };

                Optimizer.vStack.Push(new StackItem(typeof(uint)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #11
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldloc(v=vs.110).aspx
         * Description : Loads the local variable at a specific index onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var index = ((OpVar)xOp).Value;

            var body      = method.GetMethodBody();
            var EBPoffset = Helper.GetVariableOffset(body, index, Config.TargetPlatform);

            var varType = body.LocalVariables[index].LocalType;
            var size    = Helper.GetTypeSize(varType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * The local variable value at the specified index is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (size > 4)
                {
                    throw new Exception("LocalVariable size > 4 not supported");
                }

                new Push {
                    DestinationReg = Register.EBP, DestinationIndirect = true, DestinationDisplacement = -EBPoffset
                };
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.vStack.Push(new StackItem(varType));
            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #12
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Leave(v=vs.110).aspx
         * Description : Exits a protected region of code, unconditionally transferring control to a specific target instruction.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var offset     = ((OpBranch)xOp).Value;
            var xTrueLabel = Helper.GetLabel(offset);

            /* No evaluation stack behaviors are performed by this operation.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                new Jmp {
                    DestinationRef = xTrueLabel
                };

                Optimizer.SaveStack(offset);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #13
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Sizeof(v=vs.110).aspx
         * Description : Pushes the size, in bytes, of a supplied value type onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var type = ((OpType)xOp).Value;

            /* The stack transitional behavior, in sequential order, is:
             * The size (in bytes) of the supplied value type (valType) is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                new Push {
                    DestinationRef = "0x" + Helper.GetTypeSize(type, Config.TargetPlatform).ToString("X")
                };
                Optimizer.vStack.Push(new StackItem(typeof(uint)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #14
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldsflda(v=vs.110).aspx
         * Description : Pushes the address of a static field onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var field     = ((OpField)xOp).Value;
            var fieldName = field.FullName();
            var size      = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform);

            string cctor_addref = null;

            var cctor = (field.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (cctor != null)
            {
                cctor_addref = cctor.FullName();
            }

            /* The stack transitional behavior, in sequential order, is:
             * The value of the specific field is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                new Push {
                    DestinationRef = fieldName
                };

                Optimizer.vStack.Push(new StackItem(typeof(uint)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #15
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Throw(v=vs.110).aspx
         * Description : Throws the exception object currently on the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var item = Optimizer.vStack.Pop();

            /* The stack transitional behavior, in sequential order, is:
             * An object reference (to an exception) is pushed onto the stack.
             * The object reference is popped from the stack and the exception thrown.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.ECX
                };
                new Jmp {
                    DestinationRef = xOp.HandlerRef
                };
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #16
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldobj(v=vs.110).aspx
         * Description : Copies the value type object pointed to by an address to the top of the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var xOpType = ((OpType)xOp).Value;
            var size    = Helper.GetTypeSize(xOpType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * The address of a value type object is pushed onto the stack.
             * The address is popped from the stack and the instance at that particular address is looked up.
             * The value of the object stored at that address is pushed onto the stack.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                for (int i = 1; i <= (size / 4); i++)
                {
                    new Push
                    {
                        DestinationReg          = Register.EAX,
                        DestinationIndirect     = true,
                        DestinationDisplacement = (size - (i * 4))
                    };
                }

                switch (size % 4)
                {
                case 0: break;

                case 1:
                {
                    new Movzx {
                        DestinationReg = Register.EAX, SourceReg = Register.ESI, SourceIndirect = true, Size = 8
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                break;

                case 2:
                {
                    new Movzx {
                        DestinationReg = Register.EAX, SourceReg = Register.ESI, SourceIndirect = true, Size = 16
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                break;

                default:
                    throw new Exception("Unsupported Size");
                }

                Optimizer.vStack.Push(new StackItem(xOpType));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #17
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Clt_Un(v=vs.110).aspx
         * Description : Compares the unsigned or unordered values value1 and value2. If value1 is less than value2, then the integer value 1 (int32) is pushed onto the evaluation stack; otherwise 0 (int32) is pushed onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 2)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 2");
            }

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();

            var xCurrentLabel = Helper.GetLabel(xOp.Position);
            var xNextLabel    = Helper.GetLabel(xOp.NextPosition);

            var size = Math.Max(Helper.GetTypeSize(itemA.OperandType, Config.TargetPlatform),
                                Helper.GetTypeSize(itemB.OperandType, Config.TargetPlatform));

            /* The stack transitional behavior, in sequential order, is:
             * value1 is pushed onto the stack.
             * value2 is pushed onto the stack.
             * value2 and value1 are popped from the stack; clt.un tests if value1 is less than value2.
             * If value1 is less than value2, 1 is pushed onto the stack; otherwise 0 is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (itemA.IsFloat || itemB.IsFloat || size > 4)
                {
                    throw new Exception(string.Format("UnImplemented '{0}'", msIL));
                }

                if (!itemA.SystemStack || !itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Pop {
                    DestinationReg = Register.EDX
                };
                new Cmp {
                    DestinationReg = Register.EDX, SourceReg = Register.EAX
                };
                new Setb {
                    DestinationReg = Register.AL
                };
                new Movzx {
                    DestinationReg = Register.EAX, SourceReg = Register.AL, Size = 8
                };
                new Push {
                    DestinationReg = Register.EAX
                };

                Optimizer.vStack.Push(new StackItem(typeof(bool)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #18
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Call(v=vs.110).aspx
         * Description : Calls the method indicated by the passed method descriptor.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var xOpMethod  = (OpMethod)xOp;
            var target     = xOpMethod.Value;
            var targetinfo = target as MethodInfo;

            var  addressRefernce = target.FullName();
            bool NoException     = target.GetCustomAttribute <NoExceptionAttribute>() != null;
            var  parameters      = target.GetParameters();

            int count      = parameters.Length;
            int stacksize  = parameters.Select(a => Helper.GetTypeSize(a.ParameterType, Config.TargetPlatform, true)).Sum();
            int returnSize = 0;

            if (targetinfo != null)
            {
                returnSize = Helper.GetTypeSize(targetinfo.ReturnType, Config.TargetPlatform, true);
            }

            if (!target.IsStatic)
            {
                count++;

                Type ArgType = target.DeclaringType;
                if (target.DeclaringType.IsValueType)
                {
                    ArgType = ArgType.MakeByRefType();
                }

                stacksize += Helper.GetTypeSize(ArgType, Config.TargetPlatform, true);
            }

            if (Optimizer.vStack.Count < count)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < expected size");
            }

            /* The stack transitional behavior, in sequential order, is:
             * Method arguments arg1 through argN are pushed onto the stack.
             * Method arguments arg1 through argN are popped from the stack; the method call is performed with these arguments
             * and control is transferred to the method referred to by the method descriptor. When complete,
             * a return value is generated by the callee method and sent to the caller.
             * The return value is pushed onto the stack.
             */

            int index = count;

            while (index > 0)
            {
                Optimizer.vStack.Pop();
                index--;
            }

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (returnSize > 8)
                {
                    throw new Exception(string.Format("UnImplemented '{0}' Return-type: '{1}'", msIL, targetinfo.ReturnType));
                }

                new Call {
                    DestinationRef = addressRefernce
                };

                switch (xOpMethod.CallingConvention)
                {
                case CallingConvention.StdCall: break;

                case CallingConvention.Cdecl:
                {
                    new Add {
                        DestinationReg = Register.ESP, SourceRef = "0x" + stacksize.ToString("X")
                    };
                }
                break;

                default:
                    throw new Exception(string.Format("CallingConvention '{0}' not supported", xOpMethod.CallingConvention));
                }

                if (!NoException)
                {
                    new Test {
                        DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                    };
                    new Jmp {
                        Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                    };
                    Optimizer.SaveStack(xOp.HandlerPosition);
                }

                if (targetinfo != null && targetinfo.ReturnType != typeof(void))
                {
                    if (returnSize == 8)
                    {
                        new Push {
                            DestinationReg = Register.EDX
                        }
                    }
                    ;
                    new Push {
                        DestinationReg = Register.EAX
                    };
                    Optimizer.vStack.Push(new StackItem(targetinfo.ReturnType));
                }

                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #19
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldsfld(v=vs.110).aspx
         * Description : Pushes the value of a static field onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var field     = ((OpField)xOp).Value;
            var fieldName = field.FullName();
            var size      = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform);

            string cctor_addref = null;

            var cctor = (field.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (cctor != null)
            {
                cctor_addref = cctor.FullName();
            }

            /* The stack transitional behavior, in sequential order, is:
             * The value of the specific field is pushed onto the stack.
             */

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!string.IsNullOrEmpty(cctor_addref) && cctor != method)
                {
                    new Call {
                        DestinationRef = cctor_addref
                    }
                }
                ;

                for (int i = 1; i <= (size / 4); i++)
                {
                    new Push
                    {
                        DestinationRef          = fieldName,
                        DestinationIndirect     = true,
                        DestinationDisplacement = (size - (i * 4))
                    };
                }

                switch (size % 4)
                {
                case 0: break;

                case 1:
                {
                    new Movzx {
                        DestinationReg = Register.EAX, SourceRef = fieldName, SourceIndirect = true, Size = 8
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                break;

                case 2:
                {
                    new Movzx {
                        DestinationReg = Register.EAX, SourceRef = fieldName, SourceIndirect = true, Size = 16
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                break;

                default:
                    throw new Exception("Unsupported Size");
                }

                Optimizer.vStack.Push(new StackItem(field.FieldType));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #20
0
 internal abstract void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer);
Beispiel #21
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldfld(v=vs.110).aspx
         * Description : Finds the value of a field in the object whose reference is currently on the evaluation stack
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var field  = ((OpField)xOp).Value;
            var offset = Helper.GetFieldOffset(field.DeclaringType, field, Config.TargetPlatform);
            var size   = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * An object reference (or pointer) is pushed onto the stack.
             * The object reference (or pointer) is popped from the stack; the value of the specified field in the object is found.
             * The value stored in the field is pushed onto the stack.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };

                for (int i = 1; i <= (size / 4); i++)
                {
                    new Push
                    {
                        DestinationReg          = Register.EAX,
                        DestinationIndirect     = true,
                        DestinationDisplacement = (size - (i * 4) + offset)
                    };
                }

                switch (size % 4)
                {
                case 0: break;

                case 1:
                {
                    new Movzx {
                        DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true, SourceDisplacement = offset, Size = 8
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                break;

                case 2:
                {
                    new Movzx {
                        DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true, SourceDisplacement = offset, Size = 16
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                break;

                default:
                    throw new Exception("Unsupported Size");
                }
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.vStack.Push(new StackItem(field.FieldType));
            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #22
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stsfld(v=vs.110).aspx
         * Description : Replaces the value of a static field with a value from the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var field     = ((OpField)xOp).Value;
            var fieldName = field.FullName();
            var size      = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform);

            string cctor_addref = null;

            var cctor = (field.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (cctor != null)
            {
                cctor_addref = cctor.FullName();
            }

            /* The stack transitional behavior, in sequential order, is:
             * A value is pushed onto the stack.
             * A value is popped from the stack and stored in field.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                for (int i = 0; i < (size / 4); i++)
                {
                    new Pop {
                        DestinationReg = Register.EAX
                    };
                    new Mov {
                        DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = (i * 4), SourceReg = Register.EAX
                    };
                }

                int offset = size / 4;
                switch (size % 4)
                {
                case 0: break;

                case 1:
                {
                    new Pop {
                        DestinationReg = Register.EAX
                    };
                    new Mov {
                        DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = offset * 4, SourceReg = Register.AL, Size = 8
                    };
                }
                break;

                case 2:
                {
                    new Pop {
                        DestinationReg = Register.EAX
                    };
                    new Mov {
                        DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = offset * 4, SourceReg = Register.AX, Size = 16
                    };
                }
                break;

                default:
                    throw new Exception("Unsupported Size");
                }
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #23
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stfld(v=vs.110).aspx
         * Description : Replaces the value stored in the field of an object reference or pointer with a new value.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 2)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 2");
            }

            var field  = ((OpField)xOp).Value;
            var offset = Helper.GetFieldOffset(field.DeclaringType, field, Config.TargetPlatform);
            var size   = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * An object reference or pointer is pushed onto the stack.
             * A value is pushed onto the stack.
             * The value and the object reference/pointer are popped from the stack; the value of field in the object is replaced with the supplied value.
             */

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (size > 4)
                {
                    throw new Exception("Field Size > 4 not supported");
                }

                if (!itemA.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                if (!itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Pop {
                    DestinationReg = Register.EDX
                };

                switch (size)
                {
                case 1:
                {
                    new Mov {
                        DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.AL, Size = 8
                    };
                }
                break;

                case 2:
                {
                    new Mov {
                        DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.AX, Size = 16
                    };
                }
                break;

                case 4:
                {
                    new Mov {
                        DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.EAX
                    };
                }
                break;

                case 3:
                {
                    new Mov {
                        DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.AX, Size = 16
                    };
                    new Shr {
                        DestinationReg = Register.EAX, SourceRef = "0x10"
                    };
                    new Mov {
                        DestinationReg = Register.EDX, DestinationIndirect = true, DestinationDisplacement = 2 + offset, SourceReg = Register.AL, Size = 8
                    };
                }
                break;
                }
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #24
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldelema(v=vs.110).aspx
         * Description : Loads the address of the array element at a specified array index onto the top of the evaluation stack as type & (managed pointer).
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 2)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 2");
            }

            var operand = ((OpType)xOp).Value;
            var size    = Helper.GetTypeSize(operand, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * An object reference array is pushed onto the stack.
             * An index value index is pushed onto the stack.
             * index and array are popped from the stack; the value stored at position index in array is looked up.
             * The address is pushed onto the stack.
             */

            var itemA = Optimizer.vStack.Pop();
            var itemB = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (size > 4)
                {
                    throw new Exception(string.Format("UnImplemented '{0}'", msIL));
                }

                if (!itemA.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                if (!itemB.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Mov {
                    DestinationReg = Register.EDX, SourceRef = "0x" + size.ToString("X")
                };
                new Mul {
                    DestinationReg = Register.EDX
                };

                new Pop {
                    DestinationReg = Register.EDX
                };
                new Add {
                    DestinationReg = Register.EDX, SourceReg = Register.EAX
                };
                new Add {
                    DestinationReg = Register.EDX, SourceRef = "0x10"
                };

                new Push {
                    DestinationReg = Register.EDX
                };
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.vStack.Push(new StackItem(typeof(uint)));
            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #25
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Newarr(v=vs.110).aspx
         * Description : Pushes an object reference to a new zero-based, one-dimensional array whose elements are of a specific type onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var type = ((OpType)xOp).Value;
            var size = Helper.GetTypeSize(type, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * The number of elements in the array is pushed onto the stack.
             * The number of elements is popped from the stack and the array is created.
             * An object reference to the new array is pushed onto the stack.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Mov {
                    DestinationReg = Register.ESI, SourceReg = Register.ESP, SourceIndirect = true
                };
                new Mov {
                    DestinationReg = Register.EAX, SourceRef = "0x" + size.ToString()
                };
                new Mul {
                    DestinationReg = Register.ESI
                };
                new Add {
                    DestinationReg = Register.EAX, SourceRef = "0x10"
                };

                new Push {
                    DestinationReg = Register.EAX
                };
                new Call {
                    DestinationRef = Helper.Heap_Label, IsLabel = true
                };
                new Test {
                    DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                };
                new Jmp {
                    Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                };

                new Pop {
                    DestinationReg = Register.ESI
                };
                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, SourceRef = "0x" + type.GetHashCode().ToString("X")
                };
                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 4, SourceRef = "0x2"
                };
                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 8, SourceReg = Register.ESI
                };
                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 12, SourceRef = "0x" + size.ToString("X")
                };

                new Push {
                    DestinationReg = Register.EAX
                };

                Optimizer.vStack.Push(new StackItem(typeof(Array)));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #26
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Starg(v=vs.110).aspx
         * Description : Stores the value on top of the evaluation stack in the argument slot at a specified index.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            if (Optimizer.vStack.Count < 1)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < 1");
            }

            var index = ((OpVar)xOp).Value;

            int EBPoffset = Ldarg_il.GetArgumentOffset(Config, method, index);

            Type ArgType = null;

            if (!method.IsStatic)
            {
                if (index == 0)
                {
                    ArgType = method.DeclaringType;
                    if (method.DeclaringType.IsValueType)
                    {
                        ArgType = ArgType.MakeByRefType();
                    }
                }
                else
                {
                    ArgType = method.GetParameters()[index - 1].ParameterType;
                }
            }
            else
            {
                ArgType = method.GetParameters()[index].ParameterType;
            }

            int ArgSize = Helper.GetTypeSize(ArgType, Config.TargetPlatform);

            /* The stack transitional behavior, in sequential order, is:
             * The value currently on top of the stack is popped and placed in argument slot num.
             */

            var item = Optimizer.vStack.Pop();

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (ArgSize > 4)
                {
                    throw new Exception("Unsupported ArgSize");
                }

                if (!item.SystemStack)
                {
                    throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
                }

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Mov
                {
                    DestinationReg          = Register.EBP,
                    DestinationIndirect     = true,
                    DestinationDisplacement = EBPoffset,
                    SourceReg = Register.EAX
                };
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }

            Optimizer.SaveStack(xOp.NextPosition);
        }
Beispiel #27
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Newobj(v=vs.110).aspx
         * Description : Creates a new object or a new instance of a value type, pushing an object reference (type O) onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var xOpMethod    = (OpMethod)xOp;
            var functionInfo = xOpMethod.Value;

            var addressRefernce = functionInfo.FullName();
            var parameters      = functionInfo.GetParameters();
            var type            = functionInfo.DeclaringType;

            int FieldIsClassType = 0;
            var memsize          = Helper.GetStorageSize(type, Config.TargetPlatform, ref FieldIsClassType);
            var paramsize        = parameters.Sum(para => Helper.GetTypeSize(para.ParameterType, Config.TargetPlatform, true));

            Verbose.Warning("{0} : ByRefCount '{1}'", type.FullName, FieldIsClassType);
            int count = parameters.Length;

            if (Optimizer.vStack.Count < count)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < expected size");
            }

            if (xOpMethod.CallingConvention != CallingConvention.StdCall)
            {
                throw new Exception(string.Format("CallingConvention '{0}' not supported", xOpMethod.CallingConvention));
            }

            /* The stack transitional behavior, in sequential order, is:
             * Arguments arg1 through argn are pushed on the stack in sequence.
             * Arguments argn through arg1 are popped from the stack and passed to ctor for object creation.
             * A reference to the new object is pushed onto the stack.
             */

            int index = count;

            while (index > 0)
            {
                Optimizer.vStack.Pop();
                index--;
            }

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (type.IsValueType)
                {
                    throw new Exception("Newobj ValueType not implemented");
                }

                if (type == typeof(string))
                {
                    if (parameters.Length == 1)
                    {
                        var param = parameters[0].ParameterType.ToString();
                        if (param == "System.Char[]")
                        {
                            new Mov {
                                DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceIndirect = true
                            };
                            new Mov {
                                DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true, SourceDisplacement = 8
                            };
                            new Shl {
                                DestinationReg = Register.EAX, SourceRef = "0x1"
                            };
                        }
                        else if (param == "System.Char*")
                        {
                            new Push {
                                DestinationReg = Register.ESP, DestinationIndirect = true
                            };
                            new Call {
                                DestinationRef = "GetLength.System.Char*", IsLabel = true
                            };
                            new Shl {
                                DestinationReg = Register.EAX, SourceRef = "0x1"
                            };
                        }
                        else if (param == "System.SByte*")
                        {
                            new Push {
                                DestinationReg = Register.ESP, DestinationIndirect = true
                            };
                            new Call {
                                DestinationRef = "GetLength.System.SByte*", IsLabel = true
                            };
                            new Shl {
                                DestinationReg = Register.EAX, SourceRef = "0x1"
                            };
                        }
                        else
                        {
                            throw new Exception("String constructor not implemented");
                        }
                    }
                    else if (parameters.Length == 3)
                    {
                        new Mov {
                            DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceIndirect = true
                        };
                        new Shl {
                            DestinationReg = Register.EAX, SourceRef = "0x1"
                        };
                    }
                    else if (parameters.Length == 2)
                    {
                        new Mov {
                            DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceIndirect = true
                        };
                        new Shl {
                            DestinationReg = Register.EAX, SourceRef = "0x1"
                        };
                    }
                    else
                    {
                        throw new Exception("String constructor not supported");
                    }

                    new Add {
                        DestinationReg = Register.EAX, SourceRef = "0x" + memsize.ToString("X")
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                }
                else
                {
                    new Push {
                        DestinationRef = "0x" + memsize.ToString("X")
                    }
                };

                new Call {
                    DestinationRef = Helper.Heap_Label, IsLabel = true
                };
                new Test {
                    DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                };
                new Jmp {
                    Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                };

                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, SourceRef = "0x" + type.GetHashCode().ToString("X")
                };
                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 4, SourceRef = "0x" + (0x1 | FieldIsClassType << 2).ToString("X")
                };
                new Mov {
                    DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 8, SourceRef = "0x" + memsize.ToString("X")
                };

                new Push {
                    DestinationReg = Register.EAX
                };
                new Push {
                    DestinationReg = Register.EAX
                };

                for (int i = 0; i < count; i++)
                {
                    if (Helper.GetTypeSize(parameters[i].ParameterType, Config.TargetPlatform) > 4)
                    {
                        throw new Exception("unsupported size");
                    }
                    new Push {
                        DestinationReg = Register.ESP, DestinationDisplacement = (paramsize + 4), DestinationIndirect = true
                    };
                }

                new Call {
                    DestinationRef = functionInfo.FullName()
                };
                new Test {
                    DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                };
                new Jmp {
                    Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                };

                new Pop {
                    DestinationReg = Register.EAX
                };
                new Add {
                    DestinationReg = Register.ESP, SourceRef = "0x" + paramsize.ToString("X")
                };
                new Push {
                    DestinationReg = Register.EAX
                };

                Optimizer.vStack.Push(new StackItem(type));
                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }
Beispiel #28
0
        /*
         * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Callvirt(v=vs.110).aspx
         * Description : Calls a late-bound method on an object, pushing the return value onto the evaluation stack.
         */
        internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
        {
            var xOpMethod    = (OpMethod)xOp;
            var functionInfo = xOpMethod.Value as MethodInfo;

            var addressRefernce = functionInfo.FullName();
            var parameters      = functionInfo.GetParameters();

            var size       = parameters.Sum(a => Helper.GetTypeSize(a.ParameterType, Config.TargetPlatform, true));
            int returnSize = 0;

            if (functionInfo != null)
            {
                returnSize = Helper.GetTypeSize(functionInfo.ReturnType, Config.TargetPlatform, true);
            }

            int count = parameters.Length;

            if (!functionInfo.IsStatic)
            {
                count++;
            }

            if (Optimizer.vStack.Count < count)
            {
                throw new Exception("Internal Compiler Error: vStack.Count < expected size");
            }

            if (xOpMethod.CallingConvention != CallingConvention.StdCall)
            {
                throw new Exception(string.Format("CallingConvention '{0}' not supported", xOpMethod.CallingConvention));
            }

            /* The stack transitional behavior, in sequential order, is:
             * An object reference obj is pushed onto the stack.
             * Method arguments arg1 through argN are pushed onto the stack.
             * Method arguments arg1 through argN and the object reference obj are popped from the stack;
             * the method call is performed with these arguments and control is transferred to the method
             * in obj referred to by the method metadata token. When complete, a return value is generated
             * by the callee method and sent to the caller.
             * The return value is pushed onto the stack.
             */

            while (count > 0)
            {
                Optimizer.vStack.Pop();
                count--;
            }

            switch (Config.TargetPlatform)
            {
            case Architecture.x86:
            {
                if (returnSize > 8)
                {
                    throw new Exception(string.Format("UnImplemented '{0}' Return-type: '{1}'", msIL, functionInfo.ReturnType));
                }

                if (functionInfo.IsStatic || functionInfo.IsFinal || !functionInfo.IsVirtual || !functionInfo.IsAbstract)
                {
                    new Call {
                        DestinationRef = addressRefernce
                    };
                    new Test {
                        DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                    };
                    new Jmp {
                        Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                    };
                    Optimizer.SaveStack(xOp.HandlerPosition);
                }
                else
                {
                    new Mov {
                        DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceDisplacement = size, SourceIndirect = true
                    };
                    new Mov {
                        DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true
                    };

                    new Push {
                        DestinationRef = Helper.VTable_Flush
                    };
                    new Push {
                        DestinationRef = "0x" + xOpMethod.MethodUID.ToString("X")
                    };
                    new Push {
                        DestinationReg = Register.EAX
                    };
                    new Call {
                        DestinationRef = Helper.VTable_Label, IsLabel = true
                    };
                    new Test {
                        DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                    };
                    new Jmp {
                        Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                    };
                    Optimizer.SaveStack(xOp.HandlerPosition);

                    if (functionInfo.DeclaringType == typeof(object))
                    {
                        throw new Exception("Callvirt Object Declaring type not implemented");
                    }

                    new Call {
                        DestinationRef = "EAX"
                    };
                    new Test {
                        DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF"
                    };
                    new Jmp {
                        Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef
                    };
                }

                if (functionInfo.ReturnType != typeof(void))
                {
                    if (returnSize == 8)
                    {
                        new Push {
                            DestinationReg = Register.EDX
                        }
                    }
                    ;
                    new Push {
                        DestinationReg = Register.EAX
                    };
                    Optimizer.vStack.Push(new StackItem(functionInfo.ReturnType));
                }

                Optimizer.SaveStack(xOp.NextPosition);
            }
            break;

            default:
                throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
            }
        }