Пример #1
0
        public int Attach(IDebugProgram2[] programs, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            var            program = programs[0];
            IDebugProcess2 process;

            program.GetProcess(out process);
            Guid processId;

            process.GetProcessId(out processId);
            if (processId != this.processId.guidProcessId)
            {
                return(VSConstants.S_FALSE);
            }

            EngineUtils.RequireOk(program.GetProgramId(out programId));

            Task.Run(() => {
                waiter.WaitOne();

                // connect to the local Mono Debugger or SSH tunnel.
                var localhost = IPAddress.Parse("127.0.0.1");
                Session.Run(new SoftDebuggerStartInfo(new SoftDebuggerConnectArgs("", localhost, MonoDebuggerPort)),
                            new DebuggerSessionOptions {
                    EvaluationOptions = EvaluationOptions.DefaultOptions, ProjectAssembliesOnly = false
                });
            });

            MonoEngineCreateEvent.Send(this);
            MonoProgramCreateEvent.Send(this);

            return(VSConstants.S_OK);
        }
        public void Attach(IDebugProgram2 program)
        {
            IDebugProcess2 process;

            program.GetProcess(out process);
            Guid processId;

            process.GetProcessId(out processId);


            if (processId != _processId.guidProcessId)
            {
                throw new DebuggerInitializeException("Cannot attach to specified program.");
            }

            EngineUtils.RequireOk(program.GetProgramId(out _programId));

            Task.Run(() =>
            {
                _waiter.WaitOne();

                var ipAddress = new IPAddress(new byte[] { 0x7f, 0x00, 0x00, 0x01 });
                Session.Run(new SoftDebuggerStartInfo(new SoftDebuggerConnectArgs("samp-server", ipAddress, DebuggerAddress.Port)),
                            new DebuggerSessionOptions
                {
                    EvaluationOptions     = EvaluationOptions.DefaultOptions,
                    ProjectAssembliesOnly = false
                });
            });

            MonoEngineCreateEvent.Send(_engine);
            SampSharpCreateEvent.Send(_engine);
        }
Пример #3
0
        public int Attach(IDebugProgram2[] programs, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            var            program = programs[0];
            IDebugProcess2 process;

            program.GetProcess(out process);
            Guid processId;

            process.GetProcessId(out processId);
            if (processId != this.processId.guidProcessId)
            {
                return(VSConstants.S_FALSE);
            }

            EngineUtils.RequireOk(program.GetProgramId(out programId));

            Task.Run(() =>
            {
                waiter.WaitOne();

                var ipAddress = HostUtils.ResolveHostOrIPAddress(settings.Host);
                Session.Run(new SoftDebuggerStartInfo(new SoftDebuggerConnectArgs("", ipAddress, 6438)),
                            new DebuggerSessionOptions {
                    EvaluationOptions = EvaluationOptions.DefaultOptions, ProjectAssembliesOnly = false
                });
            });

            MonoEngineCreateEvent.Send(this);
            MonoProgramCreateEvent.Send(this);

            return(VSConstants.S_OK);
        }
Пример #4
0
        public void Send(IDebugEvent2 eventObject, string iidEvent, IDebugProgram2 program, IDebugThread2 thread)
        {
            uint attributes;
            Guid riidEvent = new Guid(iidEvent);

            EngineUtils.RequireOk(eventObject.GetAttributes(out attributes));
            EngineUtils.RequireOk(_eventCallback.Event(_engine, null, program, thread, eventObject, ref riidEvent, attributes));
        }
Пример #5
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);

            try
            {
                // We are being asked to debug a process when we currently aren't debugging anything
                _pollThread = new WorkerThread();

                _pollThread.RunOperation(() =>
                {
                    var endpoint     = new IPEndPoint(IPAddress.Parse(args.Split('=')[1]), 8085);
                    _debuggedProcess = new DebuggedProcess(endpoint, _engineCallback, _pollThread, this);

                    _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError;

                    return(_debuggedProcess.Initialize());
                });

                EngineUtils.RequireOk(port.GetProcess(_debuggedProcess.Id, out process));

                return(VSConstants.S_OK);
            }
            catch (Exception e) when(ExceptionHelper.BeforeCatch(e, reportOnlyCorrupting: true))
            {
                // 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.
                SendStartDebuggingError(e);
            }

            Dispose();

            return(VSConstants.E_ABORT);
        }
Пример #6
0
        public static int GetProcessId(IDebugProcess2 process)
        {
            AD_PROCESS_ID[] pid = new AD_PROCESS_ID[1];
            EngineUtils.RequireOk(process.GetPhysicalProcessId(pid));

            if (pid[0].ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM)
            {
                return(0);
            }

            return((int)pid[0].dwProcessId);
        }
Пример #7
0
        // Attach the debug engine to a program.
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            if (celtPrograms != 1)
            {
                Debug.Fail("SampleEngine only expects to see one program in a process");
                throw new ArgumentException();
            }

            try
            {
                AD_PROCESS_ID processId = EngineUtils.GetProcessId(rgpPrograms[0]);

                EngineUtils.RequireOk(rgpPrograms[0].GetProgramId(out _ad7ProgramId));

                // Attach can either be called to attach to a new process, or to complete an attach
                // to a launched process
                if (_pollThread == null)
                {
                    // We are being asked to debug a process when we currently aren't debugging anything
                    _pollThread = new WorkerThread();

                    _engineCallback = new EngineCallback(this, ad7Callback);

                    _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError;
                }
                else
                {
                    if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id))
                    {
                        Debug.Fail("Asked to attach to a process while we are debugging");
                        return(VSConstants.E_FAIL);
                    }
                }

                AD7EngineCreateEvent.Send(this);
                AD7ProgramCreateEvent.Send(this);
                this.ProgramCreateEventSent = true;

                return(VSConstants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e) when(ExceptionHelper.BeforeCatch(e, reportOnlyCorrupting: true))
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Пример #8
0
        /// <summary>
        ///     Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
        /// </summary>
        /// <param name="process"></param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
        public int ResumeProcess(IDebugProcess2 process)
        {
            IDebugPort2 port;

            EngineUtils.RequireOk(process.GetPort(out port));

            var defaultPort = (IDebugDefaultPort2)port;
            IDebugPortNotify2 portNotify;

            EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify));

            EngineUtils.RequireOk(portNotify.AddProgramNode(Program.Node));

            return(S_OK);
        }
Пример #9
0
        public int ResumeProcess(IDebugProcess2 process)
        {
            IDebugPort2 port;

            EngineUtils.RequireOk(process.GetPort(out port));

            IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port;
            IDebugPortNotify2  portNotify;

            EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify));

            EngineUtils.RequireOk(portNotify.AddProgramNode(new MonoProgramNode(processId)));

            return(VSConstants.S_OK);
        }
Пример #10
0
        // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
        int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process)
        {
            Debug.Assert(_pollThread != null);
            Debug.Assert(_engineCallback != null);
            Debug.Assert(_debuggedProcess != null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            try
            {
                AD_PROCESS_ID processId = EngineUtils.GetProcessId(process);

                if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id))
                {
                    return(VSConstants.S_FALSE);
                }

                // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach
                // which will complete the hookup with AD7
                IDebugPort2 port;
                EngineUtils.RequireOk(process.GetPort(out port));

                IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port;

                IDebugPortNotify2 portNotify;
                EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify));

                EngineUtils.RequireOk(portNotify.AddProgramNode(new AD7ProgramNode(_debuggedProcess.Id)));

                if (_ad7ProgramId == Guid.Empty)
                {
                    Debug.Fail("Unexpected problem -- IDebugEngine2.Attach wasn't called");
                    return(VSConstants.E_FAIL);
                }

                // NOTE: We wait for the program create event to be continued before we really resume the process

                return(VSConstants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e) when(ExceptionHelper.BeforeCatch(e, reportOnlyCorrupting: true))
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Пример #11
0
        int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 aProcess)
        {
            // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
            try
            {
                // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach
                // which will complete the hookup with AD7
                var xProcess = aProcess as AD7Process;
                if (xProcess == null)
                {
                    return(VSConstants.E_INVALIDARG);
                }
                IDebugPort2 xPort;
                EngineUtils.RequireOk(aProcess.GetPort(out xPort));
                var xDefPort = (IDebugDefaultPort2)xPort;
                IDebugPortNotify2 xNotify;
                EngineUtils.RequireOk(xDefPort.GetPortNotify(out xNotify));

                // This triggers Attach
                EngineUtils.RequireOk(xNotify.AddProgramNode(mProgNode));

                Callback.OnModuleLoad(mModule);
                Callback.OnSymbolSearch(mModule, xProcess.mISO.Replace("iso", "pdb"), enum_MODULE_INFO_FLAGS.MIF_SYMBOLS_LOADED);
                // Important!
                //
                // This call triggers setting of breakpoints that exist before run.
                // So it must be called before we resume the process.
                // If not called VS will call it after our 3 startup events, but thats too late.
                // This line was commented out in earlier Cosmos builds and caused problems with
                // breakpoints and timing.
                Callback.OnThreadStart(mThread);

                // Not sure what this does exactly. It was commented out before
                // but so was a lot of stuff we actually needed. If its uncommented it
                // throws:
                //  "Operation is not valid due to the current state of the object."
                //AD7EntrypointEvent.Send(this);

                // Now finally release our process to go after breakpoints are set
                mProcess.ResumeFromLaunch();
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
            return(VSConstants.S_OK);
        }
Пример #12
0
        internal void Send(IDebugEvent2 eventObject, string iidEvent, IDebugProgram2 program, IDebugThread2 thread)
        {
            uint attributes;
            var  riidEvent = new Guid(iidEvent);

            EngineUtils.RequireOk(eventObject.GetAttributes(out attributes));

            Debug.WriteLine(string.Format("Sending Event: {0} {1}", eventObject.GetType(), iidEvent));
            try
            {
                EngineUtils.RequireOk(_events.Event(this, null, program, thread, eventObject, ref riidEvent, attributes));
            }
            catch (InvalidCastException)
            {
                // COM object has gone away
            }
        }
Пример #13
0
        // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
        int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process)
        {
            if (_events == null)
            {
                // process failed to start
                return(VSConstants.E_FAIL);
            }

            Debug.Assert(_events != null);
            Debug.Assert(_process != null);
            Debug.Assert(_process != null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            int processId = EngineUtils.GetProcessId(process);

            if (processId != _process.Id)
            {
                Debug.WriteLine("ResumeProcess fails, wrong process");
                return(VSConstants.S_FALSE);
            }

            // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach
            // which will complete the hookup with AD7
            IDebugPort2 port;

            EngineUtils.RequireOk(process.GetPort(out port));

            var defaultPort = (IDebugDefaultPort2)port;

            IDebugPortNotify2 portNotify;

            EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify));

            EngineUtils.RequireOk(portNotify.AddProgramNode(new AD7ProgramNode(_process.Id)));

            if (_ad7ProgramId == Guid.Empty)
            {
                Debug.WriteLine("ResumeProcess fails, empty program guid");
                Debug.Fail("Unexpected problem -- IDebugEngine2.Attach wasn't called");
                return(VSConstants.E_FAIL);
            }

            Debug.WriteLine("ResumeProcess return S_OK");
            return(VSConstants.S_OK);
        }
Пример #14
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(_events == null);
            Debug.Assert(_process == null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            _events = ad7Callback;

            List <string[]> dirMapping = null;

            Guid processId;

            if (Guid.TryParse(exe, out processId))
            {
                _process      = DebugConnectionListener.GetProcess(processId);
                _attached     = true;
                _pseudoAttach = true;
            }
            else
            {
                _process = new NodeProcess(exe, args, dir, BreakOnAllExceptions, dirMapping);
            }

            _programCreated = false;

            AttachProcessEvents(_process);

            _process.Start();

            var adProcessId = new AD_PROCESS_ID
            {
                ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM,
                dwProcessId   = (uint)_process.Id
            };

            EngineUtils.RequireOk(port.GetProcess(adProcessId, out process));
            Debug.WriteLine("NodeEngine LaunchSuspended returning S_OK");
            Debug.Assert(process != null);
            Debug.Assert(!_process.HasExited);

            return(VSConstants.S_OK);
        }
Пример #15
0
        public int Attach(IDebugProgram2[] programs, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            var            program = programs[0];
            IDebugProcess2 process;

            program.GetProcess(out process);
            Guid processId;

            process.GetProcessId(out processId);
            if (processId != this.processId.guidProcessId)
            {
                return(VSConstants.S_FALSE);
            }

            EngineUtils.RequireOk(program.GetProgramId(out programId));

            Session.Run(new SoftDebuggerStartInfo(new SoftDebuggerConnectArgs("", new IPAddress(new byte[] { 192, 168, 137, 3 }), 12345)),
                        new DebuggerSessionOptions {
                EvaluationOptions = EvaluationOptions.DefaultOptions, ProjectAssembliesOnly = false
            });

            return(VSConstants.S_OK);
        }
Пример #16
0
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint aCeltPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            // Attach the debug engine to a program.
            //
            // Attach can either be called to attach to a new process, or to complete an attach
            // to a launched process.
            // So could we simplify and move code from LaunchSuspended to here and maybe even
            // eliminate the debughost? Although I supposed DebugHost has some other uses as well.

            if (aCeltPrograms != 1)
            {
                System.Diagnostics.Debug.Fail("Cosmos Debugger only supports one debug target at a time.");
                throw new ArgumentException();
            }

            try
            {
                EngineUtils.RequireOk(rgpPrograms[0].GetProgramId(out mProgramID));

                mProgram = rgpPrograms[0];
                AD7EngineCreateEvent.Send(this);
                AD7ProgramCreateEvent.Send(this);
                AD7ModuleLoadEvent.Send(this, mModule, true);

                // Dummy main thread
                // We dont support threads yet, but the debugger expects threads.
                // So we create a dummy object to represente our only "thread".
                mThread = new AD7Thread(this, mProcess);
                AD7LoadCompleteEvent.Send(this, mThread);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
            return(VSConstants.S_OK);
        }
Пример #17
0
        // Attach the debug engine to a program.
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            if (celtPrograms != 1)
            {
                Debug.Fail("Node debugging only supports one program in a process");
                throw new ArgumentException();
            }

            IDebugProgram2 program   = rgpPrograms[0];
            int            processId = EngineUtils.GetProcessId(program);

            if (processId == 0)
            {
                // engine only supports system processes
                Debug.WriteLine("NodeEngine failed to get process id during attach");
                return(VSConstants.E_NOTIMPL);
            }

            EngineUtils.RequireOk(program.GetProgramId(out _ad7ProgramId));

            // Attach can either be called to attach to a new process, or to complete an attach
            // to a launched process
            if (_process == null)
            {
                // TODO: Where do we get the language version from?
                _events = ad7Callback;

                // Check if we're attaching remotely using the node remote debugging transport
                if (!NodeProcess.TryAttach(processId, out _process))
                {
                    MessageBox.Show("Failed to attach debugger:\n", null, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(VSConstants.E_FAIL);
                }

                AttachProcessEvents(_process);
                _attached = true;
            }
            else
            {
                if (processId != _process.Id)
                {
                    Debug.Fail("Asked to attach to a process while we are debugging");
                    return(VSConstants.E_FAIL);
                }
            }

            AD7EngineCreateEvent.Send(this);

            lock (_syncLock)
            {
                _programCreated = true;

                if (_processLoadedThread != null)
                {
                    SendLoadComplete(_processLoadedThread);
                }
            }

            Debug.WriteLine("NodeEngine Attach returning S_OK");
            return(VSConstants.S_OK);
        }