示例#1
0
        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);
        }
示例#2
0
        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));
                }
            }
        }
示例#6
0
        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);
        }
示例#7
0
        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))
 {
 }