DbgDotNetValueResult?Box_CorDebug(DbgEvaluationInfo evalInfo) { engine.VerifyCorDebugThread(); evalInfo.CancellationToken.ThrowIfCancellationRequested(); var corValue = TryGetCorValue(); if (corValue == null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } if (!ILDbgEngineStackFrame.TryGetEngineStackFrame(evalInfo.Frame, out var ilFrame)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } // Even if it's boxed, box the unboxed value. This code path should only be called if // the compiler thinks it's an unboxed value, so we must make a new boxed value. if (corValue.IsReference) { corValue = corValue.GetDereferencedValue(out int hr); if (corValue == null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } } if (corValue.IsBox) { corValue = corValue.GetBoxedValue(out int hr); if (corValue == null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } } return(engine.Box_CorDebug(evalInfo, ilFrame.GetCorAppDomain(), corValue, Type)); }
public static DebugViewNoResultsValueNode TryCreate(DbgEvaluationInfo evalInfo, string expression, DbgDotNetValueResult valueResult) { DbgDotNetValueResult getterResult = default; try { if (!valueResult.ValueIsException) { return(null); } var appDomain = valueResult.Value.Type.AppDomain; var emptyProperty = valueResult.Value.Type.GetProperty(EmptyPropertyName, DmdSignatureCallingConvention.HasThis | DmdSignatureCallingConvention.Property, 0, appDomain.System_String, Array.Empty <DmdType>(), throwOnError: false); var emptyGetter = emptyProperty?.GetGetMethod(DmdGetAccessorOptions.All); if ((object)emptyGetter == null) { return(null); } var runtime = evalInfo.Runtime.GetDotNetRuntime(); getterResult = runtime.Call(evalInfo, valueResult.Value, emptyGetter, Array.Empty <object>(), DbgDotNetInvokeOptions.None); if (!getterResult.IsNormalResult) { return(null); } var rawValue = getterResult.Value.GetRawValue(); if (!rawValue.HasRawValue || rawValue.ValueType != DbgSimpleValueType.StringUtf16 || !(rawValue.RawValue is string emptyMessage)) { return(null); } return(new DebugViewNoResultsValueNode(expression, emptyMessage)); } finally { getterResult.Value?.Dispose(); } }
internal DbgDotNetValueResult CreateValue_CorDebug(DbgEvaluationInfo evalInfo, ILDbgEngineStackFrame ilFrame, object?value) { debuggerThread.VerifyAccess(); evalInfo.CancellationToken.ThrowIfCancellationRequested(); if (value is DbgDotNetValueImpl) { return(DbgDotNetValueResult.Create((DbgDotNetValueImpl)value)); } var tmp = CheckFuncEval(evalInfo); if (!(tmp is null)) { return(tmp.Value); } var dnThread = GetThread(evalInfo.Frame.Thread); var createdValues = new List <CorValue>(); CorValue?createdCorValue = null; try { var appDomain = ilFrame.GetCorAppDomain(); var reflectionAppDomain = ilFrame.GetReflectionModule().AppDomain; using (var dnEval = dnDebugger.CreateEval(evalInfo.CancellationToken, suspendOtherThreads: (evalInfo.Context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(evalInfo.Context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, evalInfo); var converter = new EvalArgumentConverter(this, dnEval, appDomain, reflectionAppDomain, createdValues); var evalRes = converter.Convert(value, reflectionAppDomain.System_Object, out var newValueType); if (!(evalRes.ErrorMessage is null)) { return(DbgDotNetValueResult.CreateError(evalRes.ErrorMessage)); } var resultValue = CreateDotNetValue_CorDebug(evalRes.CorValue !, reflectionAppDomain, tryCreateStrongHandle: true); createdCorValue = evalRes.CorValue; return(DbgDotNetValueResult.Create(resultValue)); } } catch (TimeoutException) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } finally { foreach (var v in createdValues) { if (!v.Equals(createdCorValue)) { dnDebugger.DisposeHandle(v); } } } }
bool TryFormatKeyValuePair(DbgDotNetValue value) { var info = KeyValuePairTypeUtils.TryGetFields(value.Type); if ((object)info.keyField == null) { return(false); } var runtime = evalInfo.Runtime.GetDotNetRuntime(); DbgDotNetValueResult keyResult = default, valueResult = default;
/// <summary> /// Gets the builder instance. It's assumed to be stored in a field in the current 'this' instance. /// /// The decompiler should already know the field. If that info isn't available, we'll try to find /// the field by name, and if that fails, by field type. /// /// null is returned if we couldn't find the field or if we failed to read the field. /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="builderFieldModule">Module of builder field or null if unknown</param> /// <param name="builderFieldToken">Token of builder field or 0 if unknown</param> /// <returns></returns> public static DbgDotNetValue?TryGetBuilder(DbgEvaluationInfo evalInfo, DmdModule?builderFieldModule, uint builderFieldToken) { DbgDotNetValueResult thisArg = default; DbgDotNetValueResult tmpResult = default; try { var runtime = evalInfo.Runtime.GetDotNetRuntime(); thisArg = runtime.GetParameterValue(evalInfo, 0); if (!thisArg.IsNormalResult || thisArg.Value !.IsNull) { return(null); } if (thisArg.Value.Type.IsByRef) { tmpResult = thisArg.Value.LoadIndirect(); if (!tmpResult.IsNormalResult || tmpResult.Value !.IsNull) { return(null); } thisArg.Value?.Dispose(); thisArg = tmpResult; tmpResult = default; } DmdFieldInfo?builderField = null; if (builderFieldModule is not null && builderFieldToken != 0) { builderField = thisArg.Value.Type.GetField(builderFieldModule, (int)builderFieldToken); } if (builderField is null) { builderField = TryGetBuilderField(thisArg.Value.Type); } if (builderField is null) { return(null); } Debug.Assert((object)builderField == TryGetBuilderFieldByType(thisArg.Value.Type)); Debug2.Assert(TryGetBuilderFieldByname(thisArg.Value.Type) is null || (object?)TryGetBuilderFieldByname(thisArg.Value.Type) == TryGetBuilderFieldByType(thisArg.Value.Type)); tmpResult = runtime.LoadField(evalInfo, thisArg.Value, builderField); if (!tmpResult.IsNormalResult || tmpResult.Value !.IsNull) { return(null); } var fieldValue = tmpResult.Value; tmpResult = default; return(fieldValue); } finally { thisArg.Value?.Dispose(); tmpResult.Value?.Dispose(); } }
DbgDotNetValueResult GetArrayElementAt_MonoDebug(uint index) { Debug.Assert(Type.IsArray); engine.VerifyMonoDebugThread(); var info = GetArrayElementValueLocation_MonoDebug(index); if (!(info.errorMessage is null)) { return(DbgDotNetValueResult.CreateError(info.errorMessage)); } return(DbgDotNetValueResult.Create(engine.CreateDotNetValue_MonoDebug(info.valueLocation !))); }
public override DbgDotNetValueNode[] GetChildren(LanguageValueNodeFactory valueNodeFactory, DbgEvaluationInfo evalInfo, ulong index, int count, DbgValueNodeEvaluationOptions options, ReadOnlyCollection <string>?formatSpecifiers) { var runtime = evalInfo.Runtime.GetDotNetRuntime(); var res = count == 0 ? Array.Empty <DbgDotNetValueNode>() : new DbgDotNetValueNode[count]; var valueResults = new List <DbgDotNetValueResult>(); DbgDotNetValueResult valueResult = default; try { for (int i = 0; i < res.Length; i++) { evalInfo.CancellationToken.ThrowIfCancellationRequested(); ref readonly var info = ref tupleFields[(int)index + i];
DbgDotNetValue RecordValue(DbgDotNetValueResult result) { if (result.HasError) throw new InterpreterMessageException(result.ErrorMessage); if (result.ValueIsException) throw new InterpreterThrownExceptionException(result.Value); var dnValue = result.Value; if (dnValue == null) throw new InterpreterMessageException(PredefinedEvaluationErrorMessages.InternalDebuggerError); return RecordValue(dnValue); }
DbgDotNetValueResult CreateInstanceCore(DmdConstructorInfo ctor, ILValue[] arguments) { if (ctor.IsStatic) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.InternalDebuggerError)); } const DotNetClassHookCallOptions options = DotNetClassHookCallOptions.None; foreach (var anyHook in anyClassHooks) { var res = anyHook.CreateInstance(options, ctor, arguments); if (res != null) { return(DbgDotNetValueResult.Create(res)); } } var type = ctor.DeclaringType; if (type.IsConstructedGenericType) { type = type.GetGenericTypeDefinition(); } var typeName = DmdTypeName.Create(type); if (classHooks.TryGetValue(typeName, out var hook)) { if (DmdWellKnownTypeUtils.TryGetWellKnownType(typeName, out var wellKnownType)) { if (type != type.AppDomain.GetWellKnownType(wellKnownType, isOptional: true)) { hook = null; } } if (hook != null) { var res = hook.CreateInstance(options, ctor, arguments); if (res != null) { return(DbgDotNetValueResult.Create(res)); } } } if (!canFuncEval) { throw new InterpreterMessageException(PredefinedEvaluationErrorMessages.FuncEvalDisabled); } return(runtime.CreateInstance(evalInfo, ctor, Convert(arguments, ctor.GetMethodSignature().GetParameterTypes()), DbgDotNetInvokeOptions.None)); }
DbgDotNetValueResult Dereference_CorDebug() { Debug.Assert((Type.IsByRef && !IsNullByRef) || (Type.IsPointer && !IsNull)); engine.VerifyCorDebugThread(); int hr = -1; var dereferencedValue = TryGetCorValue()?.GetDereferencedValue(out hr); // We sometimes get 0x80131C49 = CORDBG_E_READVIRTUAL_FAILURE if (dereferencedValue is null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } return(DbgDotNetValueResult.Create(engine.CreateDotNetValue_CorDebug(dereferencedValue, Type.AppDomain, tryCreateStrongHandle: true))); }
// This method calls ICorDebugEval2.NewParameterizedArray() which doesn't support creating SZ arrays // with any element type. See the caller of this method (CreateSZArrayCore) for more info. internal DbgDotNetValueResult CreateSZArray_CorDebug(DbgEvaluationInfo evalInfo, CorAppDomain appDomain, DmdType elementType, int length) { debuggerThread.VerifyAccess(); evalInfo.CancellationToken.ThrowIfCancellationRequested(); var tmp = CheckFuncEval(evalInfo); if (!(tmp is null)) { return(tmp.Value); } var dnThread = GetThread(evalInfo.Frame.Thread); try { using (var dnEval = dnDebugger.CreateEval(evalInfo.CancellationToken, suspendOtherThreads: (evalInfo.Context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(evalInfo.Context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, evalInfo); var corType = GetType(appDomain, elementType); var res = dnEval.CreateSZArray(corType, length, out int hr); if (res is null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } Debug.Assert(!res.Value.WasException, "Shouldn't throw " + nameof(ArgumentOutOfRangeException)); if (res.Value.WasCustomNotification) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.FuncEvalRequiresAllThreadsToRun)); } if (res.Value.WasCancelled) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } if (res.Value.WasException) { return(DbgDotNetValueResult.CreateException(CreateDotNetValue_CorDebug(res.Value.ResultOrException !, elementType.AppDomain, tryCreateStrongHandle: true))); } return(DbgDotNetValueResult.Create(CreateDotNetValue_CorDebug(res.Value.ResultOrException !, elementType.AppDomain, tryCreateStrongHandle: true))); } } catch (TimeoutException) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } }
internal DbgDotNetValueResult FuncEvalCall_AnyThread_MonoDebug(DmdMethodBase method, DbgDotNetValue obj, object[] arguments, DbgDotNetInvokeOptions invokeOptions, bool newObj) { debuggerThread.VerifyAccess(); var cancellationToken = CancellationToken.None; foreach (var thread in GetFuncEvalCallThreads(method.AppDomain)) { var res = FuncEvalCallCore_MonoDebug(null, null, thread, method, obj, arguments, invokeOptions, newObj, cancellationToken); if (!res.HasError) { return(res); } } return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.InternalDebuggerError)); }
internal DbgDotNetValueResult FuncEvalCreateInstanceNoCtor_CorDebug(DbgEvaluationInfo evalInfo, CorAppDomain appDomain, DmdType typeToCreate) { debuggerThread.VerifyAccess(); evalInfo.CancellationToken.ThrowIfCancellationRequested(); var tmp = CheckFuncEval(evalInfo); if (tmp != null) { return(tmp.Value); } var dnThread = GetThread(evalInfo.Frame.Thread); try { using (var dnEval = dnDebugger.CreateEval(evalInfo.CancellationToken, suspendOtherThreads: (evalInfo.Context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(evalInfo.Context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, evalInfo); var corType = GetType(appDomain, typeToCreate); var res = dnEval.CreateDontCallConstructor(corType, out int hr); if (res == null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } if (res.Value.WasCustomNotification) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.FuncEvalRequiresAllThreadsToRun)); } if (res.Value.WasCancelled) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } if (res.Value.WasException) { return(DbgDotNetValueResult.CreateException(CreateDotNetValue_CorDebug(res.Value.ResultOrException, typeToCreate.AppDomain, tryCreateStrongHandle: true))); } return(DbgDotNetValueResult.Create(CreateDotNetValue_CorDebug(res.Value.ResultOrException, typeToCreate.AppDomain, tryCreateStrongHandle: true))); } } catch (TimeoutException) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } }
DbgDotNetValueResult CallCore(DbgDotNetValue obj, bool isCallvirt, DmdMethodBase method, ILValue[] arguments) { var options = isCallvirt ? DotNetClassHookCallOptions.IsCallvirt : DotNetClassHookCallOptions.None; foreach (var anyHook in anyClassHooks) { var res = anyHook.Call(options, obj, method, arguments); if (res != null) { return(DbgDotNetValueResult.Create(res)); } } var type = method.DeclaringType; if (type.IsConstructedGenericType) { type = type.GetGenericTypeDefinition(); } var typeName = DmdTypeName.Create(type); if (classHooks.TryGetValue(typeName, out var hook)) { if (DmdWellKnownTypeUtils.TryGetWellKnownType(typeName, out var wellKnownType)) { if (type != type.AppDomain.GetWellKnownType(wellKnownType, isOptional: true)) { hook = null; } } if (hook != null) { var res = hook.Call(options, obj, method, arguments); if (res != null) { return(DbgDotNetValueResult.Create(res)); } } } if (!canFuncEval) { throw new InterpreterMessageException(PredefinedEvaluationErrorMessages.FuncEvalDisabled); } var invokeOptions = isCallvirt ? DbgDotNetInvokeOptions.None : DbgDotNetInvokeOptions.NonVirtual; return(runtime.Call(evalInfo, obj, method, Convert(arguments, method.GetMethodSignature().GetParameterTypes()), invokeOptions)); }
public override DbgDotNetValueResult LoadIndirect() { if (!Type.IsByRef) { return(base.LoadIndirect()); } if (IsNullByRef) { return(DbgDotNetValueResult.Create(new SyntheticNullValue(Type.GetElementType()))); } if (engine.CheckMonoDebugThread()) { return(Dereference_MonoDebug()); } return(engine.InvokeMonoDebugThread(() => Dereference_MonoDebug())); }
bool InitializeListDebugView(DbgEvaluationInfo evalInfo) { var info = EnumerableDebugViewHelper.GetListEnumerableMethods(instanceValue.Type, enumerableType); if ((object)info.ctor == null) { return(false); } DbgDotNetValueResult collTypeResult = default; DbgDotNetValueResult toArrayResult = default; bool error = true; try { var runtime = evalInfo.Runtime.GetDotNetRuntime(); collTypeResult = runtime.CreateInstance(evalInfo, info.ctor, new[] { instanceValue }, DbgDotNetInvokeOptions.None); if (!collTypeResult.IsNormalResult) { return(false); } var expr = valueNodeProviderFactory.GetNewObjectExpression(info.ctor, valueExpression, expectedType); toArrayResult = runtime.Call(evalInfo, collTypeResult.Value, info.toArrayMethod, Array.Empty <object>(), DbgDotNetInvokeOptions.None); if (toArrayResult.HasError) { return(false); } expr = valueNodeProviderFactory.GetCallExpression(info.toArrayMethod, expr); var result = valueNodeProviderFactory.Create(evalInfo, false, toArrayResult.Value.Type, new DbgDotNetValueNodeInfo(toArrayResult.Value, expr), evalOptions); if (result.Provider == null) { return(false); } realProvider = result.Provider; error = false; return(true); } finally { collTypeResult.Value?.Dispose(); if (error) { toArrayResult.Value?.Dispose(); } } }
internal DbgDotNetValueResult Box_CorDebug(DbgEvaluationInfo evalInfo, CorAppDomain appDomain, CorValue value, DmdType type) { debuggerThread.VerifyAccess(); evalInfo.CancellationToken.ThrowIfCancellationRequested(); var tmp = CheckFuncEval(evalInfo); if (!(tmp is null)) { return(tmp.Value); } var dnThread = GetThread(evalInfo.Frame.Thread); var createdValues = new List <CorValue>(); CorValue?boxedValue = null; try { using (var dnEval = dnDebugger.CreateEval(evalInfo.CancellationToken, suspendOtherThreads: (evalInfo.Context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(evalInfo.Context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, evalInfo); boxedValue = BoxIfNeeded(dnEval, appDomain, createdValues, value, type.AppDomain.System_Object, type); if (boxedValue is null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(-1))); } return(DbgDotNetValueResult.Create(CreateDotNetValue_CorDebug(boxedValue, type.AppDomain, tryCreateStrongHandle: true))); } } catch (TimeoutException) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } finally { foreach (var v in createdValues) { if (!v.Equals(boxedValue)) { dnDebugger.DisposeHandle(v); } } } }
public override DbgDotNetValueResult GetVariable(int index) { if ((uint)index < (uint)realLocalVariables.Count) { return(localsProvider.GetVariable(index)); } if ((uint)index < (uint)localVariables.Count) { var type = localVariables[index].LocalType; if (!extraLocals.TryGetValue(index, out var localValue)) { localValue = runtime.GetDefaultValue(type); extraLocals.Add(index, localValue); } return(DbgDotNetValueResult.Create(localValue)); } return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.InternalDebuggerError)); }
DbgDotNetValueResult GetArrayElementAt_CorDebug(uint index) { Debug.Assert(Type.IsArray); engine.VerifyCorDebugThread(); var corValue = TryGetCorValue(); if (corValue == null || corValue.IsNull) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } using (var obj = new ArrayObjectValue(engine, corValue)) { int hr = -1; var elemValue = obj.Value?.GetElementAtPosition(index, out hr); if (elemValue == null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } return(DbgDotNetValueResult.Create(engine.CreateDotNetValue_CorDebug(elemValue, Type.AppDomain, tryCreateStrongHandle: true))); } }
ILValue CreateILValue(DbgDotNetValueResult result) { if (result.HasError) { throw new InterpreterMessageException(result.ErrorMessage); } if (result.ValueIsException) { throw new InterpreterThrownExceptionException(result.Value); } var dnValue = result.Value; if (dnValue == null) { throw new InterpreterMessageException(PredefinedEvaluationErrorMessages.InternalDebuggerError); } return(CreateILValue(dnValue)); }
internal DbgDotNetValueResult?CheckFuncEval(DbgEvaluationContext context) { debuggerThread.VerifyAccess(); if (!IsPaused) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.CanFuncEvalOnlyWhenPaused)); } if (isUnhandledException) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.CantFuncEvalWhenUnhandledExceptionHasOccurred)); } if (context.ContinueContext.HasData <EvalTimedOut>()) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOutNowDisabled)); } if (IsEvaluating) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.CantFuncEval)); } return(null); }
bool FormatValue(uint index, bool needSpace) { var runtime = evalInfo.Runtime.GetDotNetRuntime(); DbgDotNetValueResult parameterValue = default; DbgDotNetValue dereferencedValue = null; try { parameterValue = runtime.GetParameterValue(evalInfo, index); if (parameterValue.IsNormalResult) { if (needSpace) { WriteSpace(); OutputWrite("=", BoxedTextColor.Operator); WriteSpace(); } needSpace = true; var valueFormatter = new CSharpValueFormatter(output, evalInfo, languageFormatter, valueOptions, cultureInfo); var value = parameterValue.Value; if (value.Type.IsByRef) { value = dereferencedValue = value.LoadIndirect().Value; } if (value == null) { OutputWrite("???", BoxedTextColor.Error); } else { valueFormatter.Format(value); } } } finally { parameterValue.Value?.Dispose(); dereferencedValue?.Dispose(); } return(needSpace); }
bool FormatValue(DbgStackFrame frame, uint index, bool needSpace) { var runtime = context.Runtime.GetDotNetRuntime(); DbgDotNetValueResult parameterValue = default; DbgDotNetValue dereferencedValue = null; try { parameterValue = runtime.GetParameterValue(context, frame, index, cancellationToken); if (parameterValue.IsNormalResult) { if (needSpace) { WriteSpace(); OutputWrite("=", BoxedTextColor.Operator); WriteSpace(); } needSpace = true; var valueFormatter = new VisualBasicValueFormatter(output, context, frame, languageFormatter, valueOptions, cultureInfo, cancellationToken); var value = parameterValue.Value; if (value.Type.IsByRef) { value = dereferencedValue = value.LoadIndirect(); } if (value == null) { OutputWrite("???", BoxedTextColor.Error); } else { valueFormatter.Format(value); } } } finally { parameterValue.Value?.Dispose(); dereferencedValue?.Dispose(); } return(needSpace); }
DbgDotNetValueResult FuncEvalCallCore_MonoDebug(DbgEvaluationContext contextOpt, DbgStackFrame frameOpt, DbgThread thread, DmdMethodBase method, DbgDotNetValue obj, object[] arguments, DbgDotNetInvokeOptions invokeOptions, bool newObj, CancellationToken cancellationToken) { // ReturnOutThis is only available since 2.35 so we'll special case the common case where a struct ctor // is called (CALL/CALLVIRT). We'll change it to a NEWOBJ and then copy the result to the input 'this' value. if (!newObj && obj is DbgDotNetValueImpl objImpl && method is DmdConstructorInfo ctor && ctor.ReflectedType.IsValueType) { var res = FuncEvalCallCoreReal_MonoDebug(contextOpt, frameOpt, thread, method, null, arguments, invokeOptions, true, cancellationToken); if (res.IsNormalResult) { try { var error = objImpl.ValueLocation.Store(((DbgDotNetValueImpl)res.Value).Value); if (error != null) { res.Value?.Dispose(); return(DbgDotNetValueResult.CreateError(error)); } } catch { res.Value?.Dispose(); throw; } } return(res); }
internal DbgDotNetValueResult FuncEvalCall_CorDebug(DbgEvaluationInfo evalInfo, CorAppDomain appDomain, DmdMethodBase method, DbgDotNetValue?obj, object?[] arguments, bool newObj) { debuggerThread.VerifyAccess(); evalInfo.CancellationToken.ThrowIfCancellationRequested(); var tmp = CheckFuncEval(evalInfo); if (!(tmp is null)) { return(tmp.Value); } Debug.Assert(!newObj || method.IsConstructor); Debug.Assert(method.SpecialMethodKind == DmdSpecialMethodKind.Metadata, "Methods not defined in metadata should be emulated by other code (i.e., the caller)"); if (method.SpecialMethodKind != DmdSpecialMethodKind.Metadata) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } var reflectionAppDomain = method.AppDomain; var methodDbgModule = method.Module.GetDebuggerModule() ?? throw new InvalidOperationException(); if (!TryGetDnModule(methodDbgModule, out var methodModule)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } var func = methodModule.CorModule.GetFunctionFromToken((uint)method.MetadataToken) ?? throw new InvalidOperationException(); int hr; var dnThread = GetThread(evalInfo.Frame.Thread); var createdValues = new List <CorValue>(); try { using (var dnEval = dnDebugger.CreateEval(evalInfo.CancellationToken, suspendOtherThreads: (evalInfo.Context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(evalInfo.Context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, evalInfo); var converter = new EvalArgumentConverter(this, dnEval, appDomain, reflectionAppDomain, createdValues); var genTypeArgs = method.DeclaringType !.GetGenericArguments(); var methTypeArgs = method.GetGenericArguments(); var typeArgs = genTypeArgs.Count == 0 && methTypeArgs.Count == 0 ? Array.Empty <CorType>() : new CorType[genTypeArgs.Count + methTypeArgs.Count]; int w = 0; for (int i = 0; i < genTypeArgs.Count; i++) { typeArgs[w++] = GetType(appDomain, genTypeArgs[i]); } for (int i = 0; i < methTypeArgs.Count; i++) { typeArgs[w++] = GetType(appDomain, methTypeArgs[i]); } if (typeArgs.Length != w) { throw new InvalidOperationException(); } var paramTypes = GetAllMethodParameterTypes(method.GetMethodSignature()); if (paramTypes.Count != arguments.Length) { throw new InvalidOperationException(); } bool hiddenThisArg = !method.IsStatic && !newObj; int argsCount = arguments.Length + (hiddenThisArg ? 1 : 0); var args = argsCount == 0 ? Array.Empty <CorValue>() : new CorValue[argsCount]; w = 0; DmdType origType; var declType = method.DeclaringType; if (hiddenThisArg) { if (method is DmdMethodInfo m) { declType = m.GetBaseDefinition().DeclaringType !; } var val = converter.Convert(obj, declType, out origType); if (!(val.ErrorMessage is null)) { return(DbgDotNetValueResult.CreateError(val.ErrorMessage)); } args[w++] = BoxIfNeeded(dnEval, appDomain, createdValues, val.CorValue !, declType, origType); } for (int i = 0; i < arguments.Length; i++) { var paramType = paramTypes[i]; var val = converter.Convert(arguments[i], paramType, out origType); if (!(val.ErrorMessage is null)) { return(DbgDotNetValueResult.CreateError(val.ErrorMessage)); } var valType = origType ?? new ReflectionTypeCreator(this, method.AppDomain).Create(val.CorValue !.ExactType); args[w++] = BoxIfNeeded(dnEval, appDomain, createdValues, val.CorValue !, paramType, valType); } if (args.Length != w) { throw new InvalidOperationException(); } // Derefence/unbox the values here now that they can't get neutered for (int i = 0; i < args.Length; i++) { DmdType argType; if (!hiddenThisArg) { argType = paramTypes[i]; } else if (i == 0) { argType = declType; } else { argType = paramTypes[i - 1]; } CorValue?arg = args[i]; if (argType.IsValueType || argType.IsPointer || argType.IsFunctionPointer) { if (arg.IsReference) { if (arg.IsNull) { throw new InvalidOperationException(); } arg = arg.GetDereferencedValue(out hr); if (arg is null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } } if (arg.IsBox) { arg = arg.GetBoxedValue(out hr); if (arg is null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } } args[i] = arg; } } var res = newObj ? dnEval.CallConstructor(func, typeArgs, args, out hr) : dnEval.Call(func, typeArgs, args, out hr); if (res is null) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.GetErrorMessage(hr))); } if (res.Value.WasCustomNotification) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.FuncEvalRequiresAllThreadsToRun)); } if (res.Value.WasCancelled) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } if (res.Value.WasException) { return(DbgDotNetValueResult.CreateException(CreateDotNetValue_CorDebug(res.Value.ResultOrException !, reflectionAppDomain, tryCreateStrongHandle: true))); } return(DbgDotNetValueResult.Create(CreateDotNetValue_CorDebug(res.Value.ResultOrException !, reflectionAppDomain, tryCreateStrongHandle: true))); } } catch (TimeoutException) { return(DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(DbgDotNetValueResult.CreateError(CordbgErrorHelper.InternalError)); } finally { foreach (var value in createdValues) { dnDebugger.DisposeHandle(value); } } }
protected override (DbgDotNetValueNode node, bool canHide) TryCreateInstanceValueNode(DbgDotNetValueResult valueResult) { if (!valueResult.ValueIsException) { return(null, false); } if (valueResult.Value.Type != valueResult.Value.Type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Linq_SystemCore_EnumerableDebugViewEmptyException, isOptional: true)) { return(null, false); } valueResult.Value?.Dispose(); return(new ResultsViewNoResultsValueNode(Expression), false); }
protected override (DbgDotNetValueNode node, bool canHide) CreateValueNode(DbgEvaluationContext context, DbgStackFrame frame, int index, DbgValueNodeEvaluationOptions options, CancellationToken cancellationToken) { var runtime = context.Runtime.GetDotNetRuntime(); DbgDotNetValueResult valueResult = default; try { ref var info = ref membersCollection.Members[index]; var typeExpression = GetExpression(info.Member.DeclaringType); string expression, imageName; bool isReadOnly; DmdType expectedType; switch (info.Member.MemberType) { case DmdMemberTypes.Field: var field = (DmdFieldInfo)info.Member; expression = valueNodeFactory.GetFieldExpression(typeExpression, field.Name, null, addParens: false); expectedType = field.FieldType; imageName = ImageNameUtils.GetImageName(field); valueResult = runtime.LoadField(context, frame, null, field, cancellationToken); // We should be able to change read only fields (we're a debugger), but since the // compiler will complain, we have to prevent the user from editing the value. isReadOnly = field.IsLiteral || field.IsInitOnly; break; case DmdMemberTypes.Property: var property = (DmdPropertyInfo)info.Member; expression = valueNodeFactory.GetPropertyExpression(typeExpression, property.Name, null, addParens: false); expectedType = property.PropertyType; imageName = ImageNameUtils.GetImageName(property); if ((options & DbgValueNodeEvaluationOptions.NoFuncEval) != 0) { isReadOnly = true; valueResult = new DbgDotNetValueResult(PredefinedEvaluationErrorMessages.FuncEvalDisabled); } else { var getter = property.GetGetMethod(DmdGetAccessorOptions.All) ?? throw new InvalidOperationException(); valueResult = runtime.Call(context, frame, null, getter, Array.Empty <object>(), cancellationToken); isReadOnly = (object)property.GetSetMethod(DmdGetAccessorOptions.All) == null; } break; default: throw new InvalidOperationException(); } DbgDotNetValueNode newNode; if (valueResult.HasError) { newNode = valueNodeFactory.CreateError(context, frame, info.Name, valueResult.ErrorMessage, expression, false, cancellationToken); } else if (valueResult.ValueIsException) { newNode = valueNodeFactory.Create(context, frame, info.Name, valueResult.Value, options, expression, PredefinedDbgValueNodeImageNames.Error, true, false, expectedType, false, cancellationToken); } else { newNode = valueNodeFactory.Create(context, frame, info.Name, valueResult.Value, options, expression, imageName, isReadOnly, false, expectedType, false, cancellationToken); } valueResult = default; return(newNode, true); }
public override TypeMirror?Load(AssemblyMirror assembly, string typeFullName) { var res = engine.CheckFuncEval(evalInfo.Context); if (!(res is null)) { return(null); } var appDomain = evalInfo.Frame.AppDomain; if (appDomain is null) { return(null); } var state = appDomain.GetOrCreateData <LoaderState>(); if (!state.LoadedTypes.Add(typeFullName)) { return(null); } var reflectionAppDomain = appDomain.GetReflectionAppDomain() ?? throw new InvalidOperationException(); var runtime = engine.DotNetRuntime; DbgDotNetValue? asmTypeValue = null; DbgDotNetValueResult result1 = default; DbgDotNetValueResult result2 = default; try { if (state.Method_System_Reflection_Assembly_GetType_String is null) { var assemblyType = reflectionAppDomain.GetWellKnownType(DmdWellKnownType.System_Reflection_Assembly); state.Method_System_Reflection_Assembly_GetType_String = assemblyType.GetMethod(nameof(System.Reflection.Assembly.GetType), DmdSignatureCallingConvention.HasThis, 0, reflectionAppDomain.System_Type, new[] { reflectionAppDomain.System_String }, throwOnError: false); Debug.Assert(!(state.Method_System_Reflection_Assembly_GetType_String is null)); if (state.Method_System_Reflection_Assembly_GetType_String is null) { return(null); } state.Method_System_Array_CreateInstance_Type_Int32 = reflectionAppDomain.System_Array.GetMethod(nameof(Array.CreateInstance), DmdSignatureCallingConvention.Default, 0, reflectionAppDomain.System_Array, new[] { reflectionAppDomain.System_Type, reflectionAppDomain.System_Int32 }, throwOnError: false); Debug.Assert(!(state.Method_System_Array_CreateInstance_Type_Int32 is null)); if (state.Method_System_Array_CreateInstance_Type_Int32 is null) { return(null); } } if (state.Method_System_Reflection_Assembly_GetType_String is null || state.Method_System_Array_CreateInstance_Type_Int32 is null) { return(null); } asmTypeValue = engine.CreateDotNetValue_MonoDebug(reflectionAppDomain, assembly.GetAssemblyObject(), null); result1 = runtime.Call(evalInfo, asmTypeValue, state.Method_System_Reflection_Assembly_GetType_String, new[] { typeFullName }, DbgDotNetInvokeOptions.None); if (result1.IsNormalResult) { result2 = runtime.Call(evalInfo, null, state.Method_System_Array_CreateInstance_Type_Int32, new object[2] { result1.Value !, 0 }, DbgDotNetInvokeOptions.None); if (result2.IsNormalResult) { var arrayType = result2.Value !.Type; Debug.Assert(arrayType.IsSZArray); if (arrayType.IsSZArray) { return(MonoDebugTypeCreator.TryGetType(arrayType.GetElementType() !)); } } }
public override DbgDotNetValueNode[] GetChildren(LanguageValueNodeFactory valueNodeFactory, DbgEvaluationInfo evalInfo, ulong index, int count, DbgValueNodeEvaluationOptions options, ReadOnlyCollection <string>?formatSpecifiers) { var res = count == 0 ? Array.Empty <DbgDotNetValueNode>() : new DbgDotNetValueNode[count]; DbgDotNetValueResult newValue = default; try { var output = ObjectCache.AllocDotNetTextOutput(); var elementType = valueInfo.Value.Type.GetElementType() !; var castType = NeedCast(slotType, valueInfo.Value.Type) ? valueInfo.Value.Type : null; for (int i = 0; i < res.Length; i++) { evalInfo.CancellationToken.ThrowIfCancellationRequested(); string expression; uint arrayIndex = (uint)index + (uint)i; newValue = valueInfo.Value.GetArrayElementAt(arrayIndex); if (dimensionInfos.Length == 1) { int baseIndex = (int)arrayIndex + dimensionInfos[0].BaseIndex; expression = valueNodeFactory.GetExpression(valueInfo.Expression, baseIndex, castType, addParens); owner.FormatArrayName(output, baseIndex); } else { uint indexLeft = arrayIndex; Debug2.Assert(indexes is not null); for (int j = dimensionInfos.Length - 1; j >= 0; j--) { indexes[j] = (int)(indexLeft % dimensionInfos[j].Length) + dimensionInfos[j].BaseIndex; indexLeft = indexLeft / dimensionInfos[j].Length; } expression = valueNodeFactory.GetExpression(valueInfo.Expression, indexes, castType, addParens); owner.FormatArrayName(output, indexes); } var name = output.CreateAndReset(); DbgDotNetValueNode?newNode; if (newValue.HasError) { newNode = valueNodeFactory.CreateError(evalInfo, name, newValue.ErrorMessage !, expression, false); } else { newNode = null; if (CSharpDynamicPropertyHelper.IsCSharpDynamicProperty(newValue.Value !.Type)) { var info = CSharpDynamicPropertyHelper.GetRealValue(evalInfo, newValue.Value); if (info.name is not null) { newValue.Value.Dispose(); name = new DbgDotNetText(new DbgDotNetTextPart(DbgTextColor.DebugViewPropertyName, info.name)); expression = valueNodeFactory.GetFieldExpression(expression, info.valueField.Name, null, false); newNode = valueNodeFactory.Create(evalInfo, name, info.value, formatSpecifiers, options, expression, PredefinedDbgValueNodeImageNames.DynamicViewElement, true, false, info.valueField.FieldType, false); } } if (newNode is null) { newNode = valueNodeFactory.Create(evalInfo, name, newValue.Value, formatSpecifiers, options, expression, PredefinedDbgValueNodeImageNames.ArrayElement, false, false, elementType, false); } } newValue = default; res[i] = newNode; } ObjectCache.Free(ref output); } catch { evalInfo.Context.Process.DbgManager.Close(res.Where(a => a is not null)); newValue.Value?.Dispose(); throw; } return(res); }
bool TryFormatTuple(DbgDotNetValue value, int tupleArity) { Debug.Assert(TypeFormatterUtils.GetTupleArity(value.Type) == tupleArity && tupleArity > 0); OutputWrite(TupleTypeOpenParen, DbgTextColor.Punctuation); var values = ObjectCache.AllocDotNetValueList(); var runtime = evalInfo.Runtime.GetDotNetRuntime(); int index = 0; foreach (var info in TupleTypeUtils.GetTupleFields(value.Type, tupleArity)) { if (index++ > 0) { OutputWrite(",", DbgTextColor.Punctuation); WriteSpace(); } if (info.tupleIndex < 0) { OutputWrite("???", DbgTextColor.Error); break; } else { var objValue = value; DbgDotNetValueResult valueResult = default; try { foreach (var field in info.fields) { valueResult = runtime.LoadField(evalInfo, objValue, field); if (valueResult.Value != null) { values.Add(valueResult.Value); } if (valueResult.HasError || valueResult.ValueIsException) { objValue = null; break; } objValue = valueResult.Value; } valueResult = default; if (objValue == null) { OutputWrite("???", DbgTextColor.Error); break; } Format(objValue); } finally { valueResult.Value?.Dispose(); foreach (var v in values) { v?.Dispose(); } values.Clear(); } } } ObjectCache.Free(ref values); OutputWrite(TupleTypeCloseParen, DbgTextColor.Punctuation); return(true); }