예제 #1
0
        public static Type GetTypeInfo(this CorType type, CorDebuggerSession session)
        {
            Type t;

            if (CorMetadataImport.CoreTypes.TryGetValue(type.Type, out t))
            {
                return(t);
            }

            if (type.Type == CorElementType.ELEMENT_TYPE_ARRAY || type.Type == CorElementType.ELEMENT_TYPE_SZARRAY)
            {
                List <int> sizes    = new List <int> ();
                List <int> loBounds = new List <int> ();
                for (int n = 0; n < type.Rank; n++)
                {
                    sizes.Add(1);
                    loBounds.Add(0);
                }
                return(MetadataType.MakeArray(type.FirstTypeParameter.GetTypeInfo(session), sizes, loBounds));
            }

            if (type.Type == CorElementType.ELEMENT_TYPE_BYREF)
            {
                return(MetadataType.MakeByRef(type.FirstTypeParameter.GetTypeInfo(session)));
            }

            if (type.Type == CorElementType.ELEMENT_TYPE_PTR)
            {
                return(MetadataType.MakePointer(type.FirstTypeParameter.GetTypeInfo(session)));
            }

            CorMetadataImport mi = session.GetMetadataForModule(type.Class.Module.Name);

            if (mi != null)
            {
                t = mi.GetType(type.Class.Token);
                CorType[] targs = type.TypeParameters;
                if (targs.Length > 0)
                {
                    List <Type> types = new List <Type> ();
                    foreach (CorType ct in targs)
                    {
                        types.Add(ct.GetTypeInfo(session));
                    }
                    return(MetadataType.MakeGeneric(t, types));
                }
                else
                {
                    return(t);
                }
            }
            else
            {
                return(null);
            }
        }
예제 #2
0
        //
        // IEnumerator interface
        //

        #region IEnumerator Members

        public bool MoveNext()
        {
            int  token;
            uint c;

            m_corMeta.m_importer.EnumTypeDefs(ref m_enum, out token, 1, out c);
            if (c == 1) // 1 new element
            {
                m_type = m_corMeta.GetType(token);
            }
            else
            {
                m_type = null;
            }
            return(m_type != null);
        }
예제 #3
0
        private string PrintObject(int indentLevel, CorDebug.CorObjectValue ov, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            // Print generics-aware type.
            string name = InternalUtil.PrintCorType(m_process, ov.ExactType);

            var txt = new StringBuilder();

            txt.Append(name);

            if (expandDepth > 0)
            {
                // we gather the field info of the class before we do
                // funceval since funceval requires running the debugger process
                // and this in turn can cause GC and invalidate our references.
                var expandedDescription = new StringBuilder();
                if (IsComplexType)
                {
                    foreach (MDbgValue v in GetFields())
                    {
                        expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)).
                        Append("=").Append(IndentedBlock(indentLevel + 2,
                                                         v.GetStringValue(expandDepth - 1, false)));
                    }
                }

                if (ov.IsValueClass && canDoFunceval)
                // we could display even values for real Objects, but we will just show
                // "description" for valueclasses.
                {
                    CorDebug.CorClass cls      = ov.ExactType.Class;
                    CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer;
                    var mdType = importer.GetType(cls.Token) as MetadataType;

                    if (mdType.ReallyIsEnum)
                    {
                        txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType));
                    }
                    else if (m_process.IsRunning)
                    {
                        txt.Append(" <N/A during run>");
                    }
                    else
                    {
                        MDbgThread activeThread = m_process.Threads.Active;

                        CorDebug.CorValue     thisValue;
                        CorDebug.CorHeapValue hv = ov.CastToHeapValue();
                        if (hv != null)
                        {
                            // we need to pass reference value.
                            CorDebug.CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION);
                            thisValue = handle;
                        }
                        else
                        {
                            thisValue = ov;
                        }

                        try
                        {
                            CorDebug.CorEval eval = m_process.Threads.Active.CorThread.CreateEval();
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND,
                                                                         activeThread.CorThread);

                            MDbgFunction toStringFunc =
                                m_process.ResolveFunctionName(null, "System.Object", "ToString"
                                                              , thisValue.ExactType.Class.Module.Assembly.AppDomain);
                            Debug.Assert(toStringFunc != null);
                            // we should be always able to resolve ToString function.

                            eval.CallFunction(toStringFunc.CorFunction, new[] { thisValue });
                            m_process.Go();
                            do
                            {
                                m_process.StopEvent.WaitOne();
                                if (m_process.StopReason is EvalCompleteStopReason)
                                {
                                    CorDebug.CorValue cv = eval.Result;
                                    Debug.Assert(cv != null);
                                    var    mv      = new MDbgValue(m_process, cv);
                                    string valName = mv.GetStringValue(0);

                                    // just purely for esthetical reasons we 'discard' "
                                    if (valName.StartsWith("\"") && valName.EndsWith("\""))
                                    {
                                        valName = valName.Substring(1, valName.Length - 2);
                                    }

                                    txt.Append(" <").Append(valName).Append(">");
                                    break;
                                }
                                if ((m_process.StopReason is ProcessExitedStopReason) ||
                                    (m_process.StopReason is EvalExceptionStopReason))
                                {
                                    txt.Append(" <N/A cannot evaluate>");
                                    break;
                                }
                                // hitting bp or whatever should not matter -- we need to ignore it
                                m_process.Go();
                            } while (true);
                        }
                        catch (COMException e)
                        {
                            // Ignore canot copy a VC class error - Can't copy a VC with object refs in it.
                            if (e.ErrorCode != (int)CorDebug.HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS)
                            {
                                throw;
                            }
                        }
                        finally
                        {
                            // we need to resume all the threads that we have suspended no matter what.
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN,
                                                                         activeThread.CorThread);
                        }
                    }
                }
                txt.Append(expandedDescription.ToString());
            }
            return(txt.ToString());
        }
예제 #4
0
        /// <summary>
        /// Gets the full class path of the function
        /// </summary>
        /// <param name="sb">string builder to be used to create full class path</param>
        /// <param name="ct">The cortype of the function</param>

        // Ignore the complexity warning - don't want to rewrite it now.
        private void GetFunctionClassPath(StringBuilder sb, CorType ct)
        {
            //StringBuilder sb, CorType ct, CorMetadataImport importer
            switch (ct.Type)
            {
            case CorElementType.ELEMENT_TYPE_CLASS:
            case CorElementType.ELEMENT_TYPE_VALUETYPE:
                // We need to get the name from the metadata. We can get a cached metadata importer
                // from a MDbgModule, or we could get a new one from the CorModule directly.
                // Is this hash lookup to get a MDbgModule cheaper than just re-querying for the importer?
                CorClass cc = ct.Class;
                Type     tn = metaImporter.GetType(cc.Token);

                sb.Append(tn.FullName);
                //AddGenericArgs(sb, proc, ct.TypeParameters);
                return;

            // Primitives
            case CorElementType.ELEMENT_TYPE_BOOLEAN:
                sb.Append("System.Boolean"); return;

            case CorElementType.ELEMENT_TYPE_CHAR:
                sb.Append("System.Char"); return;

            case CorElementType.ELEMENT_TYPE_I1:
                sb.Append("System.SByte"); return;

            case CorElementType.ELEMENT_TYPE_U1:
                sb.Append("System.Byte"); return;

            case CorElementType.ELEMENT_TYPE_I2:
                sb.Append("System.Int16"); return;

            case CorElementType.ELEMENT_TYPE_U2:
                sb.Append("System.UInt16"); return;

            case CorElementType.ELEMENT_TYPE_I4:
                sb.Append("System.Int32"); return;

            case CorElementType.ELEMENT_TYPE_U4:
                sb.Append("System.Uint32"); return;

            case CorElementType.ELEMENT_TYPE_I8:
                sb.Append("System.Int64"); return;

            case CorElementType.ELEMENT_TYPE_U8:
                sb.Append("System.UInt64"); return;

            case CorElementType.ELEMENT_TYPE_I:
                sb.Append("System.IntPtr"); return;

            case CorElementType.ELEMENT_TYPE_U:
                sb.Append("System.UIntPtr"); return;

            case CorElementType.ELEMENT_TYPE_R4:
                sb.Append("System.Single"); return;

            case CorElementType.ELEMENT_TYPE_R8:
                sb.Append("System.Double"); return;

            // Well known class-types.
            case CorElementType.ELEMENT_TYPE_OBJECT:
                sb.Append("System.Object"); return;

            case CorElementType.ELEMENT_TYPE_STRING:
                sb.Append("System.String"); return;


            // Special compound types. Based off first type-param
            case CorElementType.ELEMENT_TYPE_SZARRAY:
            case CorElementType.ELEMENT_TYPE_ARRAY:
            case CorElementType.ELEMENT_TYPE_BYREF:
            case CorElementType.ELEMENT_TYPE_PTR:
                CorType t = ct.FirstTypeParameter;
                GetFunctionClassPath(sb, t);
                switch (ct.Type)
                {
                case CorElementType.ELEMENT_TYPE_SZARRAY:
                    sb.Append("[]");
                    return;

                case CorElementType.ELEMENT_TYPE_ARRAY:
                    int rank = ct.Rank;
                    sb.Append('[');
                    for (int i = 0; i < rank - 1; i++)
                    {
                        // <strip>@todo- could we print out exact boundaries?
                        // Probably would have to do some sort of func-eval on the array object.</strip>
                        sb.Append(',');
                    }
                    sb.Append(']');
                    return;

                case CorElementType.ELEMENT_TYPE_BYREF:
                    sb.Append("&");
                    return;

                case CorElementType.ELEMENT_TYPE_PTR:
                    sb.Append("*");
                    return;
                }
                Debug.Assert(false);                         // shouldn't have gotten here.
                return;

            // <strip>Other wacky stuff.
            // @todo - can we do a better job of printing these?</strip>
            case CorElementType.ELEMENT_TYPE_FNPTR:
                sb.Append("*(...)");
                return;

            case CorElementType.ELEMENT_TYPE_TYPEDBYREF:
                sb.Append("typedbyref");
                return;

            default:
                sb.Append("<unknown>");
                return;
            }
        }
예제 #5
0
        private string PrintObject(int indentLevel, CorObjectValue ov, int expandDepth, bool canDoFunceval, string variableName, Dictionary <string, int> variablesToLog)
        {
            Debug.Assert(expandDepth >= 0);

            if (variablesToLog == null)
            {
            }
            else if (variablesToLog.Any(variable => variable.Key.StartsWith($@"{variableName}.")))
            {
                variablesToLog = variablesToLog
                                 .Where(variable => variable.Key.StartsWith($@"{variableName}."))
                                 .ToDictionary(variable => variable.Key, variable => variable.Value);

                expandDepth = 1;
            }
            else if (variablesToLog.Any(variable => variable.Key == variableName))
            {
                var thisVariable = variablesToLog.First(variable => variable.Key == variableName);
                expandDepth    = thisVariable.Value;
                variablesToLog = null;
            }
            else
            {
                return("[SKIP]");
            }

            bool fNeedToResumeThreads = true;

            // Print generics-aware type.
            string name = InternalUtil.PrintCorType(this.m_process, ov.ExactType);

            StringBuilder txt = new StringBuilder();

            txt.Append(name);

            if (expandDepth > 0)
            {
                // we gather the field info of the class before we do
                // funceval since funceval requires running the debugger process
                // and this in turn can cause GC and invalidate our references.
                StringBuilder expandedDescription = new StringBuilder();
                if (IsComplexType)
                {
                    foreach (MDbgValue v in GetFields())
                    {
                        expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)).
                        Append("=").Append(IndentedBlock(indentLevel + 2,
                                                         v.GetStringValue(expandDepth - 1, false, $"{variableName}.{v.Name}", variablesToLog)));
                    }
                }

                // if the value we're printing is a nullable type that has no value (is null), we can't do a func eval
                // to get its value, since it will be boxed as a null pointer. We already have the information we need, so
                // we'll just take care of it now. Note that ToString() for null-valued nullable types just prints the
                // empty string.

                // bool hasValue = (bool)(GetField("hasValue").CorValue.CastToGenericValue().GetValue());

                if (IsNullableType(ov.ExactType) && !(bool)(GetField("hasValue").CorValue.CastToGenericValue().GetValue()))
                {
                    txt.Append(" < >");
                }
                else if (ov.IsValueClass && canDoFunceval)
                // we could display even values for real Objects, but we will just show
                // "description" for valueclasses.
                {
                    CorClass          cls      = ov.ExactType.Class;
                    CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer;
                    MetadataType      mdType   = importer.GetType(cls.Token) as MetadataType;

                    if (mdType.ReallyIsEnum)
                    {
                        txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType));
                    }
                    else if (m_process.IsRunning)
                    {
                        txt.Append(" <N/A during run>");
                    }
                    else
                    {
                        MDbgThread activeThread = m_process.Threads.Active;

                        CorValue     thisValue;
                        CorHeapValue hv = ov.CastToHeapValue();
                        if (hv != null)
                        {
                            // we need to pass reference value.
                            CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION);
                            thisValue = handle;
                        }
                        else
                        {
                            thisValue = ov;
                        }

                        try
                        {
                            CorEval eval = m_process.Threads.Active.CorThread.CreateEval();
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND,
                                                                         activeThread.CorThread);

                            MDbgFunction toStringFunc = m_process.ResolveFunctionName(null, "System.Object", "ToString",
                                                                                      thisValue.ExactType.Class.Module.Assembly.AppDomain);

                            Debug.Assert(toStringFunc != null); // we should be always able to resolve ToString function.

                            eval.CallFunction(toStringFunc.CorFunction, new CorValue[] { thisValue });
                            m_process.Go();
                            do
                            {
                                m_process.StopEvent.WaitOne();
                                if (m_process.StopReason is EvalCompleteStopReason)
                                {
                                    CorValue cv = eval.Result;
                                    Debug.Assert(cv != null);
                                    MDbgValue mv      = new MDbgValue(m_process, cv);
                                    string    valName = mv.GetStringValue(0, variableName, variablesToLog);

                                    // just purely for esthetical reasons we 'discard' "
                                    if (valName.StartsWith("\"") && valName.EndsWith("\""))
                                    {
                                        valName = valName.Substring(1, valName.Length - 2);
                                    }

                                    txt.Append(" <").Append(valName).Append(">");
                                    break;
                                }
                                if ((m_process.StopReason is ProcessExitedStopReason) ||
                                    (m_process.StopReason is EvalExceptionStopReason))
                                {
                                    txt.Append(" <N/A cannot evaluate>");
                                    break;
                                }
                                // hitting bp or whatever should not matter -- we need to ignore it
                                m_process.Go();
                            }while (true);
                        }
                        catch (COMException e)
                        {
                            // Ignore cannot copy a VC class error - Can't copy a VC with object refs in it.
                            if (e.ErrorCode != (int)HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS)
                            {
                                throw;
                            }
                        }
                        catch (System.NotImplementedException)
                        {
                            fNeedToResumeThreads = false;
                        }
                        finally
                        {
                            if (fNeedToResumeThreads)
                            {
                                // we need to resume all the threads that we have suspended no matter what.
                                m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN,
                                                                             activeThread.CorThread);
                            }
                        }
                    }
                }
                txt.Append(expandedDescription.ToString());
            }
            return(txt.ToString());
        }