private string PrintArray(int indentLevel, CorDebug.CorArrayValue av, int expandDepth, bool canDoFunceval) { Debug.Assert(expandDepth >= 0); var 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++) { // Arrays not starting with 0 are not implemented var 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()); }
public O2MDbgVariable(MDbgValue mdbgValue, string _parentType, string _assemblyName) { IsProperty = false; parentType = _parentType; assemblyName = _assemblyName; name = mdbgValue.Name; try { value = mdbgValue.GetStringValue(false); } catch (Exception ex) { DI.log.ex(ex, "in O2MDbgVariable(MDbgValue mdbgValue), while trying to get value for: " + mdbgValue.Name); } type = mdbgValue.TypeName; complexType = mdbgValue.IsComplexType; }
private string PrintArray(int indentLevel, CorDebug.CorArrayValue av, int expandDepth, bool canDoFunceval) { Debug.Assert(expandDepth >= 0); var 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++) { // Arrays not starting with 0 are not implemented var 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(); }
private string PrintObject(int indentLevel, CorDebug.CorObjectValue ov, int expandDepth, bool canDoFunceval) { Debug.Assert(expandDepth >= 0); // Print generics-aware type. string name = InternalUtil.PrintCorType(m_process, ov.ExactType); var txt = new StringBuilder(); txt.Append(name); if (expandDepth > 0) { // we gather the field info of the class before we do // funceval since funceval requires running the debugger process // and this in turn can cause GC and invalidate our references. var expandedDescription = new StringBuilder(); if (IsComplexType) { foreach (MDbgValue v in GetFields()) { expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)). Append("=").Append(IndentedBlock(indentLevel + 2, v.GetStringValue(expandDepth - 1, false))); } } if (ov.IsValueClass && canDoFunceval) // we could display even values for real Objects, but we will just show // "description" for valueclasses. { CorDebug.CorClass cls = ov.ExactType.Class; CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer; var mdType = importer.GetType(cls.Token) as MetadataType; if (mdType.ReallyIsEnum) { txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType)); } else if (m_process.IsRunning) txt.Append(" <N/A during run>"); else { MDbgThread activeThread = m_process.Threads.Active; CorDebug.CorValue thisValue; CorDebug.CorHeapValue hv = ov.CastToHeapValue(); if (hv != null) { // we need to pass reference value. CorDebug.CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION); thisValue = handle; } else thisValue = ov; try { CorDebug.CorEval eval = m_process.Threads.Active.CorThread.CreateEval(); m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND, activeThread.CorThread); MDbgFunction toStringFunc = m_process.ResolveFunctionName(null, "System.Object", "ToString" , thisValue.ExactType.Class.Module.Assembly.AppDomain); Debug.Assert(toStringFunc != null); // we should be always able to resolve ToString function. eval.CallFunction(toStringFunc.CorFunction, new[] {thisValue}); m_process.Go(); do { m_process.StopEvent.WaitOne(); if (m_process.StopReason is EvalCompleteStopReason) { CorDebug.CorValue cv = eval.Result; Debug.Assert(cv != null); var mv = new MDbgValue(m_process, cv); string valName = mv.GetStringValue(0); // just purely for esthetical reasons we 'discard' " if (valName.StartsWith("\"") && valName.EndsWith("\"")) valName = valName.Substring(1, valName.Length - 2); txt.Append(" <").Append(valName).Append(">"); break; } if ((m_process.StopReason is ProcessExitedStopReason) || (m_process.StopReason is EvalExceptionStopReason)) { txt.Append(" <N/A cannot evaluate>"); break; } // hitting bp or whatever should not matter -- we need to ignore it m_process.Go(); } while (true); } catch (COMException e) { // Ignore canot copy a VC class error - Can't copy a VC with object refs in it. if (e.ErrorCode != (int) CorDebug.HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS) throw; } finally { // we need to resume all the threads that we have suspended no matter what. m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN, activeThread.CorThread); } } } txt.Append(expandedDescription.ToString()); } return txt.ToString(); }
private string PrintObject(int indentLevel, CorDebug.CorObjectValue ov, int expandDepth, bool canDoFunceval) { Debug.Assert(expandDepth >= 0); // Print generics-aware type. string name = InternalUtil.PrintCorType(m_process, ov.ExactType); var txt = new StringBuilder(); txt.Append(name); if (expandDepth > 0) { // we gather the field info of the class before we do // funceval since funceval requires running the debugger process // and this in turn can cause GC and invalidate our references. var expandedDescription = new StringBuilder(); if (IsComplexType) { foreach (MDbgValue v in GetFields()) { expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)). Append("=").Append(IndentedBlock(indentLevel + 2, v.GetStringValue(expandDepth - 1, false))); } } if (ov.IsValueClass && canDoFunceval) // we could display even values for real Objects, but we will just show // "description" for valueclasses. { CorDebug.CorClass cls = ov.ExactType.Class; CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer; var mdType = importer.GetType(cls.Token) as MetadataType; if (mdType.ReallyIsEnum) { txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType)); } else if (m_process.IsRunning) { txt.Append(" <N/A during run>"); } else { MDbgThread activeThread = m_process.Threads.Active; CorDebug.CorValue thisValue; CorDebug.CorHeapValue hv = ov.CastToHeapValue(); if (hv != null) { // we need to pass reference value. CorDebug.CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION); thisValue = handle; } else { thisValue = ov; } try { CorDebug.CorEval eval = m_process.Threads.Active.CorThread.CreateEval(); m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND, activeThread.CorThread); MDbgFunction toStringFunc = m_process.ResolveFunctionName(null, "System.Object", "ToString" , thisValue.ExactType.Class.Module.Assembly.AppDomain); Debug.Assert(toStringFunc != null); // we should be always able to resolve ToString function. eval.CallFunction(toStringFunc.CorFunction, new[] { thisValue }); m_process.Go(); do { m_process.StopEvent.WaitOne(); if (m_process.StopReason is EvalCompleteStopReason) { CorDebug.CorValue cv = eval.Result; Debug.Assert(cv != null); var mv = new MDbgValue(m_process, cv); string valName = mv.GetStringValue(0); // just purely for esthetical reasons we 'discard' " if (valName.StartsWith("\"") && valName.EndsWith("\"")) { valName = valName.Substring(1, valName.Length - 2); } txt.Append(" <").Append(valName).Append(">"); break; } if ((m_process.StopReason is ProcessExitedStopReason) || (m_process.StopReason is EvalExceptionStopReason)) { txt.Append(" <N/A cannot evaluate>"); break; } // hitting bp or whatever should not matter -- we need to ignore it m_process.Go(); } while (true); } catch (COMException e) { // Ignore canot copy a VC class error - Can't copy a VC with object refs in it. if (e.ErrorCode != (int)CorDebug.HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS) { throw; } } finally { // we need to resume all the threads that we have suspended no matter what. m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN, activeThread.CorThread); } } } txt.Append(expandedDescription.ToString()); } return(txt.ToString()); }
public static void PrintCmd(string arguments, O2Thread.FuncVoidT1<string> o2Callback) { const string debuggerVarsOpt = "d"; const string noFuncevalOpt = "nf"; const string expandDepthOpt = "r"; var 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 = CommandBase.Debugger.Processes.Active.Threads.Active.CurrentFrame; if (ap.OptionPassed(debuggerVarsOpt)) { // let's print all debugger variables MDbgProcess p = CommandBase.Debugger.Processes.Active; foreach (MDbgDebuggerVar dv in p.DebuggerVars) { var v = new MDbgValue(p, dv.CorValue); CommandBase.WriteOutput(dv.Name + "=" + v.GetStringValue(expandDepth == null ? 0 : (int) expandDepth, canDoFunceval)); } } else { if (ap.Count == 0) { // get all active variables MDbgFunction f = frame.Function; var 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) { CommandBase.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 = CommandBase.Debugger.Processes.Active.ResolveVariable(ap.AsString(j), frame); if (var != null) { CommandBase.WriteOutput(ap.AsString(j) + "=" + var.GetStringValue(expandDepth == null ? 1 : (int) expandDepth, canDoFunceval)); } else { throw new MDbgShellException("Variable not found"); } } } } }
public static void FuncEvalCmd(string arguments, IMDbgShell Shell, O2Thread.FuncVoidT1<string> execOnEval) { try { var activeProcess = DI.o2MDbg.ActiveProcess; //Debugger.Processes.Active const string appDomainOption = "ad"; var 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 = activeProcess.AppDomains[ap.GetOption(appDomainOption).AsInt]; if (ad == null) { throw new ArgumentException("Invalid Appdomain Number"); } appDomain = ad.CorAppDomain; } else { appDomain = activeProcess.Threads.Active.CorThread.AppDomain; } MDbgFunction func = activeProcess.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 = activeProcess.Threads.Active.CorThread.CreateEval(); // Get Variables var vars = new ArrayList(); String arg; for (int i = 1; i < ap.Count; i++) { arg = ap.AsString(i); CorValue v = Shell.ExpressionParser.ParseExpression2(arg, activeProcess, activeProcess.Threads.Active. CurrentFrame); if (v == null) { throw new MDbgShellException("Cannot resolve expression or variable " + ap.AsString(i)); } if (v is CorGenericValue) { vars.Add(v); } 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))); activeProcess.Go().WaitOne(); // now display result of the funceval if (!(activeProcess.StopReason is EvalCompleteStopReason)) { // we could have received also EvalExceptionStopReason but it's derived from EvalCompleteStopReason Shell.IO.WriteOutput(MDbgOutputConstants.StdOutput, "Func-eval not fully completed and debuggee has stopped"); Shell.IO.WriteOutput(MDbgOutputConstants.StdOutput, "Result of funceval won't be printed when finished."); } else { eval = (activeProcess.StopReason as EvalCompleteStopReason).Eval; Debug.Assert(eval != null); CorValue cv = eval.Result; if (cv != null) { var mv = new MDbgValue(activeProcess, cv); if (execOnEval != null) // if this callback is set then execute { execOnEval(mv.GetStringValue(1)); return; } Shell.IO.WriteOutput(MDbgOutputConstants.StdOutput, "result = " + mv.GetStringValue(1)); if (cv.CastToReferenceValue() != null) if (activeProcess.DebuggerVars.SetEvalResult(cv)) Shell.IO.WriteOutput(MDbgOutputConstants.StdOutput, "results saved to $result"); } } } catch (Exception ex) { DI.log.ex(ex, "in FuncEvalCmd"); } if (execOnEval != null) // need to call this here so that the sync AutoResetEvent is set execOnEval(null); }
public static void UnwrapGCHandleCmd(string arguments) { var 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 (FormatException) { WriteError("Couldn't recognize the argument as a variable name or address"); return; } } var add = new IntPtr(handleAdd); CorReferenceValue result; try { result = Debugger.Processes.Active.CorProcess.GetReferenceValueFromGCHandle(add); } catch (COMException e) { if (e.ErrorCode == (int) HResult.CORDBG_E_BAD_REFERENCE_VALUE) { WriteError("Invalid handle address."); return; } else { throw; } } CorValue v = result.Dereference(); var 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()) WriteOutput(" " + f.Name + "=" + f.GetStringValue(0)); } else { WriteOutput(string.Format("GCHandle to {0}", mv.GetStringValue(0))); } }
public static void NewObjCmd(string arguments) { var 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(); var 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(MDbgOutputConstants.StdOutput,"Newobj command not fully completed and debuggee has stopped"); WriteOutput(MDbgOutputConstants.StdOutput,"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) { var mv = new MDbgValue(Debugger.Processes.Active, cv); WriteOutput("result = " + mv.GetStringValue(1)); if (Debugger.Processes.Active.DebuggerVars.SetEvalResult(cv)) WriteOutput(MDbgOutputConstants.StdOutput,"results saved to $result"); } } Shell.DisplayCurrentLocation(); }