// Engines notify the debugger about the results of a symbol serach by sending an instance // of IDebugSymbolSearchEvent2 public void OnSymbolSearch(DebuggedModule module, string status, uint dwStatusFlags) { string statusString = (dwStatusFlags == 1 ? "Symbols Loaded - " : "No symbols loaded") + status; AD7Module ad7Module = new AD7Module(module); AD7SymbolSearchEvent eventObject = new AD7SymbolSearchEvent(ad7Module, statusString, dwStatusFlags); Send(eventObject, AD7SymbolSearchEvent.IID, null); }
public void OnModuleUnload(DebuggedModule debuggedModule) { Debug.Assert(Worker.CurrentThreadId == m_engine.DebuggedProcess.PollThreadId); AD7Module ad7Module = (AD7Module)debuggedModule.Client; Debug.Assert(ad7Module != null); AD7ModuleLoadEvent eventObject = new AD7ModuleLoadEvent(ad7Module, false /* this is a module unload */); Send(eventObject, AD7ModuleLoadEvent.IID, null); }
// EnumModules is called by the debugger when it needs to enumerate the modules in the program. public int EnumModules(out IEnumDebugModules2 ppEnum) { Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId); DebuggedModule[] modules = m_debuggedProcess.GetModules(); AD7Module[] moduleObjects = new AD7Module[modules.Length]; for (int i = 0; i < modules.Length; i++) { moduleObjects[i] = new AD7Module(modules[i]); } ppEnum = new Microsoft.VisualStudio.Debugger.SampleEngine.AD7ModuleEnum(moduleObjects); return(Constants.S_OK); }
public void OnModuleLoad(DebuggedModule debuggedModule) { // This will get called when the entrypoint breakpoint is fired because the engine sends a mod-load event // for the exe. if (m_engine.DebuggedProcess != null) { Debug.Assert(Worker.CurrentThreadId == m_engine.DebuggedProcess.PollThreadId); } AD7Module ad7Module = new AD7Module(debuggedModule); AD7ModuleLoadEvent eventObject = new AD7ModuleLoadEvent(ad7Module, true /* this is a module load */); debuggedModule.Client = ad7Module; // The sample engine does not support binding breakpoints as modules load since the primary exe is the only module // symbols are loaded for. A production debugger will need to bind breakpoints when a new module is loaded. Send(eventObject, AD7ModuleLoadEvent.IID, null); }
// Construct a FRAMEINFO for this stack frame with the requested information. public void SetFrameInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, out FRAMEINFO frameInfo) { frameInfo = new FRAMEINFO(); uint ip = m_threadContext.eip; DebuggedModule module = m_engine.DebuggedProcess.ResolveAddress(ip); // The debugger is asking for the formatted name of the function which is displayed in the callstack window. // There are several optional parts to this name including the module, argument types and values, and line numbers. // The optional information is requested by setting flags in the dwFieldSpec parameter. if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME) != 0) { // If there is source information, construct a string that contains the module name, function name, and optionally argument names and values. if (m_hasSource) { frameInfo.m_bstrFuncName = ""; if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) { frameInfo.m_bstrFuncName = System.IO.Path.GetFileName(module.Name) + "!"; } frameInfo.m_bstrFuncName += m_functionName; if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS) != 0 && m_numParameters > 0) { frameInfo.m_bstrFuncName += "("; for (int i = 0; i < m_parameters.Length; i++) { if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES) != 0) { frameInfo.m_bstrFuncName += m_parameters[i].m_typeName + " "; } if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES) != 0) { frameInfo.m_bstrFuncName += m_parameters[i].m_name; } if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES) != 0) { frameInfo.m_bstrFuncName += "=" + m_parameters[i].m_value; } if (i < m_parameters.Length - 1) { frameInfo.m_bstrFuncName += ", "; } } frameInfo.m_bstrFuncName += ")"; } if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES) != 0) { frameInfo.m_bstrFuncName += " Line:" + m_lineNum.ToString(); } } else { // No source information, so only return the module name and the instruction pointer. if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) { frameInfo.m_bstrFuncName = EngineUtils.GetAddressDescription(module, ip); } else { frameInfo.m_bstrFuncName = EngineUtils.GetAddressDescription(null, ip); } } frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME; } // The debugger is requesting the name of the module for this stack frame. if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_MODULE) != 0 && module != null) { frameInfo.m_bstrModule = module.Name; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_MODULE; } // The debugger is requesting the range of memory addresses for this frame. // For the sample engine, this is the contents of the frame pointer. if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_STACKRANGE) != 0) { frameInfo.m_addrMin = m_threadContext.ebp; frameInfo.m_addrMax = m_threadContext.ebp; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STACKRANGE; } // The debugger is requesting the IDebugStackFrame2 value for this frame info. if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FRAME) != 0) { frameInfo.m_pFrame = this; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FRAME; } // Does this stack frame of symbols loaded? if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO) != 0) { frameInfo.m_fHasDebugInfo = m_hasSource ? 1 : 0; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO; } // Is this frame stale? if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_STALECODE) != 0) { frameInfo.m_fStaleCode = 0; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STALECODE; } // The debugger would like a pointer to the IDebugModule2 that contains this stack frame. if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP) != 0) { if (module != null) { AD7Module ad7Module = (AD7Module)module.Client; Debug.Assert(ad7Module != null); frameInfo.m_pModule = ad7Module; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP; } } }
public AD7SymbolSearchEvent(AD7Module module, string searchInfo, uint symbolFlags) { m_module = module; m_searchInfo = searchInfo; m_symbolFlags = symbolFlags; }
public AD7ModuleLoadEvent(AD7Module module, bool fLoad) { m_module = module; m_fLoad = fLoad; }
// EnumModules is called by the debugger when it needs to enumerate the modules in the program. public int EnumModules(out IEnumDebugModules2 ppEnum) { Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId); DebuggedModule[] modules = m_debuggedProcess.GetModules(); AD7Module[] moduleObjects = new AD7Module[modules.Length]; for (int i = 0; i < modules.Length; i++) { moduleObjects[i] = new AD7Module(modules[i]); } ppEnum = new Microsoft.VisualStudio.Debugger.SampleEngine.AD7ModuleEnum(moduleObjects); return Constants.S_OK; }