/// <summary> /// Recursively dereference the input value until we finally find a non-dereferenceable /// value. Along the way, optionally build up a "ptr string" that shows the addresses /// we dereference, separated by "->". /// </summary> /// <param name="value">Value to dereference</param> /// <param name="ptrStringBuilder">StringBuilder if caller wants us to generate /// a "ptr string" (in which case we'll stick it there). If caller doesn't want /// a ptr string, this can be null</param> /// <returns>CorValue we arrive at after dereferencing as many times as we can</returns> private CorValue Dereference(CorValue value, StringBuilder ptrStringBuilder) { while (true) { CorReferenceValue rv = value.CastToReferenceValue(); if (rv == null) { break; // not a reference } if (ptrStringBuilder != null) { if (ptrStringBuilder.Length > 0) { ptrStringBuilder.Append("->"); } ptrStringBuilder.Append("0x" + rv.Value.ToString("X", System.Globalization.CultureInfo.CurrentUICulture)); } // Bail as soon as we hit a reference to NULL if (rv.IsNull) { return(null); // reference to null } CorValue newValue = null; try { newValue = rv.Dereference(); } catch (COMException ce) { // Check for any errors that are expected if (ce.ErrorCode != (int)HResult.CORDBG_E_VALUE_POINTS_TO_FUNCTION) { throw; // some other error } } if (newValue == null) { break; // couldn't dereference the reference (eg. void*) } value = newValue; } return(value); }
internal CorHandleValue GetHandle(CorValue val) { CorHandleValue handleVal = null; if (!handles.TryGetValue(val.Address, out handleVal)) { handleVal = val.CastToHandleValue(); if (handleVal == null) { // Create a handle CorReferenceValue refVal = val.CastToReferenceValue(); CorHeapValue heapVal = refVal.Dereference().CastToHeapValue(); handleVal = heapVal.CreateHandle(CorDebugHandleType.HANDLE_STRONG); } handles.Add(val.Address, handleVal); } return(handleVal); }
private CorValue Dereference(CorValue value) { while (true) { CorReferenceValue rv = value.CastToReferenceValue(); if (rv == null) { break; // not a reference } if (rv.IsNull) { return(null); // reference to null } CorValue newValue = rv.Dereference(); if (newValue == null) { break; // couldn't dereference the reference (eg. void*) } value = newValue; } return(value); }
private string MakePtrString(CorValue value) { StringBuilder sb = new StringBuilder(); while (true) { CorReferenceValue rv = value.CastToReferenceValue(); if (rv == null) { break; // not a reference } if (sb.Length > 0) { sb.Append("->"); } sb.Append("0x" + rv.Value.ToString("X", System.Globalization.CultureInfo.CurrentUICulture)); CorValue newValue = null; try { newValue = rv.Dereference(); } catch (COMException ce) { if (ce.ErrorCode != (int)HResult.CORDBG_E_BAD_REFERENCE_VALUE) { throw; // some other error } } if (newValue == null) { break; // couldn't dereference the reference (eg. void* or invalid ref) } value = newValue; } return(sb.ToString()); }
public static CorValue GetRealObject(EvaluationContext ctx, CorValue obj) { CorEvaluationContext cctx = (CorEvaluationContext)ctx; if (obj == null) { return(null); } try { if (obj is CorStringValue) { return(obj); } if (obj is CorGenericValue) { return(obj); } if (obj is CorGenericValue) { return(obj); } if (obj is CorArrayValue) { return(obj); } CorArrayValue arrayVal = obj.CastToArrayValue(); if (arrayVal != null) { return(arrayVal); } CorReferenceValue refVal = obj.CastToReferenceValue(); if (refVal != null) { if (refVal.IsNull) { return(refVal); } else { cctx.Session.WaitUntilStopped(); return(GetRealObject(cctx, refVal.Dereference())); } } cctx.Session.WaitUntilStopped(); CorBoxValue boxVal = obj.CastToBoxValue(); if (boxVal != null) { return(Unbox(ctx, boxVal)); } if (obj.ExactType.Type == CorElementType.ELEMENT_TYPE_STRING) { return(obj.CastToStringValue()); } if (CorMetadataImport.CoreTypes.ContainsKey(obj.Type)) { CorGenericValue genVal = obj.CastToGenericValue(); if (genVal != null) { return(genVal); } } if (!(obj is CorObjectValue)) { return(obj.CastToObjectValue()); } } catch { // Ignore throw; } return(obj); }
private string InternalGetValue(int indentLevel, int expandDepth, bool canDoFunceval) { Debug.Assert(expandDepth >= 0); CorValue value = this.CorValue; if (value == null) { return("<N/A>"); } // Record the memory addresses if displaying them is enabled string prefix = String.Empty; StringBuilder ptrStrBuilder = null; if (m_process.m_engine.Options.ShowAddresses) { ptrStrBuilder = new StringBuilder(); } try { value = Dereference(value, ptrStrBuilder); } catch (COMException ce) { if (ce.ErrorCode == (int)HResult.CORDBG_E_BAD_REFERENCE_VALUE) { return(MakePrefixFromPtrStringBuilder(ptrStrBuilder) + "<invalid reference value>"); } throw; } prefix = MakePrefixFromPtrStringBuilder(ptrStrBuilder); if (value == null) { return(prefix + "<null>"); } Unbox(ref value); switch (value.Type) { case CorElementType.ELEMENT_TYPE_BOOLEAN: case CorElementType.ELEMENT_TYPE_I1: case CorElementType.ELEMENT_TYPE_U1: case CorElementType.ELEMENT_TYPE_I2: case CorElementType.ELEMENT_TYPE_U2: case CorElementType.ELEMENT_TYPE_I4: case CorElementType.ELEMENT_TYPE_U4: case CorElementType.ELEMENT_TYPE_I: case CorElementType.ELEMENT_TYPE_U: case CorElementType.ELEMENT_TYPE_I8: case CorElementType.ELEMENT_TYPE_U8: case CorElementType.ELEMENT_TYPE_R4: case CorElementType.ELEMENT_TYPE_R8: case CorElementType.ELEMENT_TYPE_CHAR: { object v = value.CastToGenericValue().GetValue(); string result; IFormattable vFormattable = v as IFormattable; if (vFormattable != null) { result = vFormattable.ToString(null, System.Globalization.CultureInfo.CurrentUICulture); } else { result = v.ToString(); } // let's put quotes around char values if (value.Type == CorElementType.ELEMENT_TYPE_CHAR) { result = "'" + result + "'"; } return(prefix + result); } case CorElementType.ELEMENT_TYPE_CLASS: case CorElementType.ELEMENT_TYPE_VALUETYPE: CorObjectValue ov = value.CastToObjectValue(); return(prefix + PrintObject(indentLevel, ov, expandDepth, canDoFunceval)); case CorElementType.ELEMENT_TYPE_STRING: CorStringValue sv = value.CastToStringValue(); return(prefix + '"' + sv.String + '"'); case CorElementType.ELEMENT_TYPE_SZARRAY: case CorElementType.ELEMENT_TYPE_ARRAY: CorArrayValue av = value.CastToArrayValue(); return(prefix + PrintArray(indentLevel, av, expandDepth, canDoFunceval)); case CorElementType.ELEMENT_TYPE_PTR: return(prefix + "<non-null pointer>"); case CorElementType.ELEMENT_TYPE_FNPTR: return(prefix + "0x" + value.CastToReferenceValue().Value.ToString("X")); case CorElementType.ELEMENT_TYPE_BYREF: case CorElementType.ELEMENT_TYPE_TYPEDBYREF: case CorElementType.ELEMENT_TYPE_OBJECT: default: return(prefix + "<printing value of type: " + value.Type + " not implemented>"); } }
public CorValue VariableExpressionInvoke(ExpressionParsingResult info) { //based on MdbgCommands.SetCmd(string arguments) if (info.Instance == null) { throw new Exception("Cannot resolve variable "); } if (info.Arguments == null || !info.Arguments.Any()) { throw new Exception("Cannot resolve arguments "); } // Arguments has to be in the form of variable=varName, variable=value or variable=(<type>)value, // where we use the ldasm naming convention (e.g. "int", "sbyte", "ushort", etc...) for <type>. // Example inputs: var=myInt, var=45, var=(long)45 MDbgValue lsMVar = new MDbgValue(process, info.Instance); CorValue val = info.Arguments.First(); CorGenericValue valGeneric = val as CorGenericValue; bool bIsReferenceValue = val is CorReferenceValue; if (lsMVar != null) { if (valGeneric != null) { CorValue lsVar = lsMVar.CorValue; if (lsVar == null) { throw new Exception("cannot set constant values to unavailable variables"); } // val is a primitive value CorGenericValue lsGenVal = lsVar.CastToGenericValue(); if (lsGenVal == null) { throw new Exception("cannot set constant values to non-primitive values"); } try { // We want to allow some type coercion. Eg, casting between integer precisions. lsMVar.Value = val; // This may do type coercion } catch (MDbgValueWrongTypeException) { throw new Exception(String.Format("Type mismatch. Can't convert from {0} to {1}", val.Type, lsGenVal.Type)); } } else if (bIsReferenceValue) { //reget variable lsMVar = process.ResolveVariable(info.Member, process.Threads.Active.CurrentFrame); lsMVar.Value = val; } else { if (val.CastToHeapValue() != null) { throw new Exception("Heap values should be assigned only to debugger variables"); } if (val.CastToGenericValue() != null) { lsMVar.Value = val.CastToGenericValue(); } else { lsMVar.Value = val.CastToReferenceValue(); } } } // as a last thing we do is to return new value of the variable lsMVar = process.ResolveVariable(info.Member, process.Threads.Active.CurrentFrame); return(lsMVar.CorValue); }
private string InternalGetValue(int indentLevel, int expandDepth, bool canDoFunceval, string variableName, Dictionary <string, int> variablesToLog) { Debug.Assert(expandDepth >= 0); CorValue value = this.CorValue; if (value == null) { return("<N/A>"); } // Record the memory addresses if displaying them is enabled string prefix = String.Empty; StringBuilder ptrStrBuilder = null; if (m_process.m_engine.Options.ShowAddresses) { ptrStrBuilder = new StringBuilder(); } try { value = Dereference(value, ptrStrBuilder); } catch (COMException ce) { if (ce.ErrorCode == (int)HResult.CORDBG_E_BAD_REFERENCE_VALUE) { return(MakePrefixFromPtrStringBuilder(ptrStrBuilder) + "<invalid reference value>"); } throw; } prefix = MakePrefixFromPtrStringBuilder(ptrStrBuilder); if (value == null) { return(prefix + "<null>"); } Unbox(ref value); switch (value.Type) { case CorElementType.ELEMENT_TYPE_BOOLEAN: case CorElementType.ELEMENT_TYPE_I1: case CorElementType.ELEMENT_TYPE_U1: case CorElementType.ELEMENT_TYPE_I2: case CorElementType.ELEMENT_TYPE_U2: case CorElementType.ELEMENT_TYPE_I4: case CorElementType.ELEMENT_TYPE_U4: case CorElementType.ELEMENT_TYPE_I: case CorElementType.ELEMENT_TYPE_U: case CorElementType.ELEMENT_TYPE_I8: case CorElementType.ELEMENT_TYPE_U8: case CorElementType.ELEMENT_TYPE_R4: case CorElementType.ELEMENT_TYPE_R8: case CorElementType.ELEMENT_TYPE_CHAR: { if (variablesToLog == null) { } else if (!variablesToLog.Any(variable => variable.Key == variableName)) { return("[SKIP]"); } object v = value.CastToGenericValue().GetValue(); string result; IFormattable vFormattable = v as IFormattable; if (vFormattable != null) { result = vFormattable.ToString(null, System.Globalization.CultureInfo.CurrentUICulture); } else { result = v.ToString(); } // let's put quotes around char values if (value.Type == CorElementType.ELEMENT_TYPE_CHAR) { result = "'" + result + "'"; } return(Loger.WriteThisToLog(variableName, prefix + result)); } case CorElementType.ELEMENT_TYPE_CLASS: case CorElementType.ELEMENT_TYPE_VALUETYPE: CorObjectValue ov = value.CastToObjectValue(); var objectString = PrintObject(indentLevel, ov, expandDepth, canDoFunceval, variableName, variablesToLog); string objectPrint; if (objectString == "[SKIP]") { objectPrint = "[SKIP]"; } else { objectPrint = prefix + objectString; Loger.WriteThisToLog(variableName, objectPrint.Substring(0, objectPrint.IndexOf('\n') > -1 ? objectPrint.IndexOf('\n') : objectPrint.Length)); } return(objectPrint); case CorElementType.ELEMENT_TYPE_STRING: if (variablesToLog == null) { } else if (!variablesToLog.Any(variable => variable.Key == variableName)) { return("[SKIP]"); } CorStringValue sv = value.CastToStringValue(); return(Loger.WriteThisToLog(variableName, $"{prefix}\"{sv.String}\"")); case CorElementType.ELEMENT_TYPE_SZARRAY: case CorElementType.ELEMENT_TYPE_ARRAY: CorArrayValue av = value.CastToArrayValue(); var arrayString = PrintArray(indentLevel, av, expandDepth, canDoFunceval, variableName, variablesToLog); string arrayPrint; if (arrayString == "[SKIP]") { arrayPrint = "[SKIP]"; } else { arrayPrint = prefix + arrayString; Loger.WriteThisToLog(variableName, arrayPrint.Substring(0, arrayPrint.IndexOf('\n') > -1 ? arrayPrint.IndexOf('\n') : arrayPrint.Length)); } return(arrayPrint); case CorElementType.ELEMENT_TYPE_PTR: return(Loger.WriteThisToLog(variableName, prefix + "<non-null pointer>"));; case CorElementType.ELEMENT_TYPE_FNPTR: return(Loger.WriteThisToLog(variableName, prefix + "0x" + value.CastToReferenceValue().Value.ToString("X"))); case CorElementType.ELEMENT_TYPE_BYREF: case CorElementType.ELEMENT_TYPE_TYPEDBYREF: case CorElementType.ELEMENT_TYPE_OBJECT: default: return(Loger.WriteThisToLog(variableName, prefix + "<printing value of type: " + value.Type + " not implemented>")); } }
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); } }