public int GetHostPid(AD_PROCESS_ID[] pHostProcessId) { DebugHelper.TraceEnteringMethod(); pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pHostProcessId[0].guidProcessId = _processId; return VSConstants.S_OK; }
// Gets the system process identifier for the process hosting a program. int IDebugProgramNode2.GetHostPid(AD_PROCESS_ID[] pHostProcessId) { // Return the process id of the debugged process pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pHostProcessId[0].guidProcessId = mProcessID; return VSConstants.S_OK; }
public int GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { Log.Debug("ProgramProvider: GetProviderProcessData"); if (Flags.HasFlag(enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES)) { var process = Process.GetProcessById((int) ProcessId.dwProcessId); foreach (ProcessModule module in process.Modules) { if (module.ModuleName.StartsWith("System.Management.Automation", StringComparison.OrdinalIgnoreCase)) { var node = new ScriptProgramNode(new ScriptDebugProcess(pPort, ProcessId.dwProcessId)); var programNodes = new[] { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; var destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); pProcess[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; pProcess[0].ProgramNodes.Members = destinationArray; pProcess[0].ProgramNodes.dwCount = (uint)programNodes.Length; return VSConstants.S_OK; } } } return VSConstants.S_FALSE; }
// Gets the system process identifier for the process hosting a program. int IDebugProgramNode2.GetHostPid(AD_PROCESS_ID[] pHostProcessId) { // Return the process id of the debugged process pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; pHostProcessId[0].dwProcessId = (uint)m_processId; return VSConstants.S_OK; }
public int GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { DebugHelper.TraceEnteringMethod(); ppProgramNode = null; return VSConstants.S_OK; }
public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = null; if (ProcessId.ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM) { return VSConstants.E_FAIL; } IEnumDebugProcesses2 processEnum; int hr = EnumProcesses(out processEnum); if (ErrorHandler.Failed(hr)) { return hr; } var processes = new IDebugProcess2[1]; var pids = new AD_PROCESS_ID[1]; uint fetched = 0; while (true) { hr = processEnum.Next(1, processes, ref fetched); if (ErrorHandler.Failed(hr)) { return hr; } else if (fetched == 0) { return VSConstants.E_FAIL; } if (ErrorHandler.Succeeded(processes[0].GetPhysicalProcessId(pids)) && ProcessId.dwProcessId == pids[0].dwProcessId) { ppProcess = processes[0]; return VSConstants.S_OK; } } }
// Obtains information about programs running, filtered in a variety of ways. int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) { processArray[0] = new PROVIDER_PROCESS_DATA(); if (Flags.HasFlag(enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES)) { // The debugger is asking the engine to return the program nodes it can debug. The // sample engine claims that it can debug all processes, and returns exsactly one // program node for each process. A full-featured debugger may wish to examine the // target process and determine if it understands how to debug it. var node = (IDebugProgramNode2)(new AD7ProgramNode(ProcessId.guidProcessId)); IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; processArray[0].ProgramNodes.Members = destinationArray; processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; return VSConstants.S_OK; } return VSConstants.S_FALSE; }
// Gets the system process identifier for the process hosting a program. int IDebugProgramNode2.GetHostPid(AD_PROCESS_ID[] pHostProcessId) { // Return the process id of the debugged process pHostProcessId[0] = _processId; return Constants.S_OK; }
public static AD_PROCESS_ID GetPhysicalProcessId(this IDebugProcess2 process) { Contract.Requires<ArgumentNullException>(process != null, "process"); AD_PROCESS_ID[] processId = new AD_PROCESS_ID[1]; ErrorHandler.ThrowOnFailure(process.GetPhysicalProcessId(processId)); return processId[0]; }
/// <summary> /// Gets the system process identifier for the process hosting the program. /// </summary> /// <param name="pHostProcessId">Returns the system process identifier for the hosting process.</param> /// <returns> /// If successful, returns S_OK; otherwise, returns an error code. /// </returns> public override int GetHostPid( AD_PROCESS_ID[] pHostProcessId ) { Logger.Debug( string.Empty ); pHostProcessId[0].ProcessIdType = (uint) enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pHostProcessId[0].guidProcessId = Process.Id; return VSConstants.S_OK; }
public static IDebugProcess2 GetProcess(this IDebugPort2 port, AD_PROCESS_ID processId) { Contract.Requires<ArgumentNullException>(port != null, "port"); IDebugProcess2 process; ErrorHandler.ThrowOnFailure(port.GetProcess(processId, out process)); return process; }
// Gets the system process identifier for the process hosting a program. int IDebugProgramNode2.GetHostPid(AD_PROCESS_ID[] pHostProcessId) { Log.Debug("ScriptProgramNode: Entering GetHostPid"); // Return the process id of the debugged process pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pHostProcessId[0].guidProcessId = Process.Id; return VSConstants.S_OK; }
/// <summary> /// Retrieves a list of running programs from a specified process. /// </summary> /// <param name="Flags"> /// A combination of flags from the PROVIDER_FLAGS enumeration. The following flags are typical for this call: /// /// Flag Description /// PFLAG_REMOTE_PORT Caller is running on remote machine. /// PFLAG_DEBUGGEE Caller is currently being debugged (additional information about marshalling will be returned for each node). /// PFLAG_ATTACHED_TO_DEBUGGEE Caller was attached to but not launched by the debugger. /// PFLAG_GET_PROGRAM_NODES Caller is asking for a list of program nodes to be returned. /// </param> /// <param name="pPort">The port the calling process is running on.</param> /// <param name="ProcessId">An AD_PROCESS_ID structure holding the ID of the process that contains the program in question.</param> /// <param name="EngineFilter">An array of GUIDs for debug engines assigned to debug this process (these will be used to filter the programs that are actually returned based on what the supplied engines support; if no engines are specified, then all programs will be returned).</param> /// <param name="pProcess">A PROVIDER_PROCESS_DATA structure that is filled in with the requested information.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> /// <remarks>This method is normally called by a process to obtain a list of programs running in that process. The returned information is a list of IDebugProgramNode2 objects.</remarks> public virtual int GetProviderProcessData( enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { Logger.Debug( string.Empty ); return VSConstants.E_NOTIMPL; }
public static int GetProcessId(this IDebugProcess2 process) { if (process == null) return 0; var id = new AD_PROCESS_ID[1]; if (process.GetPhysicalProcessId(id) != VSConstants.S_OK) return 0; return (int)id[0].dwProcessId; }
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; }
public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = null; if (ProcessId.ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM) { return VSConstants.E_FAIL; } ppProcess = GetProcesses().FirstOrDefault(p => p.ProcessId == ProcessId.dwProcessId); return ppProcess != null ? VSConstants.S_OK : VSConstants.E_FAIL; }
/// <summary> /// Retrieves the program node for a specific program. /// </summary> /// <param name="Flags"> /// A combination of flags from the PROVIDER_FLAGS enumeration. The following flags are typical for this call: /// /// Flag Description /// PFLAG_REMOTE_PORT Caller is running on remote machine. /// PFLAG_DEBUGGEE Caller is currently being debugged (additional information about marshalling will be returned for each node). /// PFLAG_ATTACHED_TO_DEBUGGEE Caller was attached to but not launched by the debugger. /// </param> /// <param name="pPort">The port the calling process is running on.</param> /// <param name="ProcessId">An AD_PROCESS_ID structure holding the ID of the process that contains the program in question.</param> /// <param name="guidEngine">GUID of the debug engine that the program is attached to (if any).</param> /// <param name="programId">ID of the program for which to get the program node.</param> /// <param name="ppProgramNode">An IDebugProgramNode2 object representing the requested program node.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> public virtual int GetProviderProgramNode( enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { Logger.Debug( string.Empty ); ppProgramNode = null; return VSConstants.E_NOTIMPL; }
// Obtains information about programs running, filtered in a variety of ways. int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) { processArray[0] = new PROVIDER_PROCESS_DATA(); // we handle creation of the remote program provider ourselves. This is because we always load our program provider locally which keeps // attach working when developing Python Tools and running/debugging from within VS and in the experimental hive. When we are installed // we install into the GAC so these types are available to create and then remote debugging works as well. When we're running in the // experimental hive we are not in the GAC so if we're created outside of VS (e.g. in msvsmon on the local machine) then we can't get // at our program provider and debug->attach doesn't work. if (port != null && port.QueryIsLocal() == VSConstants.S_FALSE) { IDebugCoreServer3 server; if (ErrorHandler.Succeeded(port.GetServer(out server))) { IDebugCoreServer90 dbgServer = server as IDebugCoreServer90; if (dbgServer != null) { Guid g = typeof(IDebugProgramProvider2).GUID; IntPtr remoteProviderPunk; int hr = dbgServer.CreateManagedInstanceInServer(typeof(AD7ProgramProvider).FullName, typeof(AD7ProgramProvider).Assembly.FullName, 0, ref g, out remoteProviderPunk); try { if (ErrorHandler.Succeeded(hr)) { var remoteProvider = (IDebugProgramProvider2)Marshal.GetObjectForIUnknown(remoteProviderPunk); return remoteProvider.GetProviderProcessData(Flags, null, ProcessId, EngineFilter, processArray); } } finally { if (remoteProviderPunk != IntPtr.Zero) { Marshal.Release(remoteProviderPunk); } } } } } else if ((Flags & enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0 ) { // The debugger is asking the engine to return the program nodes it can debug. We check // each process if it has a python##.dll or python##_d.dll loaded and if it does // then we report the program as being a Python process. if (DebugAttach.IsPythonProcess((int)ProcessId.dwProcessId)) { IDebugProgramNode2 node = new AD7ProgramNode((int)ProcessId.dwProcessId); IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; processArray[0].ProgramNodes.Members = destinationArray; processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; return VSConstants.S_OK; } } return VSConstants.S_FALSE; }
public DebuggedProcess(AD7Engine engine, IPAddress ipAddress, EngineCallback callback) { _engine = engine; _ipAddress = ipAddress; Instance = 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; _callback = callback; }
// Establishes a callback to watch for provider events associated with specific kinds of processes int IDebugProgramProvider2.WatchForProviderEvents(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 ad7EventCallback) { // The sample debug engine is a native debugger, and can therefore always provide a program node // in GetProviderProcessData. Non-native debuggers may wish to implement this method as a way // of monitoring the process before code for their runtime starts. For example, if implementing a // 'foo script' debug engine, one could attach to a process which might eventually run 'foo script' // before this 'foo script' started. // // To implement this method, an engine would monitor the target process and call AddProgramNode // when the target process started running code which was debuggable by the engine. The // enum_PROVIDER_FLAGS.PFLAG_ATTACHED_TO_DEBUGGEE flag indicates if the request is to start // or stop watching the process. return VSConstants.S_OK; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugProgramProvider2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int GetProviderProcessData (enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA [] processArray) { // // Retrieves a list of running programs from a specified process. // LoggingUtils.PrintFunction (); try { processArray [0] = new PROVIDER_PROCESS_DATA (); if ((Flags & enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0) { // The debugger is asking the engine to return the program nodes it can debug. The // sample engine claims that it can debug all processes, and returns exactly one // program node for each process. A full-featured debugger may wish to examine the // target process and determine if it understands how to debug it. IDebugProgramNode2 node = (IDebugProgramNode2)(new DebuggeeProgram (null)); IntPtr [] programNodes = { Marshal.GetComInterfaceForObject (node, typeof (IDebugProgramNode2)) }; IntPtr destinationArray = Marshal.AllocCoTaskMem (IntPtr.Size * programNodes.Length); Marshal.Copy (programNodes, 0, destinationArray, programNodes.Length); processArray [0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; processArray [0].ProgramNodes.Members = destinationArray; processArray [0].ProgramNodes.dwCount = (uint)programNodes.Length; return Constants.S_OK; } return Constants.S_FALSE; } catch (Exception e) { LoggingUtils.HandleException (e); return Constants.E_FAIL; } }
// Gets a program node, given a specific process ID. int IDebugProgramProvider2.GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 programNode) { // This method is used for Just-In-Time debugging support, which this program provider does not support programNode = null; return(VSConstants.E_NOTIMPL); }
public AD7ProgramNode(AD_PROCESS_ID processId, Guid engineGuid) { _processId = processId; _engineGuid = engineGuid; }
public int GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { Log.Debug("ProgramProvider: GetProviderProgramNode"); ppProgramNode = null; return(VSConstants.S_OK); }
public int WatchForProviderEvents(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 pEventCallback) { DebugHelper.TraceEnteringMethod(); 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..."); 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 GetProviderProgramNode(uint Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { ppProgramNode = null; return(S_FALSE); }
public int GetPhysicalProcessId(AD_PROCESS_ID[] pProcessId) { pProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pProcessId[0].guidProcessId = Id; return VSConstants.S_OK; }
/// <summary> /// Establishes a callback to watch for provider events associated with specific kinds of processes. /// </summary> /// <param name="flags">The flags.</param> /// <param name="port">The port.</param> /// <param name="processId">The process identifier.</param> /// <param name="engineFilter">The engine filter.</param> /// <param name="guidLaunchingEngine">The unique identifier launching engine.</param> /// <param name="eventCallback">The event callback.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> public int WatchForProviderEvents(enum_PROVIDER_FLAGS flags, IDebugDefaultPort2 port, AD_PROCESS_ID processId, CONST_GUID_ARRAY engineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 eventCallback) { return(S_OK); }
private CorDebugProcess GetProcess( IDebugProgramNode2 programNode ) { AD_PROCESS_ID[] pids = new AD_PROCESS_ID[1]; programNode.GetHostPid( pids ); return GetProcess( pids[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; }
int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { return(VSConstants.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(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); }
// Attach the debug engine to a program. public int Attach(IDebugProgram2[] portProgramArray, IDebugProgramNode2[] programNodeArray, 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(); } IDebugProgram2 portProgram = portProgramArray[0]; Exception exception = null; try { IDebugProcess2 process; EngineUtils.RequireOk(portProgram.GetProcess(out process)); AD_PROCESS_ID processId = EngineUtils.GetProcessId(process); EngineUtils.RequireOk(portProgram.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) { if (processId.ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM) { Debug.Fail("Invalid process to attach to"); throw new ArgumentException(); } IDebugPort2 port; EngineUtils.RequireOk(process.GetPort(out port)); Debug.Assert(_engineCallback == null); Debug.Assert(_debuggedProcess == null); _engineCallback = new EngineCallback(this, ad7Callback); LaunchOptions launchOptions = CreateAttachLaunchOptions(processId.dwProcessId, port); StartDebugging(launchOptions); } else { if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id)) { Debug.Fail("Asked to attach to a process while we are debugging"); return(Constants.E_FAIL); } } AD7EngineCreateEvent.Send(this); AD7ProgramCreateEvent.Send(this); this.ProgramCreateEventSent = true; return(Constants.S_OK); } catch (Exception e) when(ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true)) { exception = e; } // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and // return that the attach was canceled OnStartDebuggingFailed(exception); return(AD7_HRESULT.E_ATTACH_USER_CANCELED); }
/// <summary> /// Obtains information about programs running, filtered in a variety of ways. /// </summary> /// <param name="flags">The flags.</param> /// <param name="port">The port.</param> /// <param name="processId">The process identifier.</param> /// <param name="engineFilter">The engine filter.</param> /// <param name="process">The process.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> public int GetProviderProcessData(enum_PROVIDER_FLAGS flags, IDebugDefaultPort2 port, AD_PROCESS_ID processId, CONST_GUID_ARRAY engineFilter, PROVIDER_PROCESS_DATA[] process) { return(S_FALSE); }
public int GetHostPid(AD_PROCESS_ID[] pHostProcessId) { return _process.GetPhysicalProcessId(pHostProcessId); }
/// <summary> /// Gets a program node, given a specific process ID. /// </summary> /// <param name="flags">The flags.</param> /// <param name="port">The port.</param> /// <param name="processId">The process identifier.</param> /// <param name="guidEngine">The unique identifier engine.</param> /// <param name="programId">The program identifier.</param> /// <param name="programNode">The program node.</param> /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns> public int GetProviderProgramNode(enum_PROVIDER_FLAGS flags, IDebugDefaultPort2 port, AD_PROCESS_ID processId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 programNode) { programNode = null; return(S_FALSE); }
public int GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { DebugHelper.TraceEnteringMethod(); return(VSConstants.S_OK); }
public static AD_PROCESS_ID GetProcessId(IDebugProcess2 process) { AD_PROCESS_ID[] pid = new AD_PROCESS_ID[1]; EngineUtils.RequireOk(process.GetPhysicalProcessId(pid)); return(pid[0]); }
public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, string registryRoot) { uint processExitCode = 0; g_Process = this; _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>(); OutputStringEvent += 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 (_connected) { _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")) { // GDB sometimes returns exit codes, which don't fit into uint, like "030000000472". // And we can't throw from here, because it crashes VS. // Full exit code will still usually be reported in the Output window, // but here let's return "uint.MaxValue" just to indicate that something went wrong. if (!uint.TryParse(results.Results.FindString("exit-code"), out processExitCode)) { processExitCode = uint.MaxValue; } } // 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(new OutputMessage(message, enum_MESSAGETYPE.MT_OUTPUTSTRING, OutputMessage.Severity.Warning)); } } } 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(); } }; 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); }; MessageEvent += (object o, ResultEventArgs args) => { OutputMessage outputMessage = DecodeOutputEvent(args.Results); if (outputMessage != null) { _callback.OnOutputMessage(outputMessage); } }; BreakChangeEvent += _breakpointManager.BreakpointModified; }
public int WatchForProviderEvents(uint Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 pEventCallback) { return(S_OK); }
public int GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { Log.Debug("ProgramProvider: GetProviderProcessData"); if (Flags.HasFlag(enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES)) { var process = Process.GetProcessById((int)ProcessId.dwProcessId); foreach (ProcessModule module in process.Modules) { if (module.ModuleName.StartsWith("System.Management.Automation", StringComparison.OrdinalIgnoreCase)) { var node = new ScriptProgramNode(new ScriptDebugProcess(pPort, ProcessId.dwProcessId)); var programNodes = new[] { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; var destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); pProcess[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; pProcess[0].ProgramNodes.Members = destinationArray; pProcess[0].ProgramNodes.dwCount = (uint)programNodes.Length; return(VSConstants.S_OK); } } } return(VSConstants.S_FALSE); }
public int GetProviderProcessData(uint Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { return(S_FALSE); }
// Obtains information about programs running, filtered in a variety of ways. int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) { processArray[0] = new PROVIDER_PROCESS_DATA(); // we handle creation of the remote program provider ourselves. This is because we always load our program provider locally which keeps // attach working when developing Python Tools and running/debugging from within VS and in the experimental hive. When we are installed // we install into the GAC so these types are available to create and then remote debugging works as well. When we're running in the // experimental hive we are not in the GAC so if we're created outside of VS (e.g. in msvsmon on the local machine) then we can't get // at our program provider and debug->attach doesn't work. if (port != null && port.QueryIsLocal() == VSConstants.S_FALSE) { if (ErrorHandler.Succeeded(port.GetServer(out var server))) { if (server is IDebugCoreServer90 dbgServer) { var g = typeof(IDebugProgramProvider2).GUID; var hr = dbgServer.CreateManagedInstanceInServer(typeof(AD7ProgramProvider).FullName, typeof(AD7ProgramProvider).Assembly.FullName, 0, ref g, out var remoteProviderPunk); try { if (ErrorHandler.Succeeded(hr)) { var remoteProvider = (IDebugProgramProvider2)Marshal.GetObjectForIUnknown(remoteProviderPunk); return(remoteProvider.GetProviderProcessData(Flags, null, ProcessId, EngineFilter, processArray)); } } finally { if (remoteProviderPunk != IntPtr.Zero) { Marshal.Release(remoteProviderPunk); } } } } } else if ((Flags & enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0) { // The debugger is asking the engine to return the program nodes it can debug. We check // each process if it has a python##.dll or python##_d.dll loaded and if it does // then we report the program as being a Python process. /* * if (DebugAttach.IsPythonProcess((int)ProcessId.dwProcessId)) { * IDebugProgramNode2 node = new AD7ProgramNode((int)ProcessId.dwProcessId); * * IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; * * IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); * Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); * * processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; * processArray[0].ProgramNodes.Members = destinationArray; * processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; * * return VSConstants.S_OK; * }*/ } return(VSConstants.S_FALSE); }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { bool savedProgram = false; bool savedThread = false; if (riidEvent == processCreateEvent) { AD_PROCESS_ID[] pdwProcessId = new AD_PROCESS_ID[1]; process.GetPhysicalProcessId(pdwProcessId); Debug.Assert(!this.attachedProcesses.Contains(pdwProcessId[0].dwProcessId)); this.attachedProcesses.Add(pdwProcessId[0].dwProcessId); } else if (riidEvent == processDestroyEvent) { AD_PROCESS_ID[] pdwProcessId = new AD_PROCESS_ID[1]; process.GetPhysicalProcessId(pdwProcessId); Debug.Assert(this.attachedProcesses.Contains(pdwProcessId[0].dwProcessId)); this.attachedProcesses.Remove(pdwProcessId[0].dwProcessId); } else if (riidEvent == breakInEvent && this.currentDebugProgram != program && program != null && thread != null) { // Evaluate an expression get access to the memory context and the bitness. IDebugProperty2 debugProperty = this.EvaluateExpression(thread, "(void**)0x0 + 1"); if (debugProperty != null) { using (new DisposableComReference(debugProperty)) { DEBUG_PROPERTY_INFO[] debugPropertyInfo = new DEBUG_PROPERTY_INFO[1]; if (debugProperty.GetPropertyInfo((uint)enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE, 16, evaluateExpressionTimeout, null, 0, debugPropertyInfo) == S_OK) { IDebugMemoryContext2 memoryContext = null; IDebugMemoryBytes2 memoryBytes = null; if (debugProperty.GetMemoryContext(out memoryContext) == S_OK && debugProperty.GetMemoryBytes(out memoryBytes) == S_OK) { DisposableComReference.SetReference(ref this.currentDebugProgram, program); DisposableComReference.SetReference(ref this.currentThread, thread); DisposableComReference.SetReference(ref this.memoryContext, memoryContext); DisposableComReference.SetReference(ref this.memoryBytes, memoryBytes); ulong offset = ulong.Parse(debugPropertyInfo[0].bstrValue.Substring("0x".Length), System.Globalization.NumberStyles.AllowHexSpecifier); // Adjust the memory context and calculate the bitness. this.memoryContext.Subtract(offset, out memoryContext); DisposableComReference.SetReference(ref this.memoryContext, memoryContext); this.isPointer64Bit = (offset == 8); this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.Detaching); this.engine.DiaLoader.ClearSymbols(); savedProgram = true; savedThread = true; } else { DisposableComReference.ReleaseIfNotNull(ref memoryContext); DisposableComReference.ReleaseIfNotNull(ref memoryBytes); } } } } } else if (riidEvent == stopDebugEvent) { // The debugger stopped. Clear the references. DisposableComReference.ReleaseIfNotNull(ref this.currentDebugProgram); DisposableComReference.ReleaseIfNotNull(ref this.memoryContext); DisposableComReference.ReleaseIfNotNull(ref this.memoryBytes); this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.Detaching); this.engine.DiaLoader.ClearSymbols(); } else if (riidEvent == breakInEvent) { // The debugger broke in, notify the client. this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.Break); } else if (riidEvent == threadSwitchEvent) { // The user switched the current thread. DisposableComReference.SetReference(ref this.currentThread, thread); savedThread = true; if (this.currentThread != null) { uint threadId; thread.GetThreadId(out threadId); this.TargetThreadSystemId = threadId; } bool processChanged = false; if (process != null) { AD_PROCESS_ID[] pdwProcessId = new AD_PROCESS_ID[1]; process.GetPhysicalProcessId(pdwProcessId); if (this.TargetProcessSystemId != 0) { if (pdwProcessId[0].dwProcessId != this.TargetProcessSystemId) { this.TargetProcessSystemId = pdwProcessId[0].dwProcessId; processChanged = true; } } else { this.TargetProcessSystemId = pdwProcessId[0].dwProcessId; if (this.TargetProcessSystemId != 0) { processChanged = true; } } } else if (this.TargetProcessSystemId != 0) { this.TargetProcessSystemId = 0; processChanged = true; } if (processChanged) { DisposableComReference.SetReference(ref this.currentDebugProgram, program); savedProgram = true; if (program != null) { // Evaluate an expression get access to the memory context and the bitness. IDebugProperty2 debugProperty = this.EvaluateExpression(thread, "(void**)0x0 + 1"); if (debugProperty != null) { using (new DisposableComReference(debugProperty)) { DEBUG_PROPERTY_INFO[] debugPropertyInfo = new DEBUG_PROPERTY_INFO[1]; if (debugProperty.GetPropertyInfo((uint)enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE, 16, evaluateExpressionTimeout, null, 0, debugPropertyInfo) == S_OK) { IDebugMemoryContext2 memoryContext = null; IDebugMemoryBytes2 memoryBytes = null; if ((debugProperty.GetMemoryContext(out memoryContext) == S_OK) && (debugProperty.GetMemoryBytes(out memoryBytes) == S_OK)) { DisposableComReference.SetReference(ref this.memoryContext, memoryContext); DisposableComReference.SetReference(ref this.memoryBytes, memoryBytes); ulong offset = ulong.Parse(debugPropertyInfo[0].bstrValue.Substring("0x".Length), System.Globalization.NumberStyles.AllowHexSpecifier); // Adjust the memory context and calculate the bitness. this.memoryContext.Subtract(offset, out memoryContext); DisposableComReference.SetReference(ref this.memoryContext, memoryContext); this.isPointer64Bit = (offset == 8); } else { DisposableComReference.ReleaseIfNotNull(ref memoryContext); DisposableComReference.ReleaseIfNotNull(ref memoryBytes); } } } } this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.ChangingProcess); } } else { this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.ChangingThread); } } if (!savedProgram) { DisposableComReference.ReleaseIfNotNull(ref program); } if (!savedThread) { DisposableComReference.ReleaseIfNotNull(ref thread); } DisposableComReference.ReleaseIfNotNull(ref engine); DisposableComReference.ReleaseIfNotNull(ref process); DisposableComReference.ReleaseIfNotNull(ref debugEvent); return S_OK; }
public int GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { DebugHelper.TraceEnteringMethod(); ppProgramNode = null; return(VSConstants.S_OK); }
int IDebugProgramProvider2.WatchForProviderEvents(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 pEventCallback) { return(VSConstants.S_OK); }
// Establishes a callback to watch for provider events associated with specific kinds of processes int IDebugProgramProvider2.WatchForProviderEvents(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 ad7EventCallback) { // The sample debug engine is a native debugger, and can therefore always provide a program node // in GetProviderProcessData. Non-native debuggers may wish to implement this method as a way // of monitoring the process before code for their runtime starts. For example, if implementing a // 'foo script' debug engine, one could attach to a process which might eventually run 'foo script' // before this 'foo script' started. // // To implement this method, an engine would monitor the target process and call AddProgramNode // when the target process started running code which was debuggable by the engine. The // enum_PROVIDER_FLAGS.PFLAG_ATTACHED_TO_DEBUGGEE flag indicates if the request is to start // or stop watching the process. return(VSConstants.S_OK); }
// Obtains information about programs running, filtered in a variety of ways. int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) { processArray[0] = new PROVIDER_PROCESS_DATA(); if (EngineUtils.IsFlagSet((uint)Flags, (int)enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES)) { // The debugger is asking the engine to return the program nodes it can debug. The // sample engine claims that it can debug all processes, and returns exsactly one // program node for each process. A full-featured debugger may wish to examine the // target process and determine if it understands how to debug it. IDebugProgramNode2 node = (IDebugProgramNode2)(new AD7ProgramNode((int)ProcessId.dwProcessId)); IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; processArray[0].ProgramNodes.Members = destinationArray; processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; return(EngineConstants.S_OK); } return(EngineConstants.S_FALSE); }
int IDebugProgramProvider2.GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { ppProgramNode = null; return(VSConstants.E_NOTIMPL); }
private CorDebugProcess GetProcess( AD_PROCESS_ID ProcessId ) { AD_PROCESS_ID pid; foreach (CorDebugProcess process in m_alProcesses) { pid = process.PhysicalProcessId; if (AreProcessIdEqual(ProcessId, pid)) { return process; } } return null; }
int Microsoft.VisualStudio.Debugger.Interop.IDebugPort2.GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = ((DebugPort)this).GetProcess(ProcessId); return(COM_HResults.BOOL_TO_HRESULT_FAIL(ppProcess != null)); }
int Microsoft.VisualStudio.Debugger.Interop.IDebugPort2.GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = ((DebugPort)this).GetProcess( ProcessId ); return Utility.COM_HResults.BOOL_TO_HRESULT_FAIL( ppProcess != null ); }
public MonoProgramNode(AD_PROCESS_ID processId) { _processId = processId; }
/// <summary> /// Gets the system process identifier for the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb162159.aspx) /// </summary> /// <param name="pHostProcessId"> Returns the system process identifier for the hosting process. </param> /// <returns> VSConstants.S_OK. </returns> public int GetHostPid(AD_PROCESS_ID[] pHostProcessId) { // According to the MSDN documentation (http://msdn.microsoft.com/en-us/library/bb162159.aspx), // it should return the process id of the hosting process, but what is expected is the program ID... pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; pHostProcessId[0].guidProcessId = m_processGuid; return VSConstants.S_OK; }
public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { throw new NotImplementedException(); }
public int GetHostId(AD_PROCESS_ID[] pProcessId) { throw new NotImplementedException(); }
int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] pProcess) { throw new NotImplementedException(); }
// Gets a program node, given a specific process ID. int IDebugProgramProvider2.GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 programNode) { // This method is used for Just-In-Time debugging support, which this program provider does not support programNode = null; return VSConstants.E_NOTIMPL; }
int IDebugProgramProvider2.GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 pPort, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 ppProgramNode) { throw new NotImplementedException(); }