⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 managedcallback.cs

📁 SharpDevelop2.0.0 c#开发免费工具
💻 CS
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
//     <version>$Revision: 1408 $</version>
// </file>

// Regular expresion:
// ^{\t*}{(:Ll| )*{:i} *\(((.# {:i}, |\))|())^6\)*}\n\t*\{(.|\n)@\}
// Output: \1 - intention   \2 - declaration \3 - function name  \4-9 parameters

// Replace with:
// \1\2\n\1{\n\1\tEnterCallback(PausedReason.Other, "\3");\n\1\t\n\1\tExitCallback_Continue();\n\1}

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

using Debugger.Wrappers.CorDebug;

namespace Debugger
{
	class ManagedCallback
	{
		NDebugger debugger;
		
		public NDebugger Debugger {
			get {
				return debugger;
			}
		}
		
		public ManagedCallback(NDebugger debugger)
		{
			this.debugger = debugger;
		}
		
		void EnterCallback(PausedReason pausedReason, string name, ICorDebugProcess pProcess)
		{
			debugger.TraceMessage("Callback: " + name);
			// ExitProcess may be called at any time when debuggee is killed
			if (name != "ExitProcess") debugger.AssertRunning();
			debugger.PauseSession = new PauseSession(pausedReason);
			debugger.SelectedProcess = debugger.GetProcess(pProcess);
			debugger.SelectedProcess.IsRunning = false;
		}
		
		void EnterCallback(PausedReason pausedReason, string name, ICorDebugAppDomain pAppDomain)
		{
			EnterCallback(pausedReason, name, pAppDomain.Process);
		}
		
		void EnterCallback(PausedReason pausedReason, string name, ICorDebugThread pThread)
		{
			debugger.TraceMessage("Callback: " + name);
			// ExitProcess may be called at any time when debuggee is killed
			if (name != "ExitProcess") debugger.AssertRunning();
			Thread thread = debugger.GetThread(pThread);
			debugger.PauseSession = new PauseSession(pausedReason);
			debugger.SelectedProcess = thread.Process;
			debugger.SelectedProcess.IsRunning = false;
			debugger.SelectedProcess.SelectedThread = thread;
		}
		
		void ExitCallback_Continue()
		{
			debugger.SelectedProcess.Continue();
		}
		
		void ExitCallback_Paused()
		{
			if (debugger.Evaluating) {
				// Ignore events during property evaluation
				ExitCallback_Continue();
			} else {
				if (debugger.SelectedThread != null) {
					// Disable all steppers - do not Deactivate since function tracking still needs them
					foreach(Stepper s in debugger.SelectedThread.Steppers) {
						s.PauseWhenComplete = false;
					}
					
					debugger.SelectedThread.SelectedFunction = debugger.SelectedThread.LastFunctionWithLoadedSymbols;
				}
				debugger.Pause();
			}
		}
		
		
		#region Program folow control
		
		public void StepComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugStepper pStepper, CorDebugStepReason reason)
		{
			EnterCallback(PausedReason.StepComplete, "StepComplete (" + reason.ToString() + ")", pThread);
			
			Thread thread = debugger.GetThread(pThread);
			Stepper stepper = thread.GetStepper(pStepper);
			
			debugger.TraceMessage(" - stepper info: " + stepper.ToString());
			
			thread.Steppers.Remove(stepper);
			stepper.OnStepComplete();
			
			// There is a race condition: The tracking step out can be triggered after stepping step over
			thread.CheckExpirationOfFunctions();
			
			if (stepper.PauseWhenComplete) {
				if (debugger.SelectedThread.LastFunction.HasSymbols) {
					ExitCallback_Paused();
				} else {
					// This should not happen with JMC enabled
					debugger.TraceMessage(" - leaving code without symbols");
					
					ExitCallback_Continue();
				}
			} else {
				ExitCallback_Continue();
			}
		}
		
		// Do not pass the pBreakpoint parameter as ICorDebugBreakpoint - marshaling of it fails in .NET 1.1
		public void Breakpoint(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, IntPtr pBreakpoint)
		{
			EnterCallback(PausedReason.Breakpoint, "Breakpoint", pThread);
			
			ExitCallback_Paused();
			
//			foreach (Breakpoint b in debugger.Breakpoints) {
//				if (b.Equals(pBreakpoint)) {
//					// TODO: Check that this works
//					b.OnHit();
//				}
//			}
		}
		
		public void BreakpointSetError(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugBreakpoint pBreakpoint, uint dwError)
		{
			EnterCallback(PausedReason.Other, "BreakpointSetError", pThread);
			
			ExitCallback_Continue();
		}
		
		public unsafe void Break(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread)
		{
			EnterCallback(PausedReason.Break, "Break", pThread);

			ExitCallback_Paused();
		}

		public void ControlCTrap(ICorDebugProcess pProcess)
		{
			EnterCallback(PausedReason.ControlCTrap, "ControlCTrap", pProcess);

			ExitCallback_Paused();
		}

		public unsafe void Exception(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int unhandled)
		{
			// Exception2 is used in .NET Framework 2.0
			
			if (debugger.DebuggeeVersion.StartsWith("v1.")) {
				// Forward the call to Exception2, which handles EnterCallback and ExitCallback
				ExceptionType exceptionType = (unhandled != 0)?ExceptionType.DEBUG_EXCEPTION_UNHANDLED:ExceptionType.DEBUG_EXCEPTION_FIRST_CHANCE;
				Exception2(pAppDomain, pThread, null, 0, (CorDebugExceptionCallbackType)exceptionType, 0);
			} else {
				// This callback should be ignored in v2 applications
				EnterCallback(PausedReason.Other, "Exception", pThread);
	
				ExitCallback_Continue();	
			}
		}

		#endregion

		#region Various

		public void LogSwitch(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, uint ulReason, string pLogSwitchName, string pParentName)
		{
			EnterCallback(PausedReason.Other, "LogSwitch", pThread);

			ExitCallback_Continue();
		}
		
		public void LogMessage(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, string pLogSwitchName, string pMessage)
		{
			EnterCallback(PausedReason.Other, "LogMessage", pThread);

			debugger.OnLogMessage(pMessage);

			ExitCallback_Continue();
		}

		public void EditAndContinueRemap(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction, int fAccurate)
		{
			EnterCallback(PausedReason.Other, "EditAndContinueRemap", pThread);

			ExitCallback_Continue();
		}
		
		public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval)
		{
			EnterCallback(PausedReason.EvalComplete, "EvalException", pThread);
			
			HandleEvalComplete(pAppDomain, pThread, corEval, true);
		}
		
		public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval)
		{
			EnterCallback(PausedReason.EvalComplete, "EvalComplete", pThread);
			
			HandleEvalComplete(pAppDomain, pThread, corEval, false);			
		}
		
		void HandleEvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval, bool exception)
		{
			// Let the eval know it that the CorEval has finished
			// this will also remove the eval form PendingEvals collection
			Eval eval = debugger.GetEval(corEval);
			if (eval != null) {
				eval.OnEvalComplete(!exception);
			}
			
			if (debugger.PendingEvals.Count > 0) {
				debugger.SetupNextEvaluation(debugger.GetThread(pThread));
				ExitCallback_Continue();
			} else {
				ExitCallback_Paused();
			}
		}
		
		public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode)
		{
			EnterCallback(PausedReason.DebuggerError, "DebuggerError", pProcess);

			string errorText = String.Format("Debugger error: \nHR = 0x{0:X} \nCode = 0x{1:X}", errorHR, errorCode);
			System.Windows.Forms.MessageBox.Show(errorText);

			ExitCallback_Paused();
		}

		public void UpdateModuleSymbols(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule, IStream pSymbolStream)
		{
			EnterCallback(PausedReason.Other, "UpdateModuleSymbols", pAppDomain);

			ExitCallback_Continue();
		}

		#endregion

		#region Start of Application

		public void CreateProcess(ICorDebugProcess pProcess)
		{
			EnterCallback(PausedReason.Other, "CreateProcess", pProcess);

			// Process is added in NDebugger.Start

			ExitCallback_Continue();
		}

		public void CreateAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain)
		{
			EnterCallback(PausedReason.Other, "CreateAppDomain", pAppDomain);

			pAppDomain.Attach();

			ExitCallback_Continue();
		}

		public void LoadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly)
		{
			EnterCallback(PausedReason.Other, "LoadAssembly", pAppDomain);

			ExitCallback_Continue();
		}

		public unsafe void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule)
		{
			EnterCallback(PausedReason.Other, "LoadModule", pAppDomain);

			debugger.AddModule(pModule);

			ExitCallback_Continue();
		}

		public void NameChange(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread)
		{
			if (pAppDomain != null)	{

				EnterCallback(PausedReason.Other, "NameChange: pAppDomain", pAppDomain);

				ExitCallback_Continue();

			}
			if (pThread != null) {

				EnterCallback(PausedReason.Other, "NameChange: pThread", pThread);

				Thread thread = debugger.GetThread(pThread);
				thread.HasBeenLoaded = true;

				ExitCallback_Continue();

			}
		}

		public void CreateThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread)
		{
			// We can not use pThread since it has not been added yet
			// and we continue from this callback anyway
			EnterCallback(PausedReason.Other, "CreateThread", pAppDomain);

			debugger.AddThread(pThread);

			ExitCallback_Continue();
		}

		public void LoadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c)
		{
			EnterCallback(PausedReason.Other, "LoadClass", pAppDomain);

			ExitCallback_Continue();
		}

		#endregion

		#region Exit of Application

		public void UnloadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c)
		{
			EnterCallback(PausedReason.Other, "UnloadClass", pAppDomain);

			ExitCallback_Continue();
		}

		public void UnloadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule)
		{
			EnterCallback(PausedReason.Other, "UnloadModule", pAppDomain);

			debugger.RemoveModule(pModule);

			ExitCallback_Continue();
		}

		public void UnloadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly)
		{
			EnterCallback(PausedReason.Other, "UnloadAssembly", pAppDomain);

			ExitCallback_Continue();
		}

		public void ExitThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread)
		{
			EnterCallback(PausedReason.Other, "ExitThread", pThread);

			Thread thread = debugger.GetThread(pThread);

			debugger.RemoveThread(thread);

			if (thread.Process.SelectedThread == thread) {
				thread.Process.SelectedThread = null;
			}

			try {
				ExitCallback_Continue();
			} catch (COMException e) {
				// For some reason this sometimes happens in .NET 1.1
				debugger.TraceMessage("Continue failed in ExitThread callback: " + e.Message);
			}
		}

		public void ExitAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain)
		{
			EnterCallback(PausedReason.Other, "ExitAppDomain", pAppDomain);

			ExitCallback_Continue();
		}
		
		public void ExitProcess(ICorDebugProcess pProcess)
		{
			EnterCallback(PausedReason.Other, "ExitProcess", pProcess);
			
			Process process = debugger.GetProcess(pProcess);
			
			debugger.RemoveProcess(process);
			
			if (debugger.Processes.Count == 0) {
				// Exit callback and then terminate the debugger
				debugger.MTA2STA.AsyncCall( delegate { debugger.TerminateDebugger(); } );
			}
		}
		
		#endregion
		
		#region ICorDebugManagedCallback2 Members
		
		public void ChangeConnection(ICorDebugProcess pProcess, uint dwConnectionId)
		{
			EnterCallback(PausedReason.Other, "ChangeConnection", pProcess);
			
			ExitCallback_Continue();
		}

		public void CreateConnection(ICorDebugProcess pProcess, uint dwConnectionId, IntPtr pConnName)
		{
			EnterCallback(PausedReason.Other, "CreateConnection", pProcess);
			
			ExitCallback_Continue();
		}

		public void DestroyConnection(ICorDebugProcess pProcess, uint dwConnectionId)
		{
			EnterCallback(PausedReason.Other, "DestroyConnection", pProcess);
			
			ExitCallback_Continue();
		}

		public void Exception2(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFrame pFrame, uint nOffset, CorDebugExceptionCallbackType exceptionType, uint dwFlags)
		{
			EnterCallback(PausedReason.Exception, "Exception2 (type=" + exceptionType.ToString() + ")", pThread);
			
			// This callback is also called from Exception(...)!!!! (the .NET 1.1 version)
			// Whatch out for the zeros and null!
			// Exception -> Exception2(pAppDomain, pThread, null, 0, exceptionType, 0);
			
			debugger.SelectedThread.CurrentExceptionType = (ExceptionType)exceptionType;
			
			if (ExceptionType.DEBUG_EXCEPTION_UNHANDLED != (ExceptionType)exceptionType) {
				// Handled exception
				if (debugger.PauseOnHandledException) {
					ExitCallback_Paused();
				} else {
					ExitCallback_Continue();					
				}
			} else {
				// Unhandled exception				
				ExitCallback_Paused();
			}
		}

		public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags)
		{
			EnterCallback(PausedReason.ExceptionIntercepted, "ExceptionUnwind", pThread);
			
			if (dwEventType == CorDebugExceptionUnwindCallbackType.DEBUG_EXCEPTION_INTERCEPTED) {
				ExitCallback_Paused();
			} else {
				ExitCallback_Continue();
			}
		}

		public void FunctionRemapComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction)
		{
			EnterCallback(PausedReason.Other, "FunctionRemapComplete", pThread);
			
			ExitCallback_Continue();
		}

		public void FunctionRemapOpportunity(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pOldFunction, ICorDebugFunction pNewFunction, uint oldILOffset)
		{
			EnterCallback(PausedReason.Other, "FunctionRemapOpportunity", pThread);
			
			ExitCallback_Continue();
		}

		public void MDANotification(ICorDebugController c, ICorDebugThread t, ICorDebugMDA mda)
		{
			if (c.Is<ICorDebugAppDomain>()) {
				EnterCallback(PausedReason.Other, "MDANotification", c.CastTo<ICorDebugAppDomain>());
			} else if (c.Is<ICorDebugProcess>()){
				EnterCallback(PausedReason.Other, "MDANotification", c.CastTo<ICorDebugProcess>());
			} else {
				throw new System.Exception("Unknown callback argument");
			}
			
			ExitCallback_Continue();
		}

		#endregion
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -