int IDebugExpression2.EvaluateAsync(
   enum_EVALFLAGS dwFlags, 
   IDebugEventCallback2 pExprCallback)
 {
   // For now, no async evaluation supported.
   return VSConstants.E_NOTIMPL;
 }
        // This method evaluates the expression asynchronously.
        // This method should return immediately after it has started the expression evaluation. 
        // When the expression is successfully evaluated, an IDebugExpressionEvaluationCompleteEvent2 
        // must be sent to the IDebugEventCallback2 event callback
        int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback) {
            _tokenSource = new CancellationTokenSource();

            _frame.StackFrame.ExecuteTextAsync(_expression, _tokenSource.Token)
                .ContinueWith(p => {
                    try {
                        IDebugProperty2 property;
                        if (p.Exception != null && p.Exception.InnerException != null) {
                            property = new AD7EvalErrorProperty(p.Exception.InnerException.Message);
                        } else if (p.IsCanceled) {
                            property = new AD7EvalErrorProperty("Evaluation canceled");
                        } else if (p.IsFaulted || p.Result == null) {
                            property = new AD7EvalErrorProperty("Error");
                        } else {
                            property = new AD7Property(_frame, p.Result);
                        }

                        _tokenSource.Token.ThrowIfCancellationRequested();
                        _frame.Engine.Send(
                            new AD7ExpressionEvaluationCompleteEvent(this, property),
                            AD7ExpressionEvaluationCompleteEvent.IID,
                            _frame.Engine,
                            _frame.Thread);
                    } finally {
                        _tokenSource.Dispose();
                        _tokenSource = null;
                    }
                }, _tokenSource.Token);

            return VSConstants.S_OK;
        }
示例#3
0
        public void Dispose() {
            if (IsDisposed) {
                return;
            }

            var rSession = DebugSession.RSession;
            DebugSession.Browse -= Session_Browse;
            DebugSession.RSession.AfterRequest -= RSession_AfterRequest;
            DebugSession.RSession.Disconnected -= RSession_Disconnected;

            _events = null;
            _program = null;

            MainThread.Dispose();
            MainThread = null;

            DebugSession = null;
            RSessionProvider = null;
            DebugSessionProvider = null;

            IsDisposed = true;

            ExitBrowserAsync(rSession)
                .SilenceException<MessageTransportException>()
                .SilenceException<RException>()
                .DoNotWait();
        }
示例#4
0
文件: AD7Engine.cs 项目: e42s/VSLua
        // Attach the debug engine to a program. 
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            int processId = EngineUtils.GetProcessId(rgpPrograms[0]);
            if (processId == 0)
            {
                return VSConstants.E_NOTIMPL;
            }

            pID = (uint)processId;

            events = ad7Callback;

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

            AD7EngineCreateEvent.Send(this);

            AD7ProgramCreateEvent.Send(this);

            debugThread = new AD7Thread(this);

            AD7ThreadCreateEvent.Send(this);

            // This event is optional
            AD7LoadCompleteEvent.Send(this);
           

            return VSConstants.S_OK;
        }
        // This method evaluates the expression synchronously.
        int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult) {
            AutoResetEvent completion = new AutoResetEvent(false);
            PythonEvaluationResult result = null;
            _frame.StackFrame.ExecuteText(_expression, (obj) => {
                result = obj;
                completion.Set();
            });
            
            while (!_frame.StackFrame.Thread.Process.HasExited && !completion.WaitOne(Math.Min((int)dwTimeout, 100))) {
                if (dwTimeout <= 100) {
                    break;
                }
                dwTimeout -= 100;
            }

            if (_frame.StackFrame.Thread.Process.HasExited || result == null) {
                ppResult = null;
                return VSConstants.E_FAIL;
            } else if (result == null) {
                ppResult = null;
                return DebuggerConstants.E_EVALUATE_TIMEOUT;
            }
            ppResult = new AD7Property(_frame, result, _writable);

            return VSConstants.S_OK;
        }
示例#6
0
        public int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            if (celtPrograms == 0)
                return VSConstants.S_OK;

            if (pCallback == null)
                throw new ArgumentNullException("pCallback");
            if (rgpPrograms == null || rgpPrograms.Length < celtPrograms)
                throw new ArgumentException();
            if (rgpProgramNodes == null || rgpProgramNodes.Length < celtPrograms)
                throw new ArgumentException();

            if (celtPrograms > 1)
                throw new NotImplementedException();

            if (dwReason != enum_ATTACH_REASON.ATTACH_REASON_LAUNCH)
                throw new NotImplementedException();

            JavaDebugProgram program = rgpProgramNodes[0] as JavaDebugProgram;
            if (program == null)
                throw new NotSupportedException();

            lock (_programs)
            {
                _programs.Add(program);
            }

            DebugEvent @event = new DebugEngineCreateEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, this);
            pCallback.Event(this, program.GetProcess(), program, null, @event);

            program.InitializeDebuggerChannel(this, pCallback);
            return VSConstants.S_OK;
        }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #region IDebugProgram2 Members

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int Attach (IDebugEventCallback2 pCallback)
    {
      // 
      // Attaches to this program.
      // 

      LoggingUtils.PrintFunction ();

      Exception rethrowable = null;

      try
      {
        m_debugger.Engine.Broadcast (new JavaLangDebuggerEvent.AttachClient (), DebugProgram, null);

        return Constants.S_OK;
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);

        rethrowable = e;

        return Constants.E_FAIL;
      }
      finally
      {
        if (rethrowable != null)
        {
          throw rethrowable;
        }
      }
    }
示例#8
0
        public void Dispose() {
            if (IsDisposed) {
                return;
            }

            Tracer.Browse -= Tracer_Browse;
            Session.AfterRequest -= Session_AfterRequest;
            Session.Disconnected -= Session_Disconnected;

            var sessionProvider = WorkflowProvider.GetOrCreate().RSessions;
            sessionProvider.BrokerChanged -= SessionProvider_BrokerChanged;

            _events = null;
            _program = null;

            MainThread.Dispose();
            MainThread = null;

            Tracer = null;

            ExitBrowserAsync(Session).DoNotWait();
            Session = null;

            IsDisposed = true;
        }
示例#9
0
        // This method evaluates the expression asynchronously.
        // This method should return immediately after it has started the expression evaluation.
        // When the expression is successfully evaluated, an IDebugExpressionEvaluationCompleteEvent2
        // must be sent to the IDebugEventCallback2 event callback
        //
        // This is primarily used for the immediate window which this engine does not currently support.
        int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback)
        {
            Thread m_processingThread;
            m_processingThread = new Thread(evaluatingAsync);
            m_processingThread.Start();

            return VSConstants.S_OK;
        }
示例#10
0
 /// <summary>
 /// Attaches the session debug manager (SDM) to the process.
 /// </summary>
 /// <param name="pCallback">An IDebugEventCallback2 object that is used for debug event notification.</param>
 /// <param name="rgguidSpecificEngines">An array of GUIDs of debug engines to be used to debug programs running in the process. This parameter can be a null value. See Remarks for details.</param>
 /// <param name="celtSpecificEngines">The number of debug engines in the rgguidSpecificEngines array and the size of the rghrEngineAttach array.</param>
 /// <param name="rghrEngineAttach">An array of HRESULT codes returned by the debug engines. The size of this array is specified in the celtSpecificEngines parameter. Each code is typically either S_OK or S_ATTACH_DEFERRED. The latter indicates that the DE is currently attached to no programs.</param>
 /// <returns>
 /// If successful, returns S_OK; otherwise, returns an error code. The following table shows other possible values.
 /// 
 /// Value                                          Description
 /// E_ATTACH_DEBUGGER_ALREADY_ATTACHED             The specified process is already attached to the debugger.
 /// E_ATTACH_DEBUGGEE_PROCESS_SECURITY_VIOLATION   A security violation occurred during the attach procedure.
 /// E_ATTACH_CANNOT_ATTACH_TO_DESKTOP              A desktop process cannot be attached to the debugger.
 /// </returns>
 /// <remarks>
 /// Attaching to a process attaches the SDM to all programs running in that process that can be debugged by the debug engines (DE) specified in the rgguidSpecificEngines array. Set the rgguidSpecificEngines parameter to a null value or include GUID_NULL in the array to attach to all programs in the process.
 /// 
 /// All debug events that occur in the process are sent to the given IDebugEventCallback2 object. This IDebugEventCallback2 object is provided when the SDM calls this method.
 /// </remarks>
 public virtual int Attach( IDebugEventCallback2 pCallback,
     Guid[] rgguidSpecificEngines,
     uint celtSpecificEngines,
     int[] rghrEngineAttach)
 {
     Logger.Debug( string.Empty );
     return VSConstants.E_NOTIMPL;
 }
示例#11
0
        /// <summary>
        /// This method evaluates the expression synchronously.
        /// </summary>
        public int EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback,
            out IDebugProperty2 ppResult)
        {
            ppResult = null;
            int idx = _index;

            if (string.IsNullOrEmpty(_castExpr))
            {
                var reg = _stackFrame.GetRegistersAsync().Await((int) dwTimeout)
                                     .FirstOrDefault(r => r.Name == _registerType + _index);
                if (reg != null)
                {
                    ppResult = new DebugStackFrameValueProperty(reg, null, _stackFrame);
                    return VSConstants.S_OK;
                }
            }
            else
            {
                var tag = GetTagFromString(_castExpr);

                if (!tag.IsPrimitive() && (dwFlags & enum_EVALFLAGS.EVAL_NOSIDEEFFECTS) != 0)
                {
                    // this evaluation has "side effects" in that it might crash the VM
                    // if the cast is to "object" or "string", but the register does not 
                    // hold an object or string.
                    ppResult = new DebugConstProperty(_expression, "(this cast might crash the VM if the register is not of the casted type)", _castExpr, null)
                                                     { HasSideEffects = true };
                    return VSConstants.E_FAIL;
                }

                var isParam = _registerType == "p";

                if (isParam)
                {
                    var loc = _stackFrame.GetDocumentLocationAsync().Await((int) dwTimeout);
                    if (loc == null)
                        return VSConstants.E_FAIL;
                    var methodDiss = _stackFrame.Thread.Program.DisassemblyProvider.GetFromLocation(loc);
                    if (methodDiss == null)
                        return VSConstants.E_FAIL;
                    idx += methodDiss.Method.Body.Registers.Count - methodDiss.Method.Body.IncomingArguments;
                }

                var reg = _stackFrame.GetRegistersAsync(false, tag, idx).Await((int) dwTimeout);

                if (reg != null && reg.Count > 0)
                {
                    ppResult = new DebugStackFrameValueProperty(reg[0], null, _stackFrame, _expression)
                    {
                        HasSideEffects = !tag.IsPrimitive()
                    };
                    return VSConstants.S_OK;
                }
            }

            return VSConstants.E_FAIL;
        }
示例#12
0
 /// <summary>
 /// Attaches a debug DebugEngine (DE) to a program or programs. Called by the session debug manager (SDM) when the DE is running in-process to the SDM.
 /// </summary>
 /// <param name="rgpPrograms">An array of IDebugProgram2 objects that represent programs to be attached to. These are port programs.</param>
 /// <param name="rgpProgramNodes">An array of IDebugProgramNode2 objects that represent program nodes, one for each program. The program nodes in this array represent the same programs as in pProgram. The program nodes are given so that the DE can identify the programs to attach to.</param>
 /// <param name="celtPrograms">Number of programs and/or program nodes in the pProgram and rgpProgramNodes arrays.</param>
 /// <param name="pCallback">The IDebugEventCallback2 object to be used to send debug events to the SDM.</param>
 /// <param name="dwReason">A value from the ATTACH_REASON enumeration that specifies the reason for attaching these programs. For more information, see the Remarks section.</param>
 /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
 /// <remarks>
 /// There are three reasons for attaching to a program, as follows:
 ///     ATTACH_REASON_LAUNCH indicates that the DE is attaching to the program because the user launched the process that contains it.
 ///     ATTACH_REASON_USER indicates that the user has explicitly requested the DE to attach to a program (or the process that contains a program).
 ///     ATTACH_REASON_AUTO indicates the DE is attaching to a particular program because it is already debugging other programs in a particular process. This is also called auto-attach
 /// 
 /// When this method is called, the DE needs to send these events in sequence:
 ///     IDebugEngineCreateEvent2 (if it has not already been sent for a particular instance of the debug DebugEngine)
 ///     IDebugProgramCreateEvent2
 ///     IDebugLoadCompleteEvent2
 /// 
 /// In addition, if the reason for attaching is ATTACH_REASON_LAUNCH, the DE needs to send the IDebugEntryPointEvent2 event.
 /// Once the DE gets the IDebugProgramNode2 object corresponding to the program being debugged, it can be queried for any private interface.
 /// Before calling the methods of a program node in the array given by pProgram or rgpProgramNodes, impersonation, if required, should be enabled on the IDebugProgram2 interface that represents the program node. Normally, however, this step is not necessary. For more information, see Security Issues.
 /// </remarks>
 public virtual int Attach( IDebugProgram2[] rgpPrograms,
     IDebugProgramNode2[] rgpProgramNodes,
     uint celtPrograms,
     IDebugEventCallback2 pCallback,
     enum_ATTACH_REASON dwReason)
 {
     Logger.Debug( string.Empty );
     return VSConstants.E_NOTIMPL;
 }
示例#13
0
 /// <summary>
 /// This method evaluates the expression synchronously.
 /// </summary>
 /// <param name="dwFlags">A combination of flags from the EVALFLAGS enumeration that control expression evaluation.</param>
 /// <param name="dwTimeout">Maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait indefinitely.</param>
 /// <param name="pExprCallback">This parameter is always a null value.</param>
 /// <param name="ppResult">Returns the IDebugProperty2 object that contains the result of the expression evaluation.</param>
 /// <returns>
 /// If successful, returns S_OK; otherwise returns an error code. Some typical error codes are:
 /// Error                               Description
 /// E_EVALUATE_BUSY_WITH_EVALUATION     Another expression is currently being evaluated, and simultaneous expression evaluation is not supported.
 /// E_EVALUATE_TIMEOUT                  Evaluation timed out.
 /// </returns>
 /// <remarks>For synchronous evaluation, it is not necessary to send an event back to Visual Studio upon completion of the evaluation.</remarks>
 public int EvaluateSync( enum_EVALFLAGS dwFlags,
     uint dwTimeout,
     IDebugEventCallback2 pExprCallback,
     out IDebugProperty2 ppResult)
 {
     Logger.Debug( string.Empty );
     ppResult = null;
     return VSConstants.E_NOTIMPL;
 }
示例#14
0
 // This method evaluates the expression asynchronously.
 // This method should return immediately after it has started the expression evaluation. 
 // When the expression is successfully evaluated, an IDebugExpressionEvaluationCompleteEvent2 
 // must be sent to the IDebugEventCallback2 event callback
 //
 // This is primarily used for the immediate window which this engine does not currently support.
 int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback) {
     _frame.StackFrame.ExecuteText(_expression, (obj) => {
         _frame.Engine.Send(
             new AD7ExpressionEvaluationCompleteEvent(this, new AD7Property(_frame, obj, _writable)), 
             AD7ExpressionEvaluationCompleteEvent.IID, 
             _frame.Engine, 
             _frame.Thread);
     });
     return VSConstants.S_OK;
 }
示例#15
0
        public int EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback)
        {
            // don't use pExprCallback!

            IDebugEventCallback2 callback = _context.StackFrame.Thread.Program.Callback;
            Task<IDebugProperty2> evaluateTask = Task.Factory.StartNew(() => EvaluateImpl(dwFlags)).HandleNonCriticalExceptions();
            Task successCompletionTask = evaluateTask.ContinueWith(task => SendEvaluationCompleteEvent(task, callback), TaskContinuationOptions.OnlyOnRanToCompletion).HandleNonCriticalExceptions();
            Task failureCompletionTask = evaluateTask.ContinueWith(task => SendEvaluationCompleteEvent(null, callback), TaskContinuationOptions.NotOnRanToCompletion).HandleNonCriticalExceptions();
            return VSConstants.S_OK;
        }
示例#16
0
        internal VSEventCallbackWrapper(IDebugEventCallback2 ad7Callback)
        {
            // Obtain the GIT from COM, and store the event callback in it
            Guid CLSID_StdGlobalInterfaceTable = new Guid("00000323-0000-0000-C000-000000000046");
            Guid IID_IGlobalInterfaceTable = typeof(IGlobalInterfaceTable).GUID;
            const int CLSCTX_INPROC_SERVER = 0x1;
            _pGIT = NativeMethods.CoCreateInstance(ref CLSID_StdGlobalInterfaceTable, IntPtr.Zero, CLSCTX_INPROC_SERVER, ref IID_IGlobalInterfaceTable);

            var git = GetGlobalInterfaceTable();
            git.RegisterInterfaceInGlobal(ad7Callback, ref _IID_IDebugEventCallback2, out _cookie);
            Marshal.ReleaseComObject(git);
        }
示例#17
0
    int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
    {
      Debug.WriteLine("AD7Engine Attach");
      Guid id;

      if (( DebuggerManager.Instance != null ) && ( DebuggerManager.Instance.Debugger.IsRunning))
      {
        // If already running, abort.
        MessageBox.Show("Cannot start MySql Debugger. A MySql Debug session is already running", "Error");
        return HRESULT.E_ATTACH_FAILED_ABORT_SILENTLY;
      }

      rgpPrograms[0].GetProgramId(out id);
      if (id == Guid.Empty)
      {
        return VSConstants.E_NOTIMPL;
      }

      _events = new AD7Events(this, pCallback);

      try
      {
        DebuggerManager.Init(_events, _node, _breakpoint);
      }
      catch (Exception ex)
      {
        MessageBox.Show(_node.ParentWindow, ex.GetBaseException().Message, "Debugger Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return HRESULT.E_ATTACH_FAILED_ABORT_SILENTLY;
      }

      System.Threading.Thread thread = new System.Threading.Thread(() =>
      {
        DebuggerManager debugger = DebuggerManager.Instance;
        _node.Debugger = debugger;
        debugger.SteppingType = SteppingTypeEnum.StepInto;
        debugger.Breakpoint = new AD7Breakpoint(_node, _events);
        debugger.OnEndDebugger += () => { _events.ProgramDestroyed(_node); };
        debugger.Debugger.RestoreAtExit = true;
        debugger.Run();
      });
      thread.SetApartmentState(System.Threading.ApartmentState.STA);
      thread.Start();

      _node.Id = id;
      _events.EngineCreated();
      _events.ProgramCreated(_node);
      _events.EngineLoaded();
      _events.DebugEntryPoint();

      return VSConstants.S_OK;
    }
示例#18
0
        /// <summary>
        /// This method evaluates the expression synchronously.
        /// </summary>
        /// <param name="dwFlags">[in] A combination of flags from the EVALFLAGS enumeration that control expression evaluation.</param>
        /// <param name="dwTimeout">[in] Maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait indefinitely.</param>
        /// <param name="pExprCallback">[in]This parameter is always a null value.</param>
        /// <param name="ppResult">[out] Returns the IDebugProperty2 object that contains the result of the expression evaluation.</param>
        /// <returns>
        /// If successful, returns S_OK; otherwise returns an error code. Some typical error codes are:
        ///  * E_EVALUATE_BUSY_WITH_EVALUATION  Another expression is currently being evaluated, and simultaneous
        ///                                     expression evaluation is not supported.
        ///  * E_EVALUATE_TIMEOUT               Evaluation timed out.
        /// </returns>
        /// <remarks>
        /// For synchronous evaluation, it is not necessary to send an event back to Visual Studio upon completion of the evaluation.
        /// </remarks>
        public int EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult)
        {
            ppResult = null;

            Task<IDebugProperty2> task = Task.Factory.StartNew(() => EvaluateImpl(dwFlags)).HandleNonCriticalExceptions();
            if (!task.Wait((int)dwTimeout))
                return AD7Constants.E_EVALUATE_TIMEOUT;

            if (task.Status != TaskStatus.RanToCompletion || task.Result == null)
                return VSConstants.E_FAIL;

            ppResult = task.Result;
            return VSConstants.S_OK;
        }
示例#19
0
        public int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms,
            IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            DebugHelper.TraceEnteringMethod();

            rgpPrograms[0].GetProgramId(out _programId);
            _dispatcher.Queue(() => DebuggedProcess.Attach());
            _dispatcher.Queue(() => DebuggedProcess.WaitForAttach());

            Events.EngineCreated();
            Events.ProgramCreated();

            return VSConstants.S_OK;
        }
示例#20
0
        /// <summary>
        /// This method evaluates the expression synchronously.
        /// </summary>
        public int EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback,
            out IDebugProperty2 ppResult)
        {
            ppResult = null;

            if (string.IsNullOrEmpty(_castExpr))
            {
                var reg = _stackFrame.GetRegistersAsync().Await((int) dwTimeout)
                                     .FirstOrDefault(r => r.Name == _registerType + _index);
                if (reg != null)
                {
                    ppResult = new DebugStackFrameValueProperty(reg, null, _stackFrame);
                    return VSConstants.S_OK;
                }
            }
            else
            {
                var tag = GetTagFromString(_castExpr);

                if (!tag.IsPrimitive() && (dwFlags & enum_EVALFLAGS.EVAL_NOSIDEEFFECTS) != 0)
                {
                    // this evaluation has "side effects" in that it might crash the VM
                    // if the cast is to "object" or "string", but the register does not
                    // hold an object or string.
                    ppResult = new DebugConstProperty(_expression, "(this cast might crash a DalvikVM if the register is not of the casted type)", _castExpr, null)
                                                     { HasSideEffects = true };
                    return VSConstants.E_FAIL;
                }

                var regNames = _stackFrame.GetRegisterNamesAsync().Await((int)dwTimeout);
                var vmIdx = regNames.GetVmIndex(_registerType == "p", _index);

                if (vmIdx < 0)
                    return VSConstants.E_FAIL;

                var reg = _stackFrame.GetRegistersAsync(false, tag, vmIdx).Await((int)dwTimeout);

                if (reg != null && reg.Count > 0)
                {
                    ppResult = new DebugStackFrameValueProperty(reg[0], null, _stackFrame, _expression)
                    {
                        HasSideEffects = !tag.IsPrimitive()
                    };
                    return VSConstants.S_OK;
                }
            }

            return VSConstants.E_FAIL;
        }
示例#21
0
        /// <summary>
        /// Attaches a debug engine (DE) to a program or programs. Called by the session debug manager (SDM) when the DE is running in-process to the SDM.
        /// </summary>
        public int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            DLog.Debug(DContext.VSDebuggerComCall, "IDebugEngine2.Attach");

            // Save program
            program = rgpPrograms[0] as DebugProgram;
            if (program == null)
                return VSConstants.E_INVALIDARG;

            // Update program state
            CopyExceptionMapToProgramDelayed();

            //eventCallback.Send(process, new ProcessCreateEvent());
            eventCallback.Send(program, new ProgramCreateEvent());
            return VSConstants.S_OK;
        }
示例#22
0
 int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback) {
     _cts = new CancellationTokenSource();
     Task.Run(async () => {
         try {
             var res = await StackFrame.StackFrame.EvaluateAsync(_expression, reprMaxLength: AD7Property.ReprMaxLength);
             _cts.Token.ThrowIfCancellationRequested();
             var prop = new AD7Property(StackFrame, res);
             StackFrame.Engine.Send(new AD7ExpressionEvaluationCompleteEvent(this, prop), AD7ExpressionEvaluationCompleteEvent.IID);
         } catch (Exception ex) when (!ex.IsCriticalException()) {
             StackFrame.Engine.Send(new AD7ExpressionEvaluationCompleteEvent(ex), AD7ExpressionEvaluationCompleteEvent.IID);
         } finally {
             _cts = null;
         }
     });
     return VSConstants.S_OK;
 }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public DebugEngineCallback (DebugEngine engine, IDebugEventCallback2 ad7EventCallback)
    {
      Engine = engine;

      m_ad7EventCallback = ad7EventCallback;

      m_cLangEventCallback = new CLangDebuggerCallback (engine);

      m_javaLangEventCallback = new JavaLangDebuggerCallback (engine);

      // 
      // Register function handlers for specific events.
      // 

      m_debuggerCallback = new Dictionary<Guid, DebuggerEventDelegate> ();

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.BreakpointHit)), OnBreakpoint);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.BreakpointBound)), OnBreakpointBound);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.BreakpointError)), OnBreakpointError);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.Error)), OnError);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.Exception)), OnException);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.LoadComplete)), OnLoadComplete);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ModuleLoad)), OnModuleLoad);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.OutputString)), OnOutputString);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ProcessCreate)), OnProgramCreate);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ProgramDestroy)), OnProgramDestroy);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.StepComplete)), OnStepComplete);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.SymbolSearch)), OnSymbolSearch);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ThreadCreate)), OnThreadCreate);

      m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ThreadDestroy)), OnThreadDestroy);
    }
 int IDebugExpression2.EvaluateSync(
   enum_EVALFLAGS dwFlags, 
   uint dwTimeout, 
   IDebugEventCallback2 pExprCallback, 
   out IDebugProperty2 ppResult)
 {
   if (MySql.Debugger.Debugger.GetTagHashCode(_stackFrame._rs.OwningRoutine.SourceCode) !=
     DebuggerManager.Instance.Debugger.CurrentScope.OwningRoutine.Hash)
   {
     // This should never happen.
     ppResult = null;
     return VSConstants.E_NOTIMPL;
   }
   AD7Property prop = new AD7Property( _expr,_stackFrame.Node, _stackFrame._rs );
   ppResult = prop;
   // Send evaluation complete event
   DebuggerManager.Instance._events.ExpressionEvalCompleted( 
     _stackFrame.Node, ( IDebugExpression2 )this, ( IDebugProperty2 )prop );
   return VSConstants.S_OK;
 }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #region IDebugExpression2 Members

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int EvaluateAsync (enum_EVALFLAGS evaluateFlags, IDebugEventCallback2 eventCallback)
    {
      // 
      // Evaluate the expression asynchronously.
      // Method should return immediately after starting the expression evaluation, when completed successfully
      // a 'IDebugExpressionEvaluationCompleteEvent2' event should be sent to the provided IDebugEventCallback2 callback.
      // 

      LoggingUtils.PrintFunction ();

      try
      {
        ThreadPool.QueueUserWorkItem (delegate (object state)
        {
          try
          {
            IDebugProperty2 result;

            IDebugThread2 thread;

            LoggingUtils.RequireOk (m_stackFrame.GetThread (out thread));

            LoggingUtils.RequireOk (EvaluateSync (evaluateFlags, 0, eventCallback, out result));

            m_debugEngine.Broadcast (eventCallback, new DebugEngineEvent.ExpressionEvaluationComplete (this, result), m_debugEngine.Program, thread);
          }
          catch (Exception e)
          {
            LoggingUtils.HandleException (e);
          }
        });

        return Constants.S_OK;
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);

        return Constants.E_FAIL;
      }
    }
        /// <summary>
        /// Attaches a debug DebugEngine (DE) to a program or programs. Called by the session debug manager (SDM) when the DE is running in-process to the SDM.
        /// </summary>
        /// <param name="rgpPrograms">An array of IDebugProgram2 objects that represent programs to be attached to. These are port programs.</param>
        /// <param name="rgpProgramNodes">An array of IDebugProgramNode2 objects that represent program nodes, one for each program. The program nodes in this array represent the same programs as in pProgram. The program nodes are given so that the DE can identify the programs to attach to.</param>
        /// <param name="celtPrograms">Number of programs and/or program nodes in the pProgram and rgpProgramNodes arrays.</param>
        /// <param name="pCallback">The IDebugEventCallback2 object to be used to send debug events to the SDM.</param>
        /// <param name="dwReason">A value from the ATTACH_REASON enumeration that specifies the reason for attaching these programs. For more information, see the Remarks section.</param>
        /// <returns>
        /// If successful, returns S_OK; otherwise, returns an error code.
        /// </returns>
        public override int Attach( IDebugProgram2[] rgpPrograms,
            IDebugProgramNode2[] rgpProgramNodes,
            uint celtPrograms,
            IDebugEventCallback2 pCallback,
            enum_ATTACH_REASON dwReason)
        {
            Logger.Debug( string.Empty );
            if ( celtPrograms != 1 )
            {
                Debug.Fail( "PowerStudio Engine only expects to see one program in a process." );
                throw new ArgumentException( "celtPrograms" );
            }

            CreateOrInitializeEventSource( pCallback );
            Program = new PowerShellProgramNode( Process );

            EngineEventSource.OnDebugEngineCreate();
            EngineEventSource.OnProgramCreate( Program );
            EngineEventSource.OnLoadComplete();

            return VSConstants.S_OK;
        }
示例#27
0
        // This method evaluates the expression synchronously.
        int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult)
        {
            ppResult = null;
            if ((dwFlags & enum_EVALFLAGS.EVAL_NOSIDEEFFECTS) != 0 && _var.IsVisualized)
            {
                IVariableInformation variable = DebuggedProcess.g_Process.Natvis.Cache.Lookup(_var);
                if (variable == null)
                {
                    ppResult = new AD7ErrorProperty(_var.Name, ResourceStrings.NoSideEffectsVisualizerMessage);
                }
                else
                {
                    _var = variable;
                    ppResult = new AD7Property(_var);
                }
                return Constants.S_OK;
            }

            _var.SyncEval();
            ppResult = new AD7Property(_var);
            return Constants.S_OK;
        }
示例#28
0
        // This method evaluates the expression synchronously.
        int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult)
        {
            NodeEvaluationResult result;
            ppResult = null;

            try
            {
                result = _frame.StackFrame.EvaluateExpressionAsync(_expression).Result;
            }
            catch (Exception)
            {
                return VSConstants.E_FAIL;
            }
            
            if (result == null)
            {
                return VSConstants.E_FAIL;
            }

            ppResult = new AD7Property(result);
            return VSConstants.S_OK;
        }
示例#29
0
 // This method evaluates the expression asynchronously.
 // This method should return immediately after it has started the expression evaluation.
 // When the expression is successfully evaluated, an IDebugExpressionEvaluationCompleteEvent2
 // must be sent to the IDebugEventCallback2 event callback
 //
 // This is primarily used for the immediate window
 int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback)
 {
     if (((dwFlags & enum_EVALFLAGS.EVAL_NOSIDEEFFECTS) != 0 && (dwFlags & enum_EVALFLAGS.EVAL_ALLOWBPS) == 0) && _var.IsVisualized)
     {
         IVariableInformation variable = DebuggedProcess.g_Process.Natvis.Cache.Lookup(_var);
         if (variable == null)
         {
             _var.AsyncError(pExprCallback, new AD7ErrorProperty(_var.Name, ResourceStrings.NoSideEffectsVisualizerMessage));
         }
         else
         {
             _var = variable;    // use the old value
             Task.Run(() =>
             {
                 new EngineCallback(DebuggedProcess.g_Process.Engine, pExprCallback).OnExpressionEvaluationComplete(variable);
             });
         }
     }
     else
     {
         _var.AsyncEval(pExprCallback);
     }
     return Constants.S_OK;
 }
示例#30
0
 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)
 {
     throw new NotImplementedException();
 }
示例#31
0
        // Attach the debug engine to a program.
        public int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.Assert(_ad7ProgramId == Guid.Empty);

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

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

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

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

                    _engineCallback = new EngineCallback(this, ad7Callback);

                    // Complete the win32 attach on the poll thread
                    _pollThread.RunOperation(new Operation(delegate
                    {
                        throw new NotImplementedException();
                    }));

                    _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError;
                }
                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 (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e) when(ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true))
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
示例#32
0
 int IDebugProgram2.Attach(IDebugEventCallback2 pCallback)
 {
     return(HR.S_FALSE); // indicate that the attach happens through the engine rather than the port supplier
 }
示例#33
0
        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);
        }
示例#34
0
        public /*override*/ 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)
        {
            NLogService.TraceEnteringMethod();
            var base64Options = SerializeDebuggerOptions(pszOptions);
            var result        = _engine.LaunchSuspended(pszServer, pPort, pszExe, pszArgs, pszDir, bstrEnv, base64Options, dwLaunchFlags, hStdInput, hStdOutput, hStdError, pCallback, out ppProcess);

            return(result);
        }
        // These methods are not called by the Visual Studio debugger, so they don't need to be implemented


        /// <summary>
        /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161399.aspx)
        /// </summary>
        /// <param name="pMDMProgram"> The IDebugProgram2 interface that represents the program to attach to. </param>
        /// <param name="pCallback"> The IDebugEventCallback2 interface to be used to send debug events to the SDM. </param>
        /// <param name="dwReason"> A value from the ATTACH_REASON enumeration that specifies the reason for attaching. </param>
        /// <returns> VSConstants.E_NOTIMPL. </returns>
        public int Attach_V7(IDebugProgram2 pMDMProgram, IDebugEventCallback2 pCallback, uint dwReason)
        {
            Debug.Fail("This function is not called by the debugger");
            return(VSConstants.E_NOTIMPL);
        }
示例#36
0
 public EngineCallbacks(DebugEngine engine, Program program, IDebugProcess2 process, IDebugEventCallback2 ad7Callback)
 {
     _engine      = engine;
     _program     = program;
     _ad7Callback = ad7Callback;
     _process     = process;
 }
示例#37
0
        public int Attach(IDebugEventCallback2 pCallback)
        {
            Debug.Fail("This function is not called by the debugger");

            return(Constants.E_NOTIMPL);
        }
示例#38
0
        public int Attach(IDebugProgram2[] programs, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            var            program = programs[0];
            IDebugProcess2 process;

            program.GetProcess(out process);
            Guid processId;

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

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

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

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

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

            return(VSConstants.S_OK);
        }
示例#39
0
 public int Attach(IDebugEventCallback2 pCallback)
 {
     throw new NotImplementedException();
 }
示例#40
0
 int IDebugProgram2.Attach(IDebugEventCallback2 pCallback)
 {
     return(VSConstants.E_NOTIMPL);
 }
示例#41
0
 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)
 {
     ppProcess = null;
     return(VSConstants.E_NOTIMPL);
 }
示例#42
0
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            ThrowIfDisposed();

            if (rgpPrograms.Length != 1)
            {
                throw new ArgumentException("Zero or more than one programs", "rgpPrograms");
            }

            _program = rgpPrograms[0] as RDebugPortSupplier.DebugProgram;
            if (_program == null)
            {
                throw new ArgumentException("rgpPrograms[0] must be an " + nameof(RDebugPortSupplier.DebugProgram), "rgpPrograms");
            }

            Marshal.ThrowExceptionForHR(_program.GetProgramId(out _programId));

            _events      = pCallback;
            DebugSession = TaskExtensions.RunSynchronouslyOnUIThread(ct => DebugSessionProvider.GetDebugSessionAsync(_program.Session, ct));
            MainThread   = new AD7Thread(this);
            IsConnected  = true;

            // Enable breakpoint instrumentation.
            TaskExtensions.RunSynchronouslyOnUIThread(ct => DebugSession.EnableBreakpointsAsync(true, ct));

            // Send notification after acquiring the session - we need it in case there were any breakpoints pending before
            // the attach, in which case we'll immediately get breakpoint creation requests as soon as we send these, and
            // we will need the session to process them.
            AD7EngineCreateEvent.Send(this);
            AD7ProgramCreateEvent.Send(this);
            Send(new AD7LoadCompleteEvent(), AD7LoadCompleteEvent.IID);

            // Register event handlers after notifying VS that debug engine has loaded. This order is important because
            // we may get a Browse event immediately, and we want to raise a breakpoint notification in response to that
            // to pause the debugger - but it will be ignored unless the engine has reported its creation.
            // Also, AfterRequest must be registered before Browse, so that we never get in a situation where we get
            // Browse but not AfterRequest that follows it because of a race between raising and registration.
            DebugSession.RSession.AfterRequest += RSession_AfterRequest;
            DebugSession.RSession.Disconnected += RSession_Disconnected;

            // If we're already at the Browse prompt, registering the handler will result in its immediate invocation.
            // We want to handle that fully before we process any following AfterRequest event to avoid concurrency issues
            // where we pause and never resume, so hold the lock while adding the handler.
            lock (_browseLock) {
                DebugSession.Browse += Session_Browse;
            }

            return(VSConstants.S_OK);
        }
示例#43
0
        // Launches a process by means of the debug engine.
        // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger
        // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program
        // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language),
        // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method
        // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state.
        int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process)
        {
            Debug.Assert(_pollThread == null);
            Debug.Assert(_engineCallback == null);
            Debug.Assert(_debuggedProcess == null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            // Check if the logger was enabled late.
            Logger.LoadMIDebugLogger(_configStore);

            process = null;

            _engineCallback = new EngineCallback(this, ad7Callback);

            Exception exception;

            try
            {
                // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop
                LaunchOptions launchOptions = LaunchOptions.GetInstance(_configStore, exe, args, dir, options, _engineCallback, TargetEngine.Native, Logger);

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

                using (cancellationTokenSource)
                {
                    _pollThread.RunOperation(ResourceStrings.InitializingDebugger, cancellationTokenSource, (HostWaitLoop waitLoop) =>
                    {
                        try
                        {
                            _debuggedProcess = new DebuggedProcess(true, launchOptions, _engineCallback, _pollThread, _breakpointManager, this, _configStore);
                        }
                        finally
                        {
                            // If there is an exception from the DebuggeedProcess constructor, it is our responsibility to dispose the DeviceAppLauncher,
                            // otherwise the DebuggedProcess object takes ownership.
                            if (_debuggedProcess == null && launchOptions.DeviceAppLauncher != null)
                            {
                                launchOptions.DeviceAppLauncher.Dispose();
                            }
                        }

                        _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError;

                        return(_debuggedProcess.Initialize(waitLoop, cancellationTokenSource.Token));
                    });
                }

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

                return(Constants.S_OK);
            }
            catch (Exception e) when(ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true))
            {
                exception = e;
                // Return from the catch block so that we can let the exception unwind - the stack can get kind of big
            }

            // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and then
            // return E_ABORT.
            Logger.Flush();
            SendStartDebuggingError(exception);

            Dispose();

            return(Constants.E_ABORT);
        }
示例#44
0
        public int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            if (celtPrograms == 0)
            {
                return(VSConstants.S_OK);
            }

            if (pCallback == null)
            {
                throw new ArgumentNullException("pCallback");
            }
            if (rgpPrograms == null || rgpPrograms.Length < celtPrograms)
            {
                throw new ArgumentException();
            }
            if (rgpProgramNodes == null || rgpProgramNodes.Length < celtPrograms)
            {
                throw new ArgumentException();
            }

            if (celtPrograms > 1)
            {
                throw new NotImplementedException();
            }

            if (dwReason != enum_ATTACH_REASON.ATTACH_REASON_LAUNCH)
            {
                throw new NotImplementedException();
            }

            JavaDebugProgram program = rgpProgramNodes[0] as JavaDebugProgram;

            if (program == null)
            {
                throw new NotSupportedException();
            }

            lock (_programs)
            {
                _programs.Add(program);
            }

            DebugEvent @event = new DebugEngineCreateEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, this);

            pCallback.Event(this, program.GetProcess(), program, null, @event);

            program.InitializeDebuggerChannel(this, pCallback);
            return(VSConstants.S_OK);
        }
示例#45
0
 // WatchForExpressionEvaluationOnThread is used to cooperate between two different engines debugging
 // the same process. The sample engine doesn't cooperate with other engines, so it has nothing
 // to do here.
 public int WatchForExpressionEvaluationOnThread(IDebugProgram2 pOriginatingProgram, uint dwTid, uint dwEvalFlags, IDebugEventCallback2 pExprCallback, int fWatch)
 {
     return(Constants.S_OK);
 }
示例#46
0
        // Launches a process by means of the debug engine.
        // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger
        // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program
        // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language),
        // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method
        // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state.
        int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process)
        {
            Debug.Assert(_pollThread == null);
            Debug.Assert(_engineCallback == null);
            Debug.Assert(_debuggedProcess == null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            // Check if the logger was enabled late.
            Logger.LoadMIDebugLogger(_configStore);

            process = null;

            _engineCallback = new EngineCallback(this, ad7Callback);

            Exception exception;

            try
            {
                bool noDebug = launchFlags.HasFlag(enum_LAUNCH_FLAGS.LAUNCH_NODEBUG);

                // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop
                LaunchOptions launchOptions = LaunchOptions.GetInstance(_configStore, exe, args, dir, options, noDebug, _engineCallback, TargetEngine.Native, Logger);

                StartDebugging(launchOptions);

                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 lose our message, so we instead send up an error event, and then
            // return E_ABORT.
            OnStartDebuggingFailed(exception);

            return(Constants.E_ABORT);
        }
示例#47
0
 /// <summary>
 /// Obtains an event callback interface that can be used to send events on any threads
 /// </summary>
 /// <param name="ad7Callback">The underlying event call back which was obtained from the port</param>
 /// <returns>In VS, a thread-safe wrapper on top of the underlying SDM event callback which allows
 /// sending events on any thread. In VS Code, this just returns the provided ad7Callback. </returns>
 public static IDebugEventCallback2 GetThreadSafeEventCallback(IDebugEventCallback2 ad7Callback)
 {
     throw new NotImplementedException();
 }
示例#48
0
 public EngineCallback(AD7Engine engine, IDebugEventCallback2 pCallback)
 {
     _engine        = engine;
     _eventCallback = pCallback;
 }
示例#49
0
        public /*override*/ int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason)
        {
            NLogService.TraceEnteringMethod();

            try
            {
                _session.Run(_startInfo, _startInfo.SessionOptions);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + " - " + ex.StackTrace);
            }

            return(_engine.Attach(rgpPrograms, rgpProgramNodes, celtPrograms, pCallback, dwReason));
        }
示例#50
0
 public DebugEngineEventSource(DebugEngineBase debugEngineBase, IDebugEventCallback2 debugEventCallback)
 {
     Logger.Debug(string.Empty);
     DebugEngineBase    = debugEngineBase;
     DebugEventCallback = debugEventCallback;
 }
示例#51
0
        public int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.Assert(_program != null);

            IDebugProcess2 process;
            IDebugProgram2 program = rgpPrograms[0];

            EngineUtils.RequireOk(program.GetProcess(out process));

            Guid attachedGuid;

            EngineUtils.RequireOk(program.GetProgramId(out attachedGuid));
            _program.AttachDebugger(attachedGuid);

            Debug.WriteLine("IDebugEngine2.Attach: invoking load callbacks");
            // The SDM will invoke ContinueFromSynchronousEvent with AD7LoadCompleteEvent. At that point,
            // breakpoints from design mode will have already been placed, and the program can be launched.
            _callbacks.OnAttach();

            return(VSConstants.S_OK);
        }
示例#52
0
 public int Attach(IDebugEventCallback2 pCallback, Guid[] rgguidSpecificEngines, uint celtSpecificEngines, int[] rghrEngineAttach)
 {
     throw new NotImplementedException();
 }
示例#53
0
 // This method evaluates the expression asynchronously.
 // This method should return immediately after it has started the expression evaluation.
 // When the expression is successfully evaluated, an IDebugExpressionEvaluationCompleteEvent2
 // must be sent to the IDebugEventCallback2 event callback
 //
 // This is primarily used for the immediate window which this engine does not currently support.
 int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback)
 {
     throw new NotImplementedException();
 }
示例#54
0
 // This method evaluates the expression synchronously.
 int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult)
 {
     ppResult = new AD7Property(m_var, Process, StackFrame);
     return(VSConstants.S_OK);
 }
示例#55
0
 int IDebugProgram3.Attach(IDebugEventCallback2 pCallback)
 {
     return(IDebugProgram2.Attach(pCallback));
 }
示例#56
0
        // 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);

            Logger.LoadMIDebugLogger(_configStore);

            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);
                    if (port is IDebugUnixShellPort)
                    {
                        _unixPort = (IDebugUnixShellPort)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 lose 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);
        }
示例#57
0
        // Attach the debug engine to a program.
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.WriteLine("PythonEngine Attach Begin " + GetHashCode());

            AssertMainThread();
            Debug.Assert(_ad7ProgramId == Guid.Empty);

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

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

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

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

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

                var attachRes = PythonProcess.TryAttach(processId, out _process);
                if (attachRes != ConnErrorMessages.None)
                {
                    string msg;
                    switch (attachRes)
                    {
                    case ConnErrorMessages.CannotInjectThread: msg = "Cannot create thread in debuggee process"; break;

                    case ConnErrorMessages.CannotOpenProcess: msg = "Cannot open process for debugging"; break;

                    case ConnErrorMessages.InterpreterNotInitialized: msg = "Python interpreter has not been initialized in this process"; break;

                    case ConnErrorMessages.LoadDebuggerBadDebugger: msg = "Failed to load debugging script (incorrect version of script?)"; break;

                    case ConnErrorMessages.LoadDebuggerFailed: msg = "Failed to compile debugging script"; break;

                    case ConnErrorMessages.OutOfMemory: msg = "Out of memory"; break;

                    case ConnErrorMessages.PythonNotFound: msg = "Python interpreter not found"; break;

                    case ConnErrorMessages.TimeOut: msg = "Timeout while attaching"; break;

                    case ConnErrorMessages.UnknownVersion: msg = "Unknown Python version loaded in process"; break;

                    case ConnErrorMessages.SysNotFound: msg = "sys module not found"; break;

                    case ConnErrorMessages.SysSetTraceNotFound: msg = "settrace not found in sys module"; break;

                    case ConnErrorMessages.PyDebugAttachNotFound: msg = "Cannot find PyDebugAttach.dll at " + attachRes; break;

                    default: msg = "Unknown error"; break;
                    }

                    MessageBox.Show("Failed to attach debugger: " + msg);
                    return(VSConstants.E_FAIL);
                }

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

            AD7EngineCreateEvent.Send(this);

            lock (_syncLock) {
                _programCreated = true;
                AD7ProgramCreateEvent.Send(this);

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

            Debug.WriteLine("PythonEngine Attach returning S_OK");
            return(VSConstants.S_OK);
        }
示例#58
0
        // After engine initialization, SDM calls LaunchSuspended to start the debuggee in a suspended state.
        // ResumeProcess and Attach are invoked next.

        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)
        {
            Debug.Assert(_program == null);

            var sourceFile = new SourceFile(Path.Combine(dir, exe));
            var runner     = new BasmRunner(sourceFile, OnProgramStop);
            var bpBackend  = new BasmBreakpointBackend(runner, OnProgramStepComplete, OnProgramBreakComplete);

            _program = new Program(runner, bpBackend, sourceFile);

            var processId = _program.StartBasmProcess();

            EngineUtils.RequireOk(port.GetProcess(processId, out process));

            _callbacks         = new EngineCallbacks(this, _program, process, ad7Callback);
            _breakpointManager = new BreakpointManager(_program, bpBackend, sourceFile, _callbacks);

            Debug.WriteLine("IDebugEngineLaunch2.LaunchSuspended: returning S_OK");
            return(VSConstants.S_OK);
        }
示例#59
0
 // WatchForExpressionEvaluationOnThread is used to cooperate between two different engines debugging
 // the same process. The sample engine doesn't cooperate with other engines, so it has nothing
 // to do here.
 public int WatchForExpressionEvaluationOnThread(IDebugProgram2 pOriginatingProgram, uint dwTid, uint dwEvalFlags, IDebugEventCallback2 pExprCallback, int fWatch)
 {
     return Constants.S_OK;
 }
示例#60
0
        // Launches a process by means of the debug engine.
        // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger
        // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program
        // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language),
        // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method
        // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state.
        int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process)
        {
            Debug.WriteLine("PythonEngine LaunchSuspended Begin " + launchFlags + " " + GetHashCode());
            AssertMainThread();
            Debug.Assert(_events == null);
            Debug.Assert(_process == null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            process = null;

            _events = ad7Callback;

            PythonLanguageVersion version      = DefaultVersion;
            bool            waitOnAbnormalExit = false;
            bool            redirectOutput     = false;
            List <string[]> dirMapping         = null;

            if (options != null)
            {
                var splitOptions = options.Split(new[] { ';' }, 2);
                foreach (var optionSetting in splitOptions)
                {
                    var setting = optionSetting.Split(new[] { '=' }, 2);

                    if (setting.Length == 2)
                    {
                        switch (setting[0])
                        {
                        case VersionSetting: version = GetLanguageVersion(setting[1]); break;

                        case WaitOnAbnormalExitSetting:
                            bool value;
                            if (Boolean.TryParse(setting[1], out value))
                            {
                                waitOnAbnormalExit = value;
                            }
                            break;

                        case RedirectOutputSetting:
                            if (Boolean.TryParse(setting[1], out value))
                            {
                                redirectOutput = value;
                            }
                            break;

                        case DirMappingSetting:
                            string[] dirs = setting[1].Split('|');
                            if (dirs.Length == 2)
                            {
                                if (dirMapping == null)
                                {
                                    dirMapping = new List <string[]>();
                                }
                                Debug.WriteLine(String.Format("Mapping dir {0} to {1}", dirs[0], dirs[1]));
                                dirMapping.Add(dirs);
                            }
                            break;
                        }
                    }
                }
            }

            _process = new PythonProcess(version, exe, args, dir, env, waitOnAbnormalExit, redirectOutput, dirMapping);

            AttachEvents(_process);

            _programCreated = false;
            _loadComplete.Reset();

            _process.Start();

            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);
        }