Пример #1
0
        private string PrintArray(int indentLevel, CorArrayValue av, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            StringBuilder txt = new StringBuilder();

            txt.Append("array [");
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            for (int i = 0; i < dims.Length; ++i)
            {
                if (i != 0)
                {
                    txt.Append(",");
                }
                txt.Append(dims[i]);
            }
            txt.Append("]");

            if (expandDepth > 0 && av.Rank == 1 && av.ElementType != CorElementType.ELEMENT_TYPE_VOID)
            {
                for (int i = 0; i < dims[0]; i++)
                {
                    MDbgValue v = new MDbgValue(Process, av.GetElementAtPosition(i));
                    txt.Append("\n").Append(IndentedString(indentLevel + 1, "[" + i + "] = ")).
                    Append(IndentedBlock(indentLevel + 2,
                                         v.GetStringValue(expandDepth - 1, canDoFunceval)));
                }
            }
            return(txt.ToString());
        }
Пример #2
0
            private LocalVariableInformation GetLocalVariableInformation(MDbgValue value, VariableType variableType, int depth)
            {
                // Some MDbgValues don't have an associated CorValue. This occurs when there is no variable declaration in IL.
                if (value == null || value.CorValue == null)
                    return null;

                if (createdLocals.ContainsKey(value.CorValue.Address))
                    return createdLocals[value.CorValue.Address];

                var fields = new List<LocalVariableInformation>();

                if (value.IsComplexType && value.IsNull == false && depth < 10)
                {
                    MDbgValue[] fieldValues = value.GetFields();
                    foreach (var fieldValue in fieldValues)
                    {
                        fields.Add(GetLocalVariableInformation(fieldValue, VariableType.Field, depth + 1));
                    }
                }

                var information = new LocalVariableInformation
                {
                    TypeName = value.TypeName,
                    Name = value.Name,
                    StringValue = value.GetStringValue(false),
                    TypeOfVariable = variableType,
                    IsPrimitive = !value.IsComplexType,
                    Fields = fields
                };

                createdLocals[value.CorValue.Address] = information;

                return information;
            }
Пример #3
0
        private string PrintObject(int indentLevel, CorObjectValue ov, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            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)));
                    }
                }

                // 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);

                                    // 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();
        }
Пример #4
0
        private string PrintArray(int indentLevel, CorArrayValue av, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            StringBuilder txt = new StringBuilder();
            txt.Append("array [");
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            for (int i = 0; i < dims.Length; ++i)
            {
                if (i != 0)
                    txt.Append(",");
                txt.Append(dims[i]);
            }
            txt.Append("]");

            if (expandDepth > 0 && av.Rank == 1 && av.ElementType != CorElementType.ELEMENT_TYPE_VOID)
            {
                for (int i = 0; i < dims[0]; i++)
                {
                    MDbgValue v = new MDbgValue(Process, av.GetElementAtPosition(i));
                    txt.Append("\n").Append(IndentedString(indentLevel + 1, "[" + i + "] = ")).
            Append(IndentedBlock(indentLevel + 2,
                           v.GetStringValue(expandDepth - 1, canDoFunceval)));
                }
            }
            return txt.ToString();
        }
Пример #5
0
        public static Dictionary<string, string> GetLocalVars(MDbgEngine pDebugger, List<string> specificVarNames = null, bool debuggerVarsOpt = false, bool noFuncevalOpt = false, int? expandDepthOpt = null)
        {
            Dictionary<string, string> retVal = new Dictionary<string, string>();
            //const string debuggerVarsOpt = "d";
            //const string noFuncevalOpt = "nf";
            //const string expandDepthOpt = "r";

            //ArgParser ap = new ArgParser(arguments, debuggerVarsOpt + ";" + noFuncevalOpt + ";" + expandDepthOpt + ":1");
            bool canDoFunceval = !noFuncevalOpt;

            int? expandDepth = null;			    // we use optional here because
            // different codes bellow has different
            // default values.
            if (expandDepthOpt != null)
            {
                expandDepth = (int)expandDepthOpt;
                if (expandDepth < 0)
                    throw new MDbgShellException("Depth cannot be negative.");
            }

            MDbgFrame frame = pDebugger.Processes.Active.Threads.Active.CurrentFrame;
            if (debuggerVarsOpt)
            {
                // let's print all debugger variables
                MDbgProcess p = pDebugger.Processes.Active;
                foreach (MDbgDebuggerVar dv in p.DebuggerVars)
                {
                    MDbgValue v = new MDbgValue(p, dv.CorValue);
                    string value = v.GetStringValue(expandDepth == null ? 0 : (int)expandDepth, canDoFunceval);
                    retVal.Add(dv.Name, value);
                }
            }
            else
            {
                //!debuggerVarsOpt && !noFuncevalOpt && expandDepthOpt == null &&
                if (specificVarNames == null || specificVarNames.Count == 0)
                {
                    // get all active variables
                    MDbgFunction f = frame.Function;

                    ArrayList vars = new ArrayList();
                    MDbgValue[] vals = f.GetActiveLocalVars(frame);
                    if (vals != null)
                    {
                        vars.AddRange(vals);
                    }

                    vals = f.GetArguments(frame);
                    if (vals != null)
                    {
                        vars.AddRange(vals);
                    }
                    foreach (MDbgValue v in vars)
                    {
                        string value = v.GetStringValue(expandDepth == null ? 0 : (int)expandDepth, canDoFunceval);
                        retVal.Add(v.Name, value);
                    }
                }
                else
                {
                    // user requested printing of specific variables
                    for (int j = 0; j < specificVarNames.Count; ++j)
                    {
                        MDbgValue var = pDebugger.Processes.Active.ResolveVariable(specificVarNames[j], frame);
                        if (var != null)
                        {
                            string value = var.GetStringValue(expandDepth == null ? 1 : (int)expandDepth, canDoFunceval);
                            retVal.Add(specificVarNames[j], value);
                        }
                        else
                        {
                            throw new MDbgShellException("Variable not found");
                        }
                    }
                }
            }
            return retVal;
        }
Пример #6
0
        public static void UnwrapGCHandleCmd(string arguments)
        {
            ArgParser ap = new ArgParser(arguments);
            if (ap.Count != 1)
            {
                WriteError("Wrong arguments, should be name or address of a \"System.Runtime.InteropServices.GCHandle\" object.");
                return;
            }

            long handleAdd = 0;

            // First try to resolve the argument as a variable in the current frame
            MDbgValue var = Debugger.Processes.Active.ResolveVariable(
                                                                      ap.AsString(0),
                                                                      Debugger.Processes.Active.Threads.Active.CurrentFrame);
            if (var != null)
            {
                if (var.TypeName != "System.Runtime.InteropServices.GCHandle")
                {
                    WriteError("Variable is not of type \"System.Runtime.InteropServices.GCHandle\".");
                    return;
                }

                foreach (MDbgValue field in var.GetFields())
                {
                    if (field.Name == "m_handle")
                    {
                        handleAdd = Int64.Parse(field.GetStringValue(0));
                        break;
                    }
                }
            }
            else
            {
                // Trying to resolve as a raw address now
                try
                {
                    handleAdd = ap.GetArgument(0).AsAddress;
                }
                catch (System.FormatException)
                {
                    WriteError("Couldn't recognize the argument as a variable name or address");
                    return;
                }
            }

            IntPtr add = new IntPtr(handleAdd);
            CorReferenceValue result;

            try
            {
                result = Debugger.Processes.Active.CorProcess.GetReferenceValueFromGCHandle(add);
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                if (e.ErrorCode == (int)HResult.CORDBG_E_BAD_REFERENCE_VALUE)
                {
                    WriteError("Invalid handle address.");
                    return;
                }
                else
                {
                    throw;
                }
            }

            CorValue v = result.Dereference();
            MDbgValue mv = new MDbgValue(Debugger.Processes.Active, v);
            if (mv.IsComplexType)
            {
                WriteOutput(string.Format("GCHandle to <{0}>",
                                          InternalUtil.PrintCorType(Debugger.Processes.Active, v.ExactType)));

                // now print fields as well
                foreach (MDbgValue f in mv.GetFields())
                    CommandBase.WriteOutput(" " + f.Name + "=" + f.GetStringValue(0));
            }
            else
            {
                WriteOutput(string.Format("GCHandle to {0}", mv.GetStringValue(0)));
            }
        }
Пример #7
0
        public static void NewObjCmd(string arguments)
        {
            ArgParser ap = new ArgParser(arguments);

            string className = ap.AsString(0);
            MDbgFunction func = Debugger.Processes.Active.ResolveFunctionName(null, className, ".ctor", Debugger.Processes.Active.Threads.Active.CorThread.AppDomain);
            if (null == func)
                throw new MDbgShellException(String.Format(CultureInfo.InvariantCulture, "Could not resolve {0}", ap.AsString(0)));

            CorEval eval = Debugger.Processes.Active.Threads.Active.CorThread.CreateEval();

            ArrayList callArguments = new ArrayList();
            // parse the arguments to newobj
            int i = 1;
            while (ap.Exists(i))
            {
                string arg = ap.AsString(i);
                // this is a normal argument
                MDbgValue rsMVar = Debugger.Processes.Active.ResolveVariable(arg,
                                                                             Debugger.Processes.Active.Threads.Active.CurrentFrame);
                if (rsMVar == null)
                {
                    // cordbg supports also limited literals -- currently only NULL & I4.
                    if (string.Compare(arg, "null", true) == 0)
                    {
                        callArguments.Add(eval.CreateValue(CorElementType.ELEMENT_TYPE_CLASS, null));
                    }
                    else
                    {
                        int v;
                        if (!Int32.TryParse(arg, out v))
                            throw new MDbgShellException(string.Format(CultureInfo.InvariantCulture, "Argument '{0}' could not be resolved to variable or number",
                                                                       arg));

                        CorGenericValue gv = eval.CreateValue(CorElementType.ELEMENT_TYPE_I4, null).CastToGenericValue();
                        Debug.Assert(gv != null);
                        gv.SetValue(v);
                        callArguments.Add(gv);
                    }
                }
                else
                {
                    callArguments.Add(rsMVar.CorValue);
                }
                ++i;
            }

            eval.NewParameterizedObject(func.CorFunction, null, (CorValue[])callArguments.ToArray(typeof(CorValue)));
            Debugger.Processes.Active.Go().WaitOne();

            // now display result of the funceval
            if (!(Debugger.Processes.Active.StopReason is EvalCompleteStopReason))
            {
                // we could have received also EvalExceptionStopReason but it's derived from EvalCompleteStopReason
                WriteOutput("Newobj command not fully completed and debuggee has stopped");
                WriteOutput("Result of Newobj won't be printed when finished.");
            }
            else
            {
                eval = (Debugger.Processes.Active.StopReason as EvalCompleteStopReason).Eval;
                Debug.Assert(eval != null);

                CorValue cv = eval.Result;
                if (cv != null)
                {
                    MDbgValue mv = new MDbgValue(Debugger.Processes.Active, cv);
                    WriteOutput("result = " + mv.GetStringValue(1));
                    if (Debugger.Processes.Active.DebuggerVars.SetEvalResult(cv))
                        WriteOutput("results saved to $result");
                }
            }
            Shell.DisplayCurrentLocation();
        }
Пример #8
0
        public static void FuncEvalCmd(string arguments)
        {
            const string appDomainOption = "ad";
            ArgParser ap = new ArgParser(arguments, appDomainOption + ":1");
            if (!(ap.Count >= 1))
            {
                throw new MDbgShellException("Not Enough arguments");
            }

            // Currently debugger picks first function -- we have not implementing resolving overloaded functions.
            // Good example is Console.WriteLine -- there is 18 different types:
            // 1) [06000575] Void WriteLine()
            // 2) [06000576] Void WriteLine(Boolean)
            // 3) [06000577] Void WriteLine(Char)
            // 4) [06000578] Void WriteLine(Char[])
            // 5) [06000579] Void WriteLine(Char[], Int32, Int32)
            // 6) [0600057a] Void WriteLine(Decimal)
            // 7) [0600057b] Void WriteLine(Double)
            // 8) [0600057c] Void WriteLine(Single)
            // 9) [0600057d] Void WriteLine(Int32)
            // 10) [0600057e] Void WriteLine(UInt32)
            // 11) [0600057f] Void WriteLine(Int64)
            // 12) [06000580] Void WriteLine(UInt64)
            // 13) [06000581] Void WriteLine(Object)
            // 14) [06000582] Void WriteLine(String)
            // 15) [06000583] Void WriteLine(String, Object)
            // 16) [06000584] Void WriteLine(String, Object, Object)
            // 17) [06000585] Void WriteLine(String, Object, Object, Object)
            // 18) [06000586] Void WriteLine(String, Object, Object, Object, Object, ...)
            // 19) [06000587] Void WriteLine(String, Object[])
            //
            CorAppDomain appDomain;
            if (ap.OptionPassed(appDomainOption))
            {
                MDbgAppDomain ad = Debugger.Processes.Active.AppDomains[ap.GetOption(appDomainOption).AsInt];
                if (ad == null)
                {
                    throw new ArgumentException("Invalid Appdomain Number");
                }
                appDomain = ad.CorAppDomain;
            }
            else
            {
                appDomain = Debugger.Processes.Active.Threads.Active.CorThread.AppDomain;
            }

            MDbgFunction func = Debugger.Processes.Active.ResolveFunctionNameFromScope(ap.AsString(0), appDomain);
            if (null == func)
            {
                throw new MDbgShellException(String.Format(CultureInfo.InvariantCulture, "Could not resolve {0}", new Object[] { ap.AsString(0) }));
            }

            CorEval eval = Debugger.Processes.Active.Threads.Active.CorThread.CreateEval();

            // Get Variables
            ArrayList vars = new ArrayList();
            String arg;
            for (int i = 1; i < ap.Count; i++)
            {
                arg = ap.AsString(i);

                CorValue v = Shell.ExpressionParser.ParseExpression2(arg, Debugger.Processes.Active,
                    Debugger.Processes.Active.Threads.Active.CurrentFrame);

                if (v == null)
                {
                    throw new MDbgShellException("Cannot resolve expression or variable " + ap.AsString(i));
                }

                if (v is CorGenericValue)
                {
                    vars.Add(v as CorValue);
                }

                else
                {
                    CorHeapValue hv = v.CastToHeapValue();
                    if (hv != null)
                    {
                        // we cannot pass directly heap values, we need to pass reference to heap valus
                        CorReferenceValue myref = eval.CreateValue(CorElementType.ELEMENT_TYPE_CLASS, null).CastToReferenceValue();
                        myref.Value = hv.Address;
                        vars.Add(myref);
                    }
                    else
                    {
                        vars.Add(v);
                    }
                }

            }

            eval.CallFunction(func.CorFunction, (CorValue[])vars.ToArray(typeof(CorValue)));
            Debugger.Processes.Active.Go().WaitOne();

            // now display result of the funceval
            if (!(Debugger.Processes.Active.StopReason is EvalCompleteStopReason))
            {
                // we could have received also EvalExceptionStopReason but it's derived from EvalCompleteStopReason
                WriteOutput("Func-eval not fully completed and debuggee has stopped");
                WriteOutput("Result of funceval won't be printed when finished.");
            }
            else
            {
                eval = (Debugger.Processes.Active.StopReason as EvalCompleteStopReason).Eval;
                Debug.Assert(eval != null);

                CorValue cv = eval.Result;
                if (cv != null)
                {
                    MDbgValue mv = new MDbgValue(Debugger.Processes.Active, cv);
                    WriteOutput("result = " + mv.GetStringValue(1));
                    if (cv.CastToReferenceValue() != null)
                        if (Debugger.Processes.Active.DebuggerVars.SetEvalResult(cv))
                            WriteOutput("results saved to $result");
                }
            }
            Shell.DisplayCurrentLocation();
        }
Пример #9
0
        public static void PrintCmd(string arguments)
        {
            const string debuggerVarsOpt = "d";
            const string noFuncevalOpt = "nf";
            const string expandDepthOpt = "r";

            ArgParser ap = new ArgParser(arguments, debuggerVarsOpt + ";" + noFuncevalOpt + ";" + expandDepthOpt + ":1");
            bool canDoFunceval = !ap.OptionPassed(noFuncevalOpt);

            int? expandDepth = null;			    // we use optional here because
            // different codes bellow has different
            // default values.
            if (ap.OptionPassed(expandDepthOpt))
            {
                expandDepth = ap.GetOption(expandDepthOpt).AsInt;
                if (expandDepth < 0)
                    throw new MDbgShellException("Depth cannot be negative.");
            }

            MDbgFrame frame = Debugger.Processes.Active.Threads.Active.CurrentFrame;
            if (ap.OptionPassed(debuggerVarsOpt))
            {
                // let's print all debugger variables
                MDbgProcess p = Debugger.Processes.Active;
                foreach (MDbgDebuggerVar dv in p.DebuggerVars)
                {
                    MDbgValue v = new MDbgValue(p, dv.CorValue);
                    WriteOutput(dv.Name + "=" + v.GetStringValue(expandDepth == null ? 0 : (int)expandDepth,
                                                              canDoFunceval));
                }
            }
            else
            {
                if (ap.Count == 0)
                {
                    // get all active variables
                    MDbgFunction f = frame.Function;

                    ArrayList vars = new ArrayList();
                    MDbgValue[] vals = f.GetActiveLocalVars(frame);
                    if (vals != null)
                    {
                        vars.AddRange(vals);
                    }

                    vals = f.GetArguments(frame);
                    if (vals != null)
                    {
                        vars.AddRange(vals);
                    }
                    foreach (MDbgValue v in vars)
                    {
                        WriteOutput(v.Name + "=" + v.GetStringValue(expandDepth == null ? 0 : (int)expandDepth,
                                                                 canDoFunceval));
                    }
                }
                else
                {
                    // user requested printing of specific variables
                    for (int j = 0; j < ap.Count; ++j)
                    {
                        MDbgValue var = Debugger.Processes.Active.ResolveVariable(ap.AsString(j), frame);
                        if (var != null)
                        {
                            WriteOutput(ap.AsString(j) + "=" + var.GetStringValue(expandDepth == null ? 1
                                : (int)expandDepth, canDoFunceval));
                        }
                        else
                        {
                            throw new MDbgShellException("Variable not found");
                        }
                    }
                }
            }
        }
Пример #10
0
        private string PrintObject(int indentLevel, CorObjectValue ov, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            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)));
                    }
                }

                // 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)[0];

                            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);

                                    // 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());
        }
        //-----------------------------------------------------------------------------
        // Recursive helper to populate tree view.
        // val - value to print
        // c - node collection to add to.
        // iDepth - track how far we are to avoid infinite recursion.
        //-----------------------------------------------------------------------------
        void PrintInternal(MDbgValue val, TreeNodeCollection c, int iDepth)
        {
            if (iDepth > 10)
            {
                return;
            }

            if (val.IsArrayType)
            {                
                TreeNode n = new TreeNode(val.TypeName + " array:");
                foreach (MDbgValue vField in val.GetArrayItems())
                {
                    PrintInternal(vField, n.Nodes, iDepth + 1);
                }
                c.Add(n);
            }
            else if (val.IsComplexType)
            {    
                // This will include both instance and static fields
                // It will also include all base class fields.
                TreeNode n = new TreeNode(val.TypeName + " fields:");
                foreach (MDbgValue vField in val.GetFields())
                {                    
                    PrintInternal(vField, n.Nodes, iDepth + 1);
                }
                c.Add(n);
            }
            else
            {
                // This is a ctach-call for primitives.
                string st = val.GetStringValue(false);
                c.Add(val.Name + "=" + st + " (type='" + val.TypeName + "')");

            }
        }
Пример #12
0
        private string PrintArray(int indentLevel, CorArrayValue av, 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]");
            }

            StringBuilder txt = new StringBuilder();

            txt.Append("array [");
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            for (int i = 0; i < dims.Length; ++i)
            {
                if (i != 0)
                {
                    txt.Append(",");
                }
                txt.Append(dims[i]);
            }
            txt.Append("]");

            if (expandDepth > 0 && av.Rank == 1 && av.ElementType != CorElementType.ELEMENT_TYPE_VOID)
            {
                for (int i = 0; i < dims[0]; i++)
                {
                    MDbgValue v = new MDbgValue(Process, av.GetElementAtPosition(i));
                    var       newVariableName = $"{variableName}.[{i}]";

                    var newVariablesToLog = variablesToLog == null
                        ? null
                        : variablesToLog
                                            .ToDictionary(
                        variable => $"{newVariableName}{variable.Key.Remove(0, variableName.Length)}",
                        variable => variable.Value);

                    txt
                    .Append("\n")
                    .Append(IndentedString(indentLevel + 1, "[" + i + "] = "))
                    .Append(IndentedBlock(indentLevel + 2, v.GetStringValue(expandDepth - 1, canDoFunceval, $"{variableName}.[{i}]", newVariablesToLog)));
                }
            }
            return(txt.ToString());
        }