internal async Task Eval() { _engine.CurrentRadix(); // ensure the radix value is up-to-date string execCommandString = "-exec "; if (_strippedName.StartsWith(execCommandString)) { // special case for executing raw mi commands. string consoleCommand = _strippedName.Substring(execCommandString.Length); string consoleResults = null; try { consoleResults = await MIDebugCommandDispatcher.ExecuteCommand(consoleCommand); Value = String.Empty; this.TypeName = null; } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } UnexpectedMIResultException miException = e as UnexpectedMIResultException; string message; if (miException != null && miException.MIError != null) { message = miException.MIError; } else { message = e.Message; } SetAsError(string.Format(ResourceStrings.Failed_ExecCommandError, message)); } if (!String.IsNullOrEmpty(consoleResults)) { _debuggedProcess.WriteOutput(consoleResults); } } else { int threadId = Client.GetDebuggedThread().Id; uint frameLevel = _ctx.Level; Results results = await _engine.DebuggedProcess.MICommandFactory.VarCreate(_strippedName, threadId, frameLevel, ResultClass.None); if (results.ResultClass == ResultClass.done) { _internalName = results.FindString("name"); TypeName = results.TryFindString("type"); if (results.Contains("dynamic") && results.Contains("has_more")) { CountChildren = results.FindUint("has_more"); } else { CountChildren = results.FindUint("numchild"); } Value = results.TryFindString("value"); if ((Value == String.Empty || _format != null) && !string.IsNullOrEmpty(_internalName)) { if (_format != null) { await Format(); } else { results = await _engine.DebuggedProcess.MICommandFactory.VarEvaluateExpression(_internalName, ResultClass.None); if (results.ResultClass == ResultClass.done) { Value = results.FindString("value"); } else if (results.ResultClass == ResultClass.error) { SetAsError(results.FindString("msg")); } else { Debug.Fail("Weird msg from -var-evaluate-expression"); } } } } else if (results.ResultClass == ResultClass.error) { SetAsError(results.FindString("msg")); } else { Debug.Fail("Weird msg from -var-create"); } } }
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 async Task Eval(enum_EVALFLAGS dwFlags = 0, DAPEvalFlags dwDAPFlags = 0) { this.VerifyNotDisposed(); await _engine.UpdateRadixAsync(_engine.CurrentRadix()); // ensure the radix value is up-to-date try { string consoleCommand; if (IsConsoleExecCmd(_strippedName, out consoleCommand)) { // special case for executing raw mi commands. string consoleResults = null; consoleResults = await MIDebugCommandDispatcher.ExecuteCommand(consoleCommand, _debuggedProcess, ignoreFailures : true); Value = String.Empty; this.TypeName = null; if (!String.IsNullOrEmpty(consoleResults)) { _debuggedProcess.WriteOutput(consoleResults); } } else { bool canRunClipboardContextCommands = this._debuggedProcess.MICommandFactory.Mode == MIMode.Gdb && dwDAPFlags.HasFlag(DAPEvalFlags.CLIPBOARD_CONTEXT); int numElements = 200; if (canRunClipboardContextCommands) { string showPrintElementsResult = await MIDebugCommandDispatcher.ExecuteCommand("show print elements", _debuggedProcess, ignoreFailures : true); // Possible values for 'numElementsStr' // "Limit on string chars or array elements to print is <number>." // "Limit on string chars or array elements to print is unlimited." string numElementsStr = Regex.Match(showPrintElementsResult, @"\d+").Value; if (!string.IsNullOrEmpty(numElementsStr) && int.TryParse(numElementsStr, out numElements) && numElements != 0) { await MIDebugCommandDispatcher.ExecuteCommand("set print elements 0", _debuggedProcess, ignoreFailures : true); } } int threadId = Client.GetDebuggedThread().Id; uint frameLevel = _ctx.Level; Results results = await _engine.DebuggedProcess.MICommandFactory.VarCreate(_strippedName, threadId, frameLevel, dwFlags, ResultClass.None); if (results.ResultClass == ResultClass.done) { _internalName = results.FindString("name"); TypeName = results.TryFindString("type"); if (results.Contains("dynamic")) { IsPreformatted = true; } if (results.Contains("dynamic") && results.Contains("has_more")) { CountChildren = results.FindUint("has_more"); } else { CountChildren = results.FindUint("numchild"); } if (results.Contains("displayhint")) { DisplayHint = results.FindString("displayhint"); } if (results.Contains("attributes")) { if (results.FindString("attributes") == "noneditable") { _isReadonly = true; } _attribsFetched = true; } Value = results.TryFindString("value"); if ((Value == String.Empty || _format != null) && !string.IsNullOrEmpty(_internalName)) { if (_format != null) { await Format(); } else { results = await _engine.DebuggedProcess.MICommandFactory.VarEvaluateExpression(_internalName, ResultClass.None); if (results.ResultClass == ResultClass.done) { Value = results.FindString("value"); } else if (results.ResultClass == ResultClass.error) { SetAsError(results.FindString("msg")); } else { Debug.Fail("Unexpected format of msg from -var-evaluate-expression"); } } } } else if (results.ResultClass == ResultClass.error) { SetAsError(results.FindString("msg")); } else { Debug.Fail("Unexpected format of msg from -var-create"); } if (canRunClipboardContextCommands && numElements != 0) { await MIDebugCommandDispatcher.ExecuteCommand(string.Format(CultureInfo.InvariantCulture, "set print elements {0}", numElements), _debuggedProcess, ignoreFailures : true); } } } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } UnexpectedMIResultException miException = e as UnexpectedMIResultException; string message; if (miException != null && miException.MIError != null) { message = miException.MIError; } else { message = e.Message; } SetAsError(string.Format(ResourceStrings.Failed_ExecCommandError, message)); } }
internal async Task Eval(enum_EVALFLAGS dwFlags = 0) { this.VerifyNotDisposed(); await _engine.UpdateRadixAsync(_engine.CurrentRadix()); // ensure the radix value is up-to-date try { string consoleCommand; if (IsConsoleExecCmd(_strippedName, out consoleCommand)) { // special case for executing raw mi commands. string consoleResults = null; consoleResults = await MIDebugCommandDispatcher.ExecuteCommand(consoleCommand, _debuggedProcess, ignoreFailures : true); Value = String.Empty; this.TypeName = null; if (!String.IsNullOrEmpty(consoleResults)) { _debuggedProcess.WriteOutput(consoleResults); } } else { int threadId = Client.GetDebuggedThread().Id; uint frameLevel = _ctx.Level; Results results = await _engine.DebuggedProcess.MICommandFactory.VarCreate(_strippedName, threadId, frameLevel, dwFlags, ResultClass.None); if (results.ResultClass == ResultClass.done) { _internalName = results.FindString("name"); TypeName = results.TryFindString("type"); if (results.Contains("dynamic")) { IsPreformatted = true; } if (results.Contains("dynamic") && results.Contains("has_more")) { CountChildren = results.FindUint("has_more"); } else { CountChildren = results.FindUint("numchild"); } if (results.Contains("displayhint")) { DisplayHint = results.FindString("displayhint"); } if (results.Contains("attributes")) { if (results.FindString("attributes") == "noneditable") { _isReadonly = true; } _attribsFetched = true; } Value = results.TryFindString("value"); if ((Value == String.Empty || _format != null) && !string.IsNullOrEmpty(_internalName)) { if (_format != null) { await Format(); } else { results = await _engine.DebuggedProcess.MICommandFactory.VarEvaluateExpression(_internalName, ResultClass.None); if (results.ResultClass == ResultClass.done) { Value = results.FindString("value"); } else if (results.ResultClass == ResultClass.error) { SetAsError(results.FindString("msg")); } else { Debug.Fail("Weird msg from -var-evaluate-expression"); } } } } else if (results.ResultClass == ResultClass.error) { SetAsError(results.FindString("msg")); } else { Debug.Fail("Weird msg from -var-create"); } } } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } UnexpectedMIResultException miException = e as UnexpectedMIResultException; string message; if (miException != null && miException.MIError != null) { message = miException.MIError; } else { message = e.Message; } SetAsError(string.Format(ResourceStrings.Failed_ExecCommandError, message)); } }