Example #1
0
        protected void MethodBegin(MethodInfo aMethod)
        {
            new Comment("---------------------------------------------------------");
            new Comment("Assembly: " + aMethod.MethodBase.DeclaringType.Assembly.FullName);
            new Comment("Type: " + aMethod.MethodBase.DeclaringType.ToString());
            new Comment("Name: " + aMethod.MethodBase.Name);
            new Comment("Plugged: " + (aMethod.PlugMethod == null ? "No" : "Yes"));
            // for now:
            var shouldIncludeArgAndLocalsComment = true;
            if (shouldIncludeArgAndLocalsComment)
            {
                if (aMethod.MethodAssembler == null && !aMethod.IsInlineAssembler)
                {
                    // the body of aMethod is getting emitted
                    var xBody = aMethod.MethodBase.GetMethodBody();
                    if (xBody != null)
                    {
                        foreach (var localVariable in xBody.LocalVariables)
                        {
                            new Comment(String.Format("Local {0} at EBP-{1}", localVariable.LocalIndex, ILOp.GetEBPOffsetForLocal(aMethod, localVariable.LocalIndex)));
                        }
                    }
                    var xIdxOffset = 0u;
                    if (!aMethod.MethodBase.IsStatic)
                    {
                        new Comment(String.Format("Argument[0] $this at EBP+{0}, size = {1}", X86.IL.Ldarg.GetArgumentDisplacement(aMethod, 0), ILOp.Align(ILOp.SizeOfType(aMethod.MethodBase.DeclaringType), 4)));
                        xIdxOffset++;
                    }

                    var xParams = aMethod.MethodBase.GetParameters();
                    var xParamCount = (ushort)xParams.Length;

                    for (ushort i = 0; i < xParamCount; i++)
                    {
                        var xOffset = X86.IL.Ldarg.GetArgumentDisplacement(aMethod, (ushort)(i + xIdxOffset));
                        var xSize = X86.IL.Ldarg.SizeOfType(xParams[i].ParameterType);
                        // if last argument is 8 byte long, we need to add 4, so that debugger could read all 8 bytes from this variable in positiv direction
                        new Comment(String.Format("Argument[{3}] {0} at EBP+{1}, size = {2}", xParams[i].Name, xOffset, xSize, (xIdxOffset + i)));
                    }

                    var xMethodInfo = aMethod.MethodBase as SysReflection.MethodInfo;
                    if (xMethodInfo != null)
                    {
                        var xSize = ILOp.Align(ILOp.SizeOfType(xMethodInfo.ReturnType), 4);
                        new Comment(String.Format("Return size: {0}", xSize));
                    }
                }
            }

            // Issue label that is used for calls etc.
            string xMethodLabel;
            if (aMethod.PluggedMethod != null)
            {
                xMethodLabel = "PLUG_FOR___" + LabelName.Get(aMethod.PluggedMethod.MethodBase);
            }
            else
            {
                xMethodLabel = LabelName.Get(aMethod.MethodBase);
            }
            new Cosmos.Assembler.Label(xMethodLabel);
            //Assembler.WriteDebugVideo("Method " + aMethod.UID);

            // We could use same GUID as MethodLabelStart, but its better to keep GUIDs unique globaly for items
            // so during debugging they can never be confused as to what they point to.
            mCurrentMethodGuid = DebugInfo.CreateId();

            // We issue a second label for GUID. This is increases label count, but for now we need a master label first.
            // We issue a GUID label to reduce amount of work and time needed to construct debugging DB.
            var xLabelGuid = DebugInfo.CreateId();
            new Cosmos.Assembler.Label("GUID_" + xLabelGuid.ToString());

            mCurrentMethodLabel = "METHOD_" + xLabelGuid.ToString();
            Cosmos.Assembler.Label.LastFullLabel = mCurrentMethodLabel;

            mCurrentMethodLabelEndGuid = DebugInfo.CreateId();

            if (aMethod.MethodBase.IsStatic && aMethod.MethodBase is ConstructorInfo)
            {
                new Comment("Static constructor. See if it has been called already, return if so.");
                var xName = DataMember.FilterStringForIncorrectChars("CCTOR_CALLED__" + LabelName.GetFullName(aMethod.MethodBase.DeclaringType));
                var xAsmMember = new DataMember(xName, (byte)0);
                Assembler.DataMembers.Add(xAsmMember);
                new Compare { DestinationRef = Cosmos.Assembler.ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
                new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = ".BeforeQuickReturn" };
                new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
                new Jump { DestinationLabel = ".AfterCCTorAlreadyCalledCheck" };
                new Cosmos.Assembler.Label(".BeforeQuickReturn");
                new Mov { DestinationReg = RegistersEnum.ECX, SourceValue = 0 };
                new Return { };
                new Cosmos.Assembler.Label(".AfterCCTorAlreadyCalledCheck");
            }

            new Push { DestinationReg = Registers.EBP };
            new Mov { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };

            if (DebugMode == DebugMode.Source)
            {
                // Would be nice to use xMethodSymbols.GetSourceStartEnd but we cant
                // because its not implemented by the unmanaged code underneath.
                //
                // This doesnt seem right to store as a field, but old code had it that way so we
                // continue using a field for now.
                mSequences = DebugInfo.GetSequencePoints(aMethod.MethodBase, true);
                if (mSequences.Length > 0)
                {
                    DebugInfo.AddDocument(mSequences[0].Document);

                    var xMethod = new Method()
                    {
                        ID = mCurrentMethodGuid,
                        TypeToken = aMethod.MethodBase.DeclaringType.MetadataToken,
                        MethodToken = aMethod.MethodBase.MetadataToken,

                        LabelStartID = xLabelGuid,
                        LabelEndID = mCurrentMethodLabelEndGuid,
                        LabelCall = xMethodLabel,

                        AssemblyFileID = DebugInfo.AssemblyGUIDs[aMethod.MethodBase.DeclaringType.Assembly],
                        DocumentID = DebugInfo.DocumentGUIDs[mSequences[0].Document.ToLower()],

                        // Storing Line + Col as one item makes comparisons MUCH easier, otherwise we have to
                        // check for things like col < start col but line > start line.
                        //
                        // () around << are VERY important.. + has precedence over <<
                        LineColStart = ((Int64)mSequences[0].LineStart << 32) + mSequences[0].ColStart,
                        LineColEnd = ((Int64)(mSequences[mSequences.Length - 1].LineEnd) << 32) + mSequences[mSequences.Length - 1].ColEnd
                    };
                    DebugInfo.AddMethod(xMethod);
                }
            }

            if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null && !aMethod.IsInlineAssembler)
            {
                // the body of aMethod is getting emitted
                var xBody = aMethod.MethodBase.GetMethodBody();
                if (xBody != null)
                {
                    var xLocalsOffset = mLocals_Arguments_Infos.Count;
                    aMethod.LocalVariablesSize = 0;
                    foreach (var xLocal in xBody.LocalVariables)
                    {
                        var xInfo = new LOCAL_ARGUMENT_INFO
                        {
                            METHODLABELNAME = xMethodLabel,
                            IsArgument = false,
                            INDEXINMETHOD = xLocal.LocalIndex,
                            NAME = "Local" + xLocal.LocalIndex,
                            OFFSET = 0 - (int)ILOp.GetEBPOffsetForLocalForDebugger(aMethod, xLocal.LocalIndex),
                            TYPENAME = xLocal.LocalType.AssemblyQualifiedName
                        };
                        mLocals_Arguments_Infos.Add(xInfo);

                        var xSize = ILOp.Align(ILOp.SizeOfType(xLocal.LocalType), 4);
                        new Comment(String.Format("Local {0}, Size {1}", xLocal.LocalIndex, xSize));
                        for (int i = 0; i < xSize / 4; i++)
                        {
                            new Push { DestinationValue = 0 };
                        }
                        aMethod.LocalVariablesSize += xSize;
                        //new Sub { DestinationReg = Registers.ESP, SourceValue = ILOp.Align(ILOp.SizeOfType(xLocal.LocalType), 4) };
                    }
                    var xCecilMethod = GetCecilMethodDefinitionForSymbolReading(aMethod.MethodBase);
                    if (xCecilMethod != null && xCecilMethod.Body != null)
                    {
                        // mLocals_Arguments_Infos is one huge list, so ourlatest additions are at the end
                        for (int i = 0; i < xCecilMethod.Body.Variables.Count; i++)
                        {
                            mLocals_Arguments_Infos[xLocalsOffset + i].NAME = xCecilMethod.Body.Variables[i].Name;
                        }
                        for (int i = xLocalsOffset + xCecilMethod.Body.Variables.Count - 1; i >= xLocalsOffset; i--)
                        {
                            if (mLocals_Arguments_Infos[i].NAME.Contains('$'))
                            {
                                mLocals_Arguments_Infos.RemoveAt(i);
                            }
                        }
                    }
                }

                // debug info:
                var xIdxOffset = 0u;
                if (!aMethod.MethodBase.IsStatic)
                {
                    mLocals_Arguments_Infos.Add(new LOCAL_ARGUMENT_INFO
                    {
                        METHODLABELNAME = xMethodLabel,
                        IsArgument = true,
                        NAME = "this:" + X86.IL.Ldarg.GetArgumentDisplacement(aMethod, 0),
                        INDEXINMETHOD = 0,
                        OFFSET = X86.IL.Ldarg.GetArgumentDisplacement(aMethod, 0),
                        TYPENAME = aMethod.MethodBase.DeclaringType.AssemblyQualifiedName
                    });

                    xIdxOffset++;
                }

                var xParams = aMethod.MethodBase.GetParameters();
                var xParamCount = (ushort)xParams.Length;

                for (ushort i = 0; i < xParamCount; i++)
                {
                    var xOffset = X86.IL.Ldarg.GetArgumentDisplacement(aMethod, (ushort)(i + xIdxOffset));
                    // if last argument is 8 byte long, we need to add 4, so that debugger could read all 8 bytes from this variable in positiv direction
                    xOffset -= (int)Cosmos.IL2CPU.ILOp.Align(ILOp.SizeOfType(xParams[i].ParameterType), 4) - 4;
                    mLocals_Arguments_Infos.Add(new LOCAL_ARGUMENT_INFO
                    {
                        METHODLABELNAME = xMethodLabel,
                        IsArgument = true,
                        INDEXINMETHOD = (int)(i + xIdxOffset),
                        NAME = xParams[i].Name,
                        OFFSET = xOffset,
                        TYPENAME = xParams[i].ParameterType.AssemblyQualifiedName
                    });
                }
            }
        }
Example #2
0
        protected void MethodBegin(MethodInfo aMethod)
        {
            XS.Comment("---------------------------------------------------------");
            XS.Comment("Assembly: " + aMethod.MethodBase.DeclaringType.Assembly.FullName);
            XS.Comment("Type: " + aMethod.MethodBase.DeclaringType.ToString());
            XS.Comment("Name: " + aMethod.MethodBase.Name);
            XS.Comment("Plugged: " + (aMethod.PlugMethod == null ? "No" : "Yes"));
            // for now:
            var shouldIncludeArgAndLocalsComment = true;
            if (shouldIncludeArgAndLocalsComment)
            {
                if (aMethod.MethodAssembler == null && !aMethod.IsInlineAssembler)
                {
                    // the body of aMethod is getting emitted
                    var xBody = aMethod.MethodBase.GetMethodBody();
                    if (xBody != null)
                    {
                        foreach (var localVariable in xBody.LocalVariables)
                        {
                            XS.Comment(String.Format("Local {0} at EBP-{1}", localVariable.LocalIndex, ILOp.GetEBPOffsetForLocal(aMethod, localVariable.LocalIndex)));
                        }
                    }
                    var xIdxOffset = 0u;
                    if (!aMethod.MethodBase.IsStatic)
                    {
                        XS.Comment(String.Format("Argument[0] $this at EBP+{0}, size = {1}", X86.IL.Ldarg.GetArgumentDisplacement(aMethod, 0), ILOp.Align(ILOp.SizeOfType(aMethod.MethodBase.DeclaringType), 4)));
                        xIdxOffset++;
                    }

                    string x = aMethod.MethodBase.Name;
                    string y = aMethod.MethodBase.DeclaringType.Name;
                    var xParams = aMethod.MethodBase.GetParameters();
                    var xParamCount = (ushort)xParams.Length;

                    for (ushort i = 0; i < xParamCount; i++)
                    {
                        var xOffset = X86.IL.Ldarg.GetArgumentDisplacement(aMethod, (ushort)(i + xIdxOffset));
                        var xSize = X86.IL.Ldarg.SizeOfType(xParams[i].ParameterType);
                        // if last argument is 8 byte long, we need to add 4, so that debugger could read all 8 bytes from this variable in positiv direction
                        XS.Comment(String.Format("Argument[{3}] {0} at EBP+{1}, size = {2}", xParams[i].Name, xOffset, xSize, (xIdxOffset + i)));
                    }

                    var xMethodInfo = aMethod.MethodBase as SysReflection.MethodInfo;
                    if (xMethodInfo != null)
                    {
                        var xSize = ILOp.Align(ILOp.SizeOfType(xMethodInfo.ReturnType), 4);
                        XS.Comment(String.Format("Return size: {0}", xSize));
                    }
                }
            }

            // Issue label that is used for calls etc.
            string xMethodLabel;
            if (aMethod.PluggedMethod != null)
            {
                xMethodLabel = "PLUG_FOR___" + LabelName.Get(aMethod.PluggedMethod.MethodBase);
            }
            else
            {
                xMethodLabel = LabelName.Get(aMethod.MethodBase);
            }
            XS.Label(xMethodLabel);

            //Assembler.WriteDebugVideo("Method " + aMethod.UID);

            // We could use same GUID as MethodLabelStart, but its better to keep GUIDs unique globaly for items
            // so during debugging they can never be confused as to what they point to.
            mCurrentMethodGuid = DebugInfo.CreateId();

            // We issue a second label for GUID. This is increases label count, but for now we need a master label first.
            // We issue a GUID label to reduce amount of work and time needed to construct debugging DB.
            var xLabelGuid = DebugInfo.CreateId();
            new Label("GUID_" + xLabelGuid.ToString());

            mCurrentMethodLabel = "METHOD_" + xLabelGuid.ToString();
            Label.LastFullLabel = mCurrentMethodLabel;

            if (DebugEnabled && StackCorruptionDetection)
            {
                // if StackCorruption detection is active, we're also going to emit a stack overflow detection
                XS.Set(XSRegisters.EAX, "Before_Kernel_Stack");
                XS.Compare(XSRegisters.EAX, XSRegisters.ESP);
                XS.Jump(ConditionalTestEnum.LessThan, mCurrentMethodLabel + ".StackOverflowCheck_End");
                XS.ClearInterruptFlag();
                // don't remove the call. It seems pointless, but we need it to retrieve the EIP value
                new Call { DestinationLabel = mCurrentMethodLabel + ".StackOverflowCheck_GetAddress" };
                XS.Label(mCurrentMethodLabel + ".StackOverflowCheck_GetAddress");
                XS.Pop(XSRegisters.EAX);
                new Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
                XS.Call("DebugStub_SendStackOverflowOccurred");
                XS.Halt();
                XS.Label(mCurrentMethodLabel + ".StackOverflowCheck_End");

            }

            mCurrentMethodLabelEndGuid = DebugInfo.CreateId();

            if (aMethod.MethodBase.IsStatic && aMethod.MethodBase is ConstructorInfo)
            {
                XS.Comment("Static constructor. See if it has been called already, return if so.");
                var xName = DataMember.FilterStringForIncorrectChars("CCTOR_CALLED__" + LabelName.GetFullName(aMethod.MethodBase.DeclaringType));
                XS.DataMember(xName, 0);
                XS.Compare(xName, 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
                XS.Jump(ConditionalTestEnum.Equal, ".BeforeQuickReturn");
                XS.Set(xName, 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
                XS.Jump(".AfterCCTorAlreadyCalledCheck");
                XS.Label(".BeforeQuickReturn");
                XS.Set(XSRegisters.ECX, 0);
                XS.Return();
                XS.Label(".AfterCCTorAlreadyCalledCheck");
            }

            XS.Push(XSRegisters.EBP);
            XS.Set(XSRegisters.EBP, XSRegisters.ESP);

            if (DebugMode == DebugMode.Source)
            {
                // Would be nice to use xMethodSymbols.GetSourceStartEnd but we cant
                // because its not implemented by the unmanaged code underneath.
                //
                // This doesnt seem right to store as a field, but old code had it that way so we
                // continue using a field for now.
                mSequences = DebugInfo.GetSequencePoints(aMethod.MethodBase, true);
                if (mSequences.Length > 0)
                {
                    DebugInfo.AddDocument(mSequences[0].Document);

                    var xMethod = new Method();
                    xMethod.ID = mCurrentMethodGuid;
                    xMethod.TypeToken = aMethod.MethodBase.DeclaringType.MetadataToken;
                    xMethod.MethodToken = aMethod.MethodBase.MetadataToken;
                    xMethod.LabelStartID = xLabelGuid;
                    xMethod.LabelEndID = mCurrentMethodLabelEndGuid;
                    xMethod.LabelCall = xMethodLabel;
                    long xAssemblyFileID;
                    if (DebugInfo.AssemblyGUIDs.TryGetValue(aMethod.MethodBase.DeclaringType.Assembly, out xAssemblyFileID))
                    {
                        xMethod.AssemblyFileID = xAssemblyFileID;
                    }
                    xMethod.DocumentID = DebugInfo.DocumentGUIDs[mSequences[0].Document.ToLower()];
                    xMethod.LineColStart = ((Int64)mSequences[0].LineStart << 32) + mSequences[0].ColStart;
                    xMethod.LineColEnd = ((Int64)(mSequences[mSequences.Length - 1].LineEnd) << 32) + mSequences[mSequences.Length - 1].ColEnd;
                    DebugInfo.AddMethod(xMethod);
                }
            }

            if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null && !aMethod.IsInlineAssembler)
            {
                // the body of aMethod is getting emitted
                var xBody = aMethod.MethodBase.GetMethodBody();
                if (xBody != null)
                {
                    var xLocalsOffset = mLocals_Arguments_Infos.Count;
                    aMethod.LocalVariablesSize = 0;
                    foreach (var xLocal in xBody.LocalVariables)
                    {
                        var xInfo = new LOCAL_ARGUMENT_INFO
                        {
                            METHODLABELNAME = xMethodLabel,
                            IsArgument = false,
                            INDEXINMETHOD = xLocal.LocalIndex,
                            NAME = "Local" + xLocal.LocalIndex,
                            OFFSET = 0 - (int)ILOp.GetEBPOffsetForLocalForDebugger(aMethod, xLocal.LocalIndex),
                            TYPENAME = xLocal.LocalType.AssemblyQualifiedName
                        };
                        mLocals_Arguments_Infos.Add(xInfo);

                        var xSize = ILOp.Align(ILOp.SizeOfType(xLocal.LocalType), 4);
                        XS.Comment(String.Format("Local {0}, Size {1}", xLocal.LocalIndex, xSize));
                        for (int i = 0; i < xSize / 4; i++)
                        {
                            XS.Push(0);
                        }
                        aMethod.LocalVariablesSize += xSize;
                        //new Sub { DestinationReg = Registers.ESP, SourceValue = ILOp.Align(ILOp.SizeOfType(xLocal.LocalType), 4) };
                    }
                    var xCecilMethod = GetCecilMethodDefinitionForSymbolReading(aMethod.MethodBase);
                    if (xCecilMethod != null && xCecilMethod.Body != null)
                    {
                        // mLocals_Arguments_Infos is one huge list, so ourlatest additions are at the end
                        for (int i = 0; i < xCecilMethod.Body.Variables.Count; i++)
                        {
                            mLocals_Arguments_Infos[xLocalsOffset + i].NAME = xCecilMethod.Body.Variables[i].Name;
                        }
                        for (int i = xLocalsOffset + xCecilMethod.Body.Variables.Count - 1; i >= xLocalsOffset; i--)
                        {
                            if (mLocals_Arguments_Infos[i].NAME.Contains('$'))
                            {
                                mLocals_Arguments_Infos.RemoveAt(i);
                            }
                        }
                    }
                }

                // debug info:
                var xIdxOffset = 0u;
                if (!aMethod.MethodBase.IsStatic)
                {
                    mLocals_Arguments_Infos.Add(new LOCAL_ARGUMENT_INFO
                    {
                        METHODLABELNAME = xMethodLabel,
                        IsArgument = true,
                        NAME = "this:" + X86.IL.Ldarg.GetArgumentDisplacement(aMethod, 0),
                        INDEXINMETHOD = 0,
                        OFFSET = X86.IL.Ldarg.GetArgumentDisplacement(aMethod, 0),
                        TYPENAME = aMethod.MethodBase.DeclaringType.AssemblyQualifiedName
                    });

                    xIdxOffset++;
                }

                var xParams = aMethod.MethodBase.GetParameters();
                var xParamCount = (ushort)xParams.Length;

                for (ushort i = 0; i < xParamCount; i++)
                {
                    var xOffset = X86.IL.Ldarg.GetArgumentDisplacement(aMethod, (ushort)(i + xIdxOffset));
                    // if last argument is 8 byte long, we need to add 4, so that debugger could read all 8 bytes from this variable in positiv direction
                    xOffset -= (int)ILOp.Align(ILOp.SizeOfType(xParams[i].ParameterType), 4) - 4;
                    mLocals_Arguments_Infos.Add(new LOCAL_ARGUMENT_INFO
                    {
                        METHODLABELNAME = xMethodLabel,
                        IsArgument = true,
                        INDEXINMETHOD = (int)(i + xIdxOffset),
                        NAME = xParams[i].Name,
                        OFFSET = xOffset,
                        TYPENAME = xParams[i].ParameterType.AssemblyQualifiedName
                    });
                }
            }
        }