// Builds the friendly string for an enum value private string InternalGetEnumString(CorObjectValue ov, MetadataType type) { Debug.Assert(type != null); // Enums should always have a type IList <KeyValuePair <string, ulong> > values = type.EnumValues; // Get the underlying value ulong value = Convert.ToUInt64(ov.CastToGenericValue().UnsafeGetValueAsType(type.EnumUnderlyingType), CultureInfo.InvariantCulture); // Find a reasonable value to display StringBuilder result = new StringBuilder(); ulong remainingValue = value; bool firstTime = true; for (int i = values.Count - 1; i >= 0; i--) { if ((values[i].Value == value) || (type.ReallyIsFlagsEnum && (values[i].Value != 0) && ((values[i].Value & value) == values[i].Value))) { remainingValue &= ~(values[i].Value); // Remove the flags from the total needed for flags enums if (!firstTime) { if (type.ReallyIsFlagsEnum) { result.Insert(0, ", "); } else { result.Insert(0, " / "); } } result.Insert(0, values[i].Key); firstTime = false; } } if (remainingValue != 0) { if (firstTime) { // No matches whatsoever result.Insert(0, remainingValue); } else { // Flags enum with leftover bits result.AppendFormat(" (Unnamed bits: {0})", remainingValue); } } return(result.ToString()); }
static CorValue Unbox(EvaluationContext ctx, CorBoxValue boxVal) { CorObjectValue bval = boxVal.GetObject(); Type ptype = Type.GetType(ctx.Adapter.GetTypeName(ctx, bval.ExactType)); if (ptype != null && ptype.IsPrimitive) { ptype = bval.ExactType.GetTypeInfo(((CorEvaluationContext)ctx).Session); foreach (FieldInfo field in ptype.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (field.Name == "m_value") { CorValue val = bval.GetFieldValue(bval.ExactType.Class, field.MetadataToken); val = GetRealObject(ctx, val); return(val); } } } return(GetRealObject(ctx, bval)); }
public override object TargetObjectToObject(EvaluationContext ctx, object objr) { CorValue obj = GetRealObject(ctx, objr); if ((obj is CorReferenceValue) && ((CorReferenceValue)obj).IsNull) { return(new EvaluationResult("(null)")); } CorStringValue stringVal = obj as CorStringValue; if (stringVal != null) { return(stringVal.String); } CorArrayValue arr = obj as CorArrayValue; if (arr != null) { return(base.TargetObjectToObject(ctx, objr)); } CorEvaluationContext cctx = (CorEvaluationContext)ctx; CorObjectValue co = obj as CorObjectValue; if (co != null) { return(base.TargetObjectToObject(ctx, objr)); } CorGenericValue genVal = obj as CorGenericValue; if (genVal != null) { return(genVal.GetValue()); } return(base.TargetObjectToObject(ctx, objr)); }
string GetThreadName(CorThread thread) { // From http://social.msdn.microsoft.com/Forums/en/netfxtoolsdev/thread/461326fe-88bd-4a6b-82a9-1a66b8e65116 try { CorReferenceValue refVal = thread.ThreadVariable.CastToReferenceValue(); if (refVal.IsNull) { return(string.Empty); } CorObjectValue val = refVal.Dereference().CastToObjectValue(); if (val != null) { Type classType = val.ExactType.GetTypeInfo(this); // Loop through all private instance fields in the thread class foreach (MetadataFieldInfo fi in classType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) { if (fi.Name == "m_Name") { CorReferenceValue fieldValue = val.GetFieldValue(val.Class, fi.MetadataToken).CastToReferenceValue(); if (fieldValue.IsNull) { return(string.Empty); } else { return(fieldValue.Dereference().CastToStringValue().String); } } } } } catch (Exception) { // Ignore } return(string.Empty); }
public override object TryCast(EvaluationContext ctx, object val, object type) { CorType ctype = (CorType)GetValueType(ctx, val); CorValue obj = GetRealObject(ctx, val); string tname = GetTypeName(ctx, type); string ctypeName = GetValueTypeName(ctx, val); if (tname == "System.Object") { return(val); } if (tname == ctypeName) { return(val); } if (obj is CorStringValue) { return(ctypeName == tname ? val : null); } if (obj is CorArrayValue) { return((ctypeName == tname || ctypeName == "System.Array") ? val : null); } if (obj is CorObjectValue) { CorObjectValue co = (CorObjectValue)obj; if (IsEnum(ctx, co.ExactType)) { ValueReference rval = GetMember(ctx, null, val, "value__"); return(TryCast(ctx, rval.Value, type)); } while (ctype != null) { if (GetTypeName(ctx, ctype) == tname) { return(val); } ctype = ctype.Base; } return(null); } CorGenericValue genVal = obj as CorGenericValue; if (genVal != null) { Type t = Type.GetType(tname); if (t != null && t.IsPrimitive && t != typeof(string)) { object pval = genVal.GetValue(); try { pval = System.Convert.ChangeType(pval, t); } catch { return(null); } return(CreateValue(ctx, pval)); } else if (IsEnum(ctx, (CorType)type)) { return(CreateEnum(ctx, (CorType)type, val)); } } return(null); }
public override string CallToString(EvaluationContext ctx, object objr) { CorValue obj = GetRealObject(ctx, objr); if ((obj is CorReferenceValue) && ((CorReferenceValue)obj).IsNull) { return(string.Empty); } CorStringValue stringVal = obj as CorStringValue; if (stringVal != null) { return(stringVal.String); } CorArrayValue arr = obj as CorArrayValue; if (arr != null) { StringBuilder tn = new StringBuilder(GetDisplayTypeName(ctx, arr.ExactType.FirstTypeParameter)); tn.Append("["); int[] dims = arr.GetDimensions(); for (int n = 0; n < dims.Length; n++) { if (n > 0) { tn.Append(','); } tn.Append(dims[n]); } tn.Append("]"); return(tn.ToString()); } CorEvaluationContext cctx = (CorEvaluationContext)ctx; CorObjectValue co = obj as CorObjectValue; if (co != null) { if (IsEnum(ctx, co.ExactType)) { MetadataType rt = co.ExactType.GetTypeInfo(cctx.Session) as MetadataType; bool isFlags = rt != null && rt.ReallyIsFlagsEnum; string enumName = GetTypeName(ctx, co.ExactType); ValueReference val = GetMember(ctx, null, objr, "value__"); ulong nval = (ulong)System.Convert.ChangeType(val.ObjectValue, typeof(ulong)); ulong remainingFlags = nval; string flags = null; foreach (ValueReference evals in GetMembers(ctx, co.ExactType, null, BindingFlags.Public | BindingFlags.Static)) { ulong nev = (ulong)System.Convert.ChangeType(evals.ObjectValue, typeof(ulong)); if (nval == nev) { return(evals.Name); } if (isFlags && nev != 0 && (nval & nev) == nev) { if (flags == null) { flags = enumName + "." + evals.Name; } else { flags += " | " + enumName + "." + evals.Name; } remainingFlags &= ~nev; } } if (isFlags) { if (remainingFlags == nval) { return(nval.ToString()); } if (remainingFlags != 0) { flags += " | " + remainingFlags; } return(flags); } else { return(nval.ToString()); } } CorType targetType = (CorType)GetValueType(ctx, objr); MethodInfo met = OverloadResolve(cctx, "ToString", targetType, new CorType[0], BindingFlags.Public | BindingFlags.Instance, false); if (met != null && met.DeclaringType.FullName != "System.Object") { object[] args = new object[0]; object ores = RuntimeInvoke(ctx, targetType, objr, "ToString", args, args); CorStringValue res = GetRealObject(ctx, ores) as CorStringValue; if (res != null) { return(res.String); } } return(GetDisplayTypeName(ctx, targetType)); } CorGenericValue genVal = obj as CorGenericValue; if (genVal != null) { return(genVal.GetValue().ToString()); } return(base.CallToString(ctx, obj)); }
// Helper to get all the fields, including static fields and base types. private MDbgValue[] InternalGetFields() { List <MDbgValue> al = new List <MDbgValue>(); //dereference && (unbox); CorValue value = Dereference(CorValue, null); if (value == null) { throw new MDbgValueException("null value"); } Unbox(ref value); CorObjectValue ov = value.CastToObjectValue(); CorType cType = ov.ExactType; CorFrame cFrame = null; if (Process.Threads.HaveActive) { // we need a current frame to display thread local static values if (Process.Threads.Active.HaveCurrentFrame) { MDbgFrame temp = Process.Threads.Active.CurrentFrame; while (temp != null && !temp.IsManaged) { temp = temp.NextUp; } if (temp != null) { cFrame = temp.CorFrame; } } } MDbgModule classModule; // initialization CorClass corClass = ov.Class; classModule = Process.Modules.Lookup(corClass.Module); // iteration through class hierarchy while (true) { Type classType = classModule.Importer.GetType(corClass.Token); foreach (MetadataFieldInfo fi in classType.GetFields()) { CorValue fieldValue = null; try { if (fi.IsLiteral) { fieldValue = null; // for now we just hide the constant fields. continue; } else if (fi.IsStatic) { if (cFrame == null) { // Without a frame, we won't be able to find static values. So // just skip this guy continue; } fieldValue = cType.GetStaticFieldValue(fi.MetadataToken, cFrame); } else { // we are asuming normal field value fieldValue = ov.GetFieldValue(corClass, fi.MetadataToken); } } catch (COMException) { // we won't report any problems. } al.Add(new MDbgValue(Process, fi.Name, fieldValue)); } cType = cType.Base; if (cType == null) { break; } corClass = cType.Class; classModule = Process.Modules.Lookup(corClass.Module); } return(al.ToArray()); }
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()); }
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>"); } }
private MDbgValue[] InternalGetFields() { ArrayList al = new ArrayList(); //dereference && (unbox); CorValue value = Dereference(CorValue); if (value == null) { throw new MDbgValueException("null value"); } Unbox(ref value); CorObjectValue ov = value.CastToObjectValue(); CorType cType = ov.ExactType; CorFrame cFrame = null; if (Process.Threads.HaveActive) { // we need a current frame to display thread local static values if (Process.Threads.Active.HaveCurrentFrame) { cFrame = Process.Threads.Active.CurrentFrame.CorFrame; } } MDbgModule classModule; // initialization CorClass corClass = ov.Class; classModule = Process.Modules.Lookup(corClass.Module); // iteration through class hierarchy do { Type classType; //int parentToken; classType = classModule.Importer.GetType(corClass.Token); //classModule.Importer.GetTypeNameFromDef(classToken,out parentToken); foreach (MetadataFieldInfo fi in classType.GetFields()) { CorValue fieldValue = null; try { if (fi.IsLiteral) { fieldValue = null; // for now we just hide the constant fields. continue; } else if (fi.IsStatic) { fieldValue = cType.GetStaticFieldValue(fi.MetadataToken, cFrame); } else // we are asuming normal field value // GetFieldValueForTYpe Supersedes GetFieldValue // Will replace when all issues are resolved. //fieldValue = ov.GetFieldValueForType(cType, (uint)fi.Token); { fieldValue = ov.GetFieldValue(corClass, fi.MetadataToken); } } catch (COMException) { // we won't report any problems. } al.Add(new MDbgValue(Process, fi.Name, fieldValue)); } cType = cType.Base; if (cType == null) { break; } corClass = cType.Class; classModule = Process.Modules.Lookup(corClass.Module); }while (true); return((MDbgValue[])al.ToArray(typeof(MDbgValue))); }
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>")); } }