Example #1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

            LoggingUtils.PrintFunction();

            try
            {
                foreach (DebuggeeBreakpointPending pending in m_pendingBreakpoints.ToArray())
                {
                    //
                    // Check for matching 'bound' breakpoints.
                    //

                    uint numBoundBreakpoints;

                    IEnumDebugBoundBreakpoints2 enumeratedBoundBreakpoints;

                    LoggingUtils.RequireOk(pending.EnumBoundBreakpoints(out enumeratedBoundBreakpoints));

                    LoggingUtils.RequireOk(enumeratedBoundBreakpoints.GetCount(out numBoundBreakpoints));

                    if (numBoundBreakpoints > 0)
                    {
                        DebuggeeBreakpointBound [] boundBreakpoints = new DebuggeeBreakpointBound [numBoundBreakpoints];

                        LoggingUtils.RequireOk(enumeratedBoundBreakpoints.Next(numBoundBreakpoints, boundBreakpoints, numBoundBreakpoints));

                        for (uint i = 0; i < numBoundBreakpoints; ++i)
                        {
                            if (boundBreakpoints [i] is CLangDebuggeeBreakpointBound)
                            {
                                CLangDebuggeeBreakpointBound bound = boundBreakpoints [i] as CLangDebuggeeBreakpointBound;

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

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

        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 CreateBoundBreakpoint(MiBreakpoint breakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext)
        {
            LoggingUtils.PrintFunction();

            try
            {
                if (breakpoint == null)
                {
                    throw new ArgumentNullException("breakpoint");
                }

                if (breakpoint.IsPending())
                {
                    //
                    // Address can't be satisfied. Unsatisfied likely indicates the modules or symbols associated with the context aren't loaded, yet.
                    //

                    DebuggeeAddress pendingAddress = new DebuggeeAddress(MiBreakpoint.Pending);

                    DebuggeeCodeContext pendingContext = new CLangDebuggeeCodeContext(m_debugger, pendingAddress, documentContext);

                    LoggingUtils.RequireOk(CreateErrorBreakpoint("Additional library symbols required.", breakpoint, documentContext, pendingContext));
                }
                else if (breakpoint.IsMultiple())
                {
                    //
                    // Breakpoint satisfied to multiple locations, no single memory address available.
                    //

                    CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound(m_debugger, m_breakpointManager, this, codeContext, breakpoint);

                    lock (m_boundBreakpoints)
                    {
                        m_boundBreakpoints.Clear();

                        m_boundBreakpoints.Add(boundBreakpoint);
                    }

                    m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointBound(this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId));
                }
                else
                {
                    //
                    // Address satisfied, and the breakpoint is legitimately bound.
                    //

                    DebuggeeAddress boundAddress = new DebuggeeAddress(breakpoint.Address);

                    DebuggeeCodeContext addressContext = new CLangDebuggeeCodeContext(m_debugger, boundAddress, documentContext);

                    CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound(m_debugger, m_breakpointManager, this, addressContext, breakpoint);

                    lock (m_boundBreakpoints)
                    {
                        m_boundBreakpoints.Clear();

                        m_boundBreakpoints.Add(boundBreakpoint);
                    }

                    m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointBound(this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId));
                }

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

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

    public int CreateBoundBreakpoint (MiBreakpoint breakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext)
    {
      LoggingUtils.PrintFunction ();

      try
      {
        if (breakpoint == null)
        {
          throw new ArgumentNullException ("breakpoint");
        }

        if (breakpoint.IsPending ())
        {
          // 
          // Address can't be satisfied. Unsatisfied likely indicates the modules or symbols associated with the context aren't loaded, yet.
          // 

          DebuggeeAddress pendingAddress = new DebuggeeAddress (MiBreakpoint.Pending);

          DebuggeeCodeContext pendingContext = new CLangDebuggeeCodeContext (m_debugger, pendingAddress, documentContext);

          LoggingUtils.RequireOk (CreateErrorBreakpoint ("Additional library symbols required.", breakpoint, documentContext, pendingContext));
        }
        else if (breakpoint.IsMultiple ())
        {
          // 
          // Breakpoint satisfied to multiple locations, no single memory address available.
          // 

          CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound (m_debugger, m_breakpointManager, this, codeContext, breakpoint);

          lock (m_boundBreakpoints)
          {
            m_boundBreakpoints.Clear ();

            m_boundBreakpoints.Add (boundBreakpoint);
          }

          m_debugger.Engine.Broadcast (new DebugEngineEvent.BreakpointBound (this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread (m_debugger.NativeProgram.CurrentThreadId));
        }
        else
        {
          // 
          // Address satisfied, and the breakpoint is legitimately bound.
          // 

          DebuggeeAddress boundAddress = new DebuggeeAddress (breakpoint.Address);

          DebuggeeCodeContext addressContext = new CLangDebuggeeCodeContext (m_debugger, boundAddress, documentContext);

          CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound (m_debugger, m_breakpointManager, this, addressContext, breakpoint);

          lock (m_boundBreakpoints)
          {
            m_boundBreakpoints.Clear ();

            m_boundBreakpoints.Add (boundBreakpoint);
          }

          m_debugger.Engine.Broadcast (new DebugEngineEvent.BreakpointBound (this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread (m_debugger.NativeProgram.CurrentThreadId));
        }

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

        return Constants.E_FAIL;
      }
    }