public AD7Module(DebuggedModule debuggedModule, DebuggedProcess process) { Debug.Assert(debuggedModule != null, "No module provided?"); Debug.Assert(process != null, "No process provided?"); this.DebuggedModule = debuggedModule; this.Process = process; }
internal static void AddProcess(DebuggedProcess process) { process.DebuggerExitEvent += process_DebuggerExitEvent; lock (s_processes) { s_processes.Add(process); } }
/// <summary> /// Finds the module for this context /// </summary> /// <param name="process">process of the context</param> /// <returns>[Optional] Module, if the frame has one</returns> internal DebuggedModule FindModule(DebuggedProcess process) { // CLRDBG TODO: Use module id to find the module if (this.pc.HasValue) { return process.ResolveAddress(this.pc.Value); } return null; }
internal ThreadCache(ISampleEngineCallback callback, DebuggedProcess debugger) { _threadList = new List<DebuggedThread>(); _stackFrames = new Dictionary<int, List<ThreadContext>>(); _topContext = new Dictionary<int, ThreadContext>(); _stateChange = true; _callback = callback; _debugger = debugger; _full = false; debugger.RunModeEvent += SendThreadEvents; }
internal static Task<string> ExecuteCommand(string command, DebuggedProcess process, bool ignoreFailures = false) { if (string.IsNullOrWhiteSpace(command)) throw new ArgumentNullException("command"); if (process == null) { throw new InvalidOperationException(MICoreResources.Error_NoMIDebuggerProcess); } command = command.Trim(); if (command[0] == '-') { return ExecuteMiCommand(process, command, ignoreFailures); } else { return process.ConsoleCmdAsync(command, ignoreFailures); } }
public Disassembly(DebuggedProcess process) { _process = process; _disassemlyCache = new SortedList<ulong, DisassemblyBlock>(); }
// this is inefficient so we try and grab everything in one gulp internal static async Task<DisasmInstruction[]> Disassemble(DebuggedProcess process, ulong startAddr, ulong endAddr) { string cmd = "-data-disassemble -s " + EngineUtils.AsAddr(startAddr, process.Is64BitArch) + " -e " + EngineUtils.AsAddr(endAddr, process.Is64BitArch) + " -- 0"; Results results = await process.CmdAsync(cmd, ResultClass.None); if (results.ResultClass != ResultClass.done) { return null; } return DecodeDisassemblyInstructions(results.Find<ValueListValue>("asm_insns").AsArray<TupleValue>()); }
public DebugUnixChild(DebuggedProcess process, LaunchOptions launchOptions) { _process = process; _threadStates = new Dictionary <int, ThreadProgress>(); _launchOptions = launchOptions; }
private static async Task<string> ExecuteMiCommand(DebuggedProcess lastProcess, string command, bool ignoreFailures) { Results results = await lastProcess.CmdAsync(command, ignoreFailures ? ResultClass.None : ResultClass.done); return results.ToString(); }
public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine) { uint processExitCode = 0; g_Process = this; _bStarted = false; _pendingMessages = new StringBuilder(400); _worker = worker; _launchOptions = launchOptions; _breakpointManager = bpman; Engine = engine; _libraryLoaded = new List <string>(); _loadOrder = 0; MICommandFactory = MICommandFactory.GetInstance(launchOptions.DebuggerMIMode, this); _waitDialog = MICommandFactory.SupportsStopOnDynamicLibLoad() ? new WaitDialog(ResourceStrings.LoadingSymbolMessage, ResourceStrings.LoadingSymbolCaption) : null; Natvis = new Natvis.Natvis(this); // we do NOT have real Win32 process IDs, so we use a guid AD_PROCESS_ID pid = new AD_PROCESS_ID(); pid.ProcessIdType = (int)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pid.guidProcessId = Guid.NewGuid(); this.Id = pid; SourceLineCache = new SourceLineCache(this); _callback = callback; _moduleList = new List <DebuggedModule>(); ThreadCache = new ThreadCache(callback, this); Disassembly = new Disassembly(this); VariablesToDelete = new List <string>(); MessageEvent += delegate(object o, string message) { // We can get messages before we have started the process // but we can't send them on until it is if (_bStarted) { _callback.OnOutputString(message); } else { _pendingMessages.Append(message); } }; LibraryLoadEvent += delegate(object o, EventArgs args) { ResultEventArgs results = args as MICore.Debugger.ResultEventArgs; string file = results.Results.TryFindString("host-name"); if (!string.IsNullOrEmpty(file) && MICommandFactory.SupportsStopOnDynamicLibLoad()) { _libraryLoaded.Add(file); if (_waitDialog != null) { _waitDialog.ShowWaitDialog(file); } } else if (this.MICommandFactory.Mode == MIMode.Clrdbg) { string id = results.Results.FindString("id"); ulong baseAddr = results.Results.FindAddr("base-address"); uint size = results.Results.FindUint("size"); bool symbolsLoaded = results.Results.FindInt("symbols-loaded") != 0; var module = new DebuggedModule(id, file, baseAddr, size, symbolsLoaded, string.Empty, _loadOrder++); lock (_moduleList) { _moduleList.Add(module); } _callback.OnModuleLoad(module); } else if (!string.IsNullOrEmpty(file)) { string addr = results.Results.TryFindString("loaded_addr"); if (string.IsNullOrEmpty(addr) || addr == "-") { return; // identifies the exe, not a real load } // generate module string id = results.Results.TryFindString("name"); bool symsLoaded = true; string symPath = null; if (results.Results.Contains("symbols-path")) { symPath = results.Results.FindString("symbols-path"); if (string.IsNullOrEmpty(symPath)) { symsLoaded = false; } } else { symPath = file; } ulong loadAddr = results.Results.FindAddr("loaded_addr"); uint size = results.Results.FindUint("size"); if (String.IsNullOrEmpty(id)) { id = file; } var module = FindModule(id); if (module == null) { module = new DebuggedModule(id, file, loadAddr, size, symsLoaded, symPath, _loadOrder++); lock (_moduleList) { _moduleList.Add(module); } _callback.OnModuleLoad(module); } } }; if (_launchOptions is LocalLaunchOptions) { this.Init(new MICore.LocalTransport(), _launchOptions); } else if (_launchOptions is PipeLaunchOptions) { this.Init(new MICore.PipeTransport(), _launchOptions); } else if (_launchOptions is TcpLaunchOptions) { this.Init(new MICore.TcpTransport(), _launchOptions); } else if (_launchOptions is SerialLaunchOptions) { string port = ((SerialLaunchOptions)_launchOptions).Port; this.Init(new MICore.SerialTransport(port), _launchOptions); } else { throw new ArgumentOutOfRangeException("LaunchInfo.options"); } MIDebugCommandDispatcher.AddProcess(this); // When the debuggee exits, we need to exit the debugger ProcessExitEvent += delegate(object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful ResultEventArgs results = args as MICore.Debugger.ResultEventArgs; if (results.Results.Contains("exit-code")) { processExitCode = results.Results.FindUint("exit-code"); } // quit MI Debugger _worker.PostOperation(CmdExitAsync); if (_waitDialog != null) { _waitDialog.EndWaitDialog(); } }; // When the debugger exits, we tell AD7 we are done DebuggerExitEvent += delegate(object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful // this is the last AD7 Event we can ever send // Also the transport is closed when this returns _callback.OnProcessExit(processExitCode); Dispose(); }; DebuggerAbortedEvent += delegate(object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful // The MI debugger process unexpectedly exited. _worker.PostOperation(() => { // If the MI Debugger exits before we get a resume call, we have no way of sending program destroy. So just let start debugging fail. if (!_connected) { return; } _callback.OnError(MICoreResources.Error_MIDebuggerExited); _callback.OnProcessExit(uint.MaxValue); Dispose(); }); }; ModuleLoadEvent += async delegate(object o, EventArgs args) { // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported if (_libraryLoaded.Count != 0) { string moduleNames = string.Join(", ", _libraryLoaded); try { _libraryLoaded.Clear(); SourceLineCache.OnLibraryLoad(); await _breakpointManager.BindAsync(); await CheckModules(); _bLastModuleLoadFailed = false; } catch (Exception e) { if (this.ProcessState == MICore.ProcessState.Exited) { return; // ignore exceptions after the process has exited } string exceptionDescription = EngineUtils.GetExceptionDescription(e); string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_ExceptionProcessingModules, moduleNames, exceptionDescription); // to avoid spamming the user, if the last module failed, we send the next failure to the output windiw instead of a message box if (!_bLastModuleLoadFailed) { _callback.OnError(message); _bLastModuleLoadFailed = true; } else { _callback.OnOutputMessage(message, enum_MESSAGETYPE.MT_OUTPUTSTRING); } } } if (_waitDialog != null) { _waitDialog.EndWaitDialog(); } if (MICommandFactory.SupportsStopOnDynamicLibLoad()) { CmdContinueAsync(); } }; // When we break we need to gather information BreakModeEvent += async delegate(object o, EventArgs args) { // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported ResultEventArgs results = args as MICore.Debugger.ResultEventArgs; if (_waitDialog != null) { _waitDialog.EndWaitDialog(); } if (!this._connected) { _initialBreakArgs = results; return; } try { await HandleBreakModeEvent(results); } catch (Exception e) { if (this.ProcessState == MICore.ProcessState.Exited) { return; // ignore exceptions after the process has exited } string exceptionDescription = EngineUtils.GetExceptionDescription(e); string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_FailedToEnterBreakState, exceptionDescription); _callback.OnError(message); Terminate(); } }; RunModeEvent += delegate(object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful if (!_bStarted) { _bStarted = true; // Send any strings we got before the process came up if (_pendingMessages.Length != 0) { try { _callback.OnOutputString(_pendingMessages.ToString()); } catch { // If something goes wrong sending the output, lets not crash VS } } _pendingMessages = null; } }; ErrorEvent += delegate(object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful ResultEventArgs result = (ResultEventArgs)args; _callback.OnError(result.Results.FindString("msg")); }; ThreadCreatedEvent += delegate(object o, EventArgs args) { ResultEventArgs result = (ResultEventArgs)args; ThreadCache.ThreadEvent(result.Results.FindInt("id"), /*deleted */ false); }; ThreadExitedEvent += delegate(object o, EventArgs args) { ResultEventArgs result = (ResultEventArgs)args; ThreadCache.ThreadEvent(result.Results.FindInt("id"), /*deleted*/ true); }; BreakChangeEvent += _breakpointManager.BreakpointModified; }
internal static async Task<BindResult> Bind(string functionName, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { return EvalBindResult(await process.MICommandFactory.BreakInsert(functionName, condition, ResultClass.None), pbreak); }
private static async Task <string> ExecuteMiCommand(DebuggedProcess lastProcess, string command) { Results results = await lastProcess.CmdAsync(command, ResultClass.None); return(results.ToString()); }
internal static async Task <BindResult> Bind(string functionName, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); return(EvalBindResult(await process.MICommandFactory.BreakInsert(functionName, condition, ResultClass.None), pbreak)); }
internal static async Task <BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, IEnumerable <Checksum> checksums, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); string basename = System.IO.Path.GetFileName(documentName); // get basename from Windows path basename = process.EscapePath(basename); BindResult bindResults = EvalBindResult(await process.MICommandFactory.BreakInsert(basename, line, condition, checksums, ResultClass.None), pbreak); // On GDB, the returned line information is from the pending breakpoint instead of the bound breakpoint. // Check the address mapping to make sure the line info is correct. if (process.MICommandFactory.Mode == MIMode.Gdb && bindResults.BoundBreakpoints != null) { foreach (var boundBreakpoint in bindResults.BoundBreakpoints) { boundBreakpoint.Line = await process.LineForStartAddress(basename, boundBreakpoint.Addr); } } return(bindResults); }
internal static async Task <BindResult> Bind(string address, uint size, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); return(EvalBindWatchResult(await process.MICommandFactory.BreakWatch(address, size, ResultClass.None), pbreak, address, size)); }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(_pollThread == null); Debug.Assert(_engineCallback == null); Debug.Assert(_debuggedProcess == null); Debug.Assert(_ad7ProgramId == Guid.Empty); process = null; _engineCallback = new EngineCallback(this, ad7Callback); Exception exception; try { // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop LaunchOptions launchOptions = LaunchOptions.GetInstance(_configStore, exe, args, dir, options, _engineCallback, TargetEngine.Native, Logger); // We are being asked to debug a process when we currently aren't debugging anything _pollThread = new WorkerThread(Logger); var cancellationTokenSource = new CancellationTokenSource(); using (cancellationTokenSource) { _pollThread.RunOperation(ResourceStrings.InitializingDebugger, cancellationTokenSource, (HostWaitLoop waitLoop) => { try { _debuggedProcess = new DebuggedProcess(true, launchOptions, _engineCallback, _pollThread, _breakpointManager, this, _configStore); } finally { // If there is an exception from the DebuggeedProcess constructor, it is our responsibility to dispose the DeviceAppLauncher, // otherwise the DebuggedProcess object takes ownership. if (_debuggedProcess == null && launchOptions.DeviceAppLauncher != null) { launchOptions.DeviceAppLauncher.Dispose(); } } _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError; return(_debuggedProcess.Initialize(waitLoop, cancellationTokenSource.Token)); }); } EngineUtils.RequireOk(port.GetProcess(_debuggedProcess.Id, out process)); return(Constants.S_OK); } catch (Exception e) when(ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true)) { exception = e; // Return from the catch block so that we can let the exception unwind - the stack can get kind of big } // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and then // return E_ABORT. Logger.Flush(); SendStartDebuggingError(exception); Dispose(); return(Constants.E_ABORT); }
internal static async Task <BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, bool enabled, IEnumerable <Checksum> checksums, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); string compilerSrcName; if (!process.MapCurrentSrcToCompileTimeSrc(documentName, out compilerSrcName)) { compilerSrcName = Path.GetFileName(documentName); } return(await EvalBindResult(await process.MICommandFactory.BreakInsert(compilerSrcName, process.UseUnixSymbolPaths, line, condition, enabled, checksums, ResultClass.None), pbreak)); }
internal static async Task <BindResult> Bind(ulong codeAddress, DebuggedProcess process, string condition, bool enabled, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); return(await EvalBindResult(await process.MICommandFactory.BreakInsert(codeAddress, condition, enabled, ResultClass.None), pbreak)); }
internal static async Task<BindResult> Bind(string address, uint size, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); return EvalBindWatchResult(await process.MICommandFactory.BreakWatch(address, size, ResultClass.None), pbreak, address, size); }
internal static async Task<BindResult> Bind(ulong codeAddress, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); return EvalBindResult(await process.MICommandFactory.BreakInsert(codeAddress, condition, ResultClass.None), pbreak); }
public AD7DocumentContext(MITextPosition textPosition, AD7MemoryAddress codeContext, DebuggedProcess debuggedProcess) { _textPosition = textPosition; _codeContext = codeContext; _debuggedProcess = debuggedProcess; }
private async Task DeleteInternal(DebuggedProcess process) { if (process.ProcessState != MICore.ProcessState.Exited) { await process.MICommandFactory.BreakDelete(Number); } }
private static async Task <string> ExecuteMiCommand(DebuggedProcess lastProcess, string command, bool ignoreFailures) { Results results = await lastProcess.CmdAsync(command, ignoreFailures?ResultClass.None : ResultClass.done); return(results.ToString()); }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(_pollThread == null); Debug.Assert(_engineCallback == null); Debug.Assert(_debuggedProcess == null); Debug.Assert(_ad7ProgramId == Guid.Empty); // Check if the logger was enabled late. Logger.LoadMIDebugLogger(_configStore); process = null; _engineCallback = new EngineCallback(this, ad7Callback); Exception exception; try { // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop LaunchOptions launchOptions = LaunchOptions.GetInstance(_configStore, exe, args, dir, options, _engineCallback, TargetEngine.Native, Logger); // We are being asked to debug a process when we currently aren't debugging anything _pollThread = new WorkerThread(Logger); var cancellationTokenSource = new CancellationTokenSource(); using (cancellationTokenSource) { _pollThread.RunOperation(ResourceStrings.InitializingDebugger, cancellationTokenSource, (HostWaitLoop waitLoop) => { try { _debuggedProcess = new DebuggedProcess(true, launchOptions, _engineCallback, _pollThread, _breakpointManager, this, _configStore); } finally { // If there is an exception from the DebuggeedProcess constructor, it is our responsibility to dispose the DeviceAppLauncher, // otherwise the DebuggedProcess object takes ownership. if (_debuggedProcess == null && launchOptions.DeviceAppLauncher != null) { launchOptions.DeviceAppLauncher.Dispose(); } } _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError; return _debuggedProcess.Initialize(waitLoop, cancellationTokenSource.Token); }); } EngineUtils.RequireOk(port.GetProcess(_debuggedProcess.Id, out process)); return Constants.S_OK; } catch (Exception e) when (ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true)) { exception = e; // Return from the catch block so that we can let the exception unwind - the stack can get kind of big } // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and then // return E_ABORT. Logger.Flush(); SendStartDebuggingError(exception); Dispose(); return Constants.E_ABORT; }
internal async Task <List <BoundBreakpoint> > SyncBreakpoint(DebuggedProcess process) { ResultValue bkpt = await process.MICommandFactory.BreakInfo(Number); return(BindAddresses(bkpt)); }
internal async Task EnableAsync(bool bEnable, DebuggedProcess process) { await EnableInternal(bEnable, process); }
private async Task EnableInternal(bool bEnable, DebuggedProcess process) { await process.MICommandFactory.BreakEnable(bEnable, Number); }
public CygwinFilePathMapper(DebuggedProcess debuggedProcess) { this._debuggedProcess = debuggedProcess; this._cygwinToWindows = new Dictionary <string, string>(); }
internal void Delete(DebuggedProcess process) { process.WorkerThread.RunOperation(async() => await DeleteInternal(process)); }
public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, string registryRoot) { uint processExitCode = 0; g_Process = this; _bStarted = false; _pendingMessages = new StringBuilder(400); _worker = worker; _launchOptions = launchOptions; _breakpointManager = bpman; Engine = engine; _libraryLoaded = new List<string>(); _loadOrder = 0; MICommandFactory = MICommandFactory.GetInstance(launchOptions.DebuggerMIMode, this); _waitDialog = MICommandFactory.SupportsStopOnDynamicLibLoad() ? new WaitDialog(ResourceStrings.LoadingSymbolMessage, ResourceStrings.LoadingSymbolCaption) : null; Natvis = new Natvis.Natvis(this); // we do NOT have real Win32 process IDs, so we use a guid AD_PROCESS_ID pid = new AD_PROCESS_ID(); pid.ProcessIdType = (int)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pid.guidProcessId = Guid.NewGuid(); this.Id = pid; SourceLineCache = new SourceLineCache(this); _callback = callback; _moduleList = new List<DebuggedModule>(); ThreadCache = new ThreadCache(callback, this); Disassembly = new Disassembly(this); ExceptionManager = new ExceptionManager(MICommandFactory, _worker, _callback, registryRoot); VariablesToDelete = new List<string>(); MessageEvent += delegate (object o, string message) { // We can get messages before we have started the process // but we can't send them on until it is if (_bStarted) { _callback.OnOutputString(message); } else { _pendingMessages.Append(message); } }; LibraryLoadEvent += delegate (object o, EventArgs args) { ResultEventArgs results = args as MICore.Debugger.ResultEventArgs; string file = results.Results.TryFindString("host-name"); if (!string.IsNullOrEmpty(file) && MICommandFactory.SupportsStopOnDynamicLibLoad()) { _libraryLoaded.Add(file); if (_waitDialog != null) { _waitDialog.ShowWaitDialog(file); } } else if (this.MICommandFactory.Mode == MIMode.Clrdbg) { string id = results.Results.FindString("id"); ulong baseAddr = results.Results.FindAddr("base-address"); uint size = results.Results.FindUint("size"); bool symbolsLoaded = results.Results.FindInt("symbols-loaded") != 0; var module = new DebuggedModule(id, file, baseAddr, size, symbolsLoaded, string.Empty, _loadOrder++); lock (_moduleList) { _moduleList.Add(module); } _callback.OnModuleLoad(module); } else if (!string.IsNullOrEmpty(file)) { string addr = results.Results.TryFindString("loaded_addr"); if (string.IsNullOrEmpty(addr) || addr == "-") { return; // identifies the exe, not a real load } // generate module string id = results.Results.TryFindString("name"); bool symsLoaded = true; string symPath = null; if (results.Results.Contains("symbols-path")) { symPath = results.Results.FindString("symbols-path"); if (string.IsNullOrEmpty(symPath)) { symsLoaded = false; } } else { symPath = file; } ulong loadAddr = results.Results.FindAddr("loaded_addr"); uint size = results.Results.FindUint("size"); if (String.IsNullOrEmpty(id)) { id = file; } var module = FindModule(id); if (module == null) { module = new DebuggedModule(id, file, loadAddr, size, symsLoaded, symPath, _loadOrder++); lock (_moduleList) { _moduleList.Add(module); } _callback.OnModuleLoad(module); } } }; if (_launchOptions is LocalLaunchOptions) { this.Init(new MICore.LocalTransport(), _launchOptions); } else if (_launchOptions is PipeLaunchOptions) { this.Init(new MICore.PipeTransport(), _launchOptions); } else if (_launchOptions is TcpLaunchOptions) { this.Init(new MICore.TcpTransport(), _launchOptions); } else if (_launchOptions is SerialLaunchOptions) { string port = ((SerialLaunchOptions)_launchOptions).Port; this.Init(new MICore.SerialTransport(port), _launchOptions); } else { throw new ArgumentOutOfRangeException("LaunchInfo.options"); } MIDebugCommandDispatcher.AddProcess(this); // When the debuggee exits, we need to exit the debugger ProcessExitEvent += delegate (object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful ResultEventArgs results = args as MICore.Debugger.ResultEventArgs; if (results.Results.Contains("exit-code")) { processExitCode = results.Results.FindUint("exit-code"); } // quit MI Debugger _worker.PostOperation(CmdExitAsync); if (_waitDialog != null) { _waitDialog.EndWaitDialog(); } }; // When the debugger exits, we tell AD7 we are done DebuggerExitEvent += delegate (object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful // this is the last AD7 Event we can ever send // Also the transport is closed when this returns _callback.OnProcessExit(processExitCode); Dispose(); }; DebuggerAbortedEvent += delegate (object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful // The MI debugger process unexpectedly exited. _worker.PostOperation(() => { // If the MI Debugger exits before we get a resume call, we have no way of sending program destroy. So just let start debugging fail. if (!_connected) { return; } _callback.OnError(MICoreResources.Error_MIDebuggerExited); _callback.OnProcessExit(uint.MaxValue); Dispose(); }); }; ModuleLoadEvent += async delegate (object o, EventArgs args) { // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported if (_libraryLoaded.Count != 0) { string moduleNames = string.Join(", ", _libraryLoaded); try { _libraryLoaded.Clear(); SourceLineCache.OnLibraryLoad(); await _breakpointManager.BindAsync(); await CheckModules(); _bLastModuleLoadFailed = false; } catch (Exception e) { if (this.ProcessState == MICore.ProcessState.Exited) { return; // ignore exceptions after the process has exited } string exceptionDescription = EngineUtils.GetExceptionDescription(e); string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_ExceptionProcessingModules, moduleNames, exceptionDescription); // to avoid spamming the user, if the last module failed, we send the next failure to the output windiw instead of a message box if (!_bLastModuleLoadFailed) { _callback.OnError(message); _bLastModuleLoadFailed = true; } else { _callback.OnOutputMessage(message, enum_MESSAGETYPE.MT_OUTPUTSTRING); } } } if (_waitDialog != null) { _waitDialog.EndWaitDialog(); } if (MICommandFactory.SupportsStopOnDynamicLibLoad()) { CmdContinueAsync(); } }; // When we break we need to gather information BreakModeEvent += async delegate (object o, EventArgs args) { // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported ResultEventArgs results = args as MICore.Debugger.ResultEventArgs; if (_waitDialog != null) { _waitDialog.EndWaitDialog(); } if (!this._connected) { _initialBreakArgs = results; return; } try { await HandleBreakModeEvent(results); } catch (Exception e) { if (this.ProcessState == MICore.ProcessState.Exited) { return; // ignore exceptions after the process has exited } string exceptionDescription = EngineUtils.GetExceptionDescription(e); string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_FailedToEnterBreakState, exceptionDescription); _callback.OnError(message); Terminate(); } }; RunModeEvent += delegate (object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful if (!_bStarted) { _bStarted = true; // Send any strings we got before the process came up if (_pendingMessages.Length != 0) { try { _callback.OnOutputString(_pendingMessages.ToString()); } catch { // If something goes wrong sending the output, lets not crash VS } } _pendingMessages = null; } }; ErrorEvent += delegate (object o, EventArgs args) { // NOTE: Exceptions leaked from this method may cause VS to crash, be careful ResultEventArgs result = (ResultEventArgs)args; _callback.OnError(result.Results.FindString("msg")); }; ThreadCreatedEvent += delegate (object o, EventArgs args) { ResultEventArgs result = (ResultEventArgs)args; ThreadCache.ThreadEvent(result.Results.FindInt("id"), /*deleted */false); }; ThreadExitedEvent += delegate (object o, EventArgs args) { ResultEventArgs result = (ResultEventArgs)args; ThreadCache.ThreadEvent(result.Results.FindInt("id"), /*deleted*/true); }; BreakChangeEvent += _breakpointManager.BreakpointModified; }
internal async Task DeleteAsync(DebuggedProcess process) { await DeleteInternal(process); }
// this is inefficient so we try and grab everything in one gulp internal async Task<IEnumerable<DisasmInstruction>> Disassemble(DebuggedProcess process, string file, uint line, uint dwInstructions) { if (file.IndexOf(' ') >= 0) // only needs escaping if filename contains a space { file = process.EscapePath(file); } string cmd = "-data-disassemble -f " + file + " -l " + line.ToString() + " -n " + dwInstructions.ToString() + " -- 1"; Results results = await process.CmdAsync(cmd, ResultClass.None); if (results.ResultClass != ResultClass.done) { return null; } return DecodeSourceAnnotatedDisassemblyInstructions(results.Find<ResultListValue>("asm_insns").FindAll<TupleValue>("src_and_asm_line")); }
internal async Task<List<BoundBreakpoint>> SyncBreakpoint(DebuggedProcess process) { ResultValue bkpt = await process.MICommandFactory.BreakInfo(Number); return BindAddresses(bkpt); }
public int LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { DebugHelper.TraceEnteringMethod(); Callback = new EngineCallback(this, ad7Callback); DebuggedProcess = new DebuggedProcess(this, IPAddress.Parse(args), Callback); DebuggedProcess.ApplicationClosed += _debuggedProcess_ApplicationClosed; DebuggedProcess.StartDebugging(); process = RemoteProcess = new MonoProcess(port); return VSConstants.S_OK; }
internal static async Task<BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); string basename = System.IO.Path.GetFileName(documentName); // get basename from Windows path basename = process.EscapePath(basename); BindResult bindResults = EvalBindResult(await process.MICommandFactory.BreakInsert(basename, line, condition, ResultClass.None), pbreak); // On GDB, the returned line information is from the pending breakpoint instead of the bound breakpoint. // Check the address mapping to make sure the line info is correct. if (process.MICommandFactory.Mode == MIMode.Gdb && bindResults.BoundBreakpoints != null) { foreach (var boundBreakpoint in bindResults.BoundBreakpoints) { boundBreakpoint.Line = await process.LineForStartAddress(basename, boundBreakpoint.Addr); } } return bindResults; }
internal void Delete(DebuggedProcess process) { process.WorkerThread.RunOperation(async () => await DeleteInternal(process)); }
internal static async Task <BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { string basename = System.IO.Path.GetFileName(documentName); // get basename from Windows path Results bindResult = await process.MICommandFactory.BreakInsert(process.EscapePath(basename), line, condition, ResultClass.None); string errormsg = "Unknown error"; if (bindResult.ResultClass == ResultClass.error) { if (bindResult.Contains("msg")) { errormsg = bindResult.FindString("msg"); } if (String.IsNullOrWhiteSpace(errormsg)) { errormsg = "Unknown error"; } return(new BindResult(errormsg)); } else if (bindResult.ResultClass != ResultClass.done) { return(new BindResult(errormsg)); } TupleValue bkpt = null; ValueListValue list = null; if (bindResult.Contains("bkpt")) { ResultValue b = bindResult.Find("bkpt"); if (b is TupleValue) { bkpt = b as TupleValue; } else if (b is ValueListValue) { // "<MULTIPLE>" sometimes includes a list of bound breakpoints list = b as ValueListValue; bkpt = list.Content[0] as TupleValue; } } else { // If the source file is not found, "done" is the result without a binding // (the error is sent via an "&" string and hence lost) return(new BindResult(errormsg)); } Debug.Assert(bkpt.FindString("type") == "breakpoint"); string number = bkpt.FindString("number"); string addr = bkpt.TryFindString("addr"); PendingBreakpoint bp = new PendingBreakpoint(pbreak, number, StringToBreakpointState(addr)); if (list == null) // single breakpoint { BoundBreakpoint bbp = bp.GetBoundBreakpoint(bkpt); if (bbp == null) { return(new BindResult(bp, MICoreResources.Status_BreakpointPending)); } return(new BindResult(bp, bbp)); } else // <MULTIPLE> with list of addresses { BindResult res = new BindResult(bp); for (int i = 1; i < list.Content.Length; ++i) { BoundBreakpoint bbp = bp.GetBoundBreakpoint(list.Content[i] as TupleValue); res.BoundBreakpoints.Add(bbp); } return(res); } }
internal static async Task <BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { process.VerifyNotDebuggingCoreDump(); string basename = System.IO.Path.GetFileName(documentName); // get basename from Windows path return(EvalBindResult(await process.MICommandFactory.BreakInsert(process.EscapePath(basename), line, condition, ResultClass.None), pbreak)); }
internal void Enable(bool bEnable, DebuggedProcess process) { process.WorkerThread.RunOperation(async () => { await EnableInternal(bEnable, process); }); }
public Disassembly(DebuggedProcess process) { _process = process; _disassemlyCache = new SortedList <ulong, DisassemblyBlock>(); }
private void Dispose() { WorkerThread pollThread = _pollThread; DebuggedProcess debuggedProcess = _debuggedProcess; _engineCallback = null; _debuggedProcess = null; _pollThread = null; _ad7ProgramId = Guid.Empty; if(debuggedProcess != null) debuggedProcess.Close(); if(pollThread != null) pollThread.Close(); }
public SourceLineCache(DebuggedProcess process) { _process = process; _mapFileToLinenums = new Dictionary<string, SourceLine[]>(); }
internal async Task SetConditionAsync(string expr, DebuggedProcess process) { if (process.ProcessState != MICore.ProcessState.Exited) { await process.MICommandFactory.BreakCondition(Number, expr); } }
private static async Task<string> ExecuteMiCommand(DebuggedProcess lastProcess, string command) { Results results = await lastProcess.CmdAsync(command, ResultClass.None); return results.ToString(); }
internal static async Task<BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak) { string basename = System.IO.Path.GetFileName(documentName); // get basename from Windows path return EvalBindResult(await process.MICommandFactory.BreakInsert(process.EscapePath(basename), line, condition, ResultClass.None), pbreak); }
public CygwinFilePathMapper(DebuggedProcess debuggedProcess) { _debuggedProcess = debuggedProcess; _cygwinToWindows = new Dictionary<string, string>(); }
private void Dispose() { WorkerThread pollThread = _pollThread; DebuggedProcess debuggedProcess = _debuggedProcess; _engineCallback = null; _debuggedProcess = null; _pollThread = null; _ad7ProgramId = Guid.Empty; debuggedProcess?.Close(); pollThread?.Close(); }
public SourceLineCache(DebuggedProcess process) { _process = process; _mapFileToLinenums = new Dictionary <string, SourceLineMap>(); }