Ejemplo n.º 1
0
        private void ProcessExternalMethod(MethodBase aMethod)
        {
            ILCompiler.Logger.Write("@Processor", aMethod.FullName(), "Processing External Method");

            if (!aMethod.IsStatic)
            {
                throw new Exception("Non-static extern fields not supported");
            }

            var aAttributeData = (DllImportAttribute)aMethod.GetCustomAttribute(typeof(DllImportAttribute));

            if (aAttributeData == null)
            {
                throw new Exception("[DllImport]: Invalid Build");
            }

            string xLibName         = aAttributeData.Value;
            string xMethodLabel     = aMethod.FullName();
            string xMethodName      = aAttributeData.EntryPoint == null ? aMethod.Name : aAttributeData.EntryPoint;
            int    xCalliConvention = (int)aAttributeData.CallingConvention;
            bool   IsAtomixCompiled = (xCalliConvention == (int)aMethod.CallingConvention);

            var xParms = aMethod.GetParameters();

            /*
             * For now assume normal calli method
             * - Push Library Name
             * - Push Function Name
             * - Call Kernel API
             * - Jump to function address
             */
            Core.AssemblerCode.Add(new Label(xMethodLabel));

            // standard calli header
            Core.AssemblerCode.Add(new Push {
                DestinationReg = Registers.EBP
            });
            Core.AssemblerCode.Add(new Mov {
                DestinationReg = Registers.EBP, SourceReg = Registers.ESP
            });

            // load and get address of external function
            Core.AssemblerCode.Add(new Push {
                DestinationRef = AddStringData(xLibName)
            });
            Core.AssemblerCode.Add(new Push {
                DestinationRef = AddStringData(xMethodName)
            });

            Core.AssemblerCode.Add(new Call(Helper.lblImportDll, true));
            Core.AssemblerCode.Add(new Test {
                DestinationReg = Registers.ECX, SourceRef = "0x2"
            });

            Core.AssemblerCode.Add(new Pop {
                DestinationReg = Registers.EAX
            });

            int ArgSize     = ILHelper.GetArgumentsSize(aMethod);
            int xReturnSize = ILHelper.GetReturnTypeSize(aMethod);
            int xRetSize    = (ArgSize - xReturnSize);

            #region _CALLI_HEADER_
            if (IsAtomixCompiled)
            {
                // push the arguments from left to right
                for (int i = 0; i < xParms.Length; i++)
                {
                    int xDisplacement = ILHelper.GetArgumentDisplacement(aMethod, i);
                    int xArgSize      = aMethod.GetParameters()[i].ParameterType.SizeOf().Align();

                    for (int j = 0; j < (xArgSize / 4); j++)
                    {
                        Core.AssemblerCode.Add(
                            new Push
                        {
                            DestinationReg          = Registers.EBP,
                            DestinationIndirect     = true,
                            DestinationDisplacement = xDisplacement - (j * 4)
                        });
                    }
                }

                if (xRetSize < 0)
                {
                    Core.AssemblerCode.Add(new Sub {
                        DestinationReg = Registers.ESP, SourceRef = "0x" + (-xRetSize).ToString("x")
                    });
                    xRetSize = 0;
                }
            }
            else if (xCalliConvention == (int)CallingConvention.StdCall)
            {
                // push arguments to the stack from right to left
                for (int i = xParms.Length - 1; i >= 0; i--)
                {
                    int xDisplacement = ILHelper.GetArgumentDisplacement(aMethod, i);
                    int xArgSize      = aMethod.GetParameters()[i].ParameterType.SizeOf().Align();

                    for (int j = 0; j < (xArgSize / 4); j++)
                    {
                        Core.AssemblerCode.Add(
                            new Push
                        {
                            DestinationReg          = Registers.EBP,
                            DestinationIndirect     = true,
                            DestinationDisplacement = xDisplacement - (j * 4)
                        });
                    }
                }
            }
            #endregion

            // Call the function
            Core.AssemblerCode.Add(new Call("EAX"));

            #region _CALLI_FOOTER_
            if (xReturnSize > 0)
            {
                var xOffset = ILHelper.GetResultCodeOffset(xReturnSize, ArgSize);
                if (IsAtomixCompiled)
                {
                    // For return type Method
                    for (int i = 0; i < xReturnSize / 4; i++)
                    {
                        Core.AssemblerCode.Add(new Pop {
                            DestinationReg = Registers.EAX
                        });
                        Core.AssemblerCode.Add(new Mov
                        {
                            DestinationReg          = Registers.EBP,
                            DestinationIndirect     = true,
                            DestinationDisplacement = (xOffset + (i * 4)),
                            SourceReg = Registers.EAX
                        });
                    }
                }
                else if (xCalliConvention == (int)CallingConvention.StdCall)
                {
                    if (xReturnSize > 8)
                    {
                        throw new Exception("[Extern]: Unsupported Return Size for StdCall");
                    }

                    Core.AssemblerCode.Add(new Mov
                    {
                        DestinationReg          = Registers.EBP,
                        DestinationIndirect     = true,
                        DestinationDisplacement = xOffset,
                        SourceReg = Registers.EAX
                    });

                    if (xReturnSize == 8)
                    {
                        Core.AssemblerCode.Add(new Mov
                        {
                            DestinationReg          = Registers.EBP,
                            DestinationIndirect     = true,
                            DestinationDisplacement = (xOffset + 4),
                            SourceReg = Registers.EAX
                        });
                    }
                }
            }
            #endregion

            Core.AssemblerCode.Add(new Mov {
                DestinationReg = Registers.ECX, SourceRef = "0x0"
            });
            Core.AssemblerCode.Add(new Leave());
            Core.AssemblerCode.Add(new Ret {
                Address = (byte)xRetSize
            });

            BuildDefinations.Add(aMethod);
        }
Ejemplo n.º 2
0
        private void ProcessDelegate(MethodBase xMethod)
        {
            var lbl           = xMethod.FullName();
            var lbl_exception = lbl + ".Error";
            var lbl_end       = lbl + ".End";

            Core.AssemblerCode.Add(new Label(lbl));

            // Calli header
            Core.AssemblerCode.Add(new Push {
                DestinationReg = Registers.EBP
            });
            Core.AssemblerCode.Add(new Mov {
                DestinationReg = Registers.EBP, SourceReg = Registers.ESP
            });

            if (lbl.Contains("ctor"))
            {
                // Load Argument
                ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(0, xMethod);
                Core.AssemblerCode.Add(new Pop {
                    DestinationReg = Registers.EBX
                });

                ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(2, xMethod); // The pointer
                Core.AssemblerCode.Add(new Pop {
                    DestinationReg = Registers.EAX
                });
                Core.AssemblerCode.Add(new Add {
                    DestinationReg = Registers.EBX, SourceRef = "0xC"
                });
                Core.AssemblerCode.Add(new Mov {
                    DestinationReg = Registers.EBX, DestinationIndirect = true, SourceReg = Registers.EAX
                });

                ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(1, xMethod); // The Object
                Core.AssemblerCode.Add(new Pop {
                    DestinationReg = Registers.EAX
                });
                Core.AssemblerCode.Add(new Add {
                    DestinationReg = Registers.EBX, SourceRef = "0x4"
                });
                Core.AssemblerCode.Add(new Mov {
                    DestinationReg = Registers.EBX, DestinationIndirect = true, SourceReg = Registers.EAX
                });

                // calli footer
                Core.AssemblerCode.Add(new Mov {
                    DestinationReg = Registers.ECX, SourceRef = "0x0"
                });
                Core.AssemblerCode.Add(new Leave());
                Core.AssemblerCode.Add(new Ret {
                    Address = 0xC
                });                                                // Memory location + Object + Intptr
            }
            else if (lbl.Contains("Invoke"))
            {
                // Load Reference
                ((Ldarg)MSIL[ILCode.Ldarg]).Execute2(0, xMethod);

                Core.AssemblerCode.Add(new Pop {
                    DestinationReg = Registers.EAX
                });
                Core.AssemblerCode.Add(new Add {
                    DestinationReg = Registers.EAX, SourceRef = "0xC"
                });

                // If it is a non static field than get its parent Type memory location (object in constructor)
                if (!xMethod.IsStatic)
                {
                    Core.AssemblerCode.Add(new Push {
                        DestinationReg = Registers.EAX, DestinationDisplacement = 0x4, DestinationIndirect = true
                    });
                }

                var xParms = xMethod.GetParameters();
                int xSize  = ILHelper.GetArgumentsSize(xMethod);

                // Load arguments to throw
                int xArgSize;
                for (ushort i = 1; i <= xParms.Length; i++)
                {
                    // New Code
                    int xDisplacement = ILHelper.GetArgumentDisplacement(xMethod, i);

                    if (xMethod.IsStatic)
                    {
                        xArgSize = xMethod.GetParameters()[i].ParameterType.SizeOf().Align();
                    }
                    else
                    {
                        xArgSize = xMethod.GetParameters()[i - 1].ParameterType.SizeOf().Align();
                    }

                    for (int j = 0; j < (xArgSize / 4); j++)
                    {
                        Core.AssemblerCode.Add(
                            new Push
                        {
                            DestinationReg          = Registers.EBP,
                            DestinationIndirect     = true,
                            DestinationDisplacement = xDisplacement - (j * 4)
                        });
                    }
                }

                // Call the function
                Core.AssemblerCode.Add(new Call("[EAX]"));

                // Check for anytype of exception
                Core.AssemblerCode.Add(new Test {
                    DestinationReg = Registers.ECX, SourceRef = "0x2"
                });
                Core.AssemblerCode.Add(new Jmp {
                    Condition = ConditionalJumpEnum.JNE, DestinationRef = lbl_exception
                });

                // calli footer
                Core.AssemblerCode.Add(new Label(lbl_end));
                Core.AssemblerCode.Add(new Mov {
                    DestinationReg = Registers.ECX, SourceRef = "0x0"
                });

                Core.AssemblerCode.Add(new Label(lbl_exception));
                int xReturnSize = ILHelper.GetReturnTypeSize(xMethod);

                if (xReturnSize > 0)
                {
                    // For return type Method
                    var xOffset = ILHelper.GetResultCodeOffset(xReturnSize, xSize);
                    for (int i = 0; i < xReturnSize / 4; i++)
                    {
                        Core.AssemblerCode.Add(new Pop {
                            DestinationReg = Registers.EAX
                        });
                        Core.AssemblerCode.Add(new Mov
                        {
                            DestinationReg          = Registers.EBP,
                            DestinationIndirect     = true,
                            DestinationDisplacement = (int)(xOffset + ((i + 0) * 4)),
                            SourceReg = Registers.EAX
                        });
                    }
                }

                byte xRetSize = (byte)Math.Max(0, xSize - xReturnSize);

                Core.AssemblerCode.Add(new Leave());
                Core.AssemblerCode.Add(new Ret {
                    Address = xRetSize
                });                                                     // Parameter + Memory
            }

            BuildDefinations.Add(xMethod);
        }