static Value GetLiteralValue(DebugFieldInfo fieldInfo) { CorElementType corElemType = (CorElementType)fieldInfo.FieldProps.ConstantType; if (corElemType == CorElementType.CLASS) { // Only null literals are allowed return(Eval.CreateValue(fieldInfo.AppDomain, null)); } else if (corElemType == CorElementType.STRING) { string str = Marshal.PtrToStringUni(fieldInfo.FieldProps.ConstantPtr, (int)fieldInfo.FieldProps.ConstantStringLength); return(Eval.CreateValue(fieldInfo.AppDomain, str)); } else { DebugType type = DebugType.CreateFromType(fieldInfo.AppDomain.Mscorlib, DebugType.CorElementTypeToManagedType(corElemType)); if (fieldInfo.FieldType.IsEnum && fieldInfo.FieldType.GetEnumUnderlyingType() == type) { Value val = Eval.NewObjectNoConstructor((DebugType)fieldInfo.FieldType); Value backingField = val.GetMemberValue("value__"); backingField.CorGenericValue.SetValue(fieldInfo.FieldProps.ConstantPtr); return(val); } else { Value val = Eval.NewObjectNoConstructor(type); val.CorGenericValue.SetValue(fieldInfo.FieldProps.ConstantPtr); return(val); } } }
/// <summary> Synchronously calls a function and returns its return value </summary> public static Value InvokeMethod(MethodInfo method, Value thisValue, Value[] args) { if (method.BackingField != null) { method.Process.TraceMessage("Using backing field for " + method.FullName); return(Value.GetMemberValue(thisValue, method.BackingField, args)); } return(AsyncInvokeMethod(method, thisValue, args).WaitForResult()); }
/// <summary> Synchronously calls a function and returns its return value </summary> public static Value InvokeMethod(Thread evalThread, IMethod method, Value thisValue, Value[] args) { uint fieldToken = method.GetBackingFieldToken(); if (fieldToken != 0) { var field = method.DeclaringType.ImportField(fieldToken); if (field != null) { evalThread.Process.TraceMessage("Using backing field for " + method.FullName); return(Value.GetMemberValue(evalThread, thisValue, field, args)); } } return(AsyncInvokeMethod(evalThread, method, thisValue, args).WaitForResult()); }
/// <summary> Returs formated stacktrace for the exception </summary> /// <exception cref="GetValueException"> Getting the stacktrace involves property /// evaluation so GetValueException can be thrown in some cicumstances. </exception> public string GetStackTrace(string endOfInnerExceptionFormat) { StringBuilder sb = new StringBuilder(); if (this.InnerException != null) { sb.Append(this.InnerException.GetStackTrace(endOfInnerExceptionFormat)); sb.Append(" "); sb.Append(endOfInnerExceptionFormat); sb.AppendLine(); } // Note that evaluation is not possible after a stackoverflow exception Value stackTrace = exception.GetMemberValue("StackTrace"); if (!stackTrace.IsNull) { sb.Append(stackTrace.AsString()); sb.AppendLine(); } return(sb.ToString()); }
/// <summary> /// Formats current Value according to the given format, specified by <see cref="System.Diagnostics.DebuggerDisplayAttribute"/>. /// </summary> /// <param name="debugFormat">Format to use</param> /// <returns>Formatted string.</returns> /// <remarks> /// Not all possible expressions are supported, but only a simple set. /// Otherwise we would have to support any C# expression. /// </remarks> static string FormatDebugValue(Thread evalThread, Value value, string debugFormat) { StringBuilder formattedOutput = new StringBuilder(); StringBuilder currentFieldName = new StringBuilder(); bool insideFieldName = false; bool ignoringRestOfExpression = false; bool insideMethodBrackets = false; bool isMethodName = false; bool escapeNextChar = false; for (int i = 0; i < debugFormat.Length; i++) { char thisChar = debugFormat[i]; if (!escapeNextChar && (thisChar == '{')) { insideFieldName = true; } else if (!escapeNextChar && (thisChar == '}')) { // Insert contents of specified member, if we can find it, otherwise we display "?" string memberValueStr = "?"; // Decide if we want a method or field/property Predicate <IUnresolvedMember> isNeededMember; if (isMethodName) { // We only support methods without parameters here! isNeededMember = m => (m.Name == currentFieldName.ToString()) && (m.SymbolKind == SymbolKind.Method) && (((IUnresolvedMethod)m).Parameters.Count == 0); } else { isNeededMember = m => (m.Name == currentFieldName.ToString()) && ((m.SymbolKind == SymbolKind.Field) || (m.SymbolKind == SymbolKind.Property)); } IMember member = value.type.GetMembers(isNeededMember).FirstOrDefault(); if (member != null) { Value memberValue = value.GetMemberValue(evalThread, member); memberValueStr = memberValue.InvokeToString(evalThread); } formattedOutput.Append(memberValueStr); insideFieldName = false; ignoringRestOfExpression = false; insideMethodBrackets = false; isMethodName = false; currentFieldName.Clear(); } else if (!escapeNextChar && (thisChar == '\\')) { // Next character will be escaped escapeNextChar = true; } else if (insideFieldName && (thisChar == '(')) { insideMethodBrackets = true; } else if ((thisChar == ')') && insideMethodBrackets) { insideMethodBrackets = false; isMethodName = true; // Everything following the brackets will be ignored ignoringRestOfExpression = true; } else if (insideFieldName && !Char.IsDigit(thisChar) && !Char.IsLetter(thisChar)) { // Char seems not to belong to a field name, ignore everything from now on ignoringRestOfExpression = true; } else { if (insideFieldName) { if (!ignoringRestOfExpression) { currentFieldName.Append(thisChar); } } else { formattedOutput.Append(thisChar); } escapeNextChar = false; } } return(formattedOutput.ToString()); }
/// <summary> /// Formats current Value according to the given format, specified by <see cref="System.Diagnostics.DebuggerDisplayAttribute"/>. /// </summary> /// <param name="debugFormat">Format to use</param> /// <returns>Formatted string.</returns> /// <remarks> /// Not all possible expressions are supported, but only a simple set. /// Otherwise we would have to support any C# expression. /// </remarks> static string FormatDebugValue(Thread evalThread, Value value, string debugFormat) { StringBuilder formattedOutput = new StringBuilder(); StringBuilder currentFieldName = new StringBuilder(); bool insideFieldName = false; bool ignoringRestOfExpression = false; bool insideMethodBrackets = false; bool isMethodName = false; bool escapeNextChar = false; for (int i = 0; i < debugFormat.Length; i++) { char thisChar = debugFormat[i]; if (!escapeNextChar && (thisChar == '{')) { insideFieldName = true; } else if (!escapeNextChar && (thisChar == '}')) { // Insert contents of specified member, if we can find it, otherwise we display "?" string memberValueStr = "?"; // Decide if we want a method or field/property Predicate<IUnresolvedMember> isNeededMember; if (isMethodName) { // We only support methods without parameters here! isNeededMember = m => (m.Name == currentFieldName.ToString()) && (m.SymbolKind == SymbolKind.Method) && (((IUnresolvedMethod) m).Parameters.Count == 0); } else { isNeededMember = m => (m.Name == currentFieldName.ToString()) && ((m.SymbolKind == SymbolKind.Field) || (m.SymbolKind == SymbolKind.Property)); } IMember member = value.type.GetMembers(isNeededMember).FirstOrDefault(); if (member != null) { Value memberValue = value.GetMemberValue(evalThread, member); memberValueStr = memberValue.InvokeToString(evalThread); } formattedOutput.Append(memberValueStr); insideFieldName = false; ignoringRestOfExpression = false; insideMethodBrackets = false; isMethodName = false; currentFieldName.Clear(); } else if (!escapeNextChar && (thisChar == '\\')) { // Next character will be escaped escapeNextChar = true; } else if (insideFieldName && (thisChar == '(')) { insideMethodBrackets = true; } else if ((thisChar == ')') && insideMethodBrackets) { insideMethodBrackets = false; isMethodName = true; // Everything following the brackets will be ignored ignoringRestOfExpression = true; } else if (insideFieldName && !Char.IsDigit(thisChar) && !Char.IsLetter(thisChar)) { // Char seems not to belong to a field name, ignore everything from now on ignoringRestOfExpression = true; } else { if (insideFieldName) { if (!ignoringRestOfExpression) currentFieldName.Append(thisChar); } else { formattedOutput.Append(thisChar); } escapeNextChar = false; } } return formattedOutput.ToString(); }
public static string FormatValue(Value val) { if (val == null) { return null; } if (val.IsNull) { return "null"; } else if (val.Type.IsArray) { StringBuilder sb = new StringBuilder(); sb.Append(val.Type.Name); sb.Append(" {"); bool first = true; foreach(Value item in val.GetArrayElements()) { if (!first) sb.Append(", "); first = false; sb.Append(FormatValue(item)); } sb.Append("}"); return sb.ToString(); } else if (val.Type.GetInterface(typeof(ICollection).FullName) != null) { StringBuilder sb = new StringBuilder(); sb.Append(val.Type.Name); sb.Append(" {"); val = val.GetPermanentReference(); int count = (int)val.GetMemberValue("Count").PrimitiveValue; for(int i = 0; i < count; i++) { if (i > 0) sb.Append(", "); DebugPropertyInfo itemProperty = (DebugPropertyInfo)val.Type.GetProperty("Item"); Value item = val.GetPropertyValue(itemProperty, Eval.CreateValue(val.AppDomain, i)); sb.Append(FormatValue(item)); } sb.Append("}"); return sb.ToString(); } else if (val.Type.FullName == typeof(char).FullName) { return "'" + val.PrimitiveValue.ToString() + "'"; } else if (val.Type.FullName == typeof(string).FullName) { return "\"" + val.PrimitiveValue.ToString() + "\""; } else if (val.Type.IsPrimitive) { return val.PrimitiveValue.ToString(); } else { return val.InvokeToString(); } }