示例#1
0
文件: Ldlen.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if field to load is a floating value or the field to load
        /// is not of size 4 or 8 bytes.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            aScannerState.CurrentStackFrame.Stack.Pop();

            DB_Type arrayDBType = DebugDatabase.GetType(aScannerState.GetTypeID(aScannerState.ArrayClass));
            int lengthOffset = aScannerState.GetFieldOffset(arrayDBType, "length");

            // 1. Check array reference is not null
            //      1.1. Move array ref into eax
            //      1.2. Compare eax (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            // 2. Load array length

            string ContinueExecutionLabelBase = string.Format("{0}.IL_{1}_ContinueExecution",
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    anILOpInfo.Position);
            string ContinueExecutionLabel1 = ContinueExecutionLabelBase + "1";
            //      1.1. Move array ref into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 0, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov eax, [esp]");
            //      1.2. Compare eax (array ref) to 0
            result.AppendLine("cmp eax, 0");
            //      1.3. If not zero, jump to continue execution further down
            result.AppendLine("jnz " + ContinueExecutionLabel1);
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowNullReferenceExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel1 + ":");

            //2. Load array length
            //  - Pop array ref
            result.AppendLine("pop dword ecx");
            //  - Load length from array ref
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ecx", lengthOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [ecx+{0}]", lengthOffset));
            //  - Push array length
            result.AppendLine("push dword eax");

            aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = 4,
                isGCManaged = false
            });

            return result.ToString().Trim();
        }
示例#2
0
文件: Ldftn.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Get the ID (i.e. ASM label) of the method to load a pointer to
            string methodID = aScannerState.GetMethodID(anILOpInfo.MethodToCall);
            //If we want to load the pointer at a specified IL op number:
            if(anILOpInfo.LoadAtILOffset != int.MaxValue)
            {
                //Append the IL sub-label to the ID
                methodID += ".IL_" + anILOpInfo.LoadAtILOffset + "_0";

                //Note: This is used by try/catch/finally blocks for pushing pointers 
                //      to catch/finally handlers and filters
            }
            //Push the pointer to the function
            result.AppendLine(string.Format("push dword {0}", methodID));

            aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = 4,
                isGCManaged = false
            });

            return result.ToString().Trim();
        }
示例#3
0
文件: Switch.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if divide operands are floating point numbers or if attempting to divide 64-bit numbers.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either operand is &lt; 4 bytes long.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            StackItem testItem = aScannerState.CurrentStackFrame.Stack.Pop();

            if (testItem.isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("Switch for floats no supported!");
            }
            else if (testItem.sizeOnStackInBytes != 4)
            {
                //TODO - Support other sizes
                throw new NotSupportedException("Switch for non-int32s not supported!");
            }

            result.AppendLine("pop dword eax");
            for (int i = 0; i < anILOpInfo.ValueBytes.Length / 4; i++)
            {
                int branchPos = anILOpInfo.Position + 4 + Utils.ReadInt32(anILOpInfo.ValueBytes, i * 4);
                branchPos += anILOpInfo.ValueBytes.Length;
                branchPos += 1;

                result.AppendLine("cmp eax, " + i);
                string jumpToLabel = string.Format("{0}.IL_{1}_0", 
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    branchPos);
                result.AppendLine("je " + jumpToLabel);
            }

            return result.ToString().Trim();
        }
示例#4
0
文件: Pop.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();
            
            StackItem theItem = aScannerState.CurrentStackFrame.Stack.Pop();

            if (theItem.isNewGCObject)
            {
                //Decrement ref count

                //Get the ID of method to call as it will be labelled in the output ASM.
                string methodID = aScannerState.GetMethodID(aScannerState.DecrementRefCountMethod);
                //Append the actual call
                result.AppendLine(string.Format("call {0}", methodID));
            }

            result.AppendLine(string.Format("add esp, {0}", theItem.sizeOnStackInBytes));
        
            return result.ToString().Trim();
        }
示例#5
0
文件: Callvirt.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            MethodBase methodToCall = anILOpInfo.MethodToCall;
            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if(methodToCall is MethodInfo)
            {
                //Need to do callvirt related stuff to load address of method to call
                // - Check for invoke of a delegate - if so, treat rather differently from normal callvirt


                string call_Label = string.Format("{0}.IL_{1}_Call",
                                                aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                anILOpInfo.Position);

                if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType))
                {
                    //Callvirt to delegate method
                    // - We only support calls to Invoke at the moment
                    if (methodToCall.Name != "Invoke")
                    {
                        throw new NotSupportedException("Callvirt to Delegate method not supported! Method name: " + methodToCall.Name);
                    }
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => Utils.GetNumBytesForType(x.ParameterType)).Sum();
                    
                    // - Move into eax address of function to call from stack - delegate reference is function pointer

                    //All the parameters for the method that was called
                    List<Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();

                    int bytesForParams = allParams.Select(x => Utils.GetNumBytesForType(x)).Sum();
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesForParams, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine(string.Format("mov dword eax, [esp+{0}]", bytesForParams));


                    //Allocate space on the stack for the return value as necessary
                    Type retType = ((MethodInfo)methodToCall).ReturnType;
                    StackItem returnItem = new StackItem()
                    {
                        isFloat = Utils.IsFloat(retType),
                        sizeOnStackInBytes = Utils.GetNumBytesForType(retType),
                        isGCManaged = Utils.IsGCManaged(retType)
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else if (returnItem.sizeOnStackInBytes == 4)
                        {
                            result.AppendLine("push dword 0");
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            result.AppendLine("push dword 0");
                            result.AppendLine("push dword 0");
                        }
                        else
                        {
                            throw new NotSupportedException("Invalid return stack operand size!");
                        }
                    }
                    


                    //Append the actual call
                    result.AppendLine("call eax");
                    


                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    // - Initially at least 4 for the delegate (method) ref/pointer
                    int bytesToAdd = 4;
                    //Go through all params that must be removed
                    foreach (Type aParam in allParams)
                    {
                        //Pop the paramter off our stack 
                        //(Note: Return value was never pushed onto our stack. See above)
                        aScannerState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += Utils.GetNumBytesForType(aParam);
                    }
                        
                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the 
                        //top item on the stack
                        aScannerState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value into the eax register
                        //We will push it back on after params are skipped over.
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            result.AppendLine("pop dword eax");
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            result.AppendLine("pop dword eax");
                            result.AppendLine("pop dword edx");
                        }
                    }
                    //Skip over the params
                    result.AppendLine(string.Format("add esp, {0}", bytesToAdd));
                    //If necessary, push the return value onto the stack.
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //SUPPORT - floats (with above)

                        //The return value was stored in eax
                        //So push it back onto the stack
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            result.AppendLine("push dword eax");
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            result.AppendLine("push dword edx");
                            result.AppendLine("push dword eax");
                        }
                    }
                }
                else
                {
                    //Normal callvirt
                    // - Get object ref from loaded args
                    // - Check object ref not null
                    // - Get type table entry from object ref
                    // - Get method table from type table entry
                    // - Scan method table for the method we want
                    //      - If found, load method address
                    // - Else, check for parent type method table
                    //      - If no parent type method table, throw exception
                    // - Else, scan parent type method table

                    string methodIDValueWanted = aScannerState.GetMethodIDValue((MethodInfo)methodToCall);
                    string loopTableEntries_Label = string.Format("{0}.IL_{1}_LoopMethodTable",
                                                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                    anILOpInfo.Position);
                    string notEqual_Label = string.Format("{0}.IL_{1}_NotEqual",
                                                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                    anILOpInfo.Position);
                    string endOfTable_Label = string.Format("{0}.IL_{1}_EndOfTable",
                                                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                    anILOpInfo.Position);
                    string notFound_Label = string.Format("{0}.IL_{1}_NotFound",
                                                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                    anILOpInfo.Position);
                    string notNull_Label = string.Format("{0}.IL_{1}_NotNullMem",
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    anILOpInfo.Position);

                    
                    DB_Type declaringDBType = DebugDatabase.GetType(aScannerState.GetTypeID(methodToCall.DeclaringType));

                    //Get object ref
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => Utils.GetNumBytesForType(x.ParameterType)).Sum();
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesForAllParams, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine(string.Format("mov dword eax, [esp+{0}]", bytesForAllParams));

                    //Check object ref
                    result.AppendLine("cmp eax, 0");
                    result.AppendLine(string.Format("jnz {0}", notNull_Label));
                    result.AppendLine("call GetEIP");
                    result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.HaltMethod)));
                    result.AppendLine(notNull_Label + ":");

                    //Get type ref
                    int typeOffset = aScannerState.GetFieldOffset(declaringDBType, "_Type");
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", typeOffset, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine(string.Format("mov eax, [eax+{0}]", typeOffset));

                    //Get method table ref
                    int methodTablePtrOffset = aScannerState.GetTypeFieldOffset("MethodTablePtr");
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", methodTablePtrOffset, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine(string.Format("mov eax, [eax+{0}]", methodTablePtrOffset));

                    //Loop through entries
                    result.AppendLine(loopTableEntries_Label + ":");
                    //Load ID Val for current entry
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine("mov ebx, [eax]");
                    //Compare to wanted ID value
                    result.AppendLine("cmp ebx, " + methodIDValueWanted);
                    //If equal, load method address into eax
                    result.AppendLine("jne " + notEqual_Label);
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 4, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine("mov eax, [eax+4]");
                    result.AppendLine("jmp " + call_Label);
                    result.AppendLine(notEqual_Label + ":");
                    //Else, compare to 0 to check for end of table
                    result.AppendLine("cmp ebx, 0");
                    result.AppendLine("jz " + endOfTable_Label);
                    //Not 0? Move to next entry then loop again
                    result.AppendLine("add eax, 8");
                    result.AppendLine("jmp " + loopTableEntries_Label);
                    result.AppendLine(endOfTable_Label + ":");
                    //Compare address value to 0
                    //If not zero, there is a parent method table to check
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 4, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine("mov ebx, [eax+4]");
                    result.AppendLine("cmp ebx, 0");
                    result.AppendLine("jz " + notFound_Label);
                    //Load parent method table and loop 
                    result.AppendLine("mov eax, ebx");
                    result.AppendLine("jmp " + loopTableEntries_Label);
                    result.AppendLine(notFound_Label + ":");
                    //Throw exception!
                    result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowNullReferenceExceptionMethod)));

                    result.AppendLine(call_Label + ":");

                    //Allocate space on the stack for the return value as necessary
                    Type retType = ((MethodInfo)methodToCall).ReturnType;
                    StackItem returnItem = new StackItem()
                    {
                        isFloat = Utils.IsFloat(retType),
                        sizeOnStackInBytes = Utils.GetNumBytesForType(retType),
                        isGCManaged = Utils.IsGCManaged(retType)
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else if (returnItem.sizeOnStackInBytes == 4)
                        {
                            result.AppendLine("push dword 0");
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            result.AppendLine("push dword 0");
                            result.AppendLine("push dword 0");
                        }
                        else
                        {
                            throw new NotSupportedException("Invalid return stack operand size!");
                        }
                    }


                    //Append the actual call
                    result.AppendLine("call eax");



                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    List<Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                    //Go through each one
                    if (!methodToCall.IsStatic)
                    {
                        allParams.Insert(0, methodToCall.DeclaringType);
                    }
                    foreach (Type aParam in allParams)
                    {
                        //Pop the paramter off our stack 
                        //(Note: Return value was never pushed onto our stack. See above)
                        aScannerState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += Utils.GetNumBytesForType(aParam);
                    }
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //If there is a return value on the stack
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //We need to store the return value then pop all the params

                            //We now push the return value onto our stack as,
                            //after all is said and done below, it will be the 
                            //top item on the stack
                            aScannerState.CurrentStackFrame.Stack.Push(returnItem);

                            //SUPPORT - floats (with above)

                            //Pop the return value into the eax register
                            //We will push it back on after params are skipped over.
                            if (returnItem.sizeOnStackInBytes == 4)
                            {
                                result.AppendLine("pop dword eax");
                            }
                            else if (returnItem.sizeOnStackInBytes == 8)
                            {
                                result.AppendLine("pop dword eax");
                                result.AppendLine("pop dword edx");
                            }
                        }
                        //Skip over the params
                        result.AppendLine(string.Format("add esp, {0}", bytesToAdd));
                        //If necessary, push the return value onto the stack.
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //SUPPORT - floats (with above)

                            //The return value was stored in eax
                            //So push it back onto the stack
                            if (returnItem.sizeOnStackInBytes == 4)
                            {
                                result.AppendLine("push dword eax");
                            }
                            else if (returnItem.sizeOnStackInBytes == 8)
                            {
                                result.AppendLine("push dword edx");
                                result.AppendLine("push dword eax");
                            }
                        }
                    }
                    //No params to skip over but we might still need to store return value
                    else if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //The return value will be the top item on the stack.
                        //So all we need to do is push the return item onto our stack.
                        aScannerState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
            }
            else if(methodToCall is ConstructorInfo)
            {
                throw new NotSupportedException("How the hell are we getting callvirts to constructor methods?!");
            }
            
            return result.ToString().Trim();
        }
示例#6
0
文件: Ldelem.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            Type elementType = null;
            bool pushValue = true;
            int sizeToPush = 4;
            bool signExtend = true;
            bool isFloat = false;

            switch ((OpCodes)anILOpInfo.opCode.Value)
            {
                case OpCodes.Ldelem:
                    {
                        signExtend = false;
                        //Load the metadata token used to get the type info
                        int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                        //Get the type info for the element type
                        elementType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);
                    }
                    break;

                case OpCodes.Ldelema:
                    {
                        signExtend = false;
                        //Load the metadata token used to get the type info
                        int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                        //Get the type info for the element type
                        elementType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);
                    }
                    break;

                case OpCodes.Ldelem_R4:
                case OpCodes.Ldelem_R8:
                    //TODO - Add more LdElem op variants support
                    throw new NotSupportedException("Ldelem op variant not supported yet!");

                case OpCodes.Ldelem_I1:
                    sizeToPush = 1;
                    elementType = typeof(sbyte);
                    break;
                case OpCodes.Ldelem_I2:
                    sizeToPush = 2;
                    elementType = typeof(Int16);
                    break;

                case OpCodes.Ldelem_U1:
                    sizeToPush = 1;
                    signExtend = false;
                    elementType = typeof(byte);
                    break;
                case OpCodes.Ldelem_U2:
                    sizeToPush = 2;
                    signExtend = false;
                    elementType = typeof(UInt16);
                    break;

                case OpCodes.Ldelem_Ref:
                    signExtend = false;
                    elementType = null;
                    break;

                case OpCodes.Ldelem_U4:
                    signExtend = false;
                    elementType = typeof(UInt32);
                    break;

                case OpCodes.Ldelem_I4:
                    elementType = typeof(Int32);
                    break;

                case OpCodes.Ldelem_I8:
                    elementType = typeof(Int64);
                    break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("LdElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Push the element onto the stack

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Index of element to get as Int32 (dword)
            // 1. Array object reference as address (dword)

            string ContinueExecutionLabelBase = string.Format("{0}.IL_{1}_Load_ContinueExecution",
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    anILOpInfo.Position);
            DB_Type arrayDBType = DebugDatabase.GetType(aScannerState.GetTypeID(aScannerState.ArrayClass));
                
            // 1. Check array reference is not null
            //      1.1. Move array ref into eax
            //      1.2. Compare eax (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            string ContinueExecutionLabel1 = ContinueExecutionLabelBase + "1";
            //      1.1. Move array ref into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 4, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov eax, [esp+4]");
            //      1.2. Compare eax (array ref) to 0
            result.AppendLine("cmp eax, 0");
            //      1.3. If not zero, jump to continue execution further down
            result.AppendLine("jnz " + ContinueExecutionLabel1);
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowNullReferenceExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel1 + ":");

            // 2. Check array element type is correct
            //      2.1. Move element type ref into eax
            //      2.2. Move element type ref from array object into ebx
            //      2.3. Compare eax to ebx
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into eax
            int elemTypeOffset = aScannerState.GetFieldOffset(arrayDBType, "elemType");

            //if (elementType != null)
            //{
            //    result.AppendLine(string.Format("mov eax, {0}", aScannerState.GetTypeIdString(aScannerState.GetTypeID(elementType))));
            //    //      2.2. Move element type ref from array object into ebx
            //    //              - Calculate the offset of the field from the start of the array object
            //    //              - Move array ref into ebx
            //GlobalMethods.CheckAddrFromRegister(result, aScannerState, "esp", 4);
            //    result.AppendLine("mov ebx, [esp+4]");
            //    //              - Move elemType ref ([ebx+offset]) into ebx
            //    GlobalMethods.CheckAddrFromRegister(result, aScannerState, "ebx", elemTypeOffset);
            //    result.AppendLine(string.Format("mov ebx, [ebx+{0}]", elemTypeOffset));
            //    //      2.3. Compare eax to ebx
            //    result.AppendLine("cmp eax, ebx");
            //    //      2.4. If the same, jump to continue execution further down
            //    result.AppendLine("je " + ContinueExecutionLabel2);
            //    //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException
            //    result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowArrayTypeMismatchExceptionMethod)));
            //    result.AppendLine(ContinueExecutionLabel2 + ":");
            //}

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into eax
            //      3.2. Move array length into ebx
            //      3.2. Compare eax to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare eax to ebx
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            string ContinueExecutionLabel3_1 = ContinueExecutionLabelBase + "3_1";
            string ContinueExecutionLabel3_2 = ContinueExecutionLabelBase + "3_2";
            //      3.1. Move index into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 0, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov eax, [esp]");
            //      3.2. Move array length into ecx
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = aScannerState.GetFieldOffset(arrayDBType, "length");

            //              - Move array ref into ebx
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 4, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov ebx, [esp+4]");
            //              - Move length value ([ebx+offset]) into ebx
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", lengthOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov ebx, [ebx+{0}]", lengthOffset));
            //      3.2. Compare eax to 0
            result.AppendLine("cmp eax, 0");
            //      3.3. Jump if greater than to next test condition (3.5)
            result.AppendLine("jge " + ContinueExecutionLabel3_1);
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowIndexOutOfRangeExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel3_1 + ":");
            //      3.5. Compare eax to ebx
            result.AppendLine("cmp eax, ebx");
            //      3.6. Jump if less than to continue execution further down
            result.AppendLine("jl " + ContinueExecutionLabel3_2);
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowIndexOutOfRangeExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel3_2 + ":");

            // 4. Calculate address of element
            //      4.1. Pop index into ebx
            //      4.2. Pop array ref into eax
            //      4.3. Move element type ref (from array ref) into eax
            //      4.4. Move IsValueType (from element ref type) into ecx
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            //      4.6. Move Size (from element type ref) into eax
            //      4.7. Skip over 4.8.
            //      4.8. Move StackSize (from element type ref) into eax
            //      4.9. Mulitply eax by ebx (index by element size)
            //      4.10. Move array ref into ebx
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            //      4.12. Add eax and ebx (array ref + fields + (index * element size))

            string ContinueExecutionLabel4_1 = ContinueExecutionLabelBase + "4_1";
            string ContinueExecutionLabel4_2 = ContinueExecutionLabelBase + "4_2";
            //      4.1. Pop index into ebx
            result.AppendLine("pop ebx");
            //      4.2. Move array ref into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 0, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov eax, [esp]");
            //      4.3. Move element type ref (from array ref) into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", elemTypeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [eax+{0}]", elemTypeOffset));
            //      4.4. Move IsValueType (from element ref type) into ecx
            int isValueTypeOffset = aScannerState.GetTypeFieldOffset("IsValueType");
            result.AppendLine("mov ecx, 0");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", isValueTypeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov byte cl, [eax+{0}]", isValueTypeOffset));
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            result.AppendLine("cmp ecx, 0");
            result.AppendLine("jz " + ContinueExecutionLabel4_1);
            //      4.6. Move Size (from element type ref) into eax
            int sizeOffset = aScannerState.GetTypeFieldOffset("Size");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", sizeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [eax+{0}]", sizeOffset));
            //      4.7. Skip over 4.8.
            result.AppendLine("jmp " + ContinueExecutionLabel4_2);
            //      4.8. Move StackSize (from element type ref) into eax
            result.AppendLine(ContinueExecutionLabel4_1 + ":");
            int stackSizeOffset = aScannerState.GetTypeFieldOffset("StackSize");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", stackSizeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [eax+{0}]", stackSizeOffset));
            //      4.9. Mulitply eax by ebx (index by element size)
            result.AppendLine(ContinueExecutionLabel4_2 + ":");
            result.AppendLine("mul ebx");
            //      4.10. Pop array ref into ebx
            result.AppendLine("pop ebx");
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;
            #region Offset calculation
            {
                //Get the child links of the type (i.e. the fields of the type)
                List<DB_ComplexTypeLink> allChildLinks = arrayDBType.ChildTypes.ToList();
                //Calculate the offset
                //We use StackBytesSize since fields that are reference types are only stored as a pointer
                allFieldsOffset = allChildLinks.Sum(x => x.ChildType.IsValueType ? x.ChildType.BytesSize : x.ChildType.StackBytesSize);
            }
            #endregion
            result.AppendLine(string.Format("add ebx, {0}", allFieldsOffset));
            //      4.12. Add eax and ebx (array ref + fields + (index * element size))
            result.AppendLine("add eax, ebx");

            // 5. Push the element onto the stack
            //      5.1. Push value at [eax] (except for LdElemA op in which case just push address)
            if (pushValue)
            {
                switch (sizeToPush)
                {
                    case 1:
                        result.AppendLine("mov dword ebx, 0");
                        GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                        result.AppendLine("mov byte bl, [eax]");
                        if (signExtend)
                        {
                            throw new NotSupportedException("Sign extend byte to 4 bytes in LdElem not supported!");
                        }
                        break;
                    case 2:
                        result.AppendLine("mov dword ebx, 0");
                        GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                        result.AppendLine("mov word bx, [eax]");
                        if (signExtend)
                        {
                            result.AppendLine("cwde");
                        }
                        break;
                    case 4:
                        GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                        result.AppendLine("mov dword ebx, [eax]");
                        break;
                    case 8:
                        GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                        result.AppendLine("mov word ebx, [eax]");
                        GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 4, (OpCodes)anILOpInfo.opCode.Value);
                        result.AppendLine("mov word ecx, [eax+4]");
                        break;
                }
                if (sizeToPush == 8)
                {
                    result.AppendLine("push ecx");
                }
                result.AppendLine("push ebx");
            }
            else
            {
                result.AppendLine("push eax");
            }
            
            //      5.2. Pop index and array ref from our stack
            aScannerState.CurrentStackFrame.Stack.Pop();
            aScannerState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat = isFloat,
                isNewGCObject = false,
                isGCManaged = pushValue ? Utils.IsGCManaged(elementType) : false
            });

            return result.ToString().Trim();
        }
示例#7
0
文件: NewObj.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            MethodBase constructorMethod = anILOpInfo.MethodToCall;
            Type objectType = constructorMethod.DeclaringType;
            
            //New obj must:
            // - Ignore for creation of Delegates
            // - Allocate memory on the heap for the object
            //          - If no memory is left, throw a panic attack because we're out of memory...
            // - Call the specified constructor

            if (typeof(Delegate).IsAssignableFrom(objectType))
            {
                result.AppendLine("; Ignore newobj calls for Delegates");
                //Still need to: 
                // - Remove the "object" param but preserve the "function pointer"
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword eax, [esp]");
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 4, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [esp+4], eax");
                result.AppendLine("add esp, 4");
                return result.ToString().Trim();
            }

            //The label to jump to if allocated memory isn't null
            //i.e. not out of memory.
            string NotNullLabel = string.Format("{0}.IL_{1}_NotNullMem",
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    anILOpInfo.Position);
            

            //Attempt to allocate memory on the heap for the new object
            //This involves:
            // - Pushing the type reference onto the stack
            // - Calling GC NewObj method
            // - Check the pointer == 0, if so, out of memory

            //Push type reference
            string typeIdStr = aScannerState.GetTypeIdString(aScannerState.GetTypeID(objectType));
            result.AppendLine(string.Format("push dword {0}", typeIdStr));
            //Push a dword for return value (i.e. new object pointer)
            result.AppendLine("push dword 0");
            //Get the GC.NewObj method ID (i.e. ASM label)
            string methodLabel = aScannerState.GetMethodID(aScannerState.NewObjMethod);
            //Call GC.NewObj
            result.AppendLine(string.Format("call {0}", methodLabel));
            //Pop the return value (i.e. new object pointer)
            result.AppendLine("pop dword eax");
            //Remove arg 0 from stack
            result.AppendLine("add esp, 4");
            //Check if pointer == 0?
            result.AppendLine("cmp eax, 0");
            //If it isn't 0, not out of memory so continue execution
            result.AppendLine(string.Format("jnz {0}", NotNullLabel));
            //If we are out of memory, we have a massive problem
            //Because it means we don't have space to create a new exception object
            //So ultimately we just have to throw a kernel panic
            //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress)
            
            //result.AppendLine("call GetEIP");
            //result.AppendLine("push dword esp");
            //result.AppendLine("push dword ebp");
            //result.AppendLine("pushad");
            //result.AppendLine("mov dword eax, 0xDEADBEEF");
            //result.AppendLine("mov dword ebx, 0x1");
            //result.AppendLine("mov dword ecx, 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0");
            //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail");

            result.AppendLine("call GetEIP");
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.HaltMethod)));
            //Insert the not null label
            result.AppendLine(NotNullLabel + ":");

            //Call the specified constructor
            //This involves:
            // - Push empty dword onto stack
            // - Move all args down by one dword
            // - Move object reference into dword as first arg
            // - Call constructor
            result.AppendLine("push dword 0");
            int sizeOfArgs = 0;
            ParameterInfo[] allParams = constructorMethod.GetParameters();
            foreach(ParameterInfo aParam in allParams)
            {
                sizeOfArgs += Utils.GetNumBytesForType(aParam.ParameterType);
                aScannerState.CurrentStackFrame.Stack.Pop();
            }
            result.AppendLine("mov dword ebx, esp");
            if (sizeOfArgs > 0)
            {
                if (sizeOfArgs % 4 != 0)
                {
                    throw new InvalidOperationException("sizeOfArgs not exact multiple of 4!");
                }

                result.AppendLine(string.Format("mov dword ecx, {0}", sizeOfArgs / 4));
                string ShiftArgsLoopLabel = string.Format("{0}.IL_{1}_ShiftArgsLoop",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                result.AppendLine(ShiftArgsLoopLabel + ":");
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 4, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword edx, [ebx+4]");
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [ebx], edx");
                result.AppendLine("add ebx, 4");
                result.AppendLine(string.Format("loop {0}", ShiftArgsLoopLabel));
            }
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov dword [ebx], eax");
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(constructorMethod)));
            //Only remove args from stack - we want the object pointer to remain on the stack
            result.AppendLine(string.Format("add esp, {0}", sizeOfArgs));

            aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = 4,
                isNewGCObject = true,
                isGCManaged = true
            });

            return result.ToString().Trim();
        }
示例#8
0
文件: NewArr.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Load the metadata token used to get the type info
            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            //Get the type info for the element type
            Type elementType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);
            
            //New array must:
            // - Allocate memory on the heap for the object
            //          - If no memory is left, throw a panic attack because we're out of memory...
            // - Call the specified constructor

            //The label to jump to if allocated memory isn't null
            //i.e. not out of memory.
            string NotNullLabel = string.Format("{0}.IL_{1}_NotNullMem",
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    anILOpInfo.Position);
            

            //Attempt to allocate memory on the heap for the new array
            //This involves:
            // - (Number of elements is already on the stack)
            // - Pushing the element type reference onto the stack
            // - Calling GC NewArr method
            // - Check the pointer == 0, if so, out of memory

            //Push type reference
            string typeIdStr = aScannerState.GetTypeIdString(aScannerState.GetTypeID(elementType));
            result.AppendLine(string.Format("push dword {0}", typeIdStr));
            //Push a dword for return value (i.e. new array pointer)
            result.AppendLine("push dword 0");
            //Get the GC.NewArr method ID (i.e. ASM label)
            string methodLabel = aScannerState.GetMethodID(aScannerState.NewArrMethod);
            //Call GC.NewArr
            result.AppendLine(string.Format("call {0}", methodLabel));
            //Pop the return value (i.e. new array pointer)
            result.AppendLine("pop dword eax");
            //Remove args from stack
            result.AppendLine("add esp, 8");
            //Check if pointer == 0?
            result.AppendLine("cmp eax, 0");
            //If it isn't 0, not out of memory so continue execution
            result.AppendLine(string.Format("jnz {0}", NotNullLabel));
            //If we are out of memory, we have a massive problem
            //Because it means we don't have space to create a new exception object
            //So ultimately we just have to throw a kernel panic
            //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress)
            
            //result.AppendLine("call GetEIP");
            //result.AppendLine("push dword esp");
            //result.AppendLine("push dword ebp");
            //result.AppendLine("pushad");
            //result.AppendLine("mov dword eax, 0xDEADBEEF");
            //result.AppendLine("mov dword ebx, 0x2");
            //result.AppendLine("mov dword ecx, 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0");
            //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail");

            result.AppendLine("call GetEIP");
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.HaltMethod)));
            //Insert the not null label
            result.AppendLine(NotNullLabel + ":");

            //Push new array pointer
            result.AppendLine("push dword eax");

            aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = 4,
                isNewGCObject = true,
                isGCManaged = true
            });

            return result.ToString().Trim();
        }
示例#9
0
文件: Shr.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if either or both values to shift left are floating point values or
        /// if the values are 8 bytes in size.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either or both values to multiply are not 4 or 8 bytes
        /// in size or if the values are of different size.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Pop in reverse order to push
            StackItem itemB = aScannerState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = aScannerState.CurrentStackFrame.Stack.Pop();


            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Shift right on floats is unsupported!");
            }
            else
            {
                string op = (OpCodes)anILOpInfo.opCode.Value == OpCodes.Shr_Un ? "shr" : "sar";

                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    result.AppendLine("pop dword ecx");
                    //Pop item A
                    result.AppendLine("pop dword eax");
                    result.AppendLine(op + " eax, cl");
                    result.AppendLine("push dword eax");

                    aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged = false
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! 4,8 not supported.");
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 4))
                {
                    if ((OpCodes)anILOpInfo.opCode.Value == OpCodes.Shr_Un)
                    {
                        string shiftMoreThan32LabelName = string.Format("{0}.IL_{1}_Shift64",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string endLabelName = string.Format("{0}.IL_{1}_End",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);

                        //Pop item B
                        result.AppendLine("pop dword ecx");
                        //Pop item A (8 bytes)
                        result.AppendLine("pop dword eax");
                        result.AppendLine("pop dword edx");

                        //Check shift size
                        result.AppendLine("cmp ecx, 32");
                        result.AppendLine("jae " + shiftMoreThan32LabelName);

                        //Shr (< 32)
                        result.AppendLine("shrd eax, edx, cl");
                        result.AppendLine("shr edx, cl");
                        result.AppendLine("jmp " + endLabelName);

                        //Shr (>= 32)
                        result.AppendLine(shiftMoreThan32LabelName + ":");
                        result.AppendLine("mov eax, edx");
                        result.AppendLine("mov edx, 0");
                        result.AppendLine("sub ecx, 32");
                        result.AppendLine("shr eax, cl");

                        //Push result
                        result.AppendLine(endLabelName + ":");
                        result.AppendLine("push dword edx");
                        result.AppendLine("push dword eax");

                        aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                        {
                            isFloat = false,
                            sizeOnStackInBytes = 8,
                            isGCManaged = false
                        });
                    }
                    else
                    {
                        string shiftMoreThan32LabelName = string.Format("{0}.IL_{1}_Shift64",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string endLabelName = string.Format("{0}.IL_{1}_End",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);

                        //Pop item B
                        result.AppendLine("pop dword ecx");
                        //Pop item A (8 bytes)
                        result.AppendLine("pop dword eax");
                        result.AppendLine("pop dword edx");

                        //Check shift size
                        result.AppendLine("cmp ecx, 32");
                        result.AppendLine("jae " + shiftMoreThan32LabelName);

                        //Shr (< 32)
                        result.AppendLine("shrd eax, edx, cl");
                        result.AppendLine("sar edx, cl");
                        result.AppendLine("jmp " + endLabelName);

                        //Shr (>= 32)
                        result.AppendLine(shiftMoreThan32LabelName + ":");
                        result.AppendLine("mov eax, edx");
                        // (Preserve sign bit)
                        result.AppendLine("sar edx, 32");
                        result.AppendLine("sub ecx, 32");
                        result.AppendLine("sar eax, cl");

                        //Push result
                        result.AppendLine(endLabelName + ":");
                        result.AppendLine("push dword edx");
                        result.AppendLine("push dword eax");

                        aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                        {
                            isFloat = false,
                            sizeOnStackInBytes = 8,
                            isGCManaged = false
                        });
                    }
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 8)
                {
                    //Note: Shifting by more than 64 bits is pointless since the value will be annihilated entirely.
                    //          "64" fits well within the low 32-bits
                    //      So for this op, we do the same as the 8-4 byte version but discard the top four bytes
                    //          of the second operand
                    //      Except we must check the high bytes for non-zero value. If they are non-zero, we simply
                    //          push a result of zero.

                    if ((OpCodes)anILOpInfo.opCode.Value == OpCodes.Shr_Un)
                    {
                        string zeroLabelName = string.Format("{0}.IL_{1}_Zero",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string shiftMoreThan32LabelName = string.Format("{0}.IL_{1}_Shift64",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string end1LabelName = string.Format("{0}.IL_{1}_End1",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string end2LabelName = string.Format("{0}.IL_{1}_End2",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);

                        //Pop item B
                        result.AppendLine("pop dword ecx");
                        result.AppendLine("pop dword ebx");
                        //Pop item A (8 bytes)
                        result.AppendLine("pop dword eax");
                        result.AppendLine("pop dword edx");
                        //Check high 4 bytes of second param
                        result.AppendLine("cmp ebx, 0");
                        result.AppendLine("jz " + zeroLabelName);
                        result.AppendLine("push dword 0");
                        result.AppendLine("push dword 0");
                        result.AppendLine("jmp " + end2LabelName);
                        result.AppendLine(zeroLabelName + ":");

                        //Check shift size
                        result.AppendLine("cmp ecx, 32");
                        result.AppendLine("jae " + shiftMoreThan32LabelName);

                        //Shr (< 32)
                        result.AppendLine("shrd eax, edx, cl");
                        result.AppendLine("shr edx, cl");
                        result.AppendLine("jmp " + end1LabelName);

                        //Shr (>= 32)
                        result.AppendLine(shiftMoreThan32LabelName + ":");
                        result.AppendLine("mov eax, edx");
                        result.AppendLine("mov edx, 0");
                        result.AppendLine("sub ecx, 32");
                        result.AppendLine("shr eax, cl");

                        //Push result
                        result.AppendLine(end1LabelName + ":");
                        result.AppendLine("push dword edx");
                        result.AppendLine("push dword eax");
                        result.AppendLine(end2LabelName + ":");

                        aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                        {
                            isFloat = false,
                            sizeOnStackInBytes = 8,
                            isGCManaged = false
                        });
                    }
                    else
                    {
                        string zeroLabelName = string.Format("{0}.IL_{1}_Zero",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string shiftMoreThan32LabelName = string.Format("{0}.IL_{1}_Shift64",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string end1LabelName = string.Format("{0}.IL_{1}_End1",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);
                        string end2LabelName = string.Format("{0}.IL_{1}_End2",
                        aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                        anILOpInfo.Position);

                        //Pop item B
                        result.AppendLine("pop dword ecx");
                        result.AppendLine("pop dword ebx");
                        //Pop item A (8 bytes)
                        result.AppendLine("pop dword eax");
                        result.AppendLine("pop dword edx");
                        //Check high 4 bytes of second param
                        result.AppendLine("cmp ebx, 0");
                        result.AppendLine("jz " + zeroLabelName);
                        // (Preserve sign bit)
                        result.AppendLine("sar edx, 32");
                        result.AppendLine("push dword edx");
                        result.AppendLine("push dword edx");
                        result.AppendLine("jmp " + end2LabelName);
                        result.AppendLine(zeroLabelName + ":");

                        //Check shift size
                        result.AppendLine("cmp ecx, 32");
                        result.AppendLine("jae " + shiftMoreThan32LabelName);

                        //Shr (< 32)
                        result.AppendLine("shrd eax, edx, cl");
                        result.AppendLine("sar edx, cl");
                        result.AppendLine("jmp " + end1LabelName);

                        //Shr (>= 32)
                        result.AppendLine(shiftMoreThan32LabelName + ":");
                        result.AppendLine("mov eax, edx");
                        // (Preserve sign bit)
                        result.AppendLine("sar edx, 32");
                        result.AppendLine("sub ecx, 32");
                        result.AppendLine("sar eax, cl");

                        //Push result
                        result.AppendLine(end1LabelName + ":");
                        result.AppendLine("push dword edx");
                        result.AppendLine("push dword eax");
                        result.AppendLine(end2LabelName + ":");

                        aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                        {
                            isFloat = false,
                            sizeOnStackInBytes = 8,
                            isGCManaged = false
                        });
                    }
                }
            }


            return result.ToString().Trim();
        }
示例#10
0
文件: Stelem.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            Type elementType = null;
            //bool pushValue = true;
            int sizeToPop = 4;
            bool isFloat = false;

            switch ((OpCodes)anILOpInfo.opCode.Value)
            {
                case OpCodes.Stelem:
                    {
                        //Load the metadata token used to get the type info
                        int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                        //Get the type info for the element type
                        elementType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);
                    }
                    break;

                case OpCodes.Stelem_R4:
                case OpCodes.Stelem_R8:
                    //TODO - Add more StElem op variants support
                    throw new NotSupportedException("Stelem op variant not supported yet!");

                case OpCodes.Stelem_I1:
                    sizeToPop = 1;
                    elementType = typeof(sbyte);
                    break;
                case OpCodes.Stelem_I2:
                    sizeToPop = 2;
                    elementType = typeof(Int16);
                    break;

                case OpCodes.Stelem_Ref:
                    elementType = null;
                    break;

                case OpCodes.Stelem_I4:
                    elementType = typeof(Int32);
                    break;

                case OpCodes.Stelem_I8:
                    elementType = typeof(Int64);
                    break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("StElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Pop the value from the stack into the element

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Value to store (dword or 2 dwords)
            // 1. Index of element to get as Int32 (dword)
            // 2. Array object reference as address (dword)

            string ContinueExecutionLabelBase = string.Format("{0}.IL_{1}_Store_ContinueExecution",
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    anILOpInfo.Position);
            DB_Type arrayDBType = DebugDatabase.GetType(aScannerState.GetTypeID(aScannerState.ArrayClass));

            // 1. Check array reference is not null
            //      1.1. Move array ref into eax
            //      1.2. Compare eax (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            string ContinueExecutionLabel1 = ContinueExecutionLabelBase + "1";
            //      1.1. Move array ref into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", sizeToPop == 8 ? 12 : 8, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [esp+{0}]", sizeToPop == 8 ? 12 : 8));
            //      1.2. Compare eax (array ref) to 0
            result.AppendLine("cmp eax, 0");
            //      1.3. If not zero, jump to continue execution further down
            result.AppendLine("jnz " + ContinueExecutionLabel1);
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowNullReferenceExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel1 + ":");

            // 2. Check array element type is correct
            //      2.1. Move element type ref into eax
            //      2.2. Move element type ref from array object into ebx
            //      2.3. Compare eax to ebx
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into eax
            //if (elementType != null)
            //{
            //    result.AppendLine(string.Format("mov eax, {0}", aScannerState.GetTypeIdString(aScannerState.GetTypeID(elementType))));
            //}
            //else
            //{
            //    //Should be the same for all classes since they are (indirectly) derived from ObjectWithType
            //    int typeOffset = aScannerState.GetFieldOffset(arrayDBType, "_Type");

            //    //      - Move value (which is a ref) into eax
            //    GlobalMethods.CheckAddrFromRegister(result, aScannerState, "esp", 0);
            //    result.AppendLine("mov eax, [esp]");
            //    //      - Move value type ref (from value (ref)) into eax
            //    GlobalMethods.CheckAddrFromRegister(result, aScannerState, "eax", typeOffset);
            //    result.AppendLine(string.Format("mov eax, [eax+{0}]", typeOffset));
            //}
            ////      2.2. Move element type ref from array object into ebx
            ////              - Move array ref into ebx
            //GlobalMethods.CheckAddrFromRegister(result, aScannerState, "esp", sizeToPop == 8 ? 12 : 8);
            //result.AppendLine(string.Format("mov ebx, [esp+{0}]", sizeToPop == 8 ? 12 : 8));
            ////              - Move elemType ref ([ebx+offset]) into ebx
            int elemTypeOffset = aScannerState.GetFieldOffset(arrayDBType, "elemType");
            //GlobalMethods.CheckAddrFromRegister(result, aScannerState, "ebx", elemTypeOffset);
            //result.AppendLine(string.Format("mov ebx, [ebx+{0}]", elemTypeOffset));
            ////      2.3. Compare eax to ebx
            //result.AppendLine("cmp eax, ebx");
            ////      2.4. If the same, jump to continue execution further down
            //result.AppendLine("je " + ContinueExecutionLabel2);
            ////      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException
            //result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowArrayTypeMismatchExceptionMethod)));
            //result.AppendLine(ContinueExecutionLabel2 + ":");

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into eax
            //      3.2. Move array length into ebx
            //      3.2. Compare eax to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare eax to ebx
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            string ContinueExecutionLabel3_1 = ContinueExecutionLabelBase + "3_1";
            string ContinueExecutionLabel3_2 = ContinueExecutionLabelBase + "3_2";
            //      3.1. Move index into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", sizeToPop == 8 ? 8 : 4, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [esp+{0}]", sizeToPop == 8 ? 8 : 4));
            //      3.2. Move array length into ecx
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = aScannerState.GetFieldOffset(arrayDBType, "length");
            //              - Move array ref into ebx
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", sizeToPop == 8 ? 12 : 8, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov ebx, [esp+{0}]", sizeToPop == 8 ? 12 : 8));
            //              - Move length value ([ebx+offset]) into ebx
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", lengthOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov ebx, [ebx+{0}]", lengthOffset));
            //      3.2. Compare eax to 0
            result.AppendLine("cmp eax, 0");
            //      3.3. Jump if greater than to next test condition (3.5)
            result.AppendLine("jge " + ContinueExecutionLabel3_1);
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowIndexOutOfRangeExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel3_1 + ":");
            //      3.5. Compare eax to ebx
            result.AppendLine("cmp eax, ebx");
            //      3.6. Jump if less than to continue execution further down
            result.AppendLine("jl " + ContinueExecutionLabel3_2);
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.ThrowIndexOutOfRangeExceptionMethod)));
            result.AppendLine(ContinueExecutionLabel3_2 + ":");

            // 4. Calculate address of element
            //      4.0. Pop value into ecx:edx
            //      4.1. Pop index into ebx
            //      4.2. Pop array ref into eax
            //      4.3. Move element type ref (from array ref) into eax
            //      4.4. Push eax
            //      4.5. Move IsValueType (from element ref type) into eax
            //      4.6. If IsValueType, continue to 4.6., else goto 4.9.
            //      4.7. Pop eax
            //      4.8. Move Size (from element type ref) into eax
            //      4.9. Skip over 4.9. and 4.10.
            //      4.10. Pop eax
            //      4.11. Move StackSize (from element type ref) into eax
            //      4.12. Mulitply eax by ebx (index by element size)
            //      4.13. Move array ref into ebx
            //      4.14. Add enough to go past Kernel.FOS_System.Array fields
            //      4.15. Add eax and ebx (array ref + fields + (index * element size))

            string ContinueExecutionLabel4_1 = ContinueExecutionLabelBase + "4_1";
            string ContinueExecutionLabel4_2 = ContinueExecutionLabelBase + "4_2";
            //      4.0. Pop value into ecx:edx
            result.AppendLine("pop ecx");
            if (sizeToPop == 8)
            {
                result.AppendLine("pop edx");
            }
            //      4.1. Pop index into ebx
            result.AppendLine("pop ebx");
            //      4.2. Move array ref into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 0, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov eax, [esp]");
            //      4.3. Move element type ref (from array ref) into eax
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", elemTypeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [eax+{0}]", elemTypeOffset));
            //      4.4. Push eax
            result.AppendLine("push eax");
            //      4.5. Move IsValueType (from element ref type) into eax
            int isValueTypeOffset = aScannerState.GetTypeFieldOffset("IsValueType");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", isValueTypeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov byte al, [eax+{0}]", isValueTypeOffset));
            // Zero-out the rest of eax
            result.AppendLine("and eax, 1");
            //      4.6. If IsValueType, continue to 4.7., else goto 4.9.
            result.AppendLine("cmp eax, 0");
            result.AppendLine("jz " + ContinueExecutionLabel4_1);
            //      4.7. Pop eax
            result.AppendLine("pop eax");
            //      4.8. Move Size (from element type ref) into eax
            int sizeOffset = aScannerState.GetTypeFieldOffset("Size");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", sizeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [eax+{0}]", sizeOffset));
            //      4.9. Skip over 4.9. and 4.10.
            result.AppendLine("jmp " + ContinueExecutionLabel4_2);
            //      4.10. Pop eax
            result.AppendLine(ContinueExecutionLabel4_1 + ":");
            result.AppendLine("pop eax");
            //      4.11. Move StackSize (from element type ref) into eax
            int stackSizeOffset = aScannerState.GetTypeFieldOffset("StackSize");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", stackSizeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov eax, [eax+{0}]", stackSizeOffset));
            //      4.12. Mulitply eax by ebx (index by element size)
            result.AppendLine(ContinueExecutionLabel4_2 + ":");
            result.AppendLine("mul ebx");
            //      4.13. Pop array ref into ebx
            result.AppendLine("pop ebx");
            //      4.14. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;
            #region Offset calculation
            {
                //Get the child links of the type (i.e. the fields of the type)
                List<DB_ComplexTypeLink> allChildLinks = arrayDBType.ChildTypes.ToList();
                //Calculate the offset
                //We use StackBytesSize since fields that are reference types are only stored as a pointer
                allFieldsOffset = allChildLinks.Sum(x => x.ChildType.IsValueType ? x.ChildType.BytesSize : x.ChildType.StackBytesSize);
            }
            #endregion
            result.AppendLine(string.Format("add ebx, {0}", allFieldsOffset));
            //      4.15. Add eax and ebx (array ref + fields + (index * element size))
            result.AppendLine("add eax, ebx");

            // 5. Pop the element from the stack to array
            //      5.1. Move value in edx:ecx to [eax]
            if (sizeToPop == 8)
            {
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [eax], ecx");
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 4, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [eax+4], edx");
            }
            else if(sizeToPop == 4)
            {
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [eax], ecx");
            }
            else if (sizeToPop == 2)
            {
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov word [eax], cx");
            }
            else if (sizeToPop == 1)
            {
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov byte [eax], cl");
            }

            //      5.2. Pop index, array ref and value from our stack
            aScannerState.CurrentStackFrame.Stack.Pop();
            aScannerState.CurrentStackFrame.Stack.Pop();
            aScannerState.CurrentStackFrame.Stack.Pop();


            return result.ToString().Trim();
        }
示例#11
0
文件: Br.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if branch test operand value is a floating point value.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //This will store the offset from the current next op's position
            //to the IL op to jump to.
            int ILOffset = 0;
            //This will store the jump operation - by default, the basic jump op
            string jumpOp = "jmp";

            string inverseJumpOp = "";
            bool isNegativeTest = false;

            //The value for the jump op to test against - currently always "0" since on jnz and jz ops are used.
            string testVal = "0";
            
            switch ((OpCodes)anILOpInfo.opCode.Value)
            {
                case OpCodes.Br:
                    //Load the IL offset as signed Int 32 from the value bytes.
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    break;
                case OpCodes.Br_S:
                    //Load the IL offset as signed Int 8 from the value bytes.
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    break;
                case OpCodes.Brtrue:
                    //See above.
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-true means we want to do the jump if the operand is not equal to 0
                    //i.e. not false
                    //Set the jump op to jnz - Jump if Not Zero
                    jumpOp = "jnz";
                    break;
                case OpCodes.Brtrue_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jnz";
                    break;
                case OpCodes.Brfalse:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-true means we want to do the jump if the operand is equal to 0
                    //i.e. is false
                    //Set the jump op to jz - Jump if Zero
                    jumpOp = "jz";
                    break;
                case OpCodes.Brfalse_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jz";
                    break;

                case OpCodes.Beq:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-equal means we want to do the jump if the operand is equal to the other operand
                    //i.e. A == B
                    //Set the jump op to je - Jump if equal
                    jumpOp = "je";
                    inverseJumpOp = "jne";
                    break;
                case OpCodes.Beq_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "je";
                    inverseJumpOp = "jne";
                    break;

                case OpCodes.Bne_Un:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-equal means we want to do the jump if the operand is equal to the other operand
                    //i.e. A == B
                    //Set the jump op to je - Jump if not equal
                    jumpOp = "jne";
                    isNegativeTest = true;
                    break;
                case OpCodes.Bne_Un_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jne";
                    isNegativeTest = true;
                    break;

                case OpCodes.Bge:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-greater-than-or-equal means we want to do the jump if the operand is greater than equal to 
                    //the other operand
                    //i.e. A >= B
                    //Set the jump op to jge - Jump if greater than or equal
                    jumpOp = "jge";
                    inverseJumpOp = "jl";
                    break;
                case OpCodes.Bge_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jge";
                    inverseJumpOp = "jl";
                    break;
                case OpCodes.Bge_Un:
                    //See above : This is unsigned variant
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //See above
                    jumpOp = "jae";
                    inverseJumpOp = "jb";
                    break;
                case OpCodes.Bge_Un_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jae";
                    inverseJumpOp = "jb";
                    break;

                case OpCodes.Ble:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-less-than-or-equal means we want to do the jump if the operand is less than equal to 
                    //the other operand
                    //i.e. A <= B
                    //Set the jump op to jle - Jump if less than or equal
                    jumpOp = "jle";
                    inverseJumpOp = "jg";
                    break;
                case OpCodes.Ble_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jle";
                    inverseJumpOp = "jg";
                    break;
                case OpCodes.Ble_Un:
                    //See above : This is unsigned variant
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //See above
                    jumpOp = "jbe";
                    inverseJumpOp = "ja";
                    break;
                case OpCodes.Ble_Un_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jbe";
                    inverseJumpOp = "ja";
                    break;

                case OpCodes.Blt:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-less-than means we want to do the jump if the operand is less than
                    //the other operand
                    //i.e. A < B
                    //Set the jump op to jl - Jump if less than
                    jumpOp = "jl";
                    isNegativeTest = true;
                    break;
                case OpCodes.Blt_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jl";
                    isNegativeTest = true;
                    break;
                case OpCodes.Blt_Un:
                    //See above : This is unsigned variant
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //See above
                    jumpOp = "jb";
                    isNegativeTest = true;
                    break;
                case OpCodes.Blt_Un_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jb";
                    isNegativeTest = true;
                    break;

                case OpCodes.Bgt:
                    //See above
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //Branch-if-greater-than means we want to do the jump if the operand is greater than
                    //the other operand
                    //i.e. A > B
                    //Set the jump op to jg - Jump if greater than
                    jumpOp = "jg";
                    isNegativeTest = true;
                    break;
                case OpCodes.Bgt_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "jg";
                    isNegativeTest = true;
                    break;
                case OpCodes.Bgt_Un:
                    //See above : This is unsigned variant
                    ILOffset = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
                    //See above
                    jumpOp = "ja";
                    isNegativeTest = true;
                    break;
                case OpCodes.Bgt_Un_S:
                    //See above
                    ILOffset = (int)(sbyte)anILOpInfo.ValueBytes[0];
                    //See above
                    jumpOp = "ja";
                    isNegativeTest = true;
                    break;

            }

            if (ILOffset == 0)
            {
                //Err..why bother jumping at all if the offset is 0?
                result.AppendLine("; No jump insert - pointless 0 distance jump"); //DEBUG INFO
            }
            else
            {
                //Get the IL number of the next op
                int startILNum = anILOpInfo.NextPosition;
                //Add the offset to get the IL op num to jump to
                int ILNumToGoTo = startILNum + ILOffset;
                
                ////Find and mark the IL op to jump to as requiring a label.
                //(from ops in aScannerState.CurrentILChunk.ILOpInfos
                // where (ops.Position == ILNumToGoTo)
                // select ops).First().ASMInsertLabel = true;

                //Pre-work out the asm label for jumping to
                string jumpToLabel = string.Format("{0}.IL_{1}_0", 
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                    ILNumToGoTo);
                //Pre-work out the asm label for jumping to if the condition is not met.
                string endLabelName = string.Format("{0}.IL_{1}_End", 
                    aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), 
                    anILOpInfo.Position);
                
                //If the jump op is not a straightforward jump i.e. has one or more conditions
                if (jumpOp == "jz" || jumpOp == "jnz")
                {
                    //Pop from our stack the test item to use in the condition
                    StackItem testItem = aScannerState.CurrentStackFrame.Stack.Pop();
                    
                    if (testItem.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Branch test based on float not supported!");
                    }
                    //If the test item is Int64 or UInt64
                    else if (testItem.sizeOnStackInBytes == 8)
                    {
                        //Compare first 32 bits (low bits)
                        //Then (if necessary) compare second 32 bits (high bits)
                        
                        //Pop the low bits
                        result.AppendLine("pop dword eax");
                        //Compare the low bits to the test value
                        result.AppendLine(string.Format("cmp eax, {0}", testVal));
                        //Pre-emptively pop the high bits
                        result.AppendLine("pop dword eax");
                        
                        //If we are testing for not equal to zero:
                        if (jumpOp == "jnz")
                        {
                            //If the low bits are not zero, do the jump
                            result.AppendLine(string.Format("jnz {0}", jumpToLabel));
                            //Otherwise, test if the high bits are not 0
                            //We use "cmp" not "test" as "cmp" uses +/- test val, "test" uses & with test val.
                            result.AppendLine(string.Format("cmp eax, {0}", testVal));
                            //If the high bits are not zero, do the jump
                            result.AppendLine(string.Format("jnz {0}", jumpToLabel));
                        }
                        //If we are testing for equal to zero:
                        else if (jumpOp == "jz")
                        {
                            //If the low bits are not zero, jump to the end of these test as condition has not been met
                            result.AppendLine(string.Format("jnz {0}", endLabelName));
                            //Otherwise, test if the high bits are zero
                            result.AppendLine(string.Format("cmp eax, {0}", testVal));
                            //If they are, do the jump
                            result.AppendLine(string.Format("jz {0}", jumpToLabel));
                            //Insert the end label to be jumped to if condition is not met (see above)
                            result.AppendLine(string.Format("{0}:", endLabelName));
                        }
                        else
                        {
                            //Check that no extra ops have been added in the switch block above!
                            throw new NotSupportedException("Unsupported 64-bit branch op!");
                        }
                    }
                    //If the test item is Int32 or UInt32
                    else if (testItem.sizeOnStackInBytes == 4)
                    {
                        //Pop the test item
                        result.AppendLine("pop dword eax");
                        //Compare the test item to the test value
                        result.AppendLine(string.Format("cmp eax, {0}", testVal));
                        //Do the specified jump
                        result.AppendLine(string.Format("{0} {1}",
                            jumpOp, jumpToLabel));
                    }
                    else
                    {
                        throw new InvalidOperationException("Invalid stack operand sizes!");
                    }
                }
                else if (jumpOp == "je" || jumpOp == "jne" ||
                         jumpOp == "jge" || jumpOp == "jae" ||
                         jumpOp == "jle" || jumpOp == "jbe" ||
                         jumpOp == "jl" || jumpOp == "jb" ||
                         jumpOp == "jg" || jumpOp == "ja")
                {
                    //Pop from our stack the test items to use in the condition
                    StackItem itemB = aScannerState.CurrentStackFrame.Stack.Pop();
                    StackItem itemA = aScannerState.CurrentStackFrame.Stack.Pop();

                    if (itemA.isFloat || itemB.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Branch test based on float not supported!");
                    }
                    else if(itemA.sizeOnStackInBytes != itemB.sizeOnStackInBytes)
                    {
                        throw new InvalidOperationException("Branch test operands must be same size!");
                    }
                    else if (itemA.sizeOnStackInBytes == 8)
                    {
                        //Pop the test item B
                        result.AppendLine("pop dword ebx");
                        result.AppendLine("pop dword ecx");
                        //Pop the test item A
                        result.AppendLine("pop dword eax");
                        result.AppendLine("pop dword edx");

                        if(!isNegativeTest)
                        {
                            //Compare test item A high bits to test item B high bits
                            result.AppendLine("cmp edx, ecx");
                            //If they are not equal, abort the testing
                            result.AppendLine(string.Format("{0} {1}", inverseJumpOp, endLabelName));
                            //Else the igh bits are equal so test low bits
                            //Compare test item A low bits to test item B low bits
                            result.AppendLine("cmp eax, ebx");
                            //Do the specified jump
                            result.AppendLine(string.Format("{0} {1}", jumpOp, jumpToLabel));

                            //Insert the end label to be jumped to if condition is not met (see above)
                            result.AppendLine(string.Format("{0}:", endLabelName));
                        }
                        else
                        {
                            //Compare test item A high bits to test item B high bits
                            result.AppendLine("cmp edx, ecx");
                            //Do the specified jump
                            result.AppendLine(string.Format("{0} {1}", jumpOp, jumpToLabel));
                            //Compare test item A low bits to test item B low bits
                            result.AppendLine("cmp eax, ebx");
                            //Do the specified jump
                            result.AppendLine(string.Format("{0} {1}", jumpOp, jumpToLabel));
                        }
                    }
                    else if (itemA.sizeOnStackInBytes == 4)
                    {
                        //Pop the test item B
                        result.AppendLine("pop dword ebx");
                        //Pop the test item A
                        result.AppendLine("pop dword eax");
                        //Compare test item A to test item B
                        result.AppendLine("cmp eax, ebx");
                        //Do the specified jump
                        result.AppendLine(string.Format("{0} {1}",
                            jumpOp, jumpToLabel));
                    }
                    else
                    {
                        throw new NotSupportedException("Branch test based on supplied stack item sizes not supported!");
                    }
                }
                else
                {
                    //Do the straightforward jump...
                    result.AppendLine(string.Format("{0} {1}",
                        jumpOp, jumpToLabel));
                }
            }

            return result.ToString().Trim();
        }
示例#12
0
文件: Isinst.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            string Label_3 = string.Format("{0}.IL_{1}_Point3",
                                            aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                            anILOpInfo.Position);

            string Label_False1 = string.Format("{0}.IL_{1}_False1",
                                                aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                anILOpInfo.Position);
            string Label_False2 = string.Format("{0}.IL_{1}_False2",
                                                aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                anILOpInfo.Position);

            string Label_End = string.Format("{0}.IL_{1}_End",
                                                aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method),
                                                anILOpInfo.Position);

            // Test if the object provided inherits from the specified class
            // 1. Pop object ref
            // 1.1. Test if object ref is null:
            // 1.1.1 True: Push null and continue
            // 1.1.2 False: Go to 2
            // 2. Load object type
            // 3. Test if object type == provided type:
            //      3.1 True: Push object ref and continue
            //      3.2 False: 
            //      3.2.1. Move to base type
            //      3.2.2. Test if base type null:
            //      3.2.2.1   True: Push null and continue
            //      3.2.2.2   False: Jump back to (3)

            // 1. Pop object ref
            result.AppendLine("pop dword eax");

            // 1.1. Test if object ref is null:
            result.AppendLine("cmp eax, 0");

            result.AppendLine("jne " + Label_False1);

            // 1.1.1 True: Push null and continue
            result.AppendLine("push dword 0");
            result.AppendLine("jmp " + Label_End);

            // 1.1.2 False: Go to 2
            result.AppendLine(Label_False1 + ":");

            // 2. Load object type
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine("mov dword ebx, [eax]");
            

            // 3. Test if object type == provided type:
            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            Type theType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);
            string TestTypeId = aScannerState.GetTypeIdString(aScannerState.GetTypeID(theType));

            result.AppendLine("mov dword ecx, " + TestTypeId);

            result.AppendLine(Label_3 + ":");
            result.AppendLine("cmp ebx, ecx");


            result.AppendLine("jne " + Label_False2);

            //      3.1 True: Push object ref and continue
            result.AppendLine("push dword eax");
            result.AppendLine("jmp " + Label_End);

            //      3.2 False: 
            result.AppendLine(Label_False2 + ":");

            //      3.2.1. Move to base type
            int baseTypeOffset = aScannerState.GetTypeFieldOffset("TheBaseType");
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", baseTypeOffset, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov dword ebx, [ebx+{0}]", baseTypeOffset));

            //      3.2.2. Test if base type null:
            result.AppendLine("cmp ebx, 0");
            //      3.2.2.2   False: Jump back to (3)
            result.AppendLine("jne " + Label_3);
            
            //      3.2.2.1   True: Push null and continue
            result.AppendLine("push dword 0");
            
            result.AppendLine(Label_End + ":");

            return result.ToString().Trim();
        }
示例#13
0
文件: Clt.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if compare operands are floating point numbers or if either value is &lt; 4 bytes in length or
        /// operands are not of the same size.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Pop in reverse order to push
            StackItem itemB = aScannerState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = aScannerState.CurrentStackFrame.Stack.Pop();

            bool unsignedComparison = (OpCodes)anILOpInfo.opCode.Value == OpCodes.Clt_Un;

            string trueLabelName = string.Format("{0}.IL_{1}_True", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position);
            string elseLabelName = string.Format("{0}.IL_{1}_Else", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position);
            string endLabelName = string.Format("{0}.IL_{1}_End", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position);

            if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Add floats is unsupported!");
            }
            else if(itemA.sizeOnStackInBytes == 4 && itemB.sizeOnStackInBytes == 4)
            {
                //Pop item B
                result.AppendLine("pop dword ebx");
                //Pop item A
                result.AppendLine("pop dword eax");
                //Compare A to B
                result.AppendLine("cmp eax, ebx");
                //If A >= B, jump to Else (not-true case)
                if (unsignedComparison)
                {
                    result.AppendLine(string.Format("jae {0}", elseLabelName));
                }
                else
                {
                    result.AppendLine(string.Format("jge {0}", elseLabelName));
                }
                //Otherwise, A < B, so push true (true=1)
                result.AppendLine("push dword 1");
                //And then jump to the end of this IL op.
                result.AppendLine(string.Format("jmp {0}", endLabelName));
                //Insert the Else label.
                result.AppendLine(string.Format("{0}:", elseLabelName));
                //Else case - Push false (false=0)
                result.AppendLine("push dword 0");
                
                //Push the result onto our stack
                aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false
                });
            }
            else if (itemA.sizeOnStackInBytes == 8 && itemB.sizeOnStackInBytes == 8)
            {
                //Pop item B
                result.AppendLine("pop dword ebx");
                result.AppendLine("pop dword ecx");
                //Pop item A
                result.AppendLine("pop dword eax");
                result.AppendLine("pop dword edx");
                //If A high bytes < B high bytes : True
                //If A high bytes = B high bytes : Check, if A low bytes < B low bytes : True
                //Else : False
                
                //Compare high bytes
                result.AppendLine("cmp edx, ecx");
                //A high bytes < B high bytes? Jump to true case.
                if (unsignedComparison)
                {
                    result.AppendLine(string.Format("jb {0}", trueLabelName));
                }
                else
                {
                    result.AppendLine(string.Format("jl {0}", trueLabelName));
                }
                //A high bytes > B high bytes? Jump to else case.
                if (unsignedComparison)
                {
                    result.AppendLine(string.Format("ja {0}", elseLabelName));
                }
                else
                {
                    result.AppendLine(string.Format("jg {0}", elseLabelName));
                }
                //Otherwise, A high bytes = B high bytes
                //So compare low bytes
                result.AppendLine("cmp eax, ebx");
                //A low bytes >= B low bytes? Jump to else case.
                if (unsignedComparison)
                {
                    result.AppendLine(string.Format("jae {0}", elseLabelName));
                }
                else
                {
                    result.AppendLine(string.Format("jge {0}", elseLabelName));
                }
                //Otherwise A < B.

                //Insert True case label
                result.AppendLine(string.Format("{0}:", trueLabelName));
                //True case - Push true (true=1)
                result.AppendLine("push dword 1");
                //And then jump to the end of this IL op.
                result.AppendLine(string.Format("jmp {0}", endLabelName));
                //Insert Else case label
                result.AppendLine(string.Format("{0}:", elseLabelName));
                //Else case - Push false (false=0)
                result.AppendLine("push dword 0");

                //Push the result onto our stack
                aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    // Yes, this is supposed to be 4 - the value that just got pushed was a 
                    // true / false integer
                    sizeOnStackInBytes = 4,
                    isGCManaged = false
                });
            }
            else
            {
                throw new NotSupportedException("Unsupported number of bytes for compare less than!");
            }

            //Always append the end label
            result.AppendLine(string.Format("{0}:", endLabelName));

            return result.ToString().Trim();
        }
示例#14
0
文件: Call.cs 项目: kztao/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="anILOpInfo">See base class documentation.</param>
        /// <param name="aScannerState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            MethodBase methodToCall = anILOpInfo.MethodToCall;
            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if(methodToCall is MethodInfo)
            {
                //Allocate space on the stack for the return value as necessary
                Type retType = ((MethodInfo)methodToCall).ReturnType;
                StackItem returnItem = new StackItem()
                {
                    isFloat = Utils.IsFloat(retType),
                    sizeOnStackInBytes = Utils.GetNumBytesForType(retType),
                    isGCManaged = Utils.IsGCManaged(retType)
                };
                //We do not push the return value onto the stack unless it has size > 0
                //We do not push the return value onto our stack at this point - it is pushed after the call is done

                if (returnItem.sizeOnStackInBytes != 0)
                {
                    if (returnItem.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Cannot handle float return values!");
                    }
                    else if (returnItem.sizeOnStackInBytes == 4)
                    {
                        result.AppendLine("push dword 0");
                    }
                    else if (returnItem.sizeOnStackInBytes == 8)
                    {
                        result.AppendLine("push dword 0");
                        result.AppendLine("push dword 0");
                    }
                    else
                    {
                        throw new NotSupportedException("Invalid return stack operand size!");
                    }
                }

                //Get the ID of method to call as it will be labelled in the output ASM.
                string methodID = aScannerState.GetMethodID(methodToCall);
                //Append the actual call
                result.AppendLine(string.Format("call {0}", methodID));

                //After a call, we need to remove the return value and parameters from the stack
                //This is most easily done by just adding the total number of bytes for params and
                //return value to the stack pointer (ESP register).
                
                //Stores the number of bytes to add
                int bytesToAdd = 0;
                //All the parameters for the method that was called
                List<Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                //Go through each one
                if (!methodToCall.IsStatic)
                {
                    allParams.Insert(0, methodToCall.DeclaringType);
                }
                foreach (Type aParam in allParams)
                {
                    //Pop the paramter off our stack 
                    //(Note: Return value was never pushed onto our stack. See above)
                    aScannerState.CurrentStackFrame.Stack.Pop();
                    //Add the size of the paramter to the total number of bytes to pop
                    bytesToAdd += Utils.GetNumBytesForType(aParam);
                }
                //If the number of bytes to add to skip over params is > 0
                if (bytesToAdd > 0)
                {
                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the 
                        //top item on the stack
                        aScannerState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value into the eax register
                        //We will push it back on after params are skipped over.
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            result.AppendLine("pop dword eax");
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            result.AppendLine("pop dword eax");
                            result.AppendLine("pop dword edx");
                        }
                    }   
                    //Skip over the params
                    result.AppendLine(string.Format("add esp, {0}", bytesToAdd));
                    //If necessary, push the return value onto the stack.
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //SUPPORT - floats (with above)

                        //The return value was stored in eax
                        //So push it back onto the stack
                        if (returnItem.sizeOnStackInBytes == 4)
                        {
                            result.AppendLine("push dword eax");
                        }
                        else if (returnItem.sizeOnStackInBytes == 8)
                        {
                            result.AppendLine("push dword edx");
                            result.AppendLine("push dword eax");
                        }
                    }
                }
                //No params to skip over but we might still need to store return value
                else if (returnItem.sizeOnStackInBytes != 0)
                {
                    //The return value will be the top item on the stack.
                    //So all we need to do is push the return item onto our stack.
                    aScannerState.CurrentStackFrame.Stack.Push(returnItem);
                }
            }
            else if(methodToCall is ConstructorInfo)
            {
                ConstructorInfo aConstructor = (ConstructorInfo)methodToCall;
                if (aConstructor.IsStatic)
                {
                    //Static constructors do not have parameters or return values

                    //Get the ID of method to call as it will be labelled in the output ASM.
                    string methodID = aScannerState.GetMethodID(methodToCall);
                    //Append the actual call
                    result.AppendLine(string.Format("call {0}", methodID));
                }
                else
                {
                    //Get the ID of method to call as it will be labelled in the output ASM.
                    string methodID = aScannerState.GetMethodID(methodToCall);
                    //Append the actual call
                    result.AppendLine(string.Format("call {0}", methodID));

                    //After a call, we need to remove the parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params
                    //to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    ParameterInfo[] allParams = methodToCall.GetParameters();
                    //Go through each one
                    foreach (ParameterInfo aParam in allParams)
                    {
                        //Pop the paramter off our stack 
                        //(Note: Return value was never pushed onto our stack. See above)
                        aScannerState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += Utils.GetNumBytesForType(aParam.ParameterType);
                    }
                    //Add 4 bytes for the instance ref
                    bytesToAdd += 4;
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //Skip over the params
                        result.AppendLine(string.Format("add esp, {0}", bytesToAdd));
                    }
                }
            }
            
            return result.ToString().Trim();
        }