int ICorDebugThread.EnumerateChains(out ICorDebugChainEnum ppChains) { Debug.Assert(!IsVirtualThread); ArrayList chains = new ArrayList(); for (CorDebugThread thread = GetLastCorDebugThread(); thread != null; thread = thread.PreviousThread) { CorDebugChain chain = thread.Chain; if (chain != null) { chains.Add(chain); } } ppChains = new CorDebugEnum(chains, typeof(ICorDebugChain), typeof(ICorDebugChainEnum)); return(COM_HResults.S_OK); }
public bool RemoveVirtualThread(CorDebugThread thread) { //can only remove last thread CorDebugThread threadLast = GetLastCorDebugThread(); Debug.Assert(threadLast.IsVirtualThread && !IsVirtualThread); if (threadLast != thread) { return(false); } CorDebugThread threadNextToLast = threadLast.PreviousThread; threadNextToLast.NextThread = null; threadNextToLast.IsSuspended = threadNextToLast._fSuspendedSav; threadLast.PreviousThread = null; //Thread will be removed from process.m_alThreads when the ThreadTerminated breakpoint is hit return(true); }
public override void Hit(BreakpointDef breakpointDef) { CorDebugThread thread = Process.GetThread(breakpointDef.m_pid); Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackBreakpoint(thread, this, TypeToMarshal)); }
private void Break(BreakpointDef breakpointDef) { CorDebugThread thread = Process.GetThread(breakpointDef.m_pid); Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackBreak(thread)); }
private void ExceptionThrown(BreakpointDef breakpointDef) { CorDebugThread thread = Process.GetThread(breakpointDef.m_pid); thread.StoppedOnException(); CorDebugFrame frame = thread.Chain.GetFrameFromDepthnanoCLR(breakpointDef.m_depth); bool fIsEval = thread.IsVirtualThread; bool fUnhandled = (breakpointDef.m_depthExceptionHandler == BreakpointDef.c_DEPTH_UNCAUGHT); if (Process.Engine.Capabilities.ExceptionFilters) { switch (breakpointDef.m_depthExceptionHandler) { case BreakpointDef.c_DEPTH_EXCEPTION_FIRST_CHANCE: Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, breakpointDef.m_IP, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE)); break; case BreakpointDef.c_DEPTH_EXCEPTION_USERS_CHANCE: Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, breakpointDef.m_IP, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_USER_FIRST_CHANCE)); break; case BreakpointDef.c_DEPTH_EXCEPTION_HANDLER_FOUND: Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, breakpointDef.m_IP, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_CATCH_HANDLER_FOUND)); break; } } else { Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, breakpointDef.m_IP, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE)); uint depthMin = (fUnhandled) ? 0 : breakpointDef.m_depthExceptionHandler; for (uint depth = breakpointDef.m_depth; depth >= depthMin; depth--) { frame = thread.Chain.GetFrameFromDepthnanoCLR(depth); if (frame != null && frame.Function.HasSymbols && frame.Function.PdbxMethod.IsJMC) { Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, frame.IP_nanoCLR, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_USER_FIRST_CHANCE)); break; } if (depth == 0) { break; } } if (!fUnhandled) { frame = thread.Chain.GetFrameFromDepthnanoCLR(breakpointDef.m_depthExceptionHandler); Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, breakpointDef.m_IP, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_CATCH_HANDLER_FOUND)); } } if (fUnhandled) { //eval threads are virtual, and although the physical thread has an unhandled exception, the //virtual thread does not. The eval thread will get killed, but the rest of the thread chain will //survive, no need to confuse cpde by throwing an unhandled exception if (fIsEval) { CorDebugEval eval = thread.CurrentEval; eval.StoppedOnUnhandledException(); Debug.Assert(thread.IsVirtualThread); CorDebugThread threadT = thread.GetRealCorDebugThread(); CorDebugFrame frameT = threadT.Chain.ActiveFrame; //fake event to let debugging of unhandled exception occur. //Frame probably needs to be an InternalStubFrame??? frame = thread.Chain.GetFrameFromDepthCLR(thread.Chain.NumFrames - 1); #if DEBUG CorDebugInternalFrame internalFrame = frame as CorDebugInternalFrame; Debug.Assert(internalFrame != null && internalFrame.FrameType == CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL); #endif Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, frame, 0, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_CATCH_HANDLER_FOUND)); } else { Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackException(thread, null, uint.MaxValue, CorDebugExceptionCallbackType.DEBUG_EXCEPTION_UNHANDLED)); } } }
int ICorDebugEval.CallFunction(ICorDebugFunction pFunction, uint nArgs, ICorDebugValue[] ppArgs) { try { //CreateThread will cause a thread create event to occur. This is a virtual thread, so //we need to suspend processing of nanoCLR commands until we have created the thread ourselves //and the processing of a new virtual thread will be ignored. Process.SuspendCommands(true); //need to flush the breakpoints in case new breakpoints were waiting until process was resumed. Process.UpdateBreakpoints(); Debug.Assert(nArgs == ppArgs.Length); Debug.Assert(Process.IsExecutionPaused); CorDebugFunction function = (CorDebugFunction)pFunction; uint md = function.MethodDef_Index; if (function.IsVirtual && function.IsInstance) { Debug.Assert(nArgs > 0); md = this.Engine.GetVirtualMethod(function.MethodDef_Index, ((CorDebugValue)ppArgs[0]).RuntimeValue); } this.Process.SetCurrentAppDomain(this.AppDomain); //Send the selected thread ID to the device so calls that use Thread.CurrentThread work as the user expects. uint pid = this.Engine.CreateThread(md, GetScratchPadLocation(), m_threadReal.ID); if (pid == uint.MaxValue) { throw new ArgumentException("nanoCLR cannot call this function. Possible reasons include: ByRef arguments not supported"); } //If anything below fails, we need to clean up by killing the thread if (nArgs > 0) { List <RuntimeValue> stackFrameValues = this.Engine.GetStackFrameValueAll(pid, 0, function.NumArg, Engine.StackValueKind.Argument); for (int iArg = 0; iArg < nArgs; iArg++) { CorDebugValue valSrc = (CorDebugValue)ppArgs[iArg]; CorDebugValue valDst = CorDebugValue.CreateValue(stackFrameValues[iArg], m_appDomain); if (valDst.RuntimeValue.Assign(valSrc.RuntimeValue) == null) { throw new ArgumentException("nanoCLR cannot set argument " + iArg); } } } m_threadVirtual = new CorDebugThread(this.Process, pid, this); m_threadReal.AttachVirtualThread(m_threadVirtual); Debug.Assert(!m_fActive); m_fActive = true; //It is possible that a hard breakpoint is hit, the first line of the function //to evaluate. If that is the case, than breakpoints need to be drained so the //breakpoint event is fired, to avoid a race condition, where cpde resumes //execution to start the function eval before it gets the breakpoint event //This is primarily due to the difference in behaviour of the nanoCLR and the desktop. //In the desktop, the hard breakpoint will not get hit until execution is resumed. //The nanoCLR can hit the breakpoint during the Thread_Create call. Process.DrainBreakpointsAsync().Wait(); } finally { Process.SuspendCommands(false); } return(COM_HResults.S_OK); }
public void EndEval(EvalResult resultType, bool fSynchronousEval) { try { //This is used to avoid deadlock. Suspend commands synchronizes on this.Process Process.SuspendCommands(true); Debug.Assert(Utility.FImplies(fSynchronousEval, !m_fActive)); if (fSynchronousEval || m_fActive) //what to do if the eval isn't active anymore?? { bool fKillThread = false; if (m_threadVirtual != null) { if (m_threadReal.GetLastCorDebugThread() != m_threadVirtual) { throw new ArgumentException(); } m_threadReal.RemoveVirtualThread(m_threadVirtual); } //Stack frames don't appear if they are not refreshed if (fSynchronousEval) { for (CorDebugThread thread = this.m_threadReal; thread != null; thread = thread.NextThread) { thread.RefreshChain(); } } if (m_fException) { resultType = EvalResult.Exception; } //Check to see if we are able to EndEval -- is this the last virtual thread? m_fActive = false; m_resultType = resultType; switch (resultType) { case EvalResult.Complete: Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackEval(m_threadReal, this, ManagedCallbacks.ManagedCallbackEval.EventType.EvalComplete)); break; case EvalResult.Exception: Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackEval(m_threadReal, this, ManagedCallbacks.ManagedCallbackEval.EventType.EvalException)); break; case EvalResult.Abort: fKillThread = true; /* WARNING!!!! * If we do not give VS a EvalComplete message within 3 seconds of them calling ICorDebugEval::Abort then VS will attempt a RudeAbort * and will display a scary error message about a serious internal debugger error and ignore all future debugging requests, among other bad things. */ Process.EnqueueEvent(new ManagedCallbacks.ManagedCallbackEval(m_threadReal, this, ManagedCallbacks.ManagedCallbackEval.EventType.EvalComplete)); break; } if (fKillThread && m_threadVirtual != null) { Engine.KillThread(m_threadVirtual.ID); } if (resultType == EvalResult.Abort) { Process.PauseExecution(); } } } finally { Process.SuspendCommands(false); } }
public CorDebugChain(CorDebugThread thread, WireProtocol.Commands.Debugging_Thread_Stack.Reply.Call [] calls) { m_thread = thread; ArrayList frames = new ArrayList(calls.Length); bool lastFrameWasUnmanaged = false; if (thread.IsVirtualThread) { frames.Add(new CorDebugInternalFrame(this, CorDebugInternalFrameType.STUBFRAME_FUNC_EVAL)); } for (uint i = 0; i < calls.Length; i++) { WireProtocol.Commands.Debugging_Thread_Stack.Reply.Call call = calls[i]; WireProtocol.Commands.Debugging_Thread_Stack.Reply.CallEx callEx = call as WireProtocol.Commands.Debugging_Thread_Stack.Reply.CallEx; if (callEx != null) { if ((callEx.m_flags & WireProtocol.Commands.Debugging_Thread_Stack.Reply.c_AppDomainTransition) != 0) { //No internal frame is used in the nanoCLR. This is simply to display the AppDomain transition //in the callstack of Visual Studio. frames.Add(new CorDebugInternalFrame(this, CorDebugInternalFrameType.STUBFRAME_APPDOMAIN_TRANSITION)); } if ((callEx.m_flags & WireProtocol.Commands.Debugging_Thread_Stack.Reply.c_PseudoStackFrameForFilter) != 0) { //No internal frame is used in the nanoCLR for filters. This is simply to display the transition //in the callstack of Visual Studio. frames.Add(new CorDebugInternalFrame(this, CorDebugInternalFrameType.STUBFRAME_M2U)); frames.Add(new CorDebugInternalFrame(this, CorDebugInternalFrameType.STUBFRAME_U2M)); } if ((callEx.m_flags & WireProtocol.Commands.Debugging_Thread_Stack.Reply.c_MethodKind_Interpreted) != 0) { if (lastFrameWasUnmanaged) { frames.Add(new CorDebugInternalFrame(this, CorDebugInternalFrameType.STUBFRAME_U2M)); } lastFrameWasUnmanaged = false; } else { if (!lastFrameWasUnmanaged) { frames.Add(new CorDebugInternalFrame(this, CorDebugInternalFrameType.STUBFRAME_M2U)); } lastFrameWasUnmanaged = true; } } frames.Add(new CorDebugFrame(this, call, i)); } m_frames = (CorDebugFrame[])frames.ToArray(typeof(CorDebugFrame)); uint depthCLR = 0; for (int iFrame = m_frames.Length - 1; iFrame >= 0; iFrame--) { m_frames[iFrame]._depthCLR = depthCLR; depthCLR++; } }
public ManagedCallbackBreakpoint(CorDebugThread thread, CorDebugBreakpoint breakpoint, Type typeToMarshal) : base(thread) { m_breakpoint = breakpoint; m_typeToMarshal = typeToMarshal; }
public ManagedCallbackEval(CorDebugThread thread, CorDebugEval eval, EventType eventType) : base(thread) { m_eval = eval; m_eventType = eventType; }
public ManagedCallbackThread(CorDebugThread thread) : this(thread, EventType.Other) { }
public ManagedCallbackExceptionUnwind(CorDebugThread thread, CorDebugFrame frame, CorDebugExceptionUnwindCallbackType type) : base(thread) { Debug.Assert(type == CorDebugExceptionUnwindCallbackType.DEBUG_EXCEPTION_INTERCEPTED, "UnwindBegin is not supported"); m_type = type; m_frame = frame; }
public ManagedCallbackBreak(CorDebugThread thread) : base(thread) { }
public ManagedCallbackStepComplete(CorDebugThread thread, CorDebugStepper stepper, CorDebugStepReason reason) : base(thread) { m_stepper = stepper; m_reason = reason; }
public ManagedCallbackBreakpointSetError(CorDebugThread thread, CorDebugBreakpoint breakpoint, uint error) : base(thread, breakpoint) { m_error = error; }
public ManagedCallbackBreakpoint(CorDebugThread thread, CorDebugBreakpoint breakpoint) : this(thread, breakpoint, typeof(ICorDebugBreakpoint)) { }