/// <summary> /// Constructor /// </summary> /// <param name="thread">Current thread</param> public DbgDotNetStepperBreakpointEventArgs(DbgThread thread) =>
public void Initialize(DbgProcess process, DbgThread thread) { this.process = process ?? throw new ArgumentNullException(nameof(process)); this.thread = thread; }
public override DbgCodeBreakpointCheckResult ShouldBreak(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread, in DbgCodeBreakpointFilter filter)
public abstract void Print(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread, DbgCodeBreakpointTrace trace);
public override DbgEngineStepper Create(IDbgDotNetRuntime runtime, DbgDotNetEngineStepper stepper, DbgThread thread) { if (runtime == null) { throw new ArgumentNullException(nameof(runtime)); } if (stepper == null) { throw new ArgumentNullException(nameof(stepper)); } if (thread == null) { throw new ArgumentNullException(nameof(thread)); } return(new DbgEngineStepperImpl(dbgLanguageService, dbgDotNetDebugInfoService, debuggerSettings, runtime, stepper, thread)); }
/// <summary> /// Sets a new instruction pointer /// </summary> /// <param name="thread">Thread</param> /// <param name="location">New location</param> public abstract void SetIP(DbgThread thread, DbgCodeLocation location);
/// <summary> /// Gets the first non-null frame location. This location must be <see cref="DbgCodeLocation.Close"/>'d /// by the caller. /// </summary> /// <param name="thread">Thread</param> /// <returns></returns> public static (DbgCodeLocation?location, int frameIndex) GetFirstFrameLocation(DbgThread thread) { DbgStackWalker?stackWalker = null; var objsToFree = new List <DbgObject>(); try { stackWalker = thread.CreateStackWalker(); objsToFree.Add(stackWalker); int frameIndex = 0; while (frameIndex < 20) { // Usually the first frame contains a location and if not, the one after that. var frames = stackWalker.GetNextStackFrames(2); objsToFree.AddRange(frames); if (frames.Length == 0) { break; } foreach (var frame in frames) { var location = frame.Location; if (location is not null) { return(location.Clone(), frameIndex); } frameIndex++; } } } finally { if (objsToFree.Count > 0) { thread.Process.DbgManager.Close(objsToFree); } } return(null, -1); }
public override DbgEngineStepper CreateStepper(DbgThread thread) { var data = thread.GetData <DbgThreadData>(); return(dbgEngineStepperFactory.Create(DotNetRuntime, new DbgDotNetEngineStepperImpl(this), thread)); }
public abstract bool ShouldBreak(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread, DbgCodeBreakpointFilter filter);
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 is null)) { res.Value?.Dispose(); return(DbgDotNetValueResult.CreateError(error)); } } catch { res.Value?.Dispose(); throw; } } return(res); }
public DbgEngineStackWalkerImpl(Lazy <DbgDotNetNativeCodeLocationFactory> dbgDotNetNativeCodeLocationFactory, Lazy <DbgDotNetCodeLocationFactory> dbgDotNetCodeLocationFactory, DbgEngineImpl engine, DnThread dnThread, DbgThread thread, ICorDebugFrame[] framesBuffer) { this.dbgDotNetNativeCodeLocationFactory = dbgDotNetNativeCodeLocationFactory ?? throw new ArgumentNullException(nameof(dbgDotNetNativeCodeLocationFactory)); this.dbgDotNetCodeLocationFactory = dbgDotNetCodeLocationFactory ?? throw new ArgumentNullException(nameof(dbgDotNetCodeLocationFactory)); this.engine = engine ?? throw new ArgumentNullException(nameof(engine)); this.dnThread = dnThread ?? throw new ArgumentNullException(nameof(dnThread)); this.thread = thread ?? throw new ArgumentNullException(nameof(thread)); this.framesBuffer = framesBuffer ?? throw new ArgumentNullException(nameof(framesBuffer)); continueCounter = dnThread.Debugger.ContinueCounter; }
bool ShouldBreak(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread) { if (thread == null) { return(false); } var bp = (DbgCodeBreakpointImpl)boundBreakpoint.Breakpoint; if (bp.IsClosed || boundBreakpoint.IsClosed) { return(false); } var settings = bp.Settings; if (!settings.IsEnabled) { return(false); } if (!bp.RaiseHitCheck(boundBreakpoint, thread)) { return(false); } DbgCodeBreakpointCheckResult checkRes; if (settings.Filter is DbgCodeBreakpointFilter filter) { checkRes = dbgCodeBreakpointFilterChecker.Value.ShouldBreak(boundBreakpoint, thread, filter); if (checkRes.ErrorMessage != null) { boundBreakpoint.Process.DbgManager.ShowError(checkRes.ErrorMessage); return(true); } if (!checkRes.ShouldBreak) { return(false); } } if (settings.Condition is DbgCodeBreakpointCondition condition) { checkRes = dbgCodeBreakpointConditionChecker.Value.ShouldBreak(boundBreakpoint, thread, condition); if (checkRes.ErrorMessage != null) { boundBreakpoint.Process.DbgManager.ShowError(checkRes.ErrorMessage); return(true); } if (!checkRes.ShouldBreak) { return(false); } } // This counts as a hit, even if there's no 'hit count' option int currentHitCount = dbgCodeBreakpointHitCountService.Value.Hit_DbgThread(boundBreakpoint.Breakpoint); if (settings.HitCount is DbgCodeBreakpointHitCount hitCount) { checkRes = dbgCodeBreakpointHitCountChecker.Value.ShouldBreak(boundBreakpoint, thread, hitCount, currentHitCount); if (checkRes.ErrorMessage != null) { boundBreakpoint.Process.DbgManager.ShowError(checkRes.ErrorMessage); return(true); } if (!checkRes.ShouldBreak) { return(false); } } bool shouldBreak; if (settings.Trace is DbgCodeBreakpointTrace trace) { dbgCodeBreakpointTraceMessagePrinter.Value.Print(boundBreakpoint, thread, trace); shouldBreak = !trace.Continue; } else { shouldBreak = true; } if (shouldBreak) { bp.RaiseHit(boundBreakpoint, thread); } return(shouldBreak); }
public DbgEngineStackWalkerImpl(Lazy <DbgDotNetCodeLocationFactory> dbgDotNetCodeLocationFactory, DbgEngineImpl engine, ThreadMirror monoThread, DbgThread thread) { this.dbgDotNetCodeLocationFactory = dbgDotNetCodeLocationFactory ?? throw new ArgumentNullException(nameof(dbgDotNetCodeLocationFactory)); this.engine = engine ?? throw new ArgumentNullException(nameof(engine)); this.monoThread = monoThread ?? throw new ArgumentNullException(nameof(monoThread)); this.thread = thread ?? throw new ArgumentNullException(nameof(thread)); continueCounter = engine.ContinueCounter; }
/// <summary> /// Gets frame info or null if none is available /// </summary> /// <param name="thread">Thread</param> /// <returns></returns> public abstract DbgDotNetEngineStepperFrameInfo TryGetFrameInfo(DbgThread thread);
/// <summary> /// Creates a stack walker /// </summary> /// <param name="thread">Thread created by this engine</param> /// <returns></returns> public abstract DbgEngineStackWalker CreateStackWalker(DbgThread thread);
internal DnThread GetThread(DbgThread thread) => thread?.GetData <DbgThreadData>()?.DnThread ?? throw new InvalidOperationException();
/// <summary> /// Creates a stepper /// </summary> /// <param name="thread">Thread to step</param> /// <returns></returns> public abstract DbgEngineStepper CreateStepper(DbgThread thread);
/// <summary> /// Constructor /// </summary> /// <param name="thread">Thread</param> /// <param name="error">Error message or null if none</param> public DbgStepCompleteEventArgs(DbgThread thread, string error) { Thread = thread ?? throw new ArgumentNullException(nameof(thread)); Error = error; }
/// <summary> /// Checks if <see cref="SetIP(DbgThread, DbgCodeLocation)"/> can be called /// </summary> /// <param name="thread">Thread</param> /// <param name="location">New location</param> /// <returns></returns> public abstract bool CanSetIP(DbgThread thread, DbgCodeLocation location);
internal DnThread GetThread(DbgThread thread) => TryGetThreadData(thread)?.DnThread ?? throw new InvalidOperationException();
internal ThreadMirror GetThread(DbgThread thread) => TryGetThreadData(thread)?.MonoThread ?? throw new InvalidOperationException();
public override DbgCodeBreakpointCheckResult ShouldBreak(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread, in DbgCodeBreakpointHitCount hitCount, int currentHitCount)
public DbgEngineStepperImpl(DbgDotNetCodeRangeService dbgDotNetCodeRangeService, DbgEngineImpl engine, DbgThread thread, ThreadMirror monoThread) { this.dbgDotNetCodeRangeService = dbgDotNetCodeRangeService ?? throw new ArgumentNullException(nameof(dbgDotNetCodeRangeService)); this.engine = engine ?? throw new ArgumentNullException(nameof(engine)); this.thread = thread ?? throw new ArgumentNullException(nameof(thread)); this.monoThread = monoThread ?? throw new ArgumentNullException(nameof(monoThread)); }
public abstract DbgCodeBreakpointCheckResult ShouldBreak(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread, DbgCodeBreakpointCondition condition);
public abstract DbgCodeBreakpointCheckResult ShouldBreak(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread thread, in DbgCodeBreakpointFilter filter);
/// <summary> /// Freezes the thread /// </summary> /// <param name="thread">Thread</param> public abstract void Freeze(DbgThread thread);
public void Clear() { process = null; thread = null; }
/// <summary> /// Thaws the thread /// </summary> /// <param name="thread">Thread</param> public abstract void Thaw(DbgThread thread);
internal DbgDotNetValueResult FuncEvalCall_CorDebug(DbgEvaluationContext context, DbgThread thread, CorAppDomain appDomain, DmdMethodBase method, DbgDotNetValue obj, object[] arguments, bool newObj, CancellationToken cancellationToken) { debuggerThread.VerifyAccess(); cancellationToken.ThrowIfCancellationRequested(); var tmp = CheckFuncEval(context); if (tmp != 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(new DbgDotNetValueResult(CordbgErrorHelper.InternalError)); } var reflectionAppDomain = thread.AppDomain.GetReflectionAppDomain() ?? throw new InvalidOperationException(); var methodDbgModule = method.Module.GetDebuggerModule() ?? throw new InvalidOperationException(); if (!TryGetDnModule(methodDbgModule, out var methodModule)) { return(new DbgDotNetValueResult(CordbgErrorHelper.InternalError)); } var func = methodModule.CorModule.GetFunctionFromToken((uint)method.MetadataToken) ?? throw new InvalidOperationException(); var dnThread = GetThread(thread); var createdValues = new List <CorValue>(); try { using (var dnEval = dnDebugger.CreateEval(cancellationToken, suspendOtherThreads: (context.Options & DbgEvaluationContextOptions.RunAllThreads) == 0)) { dnEval.SetThread(dnThread); dnEval.SetTimeout(context.FuncEvalTimeout); dnEval.EvalEvent += (s, e) => DnEval_EvalEvent(dnEval, context); 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; if (hiddenThisArg) { var declType = method.DeclaringType; if (method is DmdMethodInfo m) { declType = m.GetBaseDefinition().DeclaringType; } var val = converter.Convert(obj, declType, out origType); if (val.ErrorMessage != null) { return(new DbgDotNetValueResult(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 != null) { return(new DbgDotNetValueResult(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 w = hiddenThisArg ? 1 : 0; for (int i = 0; i < arguments.Length; i++) { var paramType = paramTypes[i]; var arg = args[w]; if (paramType.IsValueType || paramType.IsPointer || paramType.IsFunctionPointer) { if (arg.IsReference) { if (arg.IsNull) { throw new InvalidOperationException(); } arg = arg.DereferencedValue ?? throw new InvalidOperationException(); } if (arg.IsBox) { arg = arg.BoxedValue ?? throw new InvalidOperationException(); } args[w] = arg; } w++; } if (args.Length != w) { throw new InvalidOperationException(); } var res = newObj ? dnEval.CallConstructor(func, typeArgs, args, out int hr) : dnEval.Call(func, typeArgs, args, out hr); if (res == null) { return(new DbgDotNetValueResult(CordbgErrorHelper.GetErrorMessage(hr))); } if (res.Value.WasCustomNotification) { return(new DbgDotNetValueResult(CordbgErrorHelper.FuncEvalRequiresAllThreadsToRun)); } if (res.Value.WasCancelled) { return(new DbgDotNetValueResult(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } return(new DbgDotNetValueResult(CreateDotNetValue_CorDebug(res.Value.ResultOrException, reflectionAppDomain, tryCreateStrongHandle: true), valueIsException: res.Value.WasException)); } } catch (TimeoutException) { return(new DbgDotNetValueResult(PredefinedEvaluationErrorMessages.FuncEvalTimedOut)); } catch (Exception ex) when(ExceptionUtils.IsInternalDebuggerError(ex)) { return(new DbgDotNetValueResult(CordbgErrorHelper.InternalError)); } finally { foreach (var value in createdValues) { dnDebugger.DisposeHandle(value); } } }
/// <summary> /// Creates a breakpoint /// </summary> /// <param name="thread">Thread or null to match any thread</param> /// <param name="module">Module</param> /// <param name="token">Method token</param> /// <param name="offset">IL offset</param> /// <returns></returns> public abstract DbgDotNetStepperBreakpoint CreateBreakpoint(DbgThread thread, DbgModule module, uint token, uint offset);