Exemple #1
0
        private void SerializeReturnValue(Microsoft.Samples.Debugging.MdbgEngine.MDbgValue value, CallStackEntry callStackEntry)
        {
            var methodInfo = callStackEntry.BreakpointMetadata.Details.MethodInfo;

            shell.WriteLine("Captured return value for {0}", methodInfo.Name);
            var path = Path.Combine(GetWorkingDirectory(), string.Format("{0}.{1}-{2}-{3}-returnvalue.txt", methodInfo.DeclaringType.FullName, methodInfo.Name, methodInfo.MetadataToken, callStackEntry.Identifier));

            parameterSerializer.Serialize(path, new MDbgValue[] { value });
        }
        //-----------------------------------------------------------------------------
        // Print the value to the treeview
        // This will clear out the TreeView and repopulate it with the Value.
        //-----------------------------------------------------------------------------
        void Print(MDbgValue val, TreeView t)
        {
            t.BeginUpdate();

            t.Nodes.Clear();

            if (val == null)
            {
                t.Nodes.Add("(Error:Expression not valid in this scope)");
            }
            else
            {
                PrintInternal(val, t.Nodes, 0);
            }

            t.EndUpdate();
        }
Exemple #3
0
        /// <summary>
        /// Gets the specified Field.
        /// </summary>
        /// <param name="name">The Name of the Field to get.</param>
        /// <returns>The Value of the specified Field.</returns>
        public MDbgValue GetField(string name)
        {
            MDbgValue ret = null;

            foreach (MDbgValue v in GetFields())
            {
                if (v.Name.Equals(name))
                {
                    ret = v;
                    break;
                }
            }
            if (ret == null)
            {
                throw new MDbgValueException("Field '" + name + "' not found.");
            }
            return(ret);
        }
Exemple #4
0
        /// <summary>
        /// Gets Array Items.  This function can be called only on one dimensional arrays.
        /// </summary>
        /// <returns>An array of the values for the Array Items.</returns>
        public MDbgValue[] GetArrayItems()
        {
            if (!IsArrayType)
            {
                throw new MDbgValueException("Type is not array type");
            }

            CorValue value = Dereference(CorValue, null);

            CorArrayValue av = value.CastToArrayValue();

            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            ArrayList al = new ArrayList();

            Debug.Assert(av.Rank == 1);
            for (int i = 0; i < dims[0]; i++)
            {
                MDbgValue v = new MDbgValue(Process, "[" + i + "]", av.GetElementAtPosition(i));
                al.Add(v);
            }
            return((MDbgValue[])al.ToArray(typeof(MDbgValue)));
        }
Exemple #5
0
        /// <summary>
        /// Gets the Array Item for the specified indexes
        /// </summary>
        /// <param name="indexes">Which indexes to get the Array Item for.</param>
        /// <returns>The Value for the given indexes.</returns>
        public MDbgValue GetArrayItem(params int[] indexes)
        {
            if (!IsArrayType)
                throw new MDbgValueException("Type is not array type");

            CorValue value = Dereference(CorValue, null);
            CorArrayValue av = value.CastToArrayValue();
            Debug.Assert(av != null);
            if (av.Rank != indexes.Length)
                throw new MDbgValueException("Invalid number of dimensions.");

            StringBuilder sb = new StringBuilder("[");
            for (int i = 0; i < indexes.Length; ++i)
            {
                if (i != 0)
                    sb.Append(",");
                sb.Append(indexes[i]);
            }
            sb.Append("]");

            MDbgValue v = new MDbgValue(Process, sb.ToString(), av.GetElement(indexes));
            return v;
        }
        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)));
            }
        }
        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;
        }
        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();
        }
        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();
        }
Exemple #10
0
 //zos; CSScript.Npp related changes
 static internal T GetFieldValue <T>(this MDbgValue value, string name)
 {
     return((T)value.GetField(name).CorValue.CastToGenericValue().GetValue());
 }
Exemple #11
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");
                        }
                    }
                }
            }
        }
Exemple #12
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();
        }
Exemple #13
0
        /// <summary>
        /// Gets the output of a function using MDbg.
        /// </summary>
        /// <example>
        /// 	<code lang="CS" title="Getting the Message from an Exception" description="An example showing how you would get the value of the Message property of an Exception. The variable ex is a MDbgValue object that represents the exception you are examining.">
        /// MDbgValue returnValue = ResolveFunction(debuggedProc, ex, "System.Exception.get_Message");
        /// string message = returnValue.GetStringValue(true);
        ///     </code>
        /// </example>
        /// <param name="debuggedProc">The process we are debugging.</param>
        /// <param name="ex">The MDbgValue object to execute the function on.</param>
        /// <param name="function">The full name of the function in MDbg syntax.</param>
        /// <returns>The MDbgValue that contains the return value of the function. If the function
        /// could not be evaluated, it returns null.</returns>
        private MDbgValue ResolveFunction(MDbgProcess debuggedProc, MDbgValue ex, string function)
        {
            CorAppDomain appDomain = debuggedProc.Threads.Active.CorThread.AppDomain;
            MDbgFunction func = debuggedProc.ResolveFunctionNameFromScope(function, appDomain);
            if (func == null)
                throw new Exception("A required function is missing. Are you running a template compiled with an different version of ArchAngel?");
            CorEval eval = debuggedProc.Threads.Active.CorThread.CreateEval();
            eval.CallFunction(func.CorFunction, new[] { ex.CorValue });

            debuggedProc.Go().WaitOne();

            if (!(debuggedProc.StopReason is EvalCompleteStopReason))
            {
                return null;
            }

            eval = ((EvalCompleteStopReason)debuggedProc.StopReason).Eval;
            if (eval == null)
            {
                return null;
            }

            CorValue cv = eval.Result;
            if (cv != null)
            {
                MDbgValue mv = new MDbgValue(debuggedProc, cv);
                return mv;
            }

            return null;
        }
Exemple #14
0
        private static string GetStringFromException(MDbgThread activeThread, MDbgValue ex)
        {
            ExceptionInfo exinfo = GetExceptionInfo(activeThread, ex);

            StringBuilder retVal = new StringBuilder();
            string exceptionType = exinfo.ExType;
            if (!string.IsNullOrWhiteSpace(exinfo.Function))
            {
                retVal.AppendLine("at function: " + exinfo.Function);
            }

            if (!string.IsNullOrWhiteSpace(exinfo.Message))
            {
                retVal.AppendLine("Message: " + exinfo.Message);
            }

            if (!string.IsNullOrWhiteSpace(exinfo.Source))
            {
                retVal.AppendLine("in source file: " + exinfo.Source);
            }

            if (!string.IsNullOrWhiteSpace(exinfo.Callstack))
            {
                retVal.AppendLine("Callstack: " + exinfo.Callstack);
            }

            return retVal.ToString();
        }
Exemple #15
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());
        }
Exemple #16
0
        private static ExceptionInfo GetExceptionInfo(MDbgThread activeThread, MDbgValue ex)
        {
            ExceptionInfo exinfo = new ExceptionInfo();
            exinfo.ExType = ex.TypeName;
            exinfo.Function = (ex.GetField("_exceptionMethodString").IsNull ? null : ex.GetField("_exceptionMethodString").ToString());
            exinfo.Message = (ex.GetField("_message").IsNull ? null : ex.GetField("_message").GetStringValue(false));
            exinfo.Source = (ex.GetField("_source").IsNull ? null : ex.GetField("_source").ToString());

            //StringBuilder sbCallstack = new StringBuilder();
            //try
            //{
            //    if (activeThread != null)
            //        activeThread.Frames.ToList().ForEach(f => sbCallstack.AppendLine(f.ToString()));
            //}
            //catch (Exception ex1)
            //{
            //    DebuggerUtils.HandleExceptionSilently(ex1);
            //}
            exinfo.Callstack = DebuggerUtils.GetThreadStacks(activeThread, true).ToString();
            return exinfo;
        }
        public void Serialize(string path, IEnumerable<MDbgValue> valuesList)
        {
            var values = valuesList.ToList();
            CorEval eval = debugger.Processes.Active.Threads.Active.CorThread.CreateEval();
            var functionName = "BigBrother.Serialization.JsonSerializer.Serialize" + (values.Count + 1);

            CorAppDomain appDomain = debugger.Processes.Active.Threads.Active.CorThread.AppDomain;

            if (serializers.Count == 0)
            {
                //Load BigBrother into the AppDomain. Then we can call BigBrother.Serialization.JsonSerializer's methods.
                if (useLoadFrom)
                {
                    eval.NewString("BigBrother.dll");
                    debugger.Processes.Active.Go().WaitOne();
                    var evalAssemblyName = eval.Result;
                    var fnLoad = debugger.Processes.Active.ResolveFunctionNameFromScope("System.Reflection.Assembly.LoadFrom", appDomain);
                    eval.CallParameterizedFunction(fnLoad.CorFunction, null, new CorValue[] { evalAssemblyName });
                    debugger.Processes.Active.Go().WaitOne();
                }
                else
                {
                    eval.NewString("BigBrother");
                    debugger.Processes.Active.Go().WaitOne();
                    var evalAssemblyName = eval.Result;
                    var fnLoad = debugger.Processes.Active.ResolveFunctionNameFromScope("System.Reflection.Assembly.Load", appDomain);
                    eval.CallParameterizedFunction(fnLoad.CorFunction, null, new CorValue[] { evalAssemblyName });
                    debugger.Processes.Active.Go().WaitOne();
                }
            }

            if (!serializers.ContainsKey(functionName))
            {
                serializers[functionName] = debugger.Processes.Active.ResolveFunctionNameFromScope(functionName, appDomain);
            }

            eval.NewString(path);
            debugger.Processes.Active.Go().WaitOne();
            CorValue fileName = (debugger.Processes.Active.StopReason as EvalCompleteStopReason).Eval.Result;
            var corValues = new List<CorValue>();
            corValues.Add(fileName);
            corValues.AddRange(values.Select(v => v.CorValue));
            eval.CallParameterizedFunction(serializers[functionName].CorFunction, corValues.Select(v => v.ExactType).ToArray(), corValues.ToArray());
            debugger.Processes.Active.Go().WaitOne();

            if (debugger.Processes.Active.StopReason is EvalExceptionStopReason)
            {
                var stopReason = (EvalExceptionStopReason)debugger.Processes.Active.StopReason;
                string message = new MDbgValue(debugger.Processes.Active, stopReason.Eval.Result).GetStringValue(true);
                shell.WriteLine(message);
            }
        }
Exemple #18
0
        //////////////////////////////////////////////////////////////////////////////////
        //
        //  Support for printing local printing variables
        //
        //////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Gets an Array of MDbgValues for the Active Local Vars in the given frame.
        /// </summary>
        /// <param name="managedFrame">The Frame to look in.</param>
        /// <returns>The MDbgValue[] Active Local Valiables.</returns>
        public MDbgValue[] GetActiveLocalVars(MDbgFrame managedFrame)
        {
            Debug.Assert(managedFrame != null);
            if (managedFrame == null)
            {
                throw new ArgumentException();
            }

            CorFrame frame = managedFrame.CorFrame;

            // we only support this, when the frame is our function
            Debug.Assert(frame.FunctionToken == m_function.Token);
            if (!(frame.FunctionToken == m_function.Token))
            {
                throw new ArgumentException();
            }

            EnsureIsUpToDate();

            if (!m_haveSymbols)
            {
                // if we don't have symbols -- we'll print local variables as (loca1_0,local_1,local_2,...)
                // to give them names consistent with ILasm.
                int c = frame.GetLocalVariablesCount();
                if (c < 0)
                {
                    c = 0;                                                        // in case we cannot get locals,
                }
                // we'll hide them.
                MDbgValue[] locals = new MDbgValue[c];
                for (int i = 0; i < c; ++i)
                {
                    CorValue arg = null;
                    try
                    {
                        arg = frame.GetLocalVariable(i);
                    }
                    catch (System.Runtime.InteropServices.COMException e)
                    {
                        if (e.ErrorCode != (int)Microsoft.Samples.Debugging.CorDebug.HResult.CORDBG_E_IL_VAR_NOT_AVAILABLE)
                        {
                            throw;
                        }
                    }
                    locals[i] = new MDbgValue(m_module.Process, "local_" + (i), arg);
                }
                return(locals);
            }

            uint ip;
            CorDebugMappingResult mappingResult;

            frame.GetIP(out ip, out mappingResult);

            ArrayList    al    = new ArrayList();
            ISymbolScope scope = SymMethod.RootScope;

            AddLocalVariablesToList(frame, (int)ip, al, scope);

            return((MDbgValue[])al.ToArray(typeof(MDbgValue)));
        }
Exemple #19
0
        /// <summary>
        /// Gets Array Items.  This function can be called only on one dimensional arrays.
        /// </summary>
        /// <returns>An array of the values for the Array Items.</returns>
        public MDbgValue[] GetArrayItems()
        {
            if (!IsArrayType)
                throw new MDbgValueException("Type is not array type");

            CorValue value = Dereference(CorValue, null);

            CorArrayValue av = value.CastToArrayValue();
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            ArrayList al = new ArrayList();
            Debug.Assert(av.Rank == 1);
            for (int i = 0; i < dims[0]; i++)
            {
                MDbgValue v = new MDbgValue(Process, "[" + i + "]", av.GetElementAtPosition(i));
                al.Add(v);
            }
            return (MDbgValue[])al.ToArray(typeof(MDbgValue));
        }
Exemple #20
0
        // Helper to parse args to get a value for a GC handle.
        //
        // Syntax for gchandle. Ultimately need to compute an address.
        //  gchandle(var) where var is System.Runtime.InteropServices.GCHandle, address=var.m_handle
        //  gchandle(integer) where address =integer
        //  gchandle(var, offset) where var is a valuetype, then we do address= (IntPtr*) (&var + offset*sizeof(IntPtr))
        internal MDbgValue ParseGCHandleArgs(string stName, string[] args, MDbgFrame scope)
        {
            if (args.Length != 1 && args.Length != 2)
            {
                throw new MDbgException("Wrong number of args to gchandle function.");
            }

            string stVarBase = args[0];
            MDbgValue varBase = ResolveVariable(stVarBase, scope);
            //MDbgValue varBase = Shell.ExpressionParser.ParseExpression(stVarBase,this, scope);

            IntPtr add;

            if (args.Length == 2)
            {
                if (varBase == null)
                {
                    throw new MDbgException("Can't resolve var '" + stVarBase + "'");
                }

                // Form: gchandle(var, offset)
                CorGenericValue gv = varBase.CorValue.CastToGenericValue();
                IntPtr[] ar = null;
                if (gv != null)
                {
                    ar = gv.GetValueAsIntPtrArray();
                }
                if (ar == null)
                {
                    throw new MDbgException("Variable '" + stVarBase + "' is not a value type.");
                }

                int offset = Int32.Parse(args[1], CultureInfo.InvariantCulture);
                add = ar[offset];
            }
            else
            {
                if (varBase != null)
                {
                    add = IntPtr.Zero;
                    // Form: gchandle(var)
                    if (varBase.TypeName != "System.Runtime.InteropServices.GCHandle")
                    {
                        throw new MDbgException("Variable is not of type \"System.Runtime.InteropServices.GCHandle\".");
                    }

                    foreach (MDbgValue field in varBase.GetFields())
                    {
                        if (field.Name == "m_handle")
                        {
                            int handleAddress = Int32.Parse(field.GetStringValue(0));
                            add = new IntPtr(handleAddress);
                            break;
                        }
                    }
                }
                else
                {
                    // Trying to resolve as a raw address now
                    // form: gchandle(integer)
                    int handleAddress;
                    if (!Int32.TryParse(stVarBase, out handleAddress))
                    {
                        throw new MDbgException("Couldn't recognize the argument as a variable name or address");
                    }
                    add = new IntPtr(handleAddress);
                }
            }

            CorReferenceValue result;

            try
            {
                result = this.CorProcess.GetReferenceValueFromGCHandle(add);
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                if (e.ErrorCode == (int)HResult.CORDBG_E_BAD_REFERENCE_VALUE)
                {
                    throw new MDbgException("Invalid handle address.");
                }
                else
                {
                    throw;
                }
            }
            MDbgValue var = new MDbgValue(this, stName, result);
            return var;
        }
Exemple #21
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();
        }
        //-----------------------------------------------------------------------------
        // 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 + "')");

            }
        }
Exemple #23
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;
            }
Exemple #24
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());
        }
Exemple #25
0
        //////////////////////////////////////////////////////////////////////////////////
        //
        //  Support for printing local printing variables
        //
        //////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Gets an Array of MDbgValues for the Active Local Vars in the given frame.
        /// </summary>
        /// <param name="managedFrame">The Frame to look in.</param>
        /// <returns>The MDbgValue[] Active Local Valiables.</returns>
        public MDbgValue[] GetActiveLocalVars(MDbgFrame managedFrame)
        {
            Debug.Assert(managedFrame != null);
            if (managedFrame == null)
                throw new ArgumentException();

            CorFrame frame = managedFrame.CorFrame;

            // we only support this, when the frame is our function
            Debug.Assert(frame.FunctionToken == m_function.Token);
            if (!(frame.FunctionToken == m_function.Token))
                throw new ArgumentException();

            EnsureIsUpToDate();

            if (!m_haveSymbols)
            {
                // if we don't have symbols -- we'll print local variables as (loca1_0,local_1,local_2,...)
                // to give them names consistent with ILasm.
                int c = frame.GetLocalVariablesCount();
                if (c < 0)
                    c = 0;                                    // in case we cannot get locals,
                // we'll hide them.
                MDbgValue[] locals = new MDbgValue[c];
                for (int i = 0; i < c; ++i)
                {
                    CorValue arg = null;
                    try
                    {
                        arg = frame.GetLocalVariable(i);
                    }
                    catch (System.Runtime.InteropServices.COMException e)
                    {
                        if (e.ErrorCode != (int)Microsoft.Samples.Debugging.CorDebug.HResult.CORDBG_E_IL_VAR_NOT_AVAILABLE)
                            throw;
                    }
                    locals[i] = new MDbgValue(m_module.Process, "local_" + (i), arg);
                }
                return locals;
            }

            uint ip;
            CorDebugMappingResult mappingResult;
            frame.GetIP(out ip, out mappingResult);

            ArrayList al = new ArrayList();
            ISymbolScope scope = SymMethod.RootScope;
            AddLocalVariablesToList(frame, (int)ip, al, scope);

            return (MDbgValue[])al.ToArray(typeof(MDbgValue));
        }
Exemple #26
0
        /// <summary>
        /// Resolves a Variable name in a given scope.
        /// </summary>
        /// <param name="variableName">The name of the variable to resolve.</param>
        /// <param name="scope">The MDbgFrame to look in for that variable.</param>
        /// <returns>The MDbgValue that the given variable has in the given scope.</returns>
        public MDbgValue ResolveVariable(string variableName, MDbgFrame scope)
        {
            Debug.Assert(variableName != null);
            Debug.Assert(scope != null);

            // variableName should have this form:
            // [[module][#<appdomain>]!][(([namespace.]+)<type.>)|.]variable([.field]*)

            // Syntax in BNF form:
            //
            // Expr --> module_scope '!' var_expr
            //         | var_expr
            // module_scope --> <module name>  // as determined by Modules.Lookup
            // var_expr --> var_root
            //            | var_expr '.' <id:field>
            //            | var_expr '[' <integer> ']'
            // var_root --> psuedo_var | local_var | parameter_var | global_var | static_class_var\
            //            | 'gchandle(' ... ')' // see ParseGCHandleArgs
            // psuedo_var --> '$' <id>   // as determined by DebuggerVars.HaveVariable
            // local_var --> <id> // as determined by f.GetActiveLocalVars
            // parameter_var --> <id> // as determined by f.GetArguments
            // global_var --> <id> // as determined by fields on global token in each module
            // static_class_var --> (<id:namespace> '.')* <id:class> '.' <id:static field>

            MDbgModule variableModule;          // name of the module we should look into for variable resolution
            // will contain null, if no module was specified
            { // limit scope of moduleVar
                string[] moduleVar = variableName.Split(new char[] { '!' }, 2);
                Debug.Assert(moduleVar != null);
                if (moduleVar.Length > 2)
                {
                    throw new MDbgException("Illegal variable syntax.");
                }
                else if (moduleVar.Length == 2)
                {
                    variableModule = Modules.Lookup(moduleVar[0]);
                    variableName = moduleVar[1];
                    if (variableModule == null)
                        throw new MDbgException("Module not found");
                }
                else
                    variableModule = null;
            }

            // lookup 1st part
            MDbgValue var = null;
            int nextPart = 0;

            // Check for predicates
            if (variableName.StartsWith("gchandle("))
            {
                string stName;
                string[] args;
                GetExpressionFunctionArgs(ref variableName, out stName, out args);
                nextPart = 1;

                var = this.ParseGCHandleArgs(stName, args, scope);
            } // end gchandle

            string[] nameParts = variableName.Split(new char[] { '.', '[' });

            Debug.Assert(nameParts.Length >= 1);  // there must be at least one part.

            if (var != null)
            {
                // already resolved, no extra work to do.
            }

            // Let's check if we are asking for debugger var. Those vars are prefixed with $.
            // if yes, return the var.
            else if (variableName.StartsWith("$")
               && variableModule == null          // debugger vars cannot have module specifier
               )
            {
                string varName = nameParts[nextPart];
                Debug.Assert(varName.StartsWith("$"));

                if (DebuggerVars.HaveVariable(nameParts[nextPart]))
                {
                    MDbgDebuggerVar dv = DebuggerVars[nameParts[0]];
                    var = new MDbgValue(this, dv.Name, dv.CorValue);
                }
                else
                    var = null;
                nextPart++;
            }
            else
            {
                ArrayList vars = new ArrayList();
                {  // fill up vars with locals+arguments
                    MDbgFunction f = scope.Function;
                    MDbgValue[] vals = f.GetActiveLocalVars(scope);
                    if (vals != null)
                        vars.AddRange(vals);

                    vals = f.GetArguments(scope);
                    if (vals != null)
                        vars.AddRange(vals);
                }

                // try to find a match in locals and arguments first
                foreach (MDbgValue v in vars)
                    if (v.Name == nameParts[nextPart])
                    {
                        var = v;
                        nextPart++;
                        break;
                    }

                // if no match for locals and arguments, look for globals and static class members
                if (var == null)
                {
                    // now let's try to resolve static var of form Namespace.namespace.typeName.var
                    bool bGlobal = (nameParts[nextPart].Length == 0);
                    if (bGlobal)
                        nextPart++;

                    foreach (MDbgModule m in this.Modules)
                    {
                        if (variableModule != null
                           && variableModule != m)
                            continue;                       // we're interested only in certain module

                        if (bGlobal)    // global variables
                        {
                            // nil type token is used to enum global static data members
                            MetadataType gType = (MetadataType)m.Importer.GetType(0);
                            FieldInfo[] gField = gType.GetFields(0);

                            for (int i = 0; i < gField.Length; i++)
                            {
                                if (nameParts[nextPart] == gField[i].Name)
                                {
                                    var = new MDbgValue(this, "." + gField[i].Name, scope.Function.Module.CorModule.GetGlobalVariableValue(gField[i].MetadataToken));
                                    nextPart++;
                                    break;
                                }
                            }

                            if (var != null)    // done if we find the first match in any module
                                break;
                        }
                        else    // static class members
                        {
                            System.Text.StringBuilder sb = new System.Text.StringBuilder();
                            sb.Append(nameParts[nextPart]);
                            for (int i = nextPart + 1; i < nameParts.Length; i++)
                            {
                                int typeToken = m.Importer.GetTypeTokenFromName(sb.ToString());
                                if (typeToken != CorMetadataImport.TokenNotFound)
                                {
                                    // we resolved type, let's try to get statics
                                    CorClass cl = m.CorModule.GetClassFromToken(typeToken);

                                    Type classType = m.Importer.GetType(cl.Token);
                                    foreach (MetadataFieldInfo fi in classType.GetFields())
                                    {
                                        if (fi.Name != nameParts[i])
                                            continue;

                                        if (fi.IsStatic)
                                        {
                                            sb.Append(".").Append(nameParts[i]);
                                            CorValue fieldValue = cl.GetStaticFieldValue(fi.MetadataToken, scope.CorFrame);
                                            var = new MDbgValue(this, sb.ToString(), fieldValue);
                                            nextPart = i + 1;
                                            goto FieldValueFound;   // done if we find the first match in any module
                                        }
                                    }
                                }
                                sb.Append(".").Append(nameParts[i]);
                            }
                        }
                    }
                FieldValueFound:
                    ;
                }
            };

            if (var != null)
            {
                // now try to resolve remaining parts.
                for (int i = nextPart; i < nameParts.Length; i++)
                {
                    string part = nameParts[i];
                    if (part.EndsWith("]"))
                    {
                        // it is probably array index
                        string[] indexStrings = part.Substring(0, part.Length - 1).Split(',');
                        Debug.Assert(indexStrings != null && indexStrings.Length > 0);
                        int[] indexes = new int[indexStrings.Length];
                        for (int j = 0; j < indexStrings.Length; ++j)
                            indexes[j] = Int32.Parse(indexStrings[j], CultureInfo.InvariantCulture);
                        var = var.GetArrayItem(indexes);
                    }
                    else
                    {
                        // we'll treat it as field name
                        var = var.GetField(part);
                    }
                }
            }
            return var;
        }