Пример #1
0
        /// <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();

            //Push the previous method's ebp
            result.AppendLine("push dword ebp");
            //Set ebp for this method
            //See calling convention spec - this allows easy access of
            //args and locals within the method without having to track
            //temporary values (which would be a nightmare with the
            //exception handling implmentation that the kernel uses!)
            result.AppendLine("mov dword ebp, esp");

            //Allocate stack space for locals
            //Only bother if there are any locals
            if (aScannerState.CurrentILChunk.LocalVariables.Count > 0)
            {
                int totalBytes = 0;
                foreach (StackItem aLocal in aScannerState.CurrentILChunk.LocalVariables)
                {
                    totalBytes += aLocal.sizeOnStackInBytes;
                }
                //We do not use "sub esp, X" (see below) because that leaves
                //junk memory - we need memory to be "initialised" to 0 
                //so that local variables are null unless properly initialised.
                //This prevents errors in the GC.
                for (int i = 0; i < totalBytes / 4; i++)
                {
                    result.AppendLine("push dword 0");
                }
                //result.AppendLine(string.Format("sub esp, {0}", totalBytes));
            }

            return result.ToString().Trim();
        }
Пример #2
0
        /// <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
        /// <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();

            StackItem theItem = aScannerState.CurrentStackFrame.Stack.Peek();
            if (theItem.isFloat)
            {
                //SUPPORT - Not op for floats
                throw new NotSupportedException("Not op not supported for float operands!");
            }

            if (theItem.sizeOnStackInBytes == 4)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine("not eax");
                result.AppendLine("push dword eax");
            }
            else if (theItem.sizeOnStackInBytes == 8)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine("pop dword ebx");
                result.AppendLine("not eax");
                result.AppendLine("not ebx");
                result.AppendLine("push dword ebx");
                result.AppendLine("push dword eax");
            }
            else
            {
                throw new NotSupportedException("Not op not supported for operand size!");
            }

            return result.ToString().Trim();
        }
Пример #4
0
        /// <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();
        }
Пример #5
0
        /// <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 a string literal (- fixed string i.e. one programmed as "a string in code")

            //Get the string metadata token used to get the string from the assembly
            int StringMetadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            //Get the value of the string to load
            string theString = aScannerState.CurrentILChunk.Method.Module.ResolveString(StringMetadataToken);
            //Add the string literal and get its ID
            string theStringID = aScannerState.AddStringLiteral(theString, anILOpInfo);

            //Push the address of the string (i.e. address of ID - ASM label)
            result.AppendLine(string.Format("push {0}", theStringID));

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

            return result.ToString().Trim();
        }
Пример #6
0
        /// <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();

            int dwordsToRotate = anILOpInfo.ValueBytes == null ? 2 : BitConverter.ToInt32(anILOpInfo.ValueBytes, 0);
            
            int bytesShift = 0;
            for (int i = 0; i < dwordsToRotate; i++)
            {
                if (i == 0)
                {
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesShift, OpCodes.Unbox);
                    result.AppendLine(string.Format("mov eax, [esp+{0}]", bytesShift));
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesShift + 4, OpCodes.Unbox);
                    result.AppendLine(string.Format("mov dword ebx, [esp+{0}]", bytesShift + 4));
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesShift, OpCodes.Unbox);
                    result.AppendLine(string.Format("mov dword [esp+{0}], ebx", bytesShift));
                }
                else if (i == dwordsToRotate - 1)
                {
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesShift, OpCodes.Unbox);
                    result.AppendLine(string.Format("mov [esp+{0}], eax", bytesShift));
                }
                else
                {
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesShift + 4, OpCodes.Unbox);
                    result.AppendLine(string.Format("mov dword ebx, [esp+{0}]", bytesShift + 4));
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", bytesShift, OpCodes.Unbox);
                    result.AppendLine(string.Format("mov dword [esp+{0}], ebx", bytesShift));
                }
                bytesShift += 4;
            }

            return result.ToString().Trim();
        }
Пример #7
0
        /// <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();

            result.AppendLine("ret");

            return result.ToString().Trim();
        }
Пример #8
0
 /// <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)
 {
     if (anILOpInfo.IsDebugOp)
     {
         return "int3";
     }
     else
     {
         return "nop";
     }
 }
Пример #9
0
        /// <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();
        }
Пример #10
0
        /// <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 null (i.e. 0 as dword)
            aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = 4,
                isGCManaged = false
            });
            result.AppendLine("push dword 0");

            return result.ToString().Trim();
        }
Пример #11
0
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            result.AppendLine("; Method End"); //DEBUG INFO
            result.AppendLine("pop rbp");
            result.AppendLine("mov rsp, rbp");

            StackFrame currFrame = aScannerState.StackFrames.Peek();
            currFrame.Stack.Pop();

            result.AppendLine("ret");

            return result.ToString().Trim();
        }
Пример #12
0
        /// <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">
        /// 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 item to duplicate
            StackItem itemA = aScannerState.CurrentStackFrame.Stack.Pop();

            if(itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Duplicate float vals not suppported yet!");
            }
            
            if(itemA.sizeOnStackInBytes == 4)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine("push dword eax");
                result.AppendLine("push dword eax");
            }
            else if (itemA.sizeOnStackInBytes == 8)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine("pop dword edx");
                result.AppendLine("push dword edx");
                result.AppendLine("push dword eax");
                result.AppendLine("push dword edx");
                result.AppendLine("push dword eax");
            }
            else
            {
                throw new NotSupportedException("Stack item size not supported by duplicate op!");
            }

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

            return result.ToString().Trim();
        }
Пример #13
0
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            result.AppendLine("; Method Start"); //DEBUG INFO
            result.AppendLine("push rbp");
            result.AppendLine("mov rbp, rsp");

            StackFrame currFrame = aScannerState.StackFrames.Peek();
            currFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = 8
            });

            return result.ToString().Trim();
        }
Пример #14
0
        /// <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 the value to store is floating point or
        /// if the value is not 4 or 8 bytes in size.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            FieldInfo theField = aScannerState.CurrentILChunk.Method.Module.ResolveField(metadataToken);
            DB_Type objDBType = DebugDatabase.GetType(aScannerState.GetTypeID(theField.DeclaringType));

            int offset = aScannerState.GetFieldOffset(objDBType, theField.Name);

            int stackSize = Utils.GetNumBytesForType(theField.FieldType);
            int memSize = theField.FieldType.IsValueType ? Utils.GetSizeForType(theField.FieldType) : stackSize;

            StackItem value = aScannerState.CurrentStackFrame.Stack.Pop();
            StackItem objPointer = aScannerState.CurrentStackFrame.Stack.Pop();
            
            if (value.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing fields of type float not supported yet!");
            }

            //Get object pointer
            GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", stackSize, (OpCodes)anILOpInfo.opCode.Value);
            result.AppendLine(string.Format("mov ecx, [esp+{0}]", stackSize));
            //Pop and mov value
            for (int i = 0; i < memSize; i += 2)
            {
                if (memSize - i == 1)
                {
                    result.AppendLine("pop word ax");
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ecx", offset + i, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine(string.Format("mov byte [ecx+{0}], al", offset + i));
                }
                else
                {
                    result.AppendLine("pop word ax");
                    GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ecx", offset + i, (OpCodes)anILOpInfo.opCode.Value);
                    result.AppendLine(string.Format("mov word [ecx+{0}], ax", offset + i));
                }
            }
            result.AppendLine(string.Format("add esp, {0}", ((stackSize - memSize) / 2) * 2)); //Rounds down
            result.AppendLine("add esp, 4");//Pop object pointer

            return result.ToString().Trim();
        }
Пример #15
0
        /// <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();

            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            Type theType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);
            result.AppendLine(string.Format("push dword {0}", Utils.GetNumBytesForType(theType)));

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

            return result.ToString().Trim();
        }
Пример #16
0
        /// <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 the value to store is floating point.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            FieldInfo theField = aScannerState.CurrentILChunk.Method.Module.ResolveField(metadataToken);
            string fieldID = aScannerState.GetStaticFieldID(theField);

            int size = Utils.GetNumBytesForType(theField.FieldType);
            bool isFloat = Utils.IsFloat(theField.FieldType);

            StackItem value = aScannerState.CurrentStackFrame.Stack.Pop();
            
            if (isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing static fields of type float not supported yet!");
            }

            if (size == 1)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine(string.Format("mov byte [{0}], al", fieldID));
            }
            else if (size == 2)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine(string.Format("mov word [{0}], ax", fieldID));
            }
            else if (size == 4)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine(string.Format("mov dword [{0}], eax", fieldID));
            }
            else if (size == 8)
            {
                result.AppendLine("pop dword eax");
                result.AppendLine(string.Format("mov byte [{0}], eax", fieldID));
                result.AppendLine("pop dword eax");
                result.AppendLine(string.Format("mov byte [{0}+4], eax", fieldID));
            }

            return result.ToString().Trim();
        }
Пример #17
0
        /// <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();
        }
Пример #18
0
        /// <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 when loading a static float field.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Load static field

            //Load the metadata token used to get the type info
            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            //Get the type info for the object to load
            Type theType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken);

            //Get the object size information
            int size = Utils.GetNumBytesForType(theType);

            //Load the object onto the stack
            result.AppendLine("pop dword ecx");
            for (int i = size - 4; i >= 0; i -= 4)
            {
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ecx", i, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine(string.Format("mov dword eax, [ecx+{0}]", i));
                result.AppendLine("push dword eax");
            }
            int extra = size % 4;
            for (int i = extra - 1; i >= 0; i--)
            {
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ecx", i, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine(string.Format("mov byte al, [ecx+{0}]", i));
                result.AppendLine("push byte al");
            }

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

            return result.ToString().Trim();
        }
Пример #19
0
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Just removes (pops) the top value off our stack
            //But we must check that our "top value on stack" is actually on the stack and not in a register

            StackFrame currFrame = aScannerState.StackFrames.Peek();
            //We assume there is an item on the stack. If there isn't, we have gotten out of sync with the IL.
            //If debugging this, you should assume that the IL code is correct and our compiler is wrong.
            //Microsoft are much more likely to be correct than we are ;)
            StackItem topItem = currFrame.Stack.Pop();
            if (topItem.register == null)
            {
                result.AppendLine("pop");
            }
            else
            {
                result.AppendLine(string.Format("; top-most stack item in register '{0}'", topItem.register)); //DEBUG INFO
            }

            return result.ToString().Trim();
        }
Пример #20
0
        /// <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 'or' are floating point values.
        /// </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("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");
                    result.AppendLine("and eax, ebx");
                    result.AppendLine("push dword eax");

                    aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged = false
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 4) || 
                    (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the same size.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 8)
                {
                    //Pop item B to ecx:ebx
                    result.AppendLine("pop dword ebx");
                    result.AppendLine("pop dword ecx");
                    //Pop item A to edx:eax
                    result.AppendLine("pop dword eax");
                    result.AppendLine("pop dword edx");
                    //And ecx:ebx with edx:eax
                    result.AppendLine("and eax, ebx");
                    result.AppendLine("and edx, ecx");
                    result.AppendLine("push dword edx");
                    result.AppendLine("push dword eax");

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

            return result.ToString().Trim();
        }
Пример #21
0
        /// <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();
        }
Пример #22
0
        /// <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();
        }
Пример #23
0
        /// <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 when loading a static float field.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Load static field

            //Load the metadata token used to get the field info
            int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0);
            //Get the field info for the field to load
            FieldInfo theField = aScannerState.CurrentILChunk.Method.Module.ResolveField(metadataToken);
            //Get the ID (i.e. ASM label) of the field to load
            string fieldID = aScannerState.GetStaticFieldID(theField);

            //Load the field or field address
            switch ((OpCodes)anILOpInfo.opCode.Value)
            {
                case OpCodes.Ldsfld:
                    {
                        int size = Utils.GetNumBytesForType(theField.FieldType);
                        bool isFloat = Utils.IsFloat(theField.FieldType);
                        
                        if (isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Loading static fields of type float not supported yet!");
                        }

                        if(size == 1)
                        {
                            result.AppendLine("xor eax, eax");
                            result.AppendLine(string.Format("mov byte al, [{0}]", fieldID));
                            result.AppendLine("push dword eax");
                        }
                        else if(size == 2)
                        {
                            result.AppendLine("xor eax, eax");
                            result.AppendLine(string.Format("mov word ax, [{0}]", fieldID));
                            result.AppendLine("push dword eax");
                        }
                        else if(size == 4)
                        {
                            result.AppendLine(string.Format("mov dword eax, [{0}]", fieldID));
                            result.AppendLine("push dword eax");
                        }
                        else if (size == 8)
                        {
                            result.AppendLine(string.Format("mov dword eax, [{0}+4]", fieldID));
                            result.AppendLine("push dword eax");
                            result.AppendLine(string.Format("mov dword eax, [{0}]", fieldID));
                            result.AppendLine("push dword eax");
                        }

                        aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                        {
                            isFloat = isFloat,
                            sizeOnStackInBytes = (size == 8 ? 8 : 4),
                            isGCManaged = Utils.IsGCManaged(theField.FieldType)
                        });
                    }
                    break;
                case OpCodes.Ldsflda:
                    //Load the address of the field i.e. address of the ASM label
                    result.AppendLine(string.Format("push dword {0}", fieldID));

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

            return result.ToString().Trim();
        }
Пример #24
0
        /// <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 the either of the values to add are floating point.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if the either of the values to add are less than 4 bytes in size
        /// or if they are of different sizes.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Pop the operands from our stack in reverse order
            //i.e. second operand was pushed last so comes off the 
            //top of the stack first

            //Pop item B - one of the items to subtract
            StackItem itemB = aScannerState.CurrentStackFrame.Stack.Pop();
            //Pop item A - the other item to subtract
            StackItem itemA = aScannerState.CurrentStackFrame.Stack.Pop();

            //If either item item is < 4 bytes then we have a stack error.
            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            //If either item is floating point, we must use floating point conversions
            //and floating point arithmetic
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                //  - We need to convert items to float if necessary
                //  - Then use floating point arithmetic
                //  - Then push the result onto the stack and mark it as float
                // Note: Check but I think floating point arithmetic is done using 
                //       XMM registers and their specific ops.
                throw new NotSupportedException("Add floats is unsupported!");
            }
            else
            {
                //If both items are Int32s (or UInt32s - it is irrelevant)
                //Note: IL handles type conversions using other ops
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    result.AppendLine("pop dword ebx");
                    //Pop item A
                    result.AppendLine("pop dword eax");
                    //Subtract the two
                    result.AppendLine("sub eax, ebx");
                    //Push the result onto the stack
                    result.AppendLine("push dword eax");

                    //Push the result onto our stack
                    aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged = false
                    });
                }
                //Invalid if the operands are of different sizes.
                //Note: This usually occurs when a previous IL op failed to process properly.
                else if ((itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 4) || 
                    (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the same size.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 8)
                {
                    //Pop item B to ecx:ebx
                    //Pop low bits
                    result.AppendLine("pop dword ebx");
                    //Pop high bits
                    result.AppendLine("pop dword ecx");
                    //Pop item A to edx:eax
                    //Pop low bits
                    result.AppendLine("pop dword eax");
                    //Pop high bits
                    result.AppendLine("pop dword edx");
                    //Sub ecx:ebx from edx:eax
                    //Sub low bits
                    result.AppendLine("sub eax, ebx");
                    //Sub high bits including any borrow from
                    //when low bits were subtracted
                    result.AppendLine("sbb edx, ecx");
                    //Push the result
                    //Push high bits
                    result.AppendLine("push dword edx");
                    //Push low bits
                    result.AppendLine("push dword eax");

                    //Push the result onto our stack
                    aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged = false
                    });
                }
            }

            return result.ToString().Trim();
        }
Пример #25
0
        /// <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();

            //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("Divide 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");
                    if ((OpCodes)anILOpInfo.opCode.Value == OpCodes.Div_Un)
                    {
                        //Unsigned extend A to EAX:EDX
                        result.AppendLine("mov edx, 0");
                        //Do the division
                        result.AppendLine("div ebx");
                    }
                    else
                    {
                        //Sign extend A to EAX:EDX
                        result.AppendLine("cdq");
                        //Do the division
                        result.AppendLine("idiv ebx");
                    }
                    //Result stored in eax
                    result.AppendLine("push dword eax");

                    aScannerState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged = false
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) || 
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the 32-32 or 64-64.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                    itemB.sizeOnStackInBytes == 8)
                {
                    //SUPPORT - 64-bit division
                    throw new NotSupportedException("64-bit by 64-bit division not supported yet!");
                }
            }

            return result.ToString().Trim();
        }
Пример #26
0
        /// <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 the value to store is floating point.
        /// </exception>
        /// <exception cref="System.NotImplementedException">
        /// Thrown if the op is 'StIndRef'.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Pop value
            //Pop address
            //Mov [address], value

            StackItem valueItem = aScannerState.CurrentStackFrame.Stack.Pop();
            StackItem addressItem = aScannerState.CurrentStackFrame.Stack.Pop();
            int bytesToStore = 0;
            bool isFloat = false;

            switch ((OpCodes)anILOpInfo.opCode.Value)
            {
                case OpCodes.Stind_I:
                    bytesToStore = 4;
                    break;
                case OpCodes.Stind_I1:
                    bytesToStore = 1;
                    break;
                case OpCodes.Stind_I2:
                    bytesToStore = 2;
                    break;
                case OpCodes.Stind_I4:
                    bytesToStore = 4;
                    break;
                case OpCodes.Stind_I8:
                    bytesToStore = 8;
                    break;
                case OpCodes.Stind_R4:
                    bytesToStore = 4;
                    isFloat = true;
                    break;
                case OpCodes.Stind_R8:
                    bytesToStore = 8;
                    isFloat = true;
                    break;
                case OpCodes.Stind_Ref:
                    bytesToStore = 4;
                    break;
            }

            if(isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Floats not supported yet!");
            }

            if (bytesToStore == 8)
            {
                //Pop value low bits
                result.AppendLine("pop dword eax");
                //Pop value high bits
                result.AppendLine("pop dword edx");

                //Pop address
                result.AppendLine("pop dword ebx");

                //Mov [address], value
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 4, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [ebx+4], edx");
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [ebx], eax");
            }
            else if (bytesToStore == 4)
            {
                //Pop value
                result.AppendLine("pop dword eax");

                //Pop address
                result.AppendLine("pop dword ebx");

                //Mov [address], value
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov dword [ebx], eax");
            }
            else if (bytesToStore == 2)
            {
                //Pop value
                result.AppendLine("pop dword eax");

                //Pop address
                result.AppendLine("pop dword ebx");

                //Mov [address], value
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov word [ebx], ax");
            }
            else if (bytesToStore == 1)
            {
                //Pop value
                result.AppendLine("pop dword eax");

                //Pop address
                result.AppendLine("pop dword ebx");

                //Mov [address], value
                GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value);
                result.AppendLine("mov byte [ebx], al");
            }

            return result.ToString().Trim();
        }
Пример #27
0
        /// <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();
        }
Пример #28
0
        /// <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 itemToConvert = aScannerState.CurrentStackFrame.Stack.Pop();
            int numBytesToConvertTo = 0;

            switch ((OpCodes)anILOpInfo.opCode.Value)
            {
                case OpCodes.Conv_I:
                    numBytesToConvertTo = 4;
                    break;
                case OpCodes.Conv_I1:
                    numBytesToConvertTo = 1;
                    break;
                case OpCodes.Conv_I2:
                    numBytesToConvertTo = 2;
                    break;
                case OpCodes.Conv_I4:
                    numBytesToConvertTo = 4;
                    break;
                case OpCodes.Conv_I8:
                    numBytesToConvertTo = 8;
                    break;
            }

            int bytesPopped = 0;
            bool pushEDX = false;

            switch(numBytesToConvertTo)
            {
                case 1:
                    //Convert to Int8 (byte)
                    //Sign extend to dword
                    result.AppendLine("mov eax, 0");
                    result.AppendLine("pop byte al");
                    bytesPopped = 1;
                    break;
                case 2:
                    //Convert to Int16 (word)
                    //Sign extend to dword
                    result.AppendLine("mov eax, 0");
                    result.AppendLine("pop word ax");
                    result.AppendLine("cwde");
                    bytesPopped = 2;
                    break;
                case 4:
                    //Convert to Int32 (dword)
                    result.AppendLine("pop dword eax");
                    bytesPopped = 4;
                    break;
                case 8:
                    //Convert to Int64
                    if (itemToConvert.sizeOnStackInBytes == 8)
                    {
                        //Result stored in EAX:EDX
                        result.AppendLine("pop dword eax");
                        result.AppendLine("pop dword edx");
                        bytesPopped = 8;
                    }
                    else
                    {
                        //Sign extend dword to qword
                        //Result stored in EAX:EDX
                        result.AppendLine("pop dword eax");
                        result.AppendLine("cdq");
                        bytesPopped = 4;
                    }
                    pushEDX = true;
                    break;
            }

            int bytesDiff = itemToConvert.sizeOnStackInBytes - bytesPopped;
            if (bytesDiff > 0)
            {
                result.AppendLine(string.Format("add esp, {0}", bytesDiff));
            }

            if (pushEDX)
            {
                result.AppendLine("push dword edx");
            }
            result.AppendLine("push dword eax");

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

            return result.ToString().Trim();
        }
Пример #29
0
        /// <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 when the return value is a float or the size on the stack
        /// in bytes is not 4 or 8 bytes.
        /// </exception>
        public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState)
        {
            StringBuilder result = new StringBuilder();

            //Store the return value
            //Get the return type
            Type retType = (aScannerState.CurrentILChunk.Method.IsConstructor || aScannerState.CurrentILChunk.Method is ConstructorInfo ?
                typeof(void) : ((MethodInfo)aScannerState.CurrentILChunk.Method).ReturnType);
            //Get the size of the return type on stack
            int retSize = Utils.GetNumBytesForType(retType);
            //If the size isn't 0 (i.e. isn't "void" which has no return value)
            if (retSize != 0)
            {
                //Pop the return value off our stack
                StackItem retItem = aScannerState.CurrentStackFrame.Stack.Pop();

                //If it is float, well, we don't support it yet...
                if (retItem.isFloat)
                {
                    //SUPPORT - floats
                    throw new NotSupportedException("Floats return type not supported yet!");
                }
                //Otherwise, store the return value at [ebp+8]
                //[ebp+8] because that is last "argument"
                //      - read the calling convention spec
                else if (retSize == 4)
                {
                    result.AppendLine("pop dword eax");
                    result.AppendLine("mov [ebp+8], eax");
                }
                else if (retSize == 8)
                {
                    result.AppendLine("pop dword eax");
                    result.AppendLine("mov [ebp+8], eax");
                    result.AppendLine("pop dword eax");
                    result.AppendLine("mov [ebp+12], eax");
                }
                else
                {
                    throw new NotSupportedException("Return type size not supported / invalid!");
                }
            }

            //Once return value is off the stack, remove the locals
            //Deallocate stack space for locals
            //Only bother if there are any locals
            if (aScannerState.CurrentILChunk.LocalVariables.Count > 0)
            {
                //Get the total size of all locals
                int totalBytes = 0;
                foreach (StackItem aLocal in aScannerState.CurrentILChunk.LocalVariables)
                {
                    totalBytes += aLocal.sizeOnStackInBytes;
                }
                //Move esp past the locals
                result.AppendLine(string.Format("add esp, {0}", totalBytes));
            }

            //Restore ebp to previous method's ebp
            result.AppendLine("pop dword ebp");
            //This pop also takes last value off the stack which
            //means top item is the return address
            //So ret command can now be correctly executed.

            return result.ToString().Trim();
        }
Пример #30
0
        /// <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();
        }