public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { ppPort = null; string name; pRequest.GetPortName(out name); Match m = _portNameRegex.Match(name); if (!m.Success) { return Marshal.GetHRForException(new FormatException()); } string secret = m.Groups["secret"].Value; string hostName = m.Groups["hostName"].Value; ushort portNum = _defaultPort; if (m.Groups["portNum"].Success) { if (!ushort.TryParse(m.Groups["portNum"].Value, out portNum)) { return Marshal.GetHRForException(new FormatException()); } } var port = new JRemoteDebugPort(this, hostName, portNum, secret, _useSsl); ppPort = port; return 0; }
public ScriptDebugProcess(IDebugPort2 debugPort) { Log.Debug("Process: Constructor"); Id = Guid.NewGuid(); _port = debugPort; Node = new ScriptProgramNode(this); }
string _sessionName; // has no value assigned because the method that uses it is "[DEPRECATED. SHOULD ALWAYS RETURN E_NOTIMPL.]" #endregion Fields #region Constructors public AD7Process(EngineCallback aCallback, AD7Engine aEngine, IDebugPort2 aPort) { _callback = aCallback; _engine = aEngine; _port = aPort; m_program = aEngine.m_program; // m_program = new AD7Program(this, _callback, _engine.eDispatcher); }
/// <summary> /// Gets a port by it's guid. /// </summary> public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { DLog.Debug(DContext.VSDebuggerComCall, "DebugPortSupplier.GetPort"); var guid = guidPort; var port = ports.Values.FirstOrDefault(x => x.Guid == guid); ppPort = port; return (port != null) ? VSConstants.S_OK : VSConstants.S_FALSE; }
/// <summary> /// Add a port. /// </summary> public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { DLog.Debug(DContext.VSDebuggerComCall, "DebugPortSupplier.AddPort"); string name; ErrorHandler.ThrowOnFailure(pRequest.GetPortName(out name)); var port = new DebugPort(this, pRequest); ports[name] = port; ppPort = port; return VSConstants.S_OK; }
public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { string name; Marshal.ThrowExceptionForHR(pRequest.GetPortName(out name)); if (name != PortName) { ppPort = null; return VSConstants.E_INVALIDARG; } ppPort = new DebugPort(this, pRequest); return VSConstants.S_OK; }
public int EnumPorts(out IEnumDebugPorts2 ppEnum) { ConnectionInfoStore store = new ConnectionInfoStore(); IDebugPort2[] ports = new IDebugPort2[store.Connections.Count]; for (int i = 0; i < store.Connections.Count; i++) { ConnectionInfo connectionInfo = (ConnectionInfo)store.Connections[i]; ports[i] = new AD7Port(this, ConnectionManager.GetFormattedConnectionName(connectionInfo), isInAddPort: false); } ppEnum = new AD7PortEnum(ports); return HR.S_OK; }
public int AddPort(IDebugPortRequest2 request, out IDebugPort2 port) { string name; HR.Check(request.GetPortName(out name)); AD7Port newPort = new AD7Port(this, name, isInAddPort: true); if (newPort.IsConnected) { port = newPort; return HR.S_OK; } port = null; return HR.E_REMOTE_CONNECT_USER_CANCELED; }
public int AddPort(IDebugPortRequest2 request, out IDebugPort2 port) { var debugSessionMetrics = new DebugSessionMetrics(_metrics); debugSessionMetrics.UseNewDebugSessionId(); var actionRecorder = new ActionRecorder(debugSessionMetrics); port = null; if (request.GetPortName(out string gameletIdOrName) != VSConstants.S_OK) { return(VSConstants.E_FAIL); } var action = actionRecorder.CreateToolAction(ActionType.GameletGet); var gameletClient = _gameletClientFactory.Create(_cloudRunner.Intercept(action)); var gameletTask = _cancelableTaskFactory.Create( "Querying instance...", async() => await gameletClient.LoadByNameOrIdAsync(gameletIdOrName)); try { gameletTask.RunAndRecord(action); } catch (CloudException e) { Trace.WriteLine(e.ToString()); _dialogUtil.ShowError(e.Message); return(VSConstants.S_OK); } var debugPort = _debugPortFactory.Create(gameletTask.Result, this, debugSessionMetrics.DebugSessionId); _ports.Add(debugPort); port = debugPort; return(VSConstants.S_OK); }
/// <summary> /// Launch the actual debug process. /// </summary> public int LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugEngine2.LaunchSuspended"); ppProcess = null; var port = pPort as DebugPort; if (pPort == null) { return(VSConstants.E_INVALIDARG); } // Create event callback eventCallback = new EngineEventCallback(this, pCallback); // Notify creation eventCallback.Send(new EngineCreateEvent(this)); // Get debugger var guid = new Guid(pszOptions); var debugger = Launcher.GetAndRemoveDebugger(guid, out stateUpdate); // Load map file var mapFilePath = Path.ChangeExtension(pszExe, ".d42map"); var mapFile = File.Exists(mapFilePath) ? new MapFile(mapFilePath) : new MapFile(); // Create new process var process = new DebugProcess(this, port, debugger, Environment.TickCount, guid, pszExe, mapFile, eventCallback); var program = process.Program; process.Terminated += (s, x) => ((IDebugEngine2)this).DestroyProgram(program); // Record process ((DebugPort)pPort).RecordProcess(process); // Return result ppProcess = process; return(VSConstants.S_OK); }
public void RemoteDeployNotCalledDuringAttachToCore(enum_ATTACH_REASON attachReason) { var gamelet = new Gamelet { IpAddr = _gameletIp }; var expectedTarget = new SshTarget(gamelet); IDebugSessionLauncher debugSessionLauncher = CreateConfiguredDebugSessionLauncher(expectedTarget, x => { var attachedProgram = Substitute.For <ILldbAttachedProgram>(); return(Task.FromResult(attachedProgram)); }); IDebugSessionLauncherFactory debugSessionLauncherFactory = CreateDebugSessionLauncherFactory(debugSessionLauncher); int calls = 0; var remoteDeploy = Substitute.For <IRemoteDeploy>(); remoteDeploy.DeployLldbServerAsync(expectedTarget, Arg.Any <IAction>()).Returns(x => { calls++; return(Task.CompletedTask); }); IGgpDebugEngine debugEngine = CreateGgpDebugEngine(debugSessionLauncherFactory, remoteDeploy); IDebugPort2 debugPort = CreateDebugPort(gamelet); string options = null; debugEngine.LaunchSuspended("", debugPort, _exePath, null, null, null, options, enum_LAUNCH_FLAGS.LAUNCH_DEBUG, 0, 0, 0, null, out IDebugProcess2 _); IDebugProgram2 program = CreateDebugProgram(debugPort); IDebugProgram2[] rgpPrograms = { program }; var rgpProgramNodes = new[] { Substitute.For <IDebugProgramNode2>() }; debugEngine.Attach(rgpPrograms, rgpProgramNodes, _celtPrograms, null, attachReason); Assert.That(calls, Is.EqualTo(0)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int RemovePort(IDebugPort2 pPort) { // // Removes a port. This method removes the port from the port supplier's internal list of active ports. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(pPort.GetPortId(out Guid portId)); m_registeredPorts.Remove(portId); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
// Qualifier for our transport has one of the following formats: // // tcp[s]://[secret@]hostname[:port] // ws[s]://[secret@]hostname[:port][/path] // [secret@]hostname[:port] // // 'tcp' and 'tcps' are for connecting directly to ptvsd; 'ws' and 'wss' are for connecting through WebSocketProxy. // The versions ending with '...s' use SSL to secure the connection. If no scheme is specified, 'tcp' is the default. // If port is not specified, it defaults to 5678 for 'tcp' and 'tcps', 80 for 'ws' and 443 for 'wss'. public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { ppPort = null; string name; pRequest.GetPortName(out name); // Support old-style 'hostname:port' format, as well. if (!name.Contains("://")) { name = "tcp://" + name; } var uri = new Uri(name, UriKind.Absolute); var transport = DebuggerTransportFactory.Get(uri); if (transport == null) { MessageBox.Show(string.Format("Unrecognized remote debugging transport '{0}'.", uri.Scheme), null, MessageBoxButtons.OK, MessageBoxIcon.Error); return VSConstants.E_FAIL; } var validationError = transport.Validate(uri); if (validationError != null) { return validationError.HResult; } var port = new PythonRemoteDebugPort(this, pRequest, uri); // Validate connection early. Debugger automation (DTE) objects are not consistent in error checking from this // point on, so errors reported from EnumProcesses and further calls may be ignored and treated as successes // (with empty result). Reporting an error here works around that. IEnumDebugProcesses2 processes; int hr = port.EnumProcesses(out processes); if (hr < 0) { return hr; } ppPort = port; return VSConstants.S_OK; }
// Qualifier for our transport is parsed either as a tcp://, ws:// or ws:// URI, // or as 'hostname:port', where ':port' is optional. public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { ppPort = null; string name; pRequest.GetPortName(out name); // Support old-style 'hostname:port' format, as well. if (!name.Contains("://")) { name = "tcp://" + name; } var uri = new Uri(name, UriKind.Absolute); switch (uri.Scheme) { case "tcp": // tcp:// URI should only specify host and optionally port, path has no meaning and is invalid. if (uri.PathAndQuery != "/") { return new FormatException().HResult; } // Set default port if not specified. if (uri.Port < 0) { uri = new UriBuilder(uri) { Port = NodejsConstants.DefaultDebuggerPort }.Uri; } break; case "ws": case "wss": // WebSocket URIs are used as is break; default: // Anything else is not a valid debugger endpoint return new FormatException().HResult; } ppPort = new NodeRemoteDebugPort(this, pRequest, uri); return VSConstants.S_OK; }
// During startup these methods are called in this order: // -LaunchSuspended // -ResumeProcess // -Attach - Triggered by Attach int IDebugEngineLaunch2.LaunchSuspended(string aPszServer, IDebugPort2 aPort, string aDebugInfo , string aArgs, string aDir, string aEnv, string aOptions, enum_LAUNCH_FLAGS aLaunchFlags , uint aStdInputHandle, uint aStdOutputHandle, uint hStdError, IDebugEventCallback2 aAD7Callback , out IDebugProcess2 oProcess) { // 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. oProcess = null; try { mEngineCallback = new EngineCallback(this, aAD7Callback); var xDebugInfo = new NameValueCollection(); NameValueCollectionHelper.LoadFromString(xDebugInfo, aDebugInfo); //TODO: In the future we might support command line args for kernel etc //string xCmdLine = EngineUtils.BuildCommandLine(exe, args); //var processLaunchInfo = new ProcessLaunchInfo(exe, xCmdLine, dir, env, options, launchFlags, hStdInput, hStdOutput, hStdError); AD7EngineCreateEvent.Send(this); oProcess = mProcess = new AD7Process(xDebugInfo, mEngineCallback, this, aPort); // We only support one process, so just use its ID for the program ID mProgramID = mProcess.ID; //AD7ThreadCreateEvent.Send(this, xProcess.Thread); mModule = new AD7Module(); mProgNode = new AD7ProgramNode(mProcess.PhysID); } catch (NotSupportedException) { return(VSConstants.S_FALSE); } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } return(VSConstants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int EnumPorts(out IEnumDebugPorts2 ppEnum) { // // Retrieves a list of all the ports supplied by a port supplier. // LoggingUtils.PrintFunction(); try { AndroidAdb.Refresh(); var connectedDevices = AndroidAdb.GetConnectedDevices(); foreach (var device in connectedDevices) { LoggingUtils.RequireOk(AddPort(new DevicePortRequest(device), out IDebugPort2 ppPort)); } IDebugPort2 [] ports = new IDebugPort2 [m_registeredPorts.Count]; m_registeredPorts.Values.CopyTo(ports, 0); ppEnum = new DebugPortEnumerator(ports); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); ppEnum = null; return(Constants.E_FAIL); } }
int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { string[] p = pszExe.Split(':'); callback = new AD7.EngineCallback(this, pCallback); debugged = new AD7.DebuggedProcessVS(this, p[0], int.Parse(p[1])); while (debugged.Connecting) { System.Threading.Thread.Sleep(10); } if (debugged.Connected) { if (debugged.CheckDebugServerVersion()) { ppProcess = new AD7Process(pPort); this.process = ppProcess; debugged.OnDisconnected = OnDisconnected; return(Constants.S_OK); } else { debugged.Close(); MessageBox.Show(String.Format("ILRuntime Debugger version mismatch\n Expected version:{0}\n Actual version:{1}", DebuggerServer.Version, DebuggedProcess.RemoteDebugVersion), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); debugged = null; ppProcess = null; return(Constants.S_FALSE); } } else { MessageBox.Show("Cannot connect to ILRuntime", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); debugged = null; ppProcess = null; return(Constants.S_FALSE); } }
// 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; }
public int GetPort(out IDebugPort2 ppPort) { ppPort = _port; return VSConstants.S_OK; }
int IDebugPortSupplier2.GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { throw new NotImplementedException(); }
public int GetPort(out IDebugPort2 ppPort) { ppPort = this._port; return(VSConstants.S_OK); }
public int LaunchSuspended(string server, IDebugPort2 port, string exe, string args, string directory, string environment, string options, enum_LAUNCH_FLAGS launchFlags, uint standardInput, uint standardOutput, uint standardError, IDebugEventCallback2 callback, out IDebugProcess2 process) { waiter = new AutoResetEvent(false); settings = MonoDebuggerSettings.Parse(options); Task.Run(() => { var outputWindow = (IVsOutputWindow)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsOutputWindow)); var generalPaneGuid = VSConstants.GUID_OutWindowDebugPane; outputWindow.GetPane(ref generalPaneGuid, out this.outputWindow); // Upload the contents of the output folder to the target directory if (connection == null) { connection = ConnectionManager.Get(settings); if (!connection.IsConnected) { Log("Connecting SSH and SFTP..."); // Debugger.Launch(); connection.Connect(); Log("Connected"); } } Log("Uploading program..."); // Ensure target directory exists: var targetDirectories = directory.Split('/'); foreach (var part in targetDirectories) { if (!connection.Sftp.Exists(part)) { connection.Sftp.CreateDirectory(part); } connection.Sftp.ChangeDirectory(part); } foreach (var _ in targetDirectories) { connection.Sftp.ChangeDirectory(".."); } var outputDirectory = new DirectoryInfo(Path.GetDirectoryName(exe)); foreach (var file in outputDirectory.EnumerateFiles().Where(x => x.Extension == ".dll" || x.Extension == ".mdb" || x.Extension == ".exe")) { using (var stream = file.OpenRead()) { connection.Sftp.UploadFile(stream, $"{directory}/{file.Name}", true); } Log($"Uploaded {file.FullName}"); } Log("Done"); var targetExe = directory + "/" + Path.GetFileName(exe); connection.Ssh.RunCommand("cd ~"); Log("Launching application"); var commandText = $"mono --debug=mdb-optimizations --debugger-agent=transport=dt_socket,address=0.0.0.0:6438,server=y {targetExe}"; connection.Ssh.RunCommand("kill $(ps auxww | grep '" + commandText + "' | awk '{print $2}')", this.outputWindow, null); runCommand = connection.Ssh.BeginCommand(commandText, this.outputWindow, out runCommandAsyncResult); // Trigger that the app is now running for whomever might be waiting for that signal waiter.Set(); }); Session = new SoftDebuggerSession(); Session.TargetReady += (sender, eventArgs) => { var activeThread = Session.ActiveThread; ThreadManager.Add(activeThread, new MonoThread(this, activeThread)); // Session.Stop(); }; Session.ExceptionHandler = exception => true; Session.TargetExited += (sender, x) => { // runCommand.EndExecute(runCommandAsyncResult); Send(new MonoProgramDestroyEvent((uint?)x.ExitCode ?? 0), MonoProgramDestroyEvent.IID, null); }; Session.TargetUnhandledException += (sender, x) => { Send(new MonoExceptionEvent(x.Backtrace.GetFrame(0)) { IsUnhandled = true }, MonoExceptionEvent.IID, ThreadManager[x.Thread]); }; Session.LogWriter = (stderr, text) => Console.WriteLine(text); Session.OutputWriter = (stderr, text) => Console.WriteLine(text); Session.TargetThreadStarted += (sender, x) => ThreadManager.Add(x.Thread, new MonoThread(this, x.Thread)); Session.TargetThreadStopped += (sender, x) => { ThreadManager.Remove(x.Thread); }; Session.TargetStopped += (sender, x) => Console.WriteLine(x.Type); Session.TargetStarted += (sender, x) => Console.WriteLine(); Session.TargetSignaled += (sender, x) => Console.WriteLine(x.Type); Session.TargetInterrupted += (sender, x) => Console.WriteLine(x.Type); Session.TargetExceptionThrown += (sender, x) => { Send(new MonoExceptionEvent(x.Backtrace.GetFrame(0)), MonoExceptionEvent.IID, ThreadManager[x.Thread]); }; Session.TargetHitBreakpoint += (sender, x) => { var breakpoint = x.BreakEvent as Breakpoint; var pendingBreakpoint = breakpointManager[breakpoint]; Send(new MonoBreakpointEvent(new MonoBoundBreakpointsEnum(pendingBreakpoint.BoundBreakpoints)), MonoBreakpointEvent.IID, ThreadManager[x.Thread]); }; processId = new AD_PROCESS_ID(); processId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; processId.guidProcessId = Guid.NewGuid(); EngineUtils.CheckOk(port.GetProcess(processId, out process)); Callback = callback; return(VSConstants.S_OK); }
public int RemovePort(IDebugPort2 pPort) { return(VSConstants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugPortSupplier2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { // // Attempt to find a port matching the requested name, otherwise one is created. // LoggingUtils.PrintFunction(); try { string requestPortName; LoggingUtils.RequireOk(CanAddPort()); LoggingUtils.RequireOk(pRequest.GetPortName(out requestPortName)); if (string.IsNullOrWhiteSpace(requestPortName)) { throw new InvalidOperationException("Invalid/empty port name"); } ppPort = null; foreach (KeyValuePair <Guid, IDebugPort2> keyPair in m_registeredPorts) { string portName; IDebugPort2 registeredPort = keyPair.Value; LoggingUtils.RequireOk(registeredPort.GetPortName(out portName)); if (portName.Equals(requestPortName)) { ppPort = registeredPort; break; } } if (ppPort == null) { // // Create and track a new port for this request. // Guid portId; LoggingUtils.RequireOk(CreatePort(pRequest, out ppPort)); LoggingUtils.RequireOk(ppPort.GetPortId(out portId)); m_registeredPorts.Add(portId, ppPort); } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); ppPort = null; return(Constants.E_FAIL); } }
public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { throw new NotImplementedException(); }
internal AD7Process(IDebugPort2 port, AD_PROCESS_ID processId) { _port = port; this.PhysicalProcessId = processId; }
/// <summary> /// Adds a port. (http://msdn.microsoft.com/en-ca/library/bb161980.aspx) /// </summary> /// <param name="pRequest"> An IDebugPortRequest2 object that describes the port to be added. </param> /// <param name="ppPort"> Returns an IDebugPort2 object that represents the port. </param> /// <returns> VSConstants.S_OK. </returns> public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { bool sucess = true; AD7PortRequest port_request = null; AD7Port port = null; try { port_request = (AD7PortRequest)pRequest; } catch { sucess = false; string portRequestName; AD7Port defaultPort = null; pRequest.GetPortName(out portRequestName); string search = ""; if (portRequestName.ToLower().Contains("device")) search = "device"; else if (portRequestName.ToLower().Contains("simulator")) search = "simulator"; else { search = portRequestName.ToLower(); } foreach (var p in m_ports) { AD7Port tempPort = p.Value; if (defaultPort == null) defaultPort = tempPort; string tempPortName = ""; tempPort.GetPortName(out tempPortName); if (tempPortName.ToLower().Contains(search)) { port = tempPort; break; } else { string IP = search; do { int pos = IP.LastIndexOf('.'); if (pos != -1) { IP = IP.Remove(pos); if (tempPortName.Contains(IP)) { port = tempPort; break; } } else IP = ""; } while (IP != ""); if (IP != "") break; } } if (port == null) { if (defaultPort != null) { port = defaultPort; } else port = new AD7Port(this, port_request, Guid.NewGuid(), "", "", true, ""); } } if (sucess) { port = CreatePort(port_request); Guid portGuid; port.GetPortId(out portGuid); m_ports.Add(portGuid, port); } ppPort = port; return VSConstants.S_OK; }
/// <summary> /// Gets a port from a port supplier. (http://msdn.microsoft.com/en-ca/library/bb161812.aspx) /// </summary> /// <param name="guidPort"> Globally unique identifier (GUID) of the port. </param> /// <param name="ppPort"> Returns an IDebugPort2 object that represents the port. </param> /// <returns> VSConstants.S_OK. </returns> public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { ppPort = m_ports[guidPort]; return VSConstants.S_OK; }
/// <summary> /// This method launches a process by means of the debug DebugEngine (DE). /// </summary> /// <param name="pszServer">The name of the machine in which to launch the process. Use a null value to specify the local machine.</param> /// <param name="pPort">The IDebugPort2 interface representing the port that the program will run in.</param> /// <param name="pszExe">The name of the executable to be launched.</param> /// <param name="pszArgs">The arguments to pass to the executable. May be a null value if there are no arguments.</param> /// <param name="pszDir">The name of the working directory used by the executable. May be a null value if no working directory is required.</param> /// <param name="bstrEnv">Environment block of NULL-terminated strings, followed by an additional NULL terminator.</param> /// <param name="pszOptions">The options for the executable.</param> /// <param name="dwLaunchFlags">Specifies the LAUNCH_FLAGS for a session.</param> /// <param name="hStdInput">Handle to an alternate input stream. May be 0 if redirection is not required.</param> /// <param name="hStdOutput">Handle to an alternate output stream. May be 0 if redirection is not required.</param> /// <param name="hStdError">Handle to an alternate error output stream. May be 0 if redirection is not required.</param> /// <param name="pCallback">The IDebugEventCallback2 object that receives debugger events.</param> /// <param name="ppProcess">Returns the resulting IDebugProcess2 object that represents the launched process.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> /// <remarks> /// 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 DebugEngine may need to launch a program (for example, if the debug DebugEngine 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. /// </remarks> public virtual int LaunchSuspended( string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { Logger.Debug( string.Empty ); ppProcess = null; return VSConstants.E_NOTIMPL; }
/// <summary> /// Removes a port. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb162306.aspx) /// </summary> /// <param name="pPort"> An IDebugPort2 object that represents the port to be removed. </param> /// <returns> Not implemented. It should returns S_OK if successful; or an error code. </returns> public int RemovePort(IDebugPort2 pPort) { throw new NotImplementedException(); }
/// <summary> /// Gets a port from a port supplier. (http://msdn.microsoft.com/en-ca/library/bb161812.aspx) /// </summary> /// <param name="guidPort"> Globally unique identifier (GUID) of the port. </param> /// <param name="ppPort"> Returns an IDebugPort2 object that represents the port. </param> /// <returns> VSConstants.S_OK. </returns> public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { ppPort = m_ports[guidPort]; return(VSConstants.S_OK); }
/// <summary> /// Adds a port. /// </summary> /// <param name="pRequest">An IDebugPortRequest2 object that describes the port to be added.</param> /// <param name="ppPort">Returns an IDebugPort2 object that represents the port.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> /// <remarks> /// This method actually creates the requested port as well as adding it to the port supplier's internal list of active ports. The IDebugPortSupplier2::CanAddPort method can be called first to avoid possible time-consuming delays. /// </remarks> public virtual int AddPort( IDebugPortRequest2 pRequest, out IDebugPort2 ppPort ) { Logger.Debug( string.Empty ); ppPort = null; return VSConstants.E_NOTIMPL; }
/// <summary> /// Gets the port that the process is running on. /// </summary> /// <param name="ppPort">Returns an IDebugPort2 object that represents the port on which the process was launched.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> public virtual int GetPort( out IDebugPort2 ppPort ) { Logger.Debug( string.Empty ); ppPort = null; return VSConstants.E_NOTIMPL; }
// 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) { LiveLogger.WriteLine("AD7Engine LaunchSuspended Called with flags '{0}' ({1})", launchFlags, GetHashCode()); AssertMainThread(); Debug.Assert(_events == null); Debug.Assert(_process == null); Debug.Assert(_ad7ProgramId == Guid.Empty); _events = ad7Callback; var debugOptions = NodeDebugOptions.None; List<string[]> dirMapping = null; string interpreterOptions = null; ushort? debugPort = null; if (options != null) { var splitOptions = SplitOptions(options); foreach (var optionSetting in splitOptions) { var setting = optionSetting.Split(new[] { '=' }, 2); if (setting.Length == 2) { setting[1] = HttpUtility.UrlDecode(setting[1]); switch (setting[0]) { case WaitOnAbnormalExitSetting: bool value; if (Boolean.TryParse(setting[1], out value) && value) { debugOptions |= NodeDebugOptions.WaitOnAbnormalExit; } break; case WaitOnNormalExitSetting: if (Boolean.TryParse(setting[1], out value) && value) { debugOptions |= NodeDebugOptions.WaitOnNormalExit; } break; case RedirectOutputSetting: if (Boolean.TryParse(setting[1], out value) && value) { debugOptions |= NodeDebugOptions.RedirectOutput; } break; case DirMappingSetting: string[] dirs = setting[1].Split('|'); if (dirs.Length == 2) { if (dirMapping == null) { dirMapping = new List<string[]>(); } LiveLogger.WriteLine(String.Format("Mapping dir {0} to {1}", dirs[0], dirs[1])); dirMapping.Add(dirs); } break; case InterpreterOptions: interpreterOptions = setting[1]; break; case WebBrowserUrl: _webBrowserUrl = setting[1]; break; case DebuggerPort: ushort dbgPortTmp; if (ushort.TryParse(setting[1], out dbgPortTmp)) { debugPort = dbgPortTmp; } break; } } } } _process = new NodeDebugger( exe, args, dir, env, interpreterOptions, debugOptions, debugPort ); _process.Start(false); AttachEvents(_process); var adProcessId = new AD_PROCESS_ID(); adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = (uint)_process.Id; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); LiveLogger.WriteLine("AD7Engine LaunchSuspended returning S_OK"); Debug.Assert(process != null); Debug.Assert(!_process.HasExited); return VSConstants.S_OK; }
// 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(m_ad7ProgramId == Guid.Empty); m_ad7ProgramId = Guid.NewGuid(); STARTUPINFO si = new STARTUPINFO(); pi = new PROCESS_INFORMATION(); // try/finally free bool procOK = NativeMethods.CreateProcess(exe, args, IntPtr.Zero, IntPtr.Zero, false, ProcessCreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi); pID = pi.dwProcessId; Task writepipeOK = WriteNamedPipeAsync(); Task readpipeOK = ReadNamedPipeAsync(); threadHandle = pi.hThread; IntPtr processHandle = pi.hProcess; // Inject LuaDebug into host IntPtr loadLibAddr = DLLInjector.GetProcAddress(DLLInjector.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); string VS140ExtensionPath = Path.Combine(Path.GetDirectoryName(typeof(EngineConstants).Assembly.Location), "LuaDetour"); string luaDetoursDllName = Path.Combine(VS140ExtensionPath, "LuaDetours.dll"); if(!File.Exists(luaDetoursDllName)) { process = null; return VSConstants.E_FAIL; } IntPtr allocMemAddress1 = DLLInjector.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)((luaDetoursDllName.Length + 1) * Marshal.SizeOf(typeof(char))), DLLInjector.MEM_COMMIT | DLLInjector.MEM_RESERVE, DLLInjector.PAGE_READWRITE); UIntPtr bytesWritten1; DLLInjector.WriteProcessMemory(processHandle, allocMemAddress1, Encoding.Default.GetBytes(luaDetoursDllName), (uint)((luaDetoursDllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten1); IntPtr hRemoteThread1 = DLLInjector.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibAddr, allocMemAddress1, 0, IntPtr.Zero); IntPtr[] handles1 = new IntPtr[] { hRemoteThread1 }; uint index1; NativeMethods.CoWaitForMultipleHandles(0, -1, handles1.Length, handles1, out index1); string debugDllName = Path.Combine(VS140ExtensionPath, "LuaDebug32.dll"); IntPtr allocMemAddress2 = DLLInjector.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)((debugDllName.Length + 1) * Marshal.SizeOf(typeof(char))), DLLInjector.MEM_COMMIT | DLLInjector.MEM_RESERVE, DLLInjector.PAGE_READWRITE); UIntPtr bytesWritten2; DLLInjector.WriteProcessMemory(processHandle, allocMemAddress2, Encoding.Default.GetBytes(debugDllName), (uint)((debugDllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten2); IntPtr hRemoteThread2 = DLLInjector.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibAddr, allocMemAddress2, 0, IntPtr.Zero); IntPtr[] handles = new IntPtr[] { hRemoteThread2 }; uint index2; NativeMethods.CoWaitForMultipleHandles(0, -1, handles.Length, handles, out index2); AD_PROCESS_ID adProcessId = new AD_PROCESS_ID(); adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = pi.dwProcessId; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); debugProcess = process; return VSConstants.S_OK; }
public override int AddPort(IDebugPortRequest2 request, out IDebugPort2 port) { // This should never be called Debug.Fail("Why is AddPort called?"); throw new NotImplementedException(); }
public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { thePort = new SquirrelPort(this, pRequest); ppPort = (IDebugPort2)thePort; return(Microsoft.VisualStudio.VSConstants.S_OK); }
public int GetPort(out IDebugPort2 port) { port = _port; return(HR.S_OK); }
/// <summary> /// Launch the actual debug process. /// </summary> public int LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugEngine2.LaunchSuspended"); ppProcess = null; var port = pPort as DebugPort; if (pPort == null) return VSConstants.E_INVALIDARG; // Create event callback eventCallback = new EngineEventCallback(this, pCallback); // Notify creation eventCallback.Send(new EngineCreateEvent(this)); // Get debugger var guid = new Guid(pszOptions); var debugger = Launcher.GetAndRemoveDebugger(guid, out stateUpdate); // Load map file var mapFilePath = Path.ChangeExtension(pszExe, ".d42map"); var mapFile = File.Exists(mapFilePath) ? new MapFile(mapFilePath) : new MapFile(); // Create new process var process = new DebugProcess(this, port, debugger, Environment.TickCount, guid, pszExe, mapFile, eventCallback); var program = process.Program; process.Terminated += (s, x) => ((IDebugEngine2)this).DestroyProgram(program); // Record process ((DebugPort)pPort).RecordProcess(process); // Return result ppProcess = process; return VSConstants.S_OK; }
public int RemovePort(IDebugPort2 pPort) { return(VSConstants.E_NOTIMPL); }
public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { throw new NotImplementedException(); }
public int RemovePort(IDebugPort2 pPort) { return 0; }
public int GetPort(out IDebugPort2 ppPort) { ppPort = _port; return(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) { process = null; if (_mixedMode) { return VSConstants.E_NOTIMPL; } Debug.WriteLine("--------------------------------------------------------------------------------"); Debug.WriteLine("PythonEngine LaunchSuspended Begin " + launchFlags + " " + GetHashCode()); AssertMainThread(); Debug.Assert(_events == null); Debug.Assert(_process == null); Debug.Assert(_ad7ProgramId == Guid.Empty); _events = ad7Callback; _engineCreated = _programCreated = false; _loadComplete.Reset(); if (options != null) { ParseOptions(options); } Send(new AD7CustomEvent(VsPackageMessage.SetDebugOptions, this), AD7CustomEvent.IID, null, null); // If this is a windowed application, there's no console to wait on, so disable those flags if they were set. if (_debugOptions.HasFlag(PythonDebugOptions.IsWindowsApplication)) { _debugOptions &= ~(PythonDebugOptions.WaitOnNormalExit | PythonDebugOptions.WaitOnAbnormalExit); } Guid processId; if (_debugOptions.HasFlag(PythonDebugOptions.AttachRunning)) { if (!Guid.TryParse(exe, out processId)) { Debug.Fail("When PythonDebugOptions.AttachRunning is used, the 'exe' parameter must be a debug session GUID."); return VSConstants.E_INVALIDARG; } _process = DebugConnectionListener.GetProcess(processId); _attached = true; _pseudoAttach = true; } else { _process = new PythonProcess(_languageVersion, exe, args, dir, env, _interpreterOptions, _debugOptions, _dirMapping); } if (!_debugOptions.HasFlag(PythonDebugOptions.AttachRunning)) { _process.Start(false); } AttachEvents(_process); AD_PROCESS_ID adProcessId = new AD_PROCESS_ID(); adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = (uint)_process.Id; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); Debug.WriteLine("PythonEngine LaunchSuspended returning S_OK"); Debug.Assert(process != null); Debug.Assert(!_process.HasExited); return VSConstants.S_OK; }
// Token: 0x0600018B RID: 395 RVA: 0x00006252 File Offset: 0x00004452 public int GetPort(out IDebugPort2 outPort) { outPort = this.Port; return(0); }
public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { ppPort = null; return(VSConstants.E_NOTIMPL); }
/// <summary> /// Constructor. /// </summary> /// <param name="aEngine"> The AD7Engine object that represents the DE. </param> /// <param name="aPort"> The IDebugPort2 object that represents the port on which the process was launched. </param> public AD7Process(AD7Engine aEngine, IDebugPort2 aPort) { _engine = aEngine; _port = aPort; m_program = aEngine.m_program; }
public virtual IDebugProcess2 Create( IDebugPort2 port, uint pid, string title, string command) { return(new DebugProcess(debugProgramFactory, port, pid, title, command)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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) { // // Normally, VS launches a program using the IDebugPortEx2::LaunchSuspended method, and the attaches the debugger to the suspended program. // However, there are circumstances in which the DebugEngine may need to launch a program or other dependencies (e.g. tools or interpreters) in which case this method is used. // IDebugEngineLaunch2::ResumeProcess method is called to start the process after the program has been launched in a suspended state. // LoggingUtils.PrintFunction (); try { if (port == null) { throw new ArgumentNullException ("port"); } if (string.IsNullOrEmpty (exe)) { throw new ArgumentNullException ("exe"); } if (!File.Exists (exe)) { throw new FileNotFoundException ("Failed to find target application: " + exe); } m_sdmCallback = new DebugEngineCallback (this, ad7Callback); DebuggeePort debuggeePort = port as DebuggeePort; DebuggeeProcess debugProcess = null; // // Evaluate options; including current debugger target application. // if (m_launchConfiguration == null) { throw new InvalidOperationException ("No launch configuration found."); } m_launchConfiguration.FromString (options); string packageName = m_launchConfiguration ["PackageName"]; string launchActivity = m_launchConfiguration ["LaunchActivity"]; bool debugMode = m_launchConfiguration ["DebugMode"].Equals ("true"); bool openGlTrace = m_launchConfiguration ["OpenGlTrace"].Equals ("true"); bool appIsRunning = false; // // Cache any LaunchSuspended specific parameters. // m_launchConfiguration ["LaunchSuspendedExe"] = exe; m_launchConfiguration ["LaunchSuspendedDir"] = dir; m_launchConfiguration ["LaunchSuspendedEnv"] = env; // // Prevent blocking the main VS thread when launching a suspended application. // Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.ShowDialog, string.Empty), null, null); ManualResetEvent launchSuspendedMutex = new ManualResetEvent (false); Thread asyncLaunchSuspendedThread = new Thread (delegate () { try { // // Launch application on device in a 'suspended' state. // Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Starting '{0}'...", packageName)), null, null); if (!appIsRunning) { StringBuilder launchArgumentsBuilder = new StringBuilder (); launchArgumentsBuilder.Append ("start "); if (debugMode) { launchArgumentsBuilder.Append ("-D "); // debug } else { launchArgumentsBuilder.Append ("-W "); // wait } launchArgumentsBuilder.Append ("-S "); // force stop the target app before starting the activity if (openGlTrace) { launchArgumentsBuilder.Append ("--opengl-trace "); } launchArgumentsBuilder.Append (packageName + "/" + launchActivity); Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("[adb:shell:am] {0}", launchArgumentsBuilder)), null, null); string launchResponse = debuggeePort.PortDevice.Shell ("am", launchArgumentsBuilder.ToString ()); if (string.IsNullOrEmpty (launchResponse) || launchResponse.Contains ("Error:")) { throw new InvalidOperationException ("Launch intent failed:\n" + launchResponse); } } // // Query whether the target application is already running. (Double-check) // int launchAttempt = 1; int maxLaunchAttempts = 20; while (!appIsRunning) { Broadcast(new DebugEngineEvent.DebuggerConnectionEvent(DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format("Waiting for '{0}' to launch (Attempt {1} of {2})...", packageName, launchAttempt, maxLaunchAttempts)), null, null); LoggingUtils.RequireOk (debuggeePort.RefreshProcesses ()); // // Validate that the process is running and was spawned by one of the zygote processes. // uint [] zygotePids = debuggeePort.PortDevice.GetPidsFromName ("zygote"); uint [] zygote64Pids = debuggeePort.PortDevice.GetPidsFromName ("zygote64"); uint [] packagePids = debuggeePort.PortDevice.GetPidsFromName (packageName); for (int i = packagePids.Length - 1; i >= 0; --i) { uint pid = packagePids [i]; AndroidProcess packageProcess = debuggeePort.PortDevice.GetProcessFromPid (pid); bool spawnedByZygote = false; if ((zygotePids.Length > 0) && (packageProcess.ParentPid == zygotePids [0])) { spawnedByZygote = true; } else if ((zygote64Pids.Length > 0) && (packageProcess.ParentPid == zygote64Pids [0])) { spawnedByZygote = true; } if (spawnedByZygote) { debugProcess = debuggeePort.GetProcessForPid (pid); appIsRunning = (debugProcess != null); break; } } if (!appIsRunning) { if (++launchAttempt > maxLaunchAttempts) { throw new TimeoutException (string.Format ("'{0}' failed to launch. Please ensure device is unlocked.", packageName)); } Application.DoEvents (); Thread.Sleep (100); } } launchSuspendedMutex.Set (); } catch (Exception e) { LoggingUtils.HandleException (e); string error = string.Format ("[Exception] {0}\n{1}", e.Message, e.StackTrace); Broadcast (ad7Callback, new DebugEngineEvent.Error (error, true), null, null); launchSuspendedMutex.Set (); } }); asyncLaunchSuspendedThread.Start (); while (!launchSuspendedMutex.WaitOne (0)) { Application.DoEvents (); Thread.Sleep (100); } // // Attach to launched process. // if (debugProcess == null) { throw new InvalidOperationException (string.Format ("'{0}' failed to launch. Could not continue.", packageName)); } process = debugProcess; return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); process = null; try { string error = string.Format ("[Exception] {0}\n{1}", e.Message, e.StackTrace); Broadcast (ad7Callback, new DebugEngineEvent.Error (error, true), null, null); } catch { LoggingUtils.HandleException (e); } return Constants.E_FAIL; } }
public MonoProcess(IDebugPort2 pPort) { Id = Guid.NewGuid(); _port = pPort; }
int IDebugPortSupplier2.AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { throw new NotImplementedException(); }
public int GetPort(out IDebugPort2 ppPort) { DebugHelper.TraceEnteringMethod(); ppPort = _port; return VSConstants.S_OK; }
int IDebugPortSupplier2.RemovePort(IDebugPort2 pPort) { throw new NotImplementedException(); }
// 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(m_ad7ProgramId == Guid.Empty); m_ad7ProgramId = Guid.NewGuid(); STARTUPINFO si = new STARTUPINFO(); pi = new PROCESS_INFORMATION(); // try/finally free bool procOK = NativeMethods.CreateProcess(exe, args, IntPtr.Zero, IntPtr.Zero, false, ProcessCreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi); pID = pi.dwProcessId; Task writepipeOK = WriteNamedPipeAsync(); Task readpipeOK = ReadNamedPipeAsync(); threadHandle = pi.hThread; IntPtr processHandle = pi.hProcess; // Inject LuaDebug into host IntPtr loadLibAddr = DLLInjector.GetProcAddress(DLLInjector.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); string VS140ExtensionPath = Path.Combine(Path.GetDirectoryName(typeof(EngineConstants).Assembly.Location), "LuaDetour"); string luaDetoursDllName = Path.Combine(VS140ExtensionPath, "LuaDetours.dll"); if (!File.Exists(luaDetoursDllName)) { process = null; return(VSConstants.E_FAIL); } IntPtr allocMemAddress1 = DLLInjector.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)((luaDetoursDllName.Length + 1) * Marshal.SizeOf(typeof(char))), DLLInjector.MEM_COMMIT | DLLInjector.MEM_RESERVE, DLLInjector.PAGE_READWRITE); UIntPtr bytesWritten1; DLLInjector.WriteProcessMemory(processHandle, allocMemAddress1, Encoding.Default.GetBytes(luaDetoursDllName), (uint)((luaDetoursDllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten1); IntPtr hRemoteThread1 = DLLInjector.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibAddr, allocMemAddress1, 0, IntPtr.Zero); IntPtr[] handles1 = new IntPtr[] { hRemoteThread1 }; uint index1; NativeMethods.CoWaitForMultipleHandles(0, -1, handles1.Length, handles1, out index1); string debugDllName = Path.Combine(VS140ExtensionPath, "LuaDebug32.dll"); IntPtr allocMemAddress2 = DLLInjector.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)((debugDllName.Length + 1) * Marshal.SizeOf(typeof(char))), DLLInjector.MEM_COMMIT | DLLInjector.MEM_RESERVE, DLLInjector.PAGE_READWRITE); UIntPtr bytesWritten2; DLLInjector.WriteProcessMemory(processHandle, allocMemAddress2, Encoding.Default.GetBytes(debugDllName), (uint)((debugDllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten2); IntPtr hRemoteThread2 = DLLInjector.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibAddr, allocMemAddress2, 0, IntPtr.Zero); IntPtr[] handles = new IntPtr[] { hRemoteThread2 }; uint index2; NativeMethods.CoWaitForMultipleHandles(0, -1, handles.Length, handles, out index2); AD_PROCESS_ID adProcessId = new AD_PROCESS_ID(); adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = pi.dwProcessId; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); debugProcess = process; return(VSConstants.S_OK); }
public AD7Process(IDebugPort2 debugPort) { Id = Guid.NewGuid(); _port = debugPort; Node = new AD7ProgramNode(this); }
public int LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { DebugHelper.TraceEnteringMethod(); Events = new MonoDebuggerEvents(this, pCallback); DebuggedProcess = new DebuggedMonoProcess(this, IPAddress.Parse(pszArgs)); DebuggedProcess.ApplicationClosed += _debuggedProcess_ApplicationClosed; ppProcess = RemoteProcess = new MonoProcess(pPort); return VSConstants.S_OK; }
private LaunchOptions CreateAttachLaunchOptions(uint processId, IDebugPort2 port) { LaunchOptions launchOptions; var unixPort = port as IDebugUnixShellPort; if (unixPort != null) { MIMode miMode; if (_engineGuid == EngineConstants.ClrdbgEngine) { miMode = MIMode.Clrdbg; } else if (_engineGuid == EngineConstants.GdbEngine) { miMode = MIMode.Gdb; } else { // TODO: LLDB support throw new NotImplementedException(); } if (processId > int.MaxValue) { throw new ArgumentOutOfRangeException("processId"); } string getClrDbgUrl = GetMetric("GetClrDbgUrl") as string; string remoteDebuggerInstallationDirectory = GetMetric("RemoteInstallationDirectory") as string; string remoteDebuggerInstallationSubDirectory = GetMetric("RemoteInstallationSubDirectory") as string; string clrDbgVersion = GetMetric("ClrDbgVersion") as string; launchOptions = UnixShellPortLaunchOptions.CreateForAttachRequest(unixPort, (int)processId, miMode, getClrDbgUrl, remoteDebuggerInstallationDirectory, remoteDebuggerInstallationSubDirectory, clrDbgVersion); // TODO: Add a tools option page for: // AdditionalSOLibSearchPath // VisualizerFile? } else { // TODO: when we have a tools options page, we can add support for the attach dialog here pretty easily: //var defaultPort = port as IDebugDefaultPort2; //if (defaultPort != null && defaultPort.QueryIsLocal() == Constants.S_OK) //{ // launchOptions = new LocalLaunchOptions(...); //} //else //{ // // Invalid port // throw new ArgumentException(); //} throw new NotSupportedException(); } return(launchOptions); }
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; }