Beispiel #1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public DebuggeeBreakpointError FindErrorBreakpoint(uint id)
        {
            //
            // Search all registered pending breakpoints objects for a bound breakpoint matching the requested id.
            //

            LoggingUtils.PrintFunction();

            try
            {
                foreach (var pending in m_pendingBreakpoints)
                {
                    //
                    // Check for matching 'error' breakpoints.
                    //

                    int handle = pending.EnumErrorBreakpoints(enum_BP_ERROR_TYPE.BPET_ALL, out IEnumDebugErrorBreakpoints2 enumeratedErrorBreakpoints);

                    if (handle == Constants.E_BP_DELETED)
                    {
                        continue; // Skip any deleted breakpoints.
                    }

                    LoggingUtils.RequireOk(handle);

                    LoggingUtils.RequireOk(enumeratedErrorBreakpoints.GetCount(out uint numErrorBreakpoints));

                    if (numErrorBreakpoints > 0)
                    {
                        DebuggeeBreakpointError [] errorBreakpoints = new DebuggeeBreakpointError [numErrorBreakpoints];

                        LoggingUtils.RequireOk(enumeratedErrorBreakpoints.Next(numErrorBreakpoints, errorBreakpoints, numErrorBreakpoints));

                        for (uint i = 0; i < numErrorBreakpoints; ++i)
                        {
                            if (errorBreakpoints [i] is CLangDebuggeeBreakpointError)
                            {
                                CLangDebuggeeBreakpointError error = errorBreakpoints [i] as CLangDebuggeeBreakpointError;

                                if (error.GdbBreakpoint.ID == id)
                                {
                                    return(error);
                                }
                            }
                            else
                            {
                                throw new NotImplementedException("Unrecognised error breakpoint type");
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }

            return(null);
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public int CreateErrorBreakpoint(string errorReason, MiBreakpoint gdbBreakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext)
        {
            //
            // Create a C-language breakpoint. This is tied to a GDB/MI breakpoint object.
            //

            LoggingUtils.PrintFunction();

            try
            {
                CLangDebuggeeBreakpointError errorBreakpoint = new CLangDebuggeeBreakpointError(m_debugger, m_breakpointManager, this, codeContext, gdbBreakpoint, errorReason);

                lock (m_errorBreakpoints)
                {
                    m_errorBreakpoints.Clear();

                    m_errorBreakpoints.Add(errorBreakpoint);
                }

                uint numDebugPrograms = 1;

                IEnumDebugPrograms2 debugPrograms;

                IDebugProgram2 [] debugProgramsArray = new IDebugProgram2 [numDebugPrograms];

                LoggingUtils.RequireOk(m_breakpointManager.Engine.EnumPrograms(out debugPrograms));

                LoggingUtils.RequireOk(debugPrograms.Next(numDebugPrograms, debugProgramsArray, ref numDebugPrograms));

                m_breakpointManager.Engine.Broadcast(new DebugEngineEvent.BreakpointError(errorBreakpoint), debugProgramsArray [0], null);

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

                return(Constants.E_FAIL);
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void RefreshBreakpoint(object breakpoint)
        {
            //
            // Validate breakpoint input type. This function can be used for 'bound' and 'error' objects, so we need to handle this appropriately.
            //

            LoggingUtils.PrintFunction();

            CLangDebuggeeBreakpointBound boundBreakpoint = null;

            CLangDebuggeeBreakpointError errorBreakpoint = null;

            MiBreakpoint gdbBreakpoint;

            DebuggeeBreakpointResolution resolution;

            if (breakpoint == null)
            {
                throw new ArgumentNullException("breakpoint");
            }
            else if (breakpoint is CLangDebuggeeBreakpointBound)
            {
                boundBreakpoint = breakpoint as CLangDebuggeeBreakpointBound;

                gdbBreakpoint = boundBreakpoint.GdbBreakpoint;

                IDebugBreakpointResolution2 boundBreakpointResolution;

                int handle = boundBreakpoint.GetBreakpointResolution(out boundBreakpointResolution);

                if (handle == Constants.E_BP_DELETED)
                {
                    return;
                }

                LoggingUtils.RequireOk(handle);

                resolution = (DebuggeeBreakpointResolution)boundBreakpointResolution;
            }
            else if (breakpoint is CLangDebuggeeBreakpointError)
            {
                errorBreakpoint = breakpoint as CLangDebuggeeBreakpointError;

                gdbBreakpoint = errorBreakpoint.GdbBreakpoint;

                IDebugErrorBreakpointResolution2 errorBreakpointResolution;

                int handle = errorBreakpoint.GetBreakpointResolution(out errorBreakpointResolution);

                if (handle == Constants.E_BP_DELETED)
                {
                    return;
                }

                resolution = (DebuggeeBreakpointResolution)errorBreakpointResolution;

                lock (m_errorBreakpoints)
                {
                    m_errorBreakpoints.Remove(errorBreakpoint);
                }
            }
            else
            {
                throw new ArgumentException("breakpoint");
            }

            //
            // Query breakpoint info/status directly from GDB/MI.
            //

            try
            {
                string command = string.Format("-break-info {0}", gdbBreakpoint.ID);

                m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord)
                {
                    if (resultRecord == null)
                    {
                        throw new InvalidOperationException();
                    }
                    else if (resultRecord.IsError())
                    {
                        //
                        // GDB/MI breakpoint info request failed.
                        //

                        gdbBreakpoint.Address = MiBreakpoint.Pending;

                        (resolution as DebuggeeBreakpointResolution).CodeContext.Address = new DebuggeeAddress(gdbBreakpoint.Address);

                        errorBreakpoint = new CLangDebuggeeBreakpointError(m_debugger, m_breakpointManager, this, (resolution as DebuggeeBreakpointResolution).CodeContext, gdbBreakpoint, resultRecord.Records [1].Stream);

                        lock (m_errorBreakpoints)
                        {
                            m_errorBreakpoints.Add(errorBreakpoint);
                        }

                        m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointError(errorBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId));
                    }
                    else
                    {
                        //
                        // We've probably got sane breakpoint information back. Update current breakpoint values and re-process.
                        //

                        MiResultValue breakpointData = resultRecord ["BreakpointTable"] [0] ["body"] [0] ["bkpt"] [0];

                        MiBreakpoint currentGdbBreakpoint = new MiBreakpoint(breakpointData.Values);

                        DebuggeeCodeContext codeContext = (resolution as DebuggeeBreakpointResolution).CodeContext;

                        DebuggeeDocumentContext documentContext = codeContext.DocumentContext;

                        LoggingUtils.RequireOk(CreateBoundBreakpoint(currentGdbBreakpoint, documentContext, codeContext));
                    }
                });
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    private void RefreshBreakpoint (object breakpoint)
    {
      // 
      // Validate breakpoint input type. This function can be used for 'bound' and 'error' objects, so we need to handle this appropriately.
      // 

      LoggingUtils.PrintFunction ();

      CLangDebuggeeBreakpointBound boundBreakpoint = null;

      CLangDebuggeeBreakpointError errorBreakpoint = null;

      MiBreakpoint gdbBreakpoint;

      DebuggeeBreakpointResolution resolution;

      if (breakpoint == null)
      {
        throw new ArgumentNullException ("breakpoint");
      }
      else if (breakpoint is CLangDebuggeeBreakpointBound)
      {
        boundBreakpoint = breakpoint as CLangDebuggeeBreakpointBound;

        gdbBreakpoint = boundBreakpoint.GdbBreakpoint;

        IDebugBreakpointResolution2 boundBreakpointResolution;

        int handle = boundBreakpoint.GetBreakpointResolution (out boundBreakpointResolution);

        if (handle == Constants.E_BP_DELETED)
        {
          return;
        }

        LoggingUtils.RequireOk (handle);

        resolution = (DebuggeeBreakpointResolution) boundBreakpointResolution;
      }
      else if (breakpoint is CLangDebuggeeBreakpointError)
      {
        errorBreakpoint = breakpoint as CLangDebuggeeBreakpointError;

        gdbBreakpoint = errorBreakpoint.GdbBreakpoint;

        IDebugErrorBreakpointResolution2 errorBreakpointResolution;

        int handle = errorBreakpoint.GetBreakpointResolution (out errorBreakpointResolution);

        if (handle == Constants.E_BP_DELETED)
        {
          return;
        }

        resolution = (DebuggeeBreakpointResolution) errorBreakpointResolution;

        lock (m_errorBreakpoints)
        {
          m_errorBreakpoints.Remove (errorBreakpoint);
        }
      }
      else
      {
        throw new ArgumentException ("breakpoint");
      }

      // 
      // Query breakpoint info/status directly from GDB/MI.
      // 

      try
      {
        string command = string.Format ("-break-info {0}", gdbBreakpoint.ID);

        m_debugger.GdbClient.SendCommand (command, delegate (MiResultRecord resultRecord)
        {
          if (resultRecord == null)
          {
            throw new InvalidOperationException ();
          }
          else if (resultRecord.IsError ())
          {
            // 
            // GDB/MI breakpoint info request failed.
            // 

            gdbBreakpoint.Address = MiBreakpoint.Pending;

            (resolution as DebuggeeBreakpointResolution).CodeContext.Address = new DebuggeeAddress (gdbBreakpoint.Address);

            errorBreakpoint = new CLangDebuggeeBreakpointError (m_debugger, m_breakpointManager, this, (resolution as DebuggeeBreakpointResolution).CodeContext, gdbBreakpoint, resultRecord.Records [1].Stream);

            lock (m_errorBreakpoints)
            {
              m_errorBreakpoints.Add (errorBreakpoint);
            }

            m_debugger.Engine.Broadcast (new DebugEngineEvent.BreakpointError (errorBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread (m_debugger.NativeProgram.CurrentThreadId));
          }
          else
          {
            // 
            // We've probably got sane breakpoint information back. Update current breakpoint values and re-process.
            // 

            MiResultValue breakpointData = resultRecord ["BreakpointTable"] [0] ["body"] [0] ["bkpt"] [0];

            MiBreakpoint currentGdbBreakpoint = new MiBreakpoint (breakpointData.Values);

            DebuggeeCodeContext codeContext = (resolution as DebuggeeBreakpointResolution).CodeContext;

            DebuggeeDocumentContext documentContext = codeContext.DocumentContext;

            LoggingUtils.RequireOk (CreateBoundBreakpoint (currentGdbBreakpoint, documentContext, codeContext));
          }
        });
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);
      }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int CreateErrorBreakpoint (string errorReason, MiBreakpoint gdbBreakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext)
    {
      // 
      // Create a C-language breakpoint. This is tied to a GDB/MI breakpoint object.
      // 

      LoggingUtils.PrintFunction ();

      try
      {
        CLangDebuggeeBreakpointError errorBreakpoint = new CLangDebuggeeBreakpointError (m_debugger, m_breakpointManager, this, codeContext, gdbBreakpoint, errorReason);

        lock (m_errorBreakpoints)
        {
          m_errorBreakpoints.Clear ();

          m_errorBreakpoints.Add (errorBreakpoint);
        }

        uint numDebugPrograms = 1;

        IEnumDebugPrograms2 debugPrograms;

        IDebugProgram2 [] debugProgramsArray = new IDebugProgram2 [numDebugPrograms];

        LoggingUtils.RequireOk (m_breakpointManager.Engine.EnumPrograms (out debugPrograms));

        LoggingUtils.RequireOk (debugPrograms.Next (numDebugPrograms, debugProgramsArray, ref numDebugPrograms));

        m_breakpointManager.Engine.Broadcast (new DebugEngineEvent.BreakpointError (errorBreakpoint), debugProgramsArray [0], null);

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

        return Constants.E_FAIL;
      }
    }