Ejemplo n.º 1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public int GetCodeContext(ulong uCodeLocationId, out IDebugCodeContext2 ppCodeContext)
        {
            //
            // Returns a code context object corresponding to a specified code location identifier.
            //

            LoggingUtils.PrintFunction();

            try
            {
                string location = string.Format("0x{0:X8}", uCodeLocationId);

                ppCodeContext = CLangDebuggeeCodeContext.GetCodeContextForLocation(m_debugger, location);

                if (ppCodeContext == null)
                {
                    throw new InvalidOperationException();
                }

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

                ppCodeContext = null;

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

        public override int GetMemoryContext(out IDebugMemoryContext2 memoryContext)
        {
            //
            // Returns the memory context for a property value.
            //

            LoggingUtils.PrintFunction();

            memoryContext = null;

            try
            {
                //
                // Pick out a memory address from a pool of potential strings.
                //
                //   This is mainly to support GDB reporting symbols like:
                //
                //   {void (JNIEnv *, jclass)} 0xb3e66c84 <Java_com_example_hellogdbserver_HelloGdbServer_invokeCrash>
                //

                string [] expressionPool = { m_expression, m_gdbVariable.Value };

                string pattern = "(?<address>0x[A-Za-z0-9]+)";

                Regex regExMatcher = new Regex(pattern, RegexOptions.IgnoreCase);

                foreach (string expression in expressionPool)
                {
                    Match regExLineMatch = regExMatcher.Match(expression);

                    if (regExLineMatch.Success)
                    {
                        string address = regExLineMatch.Result("${address}");

                        memoryContext = CLangDebuggeeCodeContext.GetCodeContextForLocation(m_debugger, address);

                        break;
                    }
                }

                if (memoryContext == null)
                {
                    return(Constants.S_GETMEMORYCONTEXT_NO_MEMORY_CONTEXT);
                }

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

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

    public int EnumCodeContexts (IDebugDocumentPosition2 pDocPos, out IEnumDebugCodeContexts2 ppEnum)
    {
      // 
      // Enumerates the code contexts for a given position in a source file.
      // 

      LoggingUtils.PrintFunction ();

      try
      {
        string fileName;

        TEXT_POSITION [] startPos = new TEXT_POSITION [1];

        TEXT_POSITION [] endPos = new TEXT_POSITION [1];

        LoggingUtils.RequireOk (pDocPos.GetFileName (out fileName));

        LoggingUtils.RequireOk (pDocPos.GetRange (startPos, endPos));

        DebuggeeDocumentContext documentContext = new DebuggeeDocumentContext (m_debugger.Engine, fileName, startPos [0], endPos [0]);

        CLangDebuggeeCodeContext codeContext = CLangDebuggeeCodeContext.GetCodeContextForDocumentContext (m_debugger, documentContext);

        if (codeContext == null)
        {
          throw new InvalidOperationException ("Failed evaluating code-context for location.");
        }

        CLangDebuggeeCodeContext [] codeContexts = new CLangDebuggeeCodeContext [] { codeContext };

        ppEnum = new DebuggeeCodeContext.Enumerator (codeContexts);

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

        ppEnum = null;

        return Constants.E_FAIL;
      }
    }
Ejemplo n.º 4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void GetInfoFromCurrentLevel(MiResultValueTuple frameTuple)
        {
            LoggingUtils.PrintFunction();

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

                if (frameTuple.HasField("level"))
                {
                    m_stackLevel = frameTuple ["level"] [0].GetUnsignedInt();
                }

                //
                // Discover the function or shared library location.
                //

                if (frameTuple.HasField("addr"))
                {
                    m_locationAddress = new DebuggeeAddress(frameTuple ["addr"] [0].GetString());
                }
                else
                {
                    m_locationAddress = new DebuggeeAddress("0x0");
                }

                if (frameTuple.HasField("func"))
                {
                    m_locationFunction = frameTuple ["func"] [0].GetString();
                }
                else
                {
                    m_locationFunction = "??";
                }

                m_locationIsSymbolicated = !(m_locationFunction.Equals("??"));

                if (frameTuple.HasField("from"))
                {
                    m_locationModule = Path.GetFileName(frameTuple ["from"] [0].GetString());
                }
                else
                {
                    m_locationModule = string.Empty;
                }

                //
                // Generate code and document contexts for this frame location.
                //

                if (frameTuple.HasField("fullname") && frameTuple.HasField("line"))
                {
                    //
                    // If the symbol table isn't yet loaded, we'll need to specify exactly the location of this stack frame.
                    //

                    TEXT_POSITION [] textPositions = new TEXT_POSITION [2];

                    textPositions [0].dwLine = frameTuple ["line"] [0].GetUnsignedInt() - 1;

                    textPositions [0].dwColumn = 0;

                    textPositions [1].dwLine = textPositions [0].dwLine;

                    textPositions [1].dwColumn = textPositions [0].dwColumn;

                    string filename = PathUtils.ConvertPathCygwinToWindows(frameTuple ["fullname"] [0].GetString());

                    m_documentContext = new DebuggeeDocumentContext(m_debugger.Engine, filename, textPositions [0], textPositions [1]);

                    m_codeContext = CLangDebuggeeCodeContext.GetCodeContextForLocation(m_debugger, m_locationAddress.ToString());

                    if (m_codeContext == null)
                    {
                        throw new InvalidOperationException();
                    }
                }
                else
                {
                    m_codeContext = CLangDebuggeeCodeContext.GetCodeContextForLocation(m_debugger, m_locationAddress.ToString());

                    m_documentContext = (m_codeContext != null) ? m_codeContext.DocumentContext : null;
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }
Ejemplo n.º 5
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static CLangDebuggeeCodeContext GetCodeContextForLocation(CLangDebugger debugger, string location)
        {
            LoggingUtils.PrintFunction();

            try
            {
                if (string.IsNullOrEmpty(location))
                {
                    throw new ArgumentNullException("location");
                }

                if (location.StartsWith("0x"))
                {
                    location = "*" + location;
                }
                else if (location.StartsWith("\""))
                {
                    location = location.Replace("\\", "/");

                    location = location.Replace("\"", "\\\""); // required to escape the nested string.
                }

                string command = string.Format("-interpreter-exec console \"info line {0}\"", location);

                MiResultRecord resultRecord = debugger.GdbClient.SendSyncCommand(command);

                MiResultRecord.RequireOk(resultRecord, command);

                string pattern = "Line (?<line>[0-9]+) of ([\\]*\"(?<file>.+)[\\]*[\"]+) starts at address (?<startaddr>[^ ]+) (?<startsym>[^+]+[+]?[0-9]*[>]?) (but contains no code|and ends at (?<endaddr>[^ ]+) (?<endsym>[^+]+[+]?[0-9]*[>]?)?)";

                pattern = pattern.Replace("\\", "\\\\");

                Regex regExMatcher = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);

                foreach (MiStreamRecord record in resultRecord.Records)
                {
                    if (!record.Stream.StartsWith("Line"))
                    {
                        continue; // early rejection.
                    }

                    StringBuilder sanitisedStream = new StringBuilder(record.Stream);

                    sanitisedStream.Replace("\\\"", "\"");

                    sanitisedStream.Replace("\\\\", "\\");

                    Match regExLineMatch = regExMatcher.Match(sanitisedStream.ToString());

                    if (regExLineMatch.Success)
                    {
                        string line = regExLineMatch.Result("${line}");

                        string file = regExLineMatch.Result("${file}");

                        string startaddr = regExLineMatch.Result("${startaddr}");

                        string startsym = regExLineMatch.Result("${startsym}");

                        string endaddr = regExLineMatch.Result("${endaddr}");

                        string endsym = regExLineMatch.Result("${endsym}");

                        TEXT_POSITION [] documentPositions = new TEXT_POSITION [2];

                        documentPositions [0].dwLine = uint.Parse(line) - 1;

                        documentPositions [0].dwColumn = 0;

                        documentPositions [1].dwLine = documentPositions [0].dwLine;

                        documentPositions [1].dwColumn = uint.MaxValue;

                        DebuggeeAddress startAddress = new DebuggeeAddress(startaddr);

                        DebuggeeDocumentContext documentContext = new DebuggeeDocumentContext(debugger.Engine, file, documentPositions [0], documentPositions [1]);

                        CLangDebuggeeCodeContext codeContext = new CLangDebuggeeCodeContext(debugger, startAddress, documentContext);

                        documentContext.SetCodeContext(codeContext);

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

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

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

    public static CLangDebuggeeCodeContext GetCodeContextForLocation (CLangDebugger debugger, string location)
    {
      LoggingUtils.PrintFunction ();

      try
      {
        if (string.IsNullOrEmpty (location))
        {
          throw new ArgumentNullException ("location");
        }

        if (location.StartsWith ("0x"))
        {
          location = "*" + location;
        }
        else if (location.StartsWith ("\""))
        {
          location = location.Replace ("\\", "/");

          location = location.Replace ("\"", "\\\""); // required to escape the nested string.
        }

        string command = string.Format ("-interpreter-exec console \"info line {0}\"", location);

        MiResultRecord resultRecord = debugger.GdbClient.SendSyncCommand (command);

        MiResultRecord.RequireOk (resultRecord, command);

        string pattern = "Line (?<line>[0-9]+) of ([\\]*\"(?<file>.+)[\\]*[\"]+) starts at address (?<startaddr>[^ ]+) (?<startsym>[^+]+[+]?[0-9]*[>]?) (but contains no code|and ends at (?<endaddr>[^ ]+) (?<endsym>[^+]+[+]?[0-9]*[>]?)?)";

        pattern = pattern.Replace ("\\", "\\\\");

        Regex regExMatcher = new Regex (pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);

        foreach (MiStreamRecord record in resultRecord.Records)
        {
          if (!record.Stream.StartsWith ("Line"))
          {
            continue; // early rejection.
          }

          StringBuilder sanitisedStream = new StringBuilder (record.Stream);

          sanitisedStream.Replace ("\\\"", "\"");

          sanitisedStream.Replace ("\\\\", "\\");

          Match regExLineMatch = regExMatcher.Match (sanitisedStream.ToString ());

          if (regExLineMatch.Success)
          {
            string line = regExLineMatch.Result ("${line}");

            string file = regExLineMatch.Result ("${file}");

            string startaddr = regExLineMatch.Result ("${startaddr}");

            string startsym = regExLineMatch.Result ("${startsym}");

            string endaddr = regExLineMatch.Result ("${endaddr}");

            string endsym = regExLineMatch.Result ("${endsym}");

            TEXT_POSITION [] documentPositions = new TEXT_POSITION [2];

            documentPositions [0].dwLine = uint.Parse (line) - 1;

            documentPositions [0].dwColumn = 0;

            documentPositions [1].dwLine = documentPositions [0].dwLine;

            documentPositions [1].dwColumn = uint.MaxValue;

            DebuggeeAddress startAddress = new DebuggeeAddress (startaddr);

            DebuggeeDocumentContext documentContext = new DebuggeeDocumentContext (debugger.Engine, file, documentPositions [0], documentPositions [1]);

            CLangDebuggeeCodeContext codeContext = new CLangDebuggeeCodeContext (debugger, startAddress, documentContext);

            documentContext.SetCodeContext (codeContext);

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

      return null;
    }