Example #1
0
        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);
            }
        }
Example #3
0
        /// <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;
        }
Example #4
0
 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);
            }
        }
Example #6
0
 public Disassembly(DebuggedProcess process)
 {
     _process = process;
     _disassemlyCache = new SortedList<ulong, DisassemblyBlock>();
 }
Example #7
0
        // 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();
 }
Example #10
0
        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;
        }
Example #11
0
 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());
        }
Example #13
0
        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));
        }
Example #14
0
        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);
        }
Example #15
0
        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));
        }
Example #16
0
        // 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);
        }
Example #17
0
        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));
        }
Example #18
0
        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));
        }
Example #19
0
        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);
        }
Example #20
0
        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);
        }
Example #21
0
 public AD7DocumentContext(MITextPosition textPosition, AD7MemoryAddress codeContext, DebuggedProcess debuggedProcess)
 {
     _textPosition    = textPosition;
     _codeContext     = codeContext;
     _debuggedProcess = debuggedProcess;
 }
Example #22
0
 private async Task DeleteInternal(DebuggedProcess process)
 {
     if (process.ProcessState != MICore.ProcessState.Exited)
     {
         await process.MICommandFactory.BreakDelete(Number);
     }
 }
Example #23
0
        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());
        }
Example #24
0
        // 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;
        }
Example #25
0
        internal async Task <List <BoundBreakpoint> > SyncBreakpoint(DebuggedProcess process)
        {
            ResultValue bkpt = await process.MICommandFactory.BreakInfo(Number);

            return(BindAddresses(bkpt));
        }
Example #26
0
 internal async Task EnableAsync(bool bEnable, DebuggedProcess process)
 {
     await EnableInternal(bEnable, process);
 }
Example #27
0
 private async Task EnableInternal(bool bEnable, DebuggedProcess process)
 {
     await process.MICommandFactory.BreakEnable(bEnable, Number);
 }
Example #28
0
 public CygwinFilePathMapper(DebuggedProcess debuggedProcess)
 {
     this._debuggedProcess = debuggedProcess;
     this._cygwinToWindows = new Dictionary <string, string>();
 }
Example #29
0
 internal void Delete(DebuggedProcess process)
 {
     process.WorkerThread.RunOperation(async() => await DeleteInternal(process));
 }
Example #30
0
        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;
        }
Example #31
0
 internal async Task DeleteAsync(DebuggedProcess process)
 {
     await DeleteInternal(process);
 }
Example #32
0
        // 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"));
        }
Example #33
0
 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;
        }
Example #35
0
 internal async Task EnableAsync(bool bEnable, DebuggedProcess process)
 {
     await EnableInternal(bEnable, process);
 }
Example #36
0
        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;
        }
Example #37
0
 internal void Delete(DebuggedProcess process)
 {
     process.WorkerThread.RunOperation(async () => await DeleteInternal(process));
 }
Example #38
0
        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);
            }
        }
Example #39
0
        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));
        }
Example #40
0
 internal void Enable(bool bEnable, DebuggedProcess process)
 {
     process.WorkerThread.RunOperation(async () =>
     {
         await EnableInternal(bEnable, process);
     });
 }
Example #41
0
 public Disassembly(DebuggedProcess process)
 {
     _process         = process;
     _disassemlyCache = new SortedList <ulong, DisassemblyBlock>();
 }
Example #42
0
 private async Task EnableInternal(bool bEnable, DebuggedProcess process)
 {
     await process.MICommandFactory.BreakEnable(bEnable, Number);
 }
Example #43
0
        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();
        }
Example #44
0
 internal async Task DeleteAsync(DebuggedProcess process)
 {
     await DeleteInternal(process);
 }
Example #45
0
 public SourceLineCache(DebuggedProcess process)
 {
     _process = process;
     _mapFileToLinenums = new Dictionary<string, SourceLine[]>();
 }
Example #46
0
 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();
 }
Example #48
0
 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);
 }
Example #49
0
 public CygwinFilePathMapper(DebuggedProcess debuggedProcess)
 {
     _debuggedProcess = debuggedProcess;
     _cygwinToWindows = new Dictionary<string, string>();
 }
Example #50
0
        private void Dispose()
        {
            WorkerThread pollThread = _pollThread;
            DebuggedProcess debuggedProcess = _debuggedProcess;

            _engineCallback = null;
            _debuggedProcess = null;
            _pollThread = null;
            _ad7ProgramId = Guid.Empty;

            debuggedProcess?.Close();
            pollThread?.Close();
        }
Example #51
0
 public SourceLineCache(DebuggedProcess process)
 {
     _process           = process;
     _mapFileToLinenums = new Dictionary <string, SourceLineMap>();
 }