Пример #1
0
        /// <summary>
        /// Build the Inline assembly method, how? quite simple just invoke that method
        /// So, remember we want use parameters of an assembly method via c#, we have to be completely literal
        /// </summary>
        /// <param name="aMethod"></param>
        private void ExecutableMethod(MethodBase aMethod)
        {
            ILCompiler.Logger.Write("@Processor", aMethod.FullName(), "Scanning Inline Assembly Method()");
            string xMethodLabel = aMethod.FullName();

            TryToMakeGlobalSymbol(aMethod);

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

            var Attribute       = (AssemblyAttribute)aMethod.GetCustomAttribute(typeof(AssemblyAttribute));
            var NeedCalliHeader = Attribute.NeedCalliHeader;

            /* Well we check if we assign any return size than it means we are lazy
             * and we want compiler to add calli and return code.
             */
            if (NeedCalliHeader)
            {
                Core.AssemblerCode.Add(new Push {
                    DestinationReg = Registers.EBP
                });
                Core.AssemblerCode.Add(new Mov {
                    DestinationReg = Registers.EBP, SourceReg = Registers.ESP
                });
            }

            /* Do Invoke here */
            aMethod.Invoke(null, new object[aMethod.GetParameters().Length]);
            ILCompiler.Logger.Write("Method Successfully Invoked()");

            if (NeedCalliHeader)
            {
                byte RetSize = (byte)Math.Max(0, ILHelper.GetArgumentsSize(aMethod) - ILHelper.GetReturnTypeSize(aMethod));

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

            BuildDefinations.Add(aMethod);
            ILCompiler.Logger.Write("Method Build Done()");
        }
Пример #2
0
        public void FlushStringDataTable()
        {
            int    CurrentLabel = 0;
            string Content, str;

            foreach (var xObj in StringTable)
            {
                str     = xObj.Key;
                Content = xObj.Value;
                Encoding xEncoding   = Encoding.Unicode;
                var      xBytecount  = xEncoding.GetByteCount(str);
                var      xObjectData = new byte[(xBytecount) + 0x10]; // 0xC is object data offset

                Array.Copy(BitConverter.GetBytes(ILHelper.GetTypeID(typeof(string))), 0, xObjectData, 0, 4);
                Array.Copy(BitConverter.GetBytes(0x1), 0, xObjectData, 4, 4);
                Array.Copy(BitConverter.GetBytes(xObjectData.Length), 0, xObjectData, 8, 4);
                Array.Copy(BitConverter.GetBytes(str.Length), 0, xObjectData, 12, 4);
                Array.Copy(xEncoding.GetBytes(str), 0, xObjectData, 16, xBytecount);

                Core.DataMember.Add(new AsmData(Content, xObjectData));
                CurrentLabel++;
            }
        }
Пример #3
0
        /// <summary>
        /// Scan the normal method and find inline calls of virtual or real method to add it into queue
        /// After that Process method and add its assembly to main Array
        /// </summary>
        /// <param name="aMethod">The normal mathod =)</param>
        private void ScanMethod(MethodBase aMethod)
        {
            // Just a basic patch to fix Null reference exception
            var xBody = aMethod.GetMethodBody();

            var xAssemblyName = aMethod.DeclaringType.Assembly.GetName().Name;

            if (RestrictedAssembliesName.Contains(xAssemblyName) && Plugs.ContainsValue(aMethod.FullName()))
            {
                return;
            }

            if (ILHelper.IsDelegate(aMethod.DeclaringType))
            {
                ProcessDelegate(aMethod);
                return;
            }

            if (xBody == null) // Don't try to build null method
            {
                return;
            }

            // Tell logger that we are processing a method with given name and declaring type
            // Well declaring type is necessary because when we have a plugged method than
            // Its full name is the plugged value so we will not get where the plug is implemented
            // So declaring type help us to determine that
            ILCompiler.Logger.Write("@Processor", aMethod.FullName(), "Scanning Method()");
            ILCompiler.Logger.Write("Type: " + aMethod.DeclaringType.FullName);
            ILCompiler.Logger.Write("Assembly: " + xAssemblyName);

            /* Scan Method for inline virtual or real methods call */
            var xParams     = aMethod.GetParameters();
            var xParamTypes = new Type[xParams.Length];

            for (int i = 0; i < xParams.Length; i++)
            {
                xParamTypes[i] = xParams[i].ParameterType;
                QueuedMember.Enqueue(xParamTypes[i]);
            }

            bool DynamicMethod = (aMethod.DeclaringType == null);

            if (!DynamicMethod)
            {
                QueuedMember.Enqueue(aMethod.DeclaringType);
            }

            if (aMethod is MethodInfo)
            {
                QueuedMember.Enqueue(((MethodInfo)aMethod).ReturnType);
            }

            if (!DynamicMethod && aMethod.IsVirtual)
            {
                #warning Need to implement currently
            }

            /* Process method and get out its IL's array */
            // @Newlabels:   New labels is the branches where we have to assign method
            //               a label for branch/call IL's operations to perform.
            //               we make its array while making the IL's array so its make our task easier
            List <int> NewLabels = new List <int>();
            var        OpCodes   = aMethod.Process(NewLabels);

            // Here seems to be going something wrong
            ILCompiler.Logger.Write("MSIL Codes Loaded... Count::" + OpCodes.Count);

            string xMethodLabel = aMethod.FullName();

            /* Method begin */
            Core.AssemblerCode.Add(new Label(xMethodLabel));

            TryToMakeGlobalSymbol(aMethod);

            Core.AssemblerCode.Add(new Comment(Worker.OPTIMIZATION_START_FLAG));
            if (aMethod.IsStatic && aMethod is ConstructorInfo)
            {
                string aData = "cctor_" + xMethodLabel;
                Core.InsertData(new AsmData(aData, new byte[] { 0x00 }));
                Core.AssemblerCode.Add(new Cmp()
                {
                    DestinationRef = aData, DestinationIndirect = true, SourceRef = "0x0", Size = 8
                });
                Core.AssemblerCode.Add(new Jmp()
                {
                    Condition = ConditionalJumpEnum.JE, DestinationRef = Label.PrimaryLabel + ".Load"
                });
                /* Footer of method */
                Core.AssemblerCode.Add(new Mov {
                    DestinationReg = Registers.ECX, SourceRef = "0x0"
                });
                Core.AssemblerCode.Add(new Ret());

                Core.AssemblerCode.Add(new Label(".Load"));
                Core.AssemblerCode.Add(new Mov()
                {
                    DestinationRef = aData, DestinationIndirect = true, SourceRef = "0x1", Size = 8
                });
            }
            /* Calli instructions */
            Core.AssemblerCode.Add(new Push()
            {
                DestinationReg = Registers.EBP
            });
            Core.AssemblerCode.Add(new Mov()
            {
                DestinationReg = Registers.EBP, SourceReg = Registers.ESP
            });

            /* Calculate Method Variables Size */
            int Size = (from item in xBody.LocalVariables
                        select item.LocalType.SizeOf().Align()).Sum();

            if (Size > 0)
            {
                // Make a space for local variables
                Core.AssemblerCode.Add(new Sub {
                    DestinationReg = Registers.ESP, SourceRef = "0x" + Size.Align().ToString("X")
                });
            }

            ILCompiler.Logger.Write("Listening OpCodes");

            /* Exceute IL Codes */
            foreach (var Op in OpCodes)
            {
                // Check if we need exception to push?
                var xNeedsExceptionPush = (Op.Ehc != null) && (((Op.Ehc.HandlerOffset > 0 && Op.Ehc.HandlerOffset == Op.Position) || ((Op.Ehc.Flags & ExceptionHandlingClauseOptions.Filter) > 0 && Op.Ehc.FilterOffset > 0 && Op.Ehc.FilterOffset == Op.Position)) && (Op.Ehc.Flags == ExceptionHandlingClauseOptions.Clause));

                ILCompiler.Logger.Write(Op.ToString() + "; Stack Count => " + Core.vStack.Count);
                // Check if current position inside the list of label list, if yes than break label and make a new one
                if (NewLabels.Contains(Op.Position))
                {
                    var xLbl = new Label(ILHelper.GetLabel(aMethod, Op.Position));
                    if (!Core.AssemblerCode.Contains(xLbl))
                    {
                        Core.AssemblerCode.Add(xLbl);
                    }
                }

                // If catch IL here than push current error so, that catch IL pop and do what it want
                if (xNeedsExceptionPush)
                {
                    Core.AssemblerCode.Add(new Push {
                        DestinationRef = "0x0"
                    });
                    Core.AssemblerCode.Add(new Call(Helper.lblGetException, true));
                    Core.vStack.Push(4, typeof(Exception));
                }

                // Well this is just to comment whole output Assembly
                if (!DoOptimization)
                {
                    Core.AssemblerCode.Add(new Comment(Op.ToString() + "; " + Core.vStack.Count));
                }

                // Check if this IL is in out implementation
                if (MSIL.ContainsKey(Op.Code))
                {
                    // If yes than execute it
                    MSIL[Op.Code].Execute(Op, aMethod);
                }
                else
                {
                    // If it is not implementation than throw error while compilation
                    throw new Exception(Op.ToString() + "; " + xMethodLabel);
                }
                #region Queue Inline calls
                if (Op is OpMethod)
                {
                    QueuedMember.Enqueue(((OpMethod)Op).Value);
                }
                else if (Op is OpType)
                {
                    QueuedMember.Enqueue(((OpType)Op).Value);
                }
                else if (Op is OpField)
                {
                    QueuedMember.Enqueue(((OpField)Op).Value.DeclaringType);
                    if (((OpField)Op).Value.IsStatic)
                    {
                        QueuedMember.Enqueue(((OpField)Op).Value);
                    }
                }
                else if (Op is OpToken)
                {
                    var x = ((OpToken)Op);
                    if (x.ValueIsType)
                    {
                        QueuedMember.Enqueue(x.ValueType);
                    }

                    if (x.ValueIsField)
                    {
                        QueuedMember.Enqueue(x.ValueField.DeclaringType);
                        if (x.ValueField.IsStatic)
                        {
                            QueuedMember.Enqueue(x.ValueField);
                        }
                    }
                }
                #endregion
            }
            // End the method and return method, without exception
            Core.AssemblerCode.Add(new Label(xMethodLabel + ".End"));
            // We assume that if the ecx is 0x0 then the method is done without any exception
            // it can be assumed by test instruction followed by conditional jump while calling a function
            Core.AssemblerCode.Add(new Mov {
                DestinationReg = Registers.ECX, SourceRef = "0x0"
            });

            Core.AssemblerCode.Add(new Label(xMethodLabel + ".Error"));
            // Now below code save the return value to EBP varaible
            // And calculate size
            int ArgSize = ILHelper.GetArgumentsSize(aMethod);

            int ReturnSize = ILHelper.GetReturnTypeSize(aMethod);
            if (ReturnSize > 0)
            {
                // For return type Method
                var xOffset = ILHelper.GetResultCodeOffset(ReturnSize, ArgSize);
                for (int i = 0; i < ReturnSize / 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
                    });
                }
            }
            Core.AssemblerCode.Add(new Comment(Worker.OPTIMIAZTION_END_FLAG));

            byte RetSize = (byte)Math.Max(0, ILHelper.GetArgumentsSize(aMethod) - ILHelper.GetReturnTypeSize(aMethod));

            // Leave this method mean regain original EBP and ESP offset
            Core.AssemblerCode.Add(new Leave());
            // Return to parent method with given stack offset
            Core.AssemblerCode.Add(new Ret {
                Address = RetSize
            });

            // Add this method to build definations so we will not build it again
            BuildDefinations.Add(aMethod);

            // And log it
            ILCompiler.Logger.Write("Method Build Done()");
        }
Пример #4
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);
        }
Пример #5
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);
        }