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

        public void Start()
        {
            LoggingUtils.PrintFunction();

            //
            // Export an execution script ('jdb.ini') for standard start-up properties.
            //

            string [] execCommands = m_jdbSetup.CreateJdbExecutionScript();

            using (StreamWriter writer = new StreamWriter(Path.Combine(m_jdbSetup.CacheDirectory, "jdb.ini"), false, Encoding.ASCII))
            {
                foreach (string command in execCommands)
                {
                    writer.WriteLine(command);
                }
            }

            //
            // Prepare a new JDB instance. Connections must be made on the command line, so delay this until an attach request.
            //

            StringBuilder argumentBuilder = new StringBuilder();

    #if DEBUG && false
            argumentBuilder.Append(string.Format("-dbgtrace "));
    #endif

            argumentBuilder.Append(string.Format("-connect com.sun.jdi.SocketAttach:hostname={0},port={1} ", m_jdbSetup.Host, m_jdbSetup.Port));

            m_jdbClientInstance = new AsyncRedirectProcess(Path.Combine(JavaSettings.JdkRoot, @"bin\jdb.exe"), argumentBuilder.ToString());
        }
Example #2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static AsyncRedirectProcess AdbCommandAsync(AndroidDevice target, string command, string arguments)
        {
            LoggingUtils.Print(string.Format("[AndroidDevice] AdbCommandAsync: Target={0} Cmd={1} Args={2}", target.ID, command, arguments));

            AsyncRedirectProcess adbCommand = new AsyncRedirectProcess(AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", string.Format("-s {0} {1} {2}", target.ID, command, arguments));

            return(adbCommand);
        }
Example #3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public GdbServer(GdbSetup gdbSetup)
        {
            LoggingUtils.PrintFunction ();

              m_gdbSetup = gdbSetup;

              m_gdbServerInstance = null;

              m_gdbServerAttached = null;
        }
Example #4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public GdbServer(GdbSetup gdbSetup)
        {
            LoggingUtils.PrintFunction();

            m_gdbSetup = gdbSetup;

            m_gdbServerInstance = null;

            m_gdbServerAttached = null;
        }
Example #5
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    protected virtual void Dispose (bool disposing)
    {
      if (disposing)
      {
        if (m_gdbServerInstance != null)
        {
          m_gdbServerInstance.Dispose ();

          m_gdbServerInstance = null;
        }

        if (m_gdbServerAttached != null)
        {
          m_gdbServerAttached.Dispose ();

          m_gdbServerAttached = null;
        }
      }
    }
Example #6
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (m_gdbServerInstance != null)
                {
                    m_gdbServerInstance.Dispose();

                    m_gdbServerInstance = null;
                }

                if (m_gdbServerAttached != null)
                {
                    m_gdbServerAttached.Dispose();

                    m_gdbServerAttached = null;
                }
            }
        }
Example #7
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (m_jdbClientInstance != null)
                {
                    m_jdbClientInstance.Dispose();

                    m_jdbClientInstance = null;
                }

                if (m_sessionStarted != null)
                {
                    m_sessionStarted.Dispose();

                    m_sessionStarted = null;
                }
            }
        }
Example #8
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void ProcessExited(object sendingProcess, EventArgs args)
        {
            try
            {
                m_timeSinceLastOperation.Restart();

                LoggingUtils.Print(string.Format("[JdbClient] ProcessExited"));

                m_jdbClientInstance = null;

                //
                // If we're waiting on a synchronous command, signal a finish to process termination.
                //

                foreach (KeyValuePair <string, ManualResetEvent> syncKeyPair in m_syncCommandLocks)
                {
                    syncKeyPair.Value.Set();
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }
Example #9
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    protected virtual void Dispose (bool disposing)
    {
      if (disposing)
      {
        if (m_jdbClientInstance != null)
        {
          m_jdbClientInstance.Dispose ();

          m_jdbClientInstance = null;
        }

        if (m_sessionStarted != null)
        {
          m_sessionStarted.Dispose ();

          m_sessionStarted = null;
        }
      }
    }
Example #10
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public void Start ()
    {
      LoggingUtils.PrintFunction ();

      // 
      // Export an execution script ('gdb.setup') for standard start-up properties.
      // 

      string [] execCommands = m_gdbSetup.CreateGdbExecutionScript ();

      using (StreamWriter writer = new StreamWriter (Path.Combine (m_gdbSetup.CacheDirectory, "gdb.setup")))
      {
        foreach (string command in execCommands)
        {
          writer.WriteLine (command);
        }
      }

      // 
      // Spawn a new GDB instance which executes gdb.setup and begins debugging file 'app_process'.
      // 

      string clientArguments = m_gdbSetup.GdbToolArguments + string.Format (@" -fullname -x {0}", PathUtils.SantiseWindowsPath (Path.Combine (m_gdbSetup.CacheDirectory, "gdb.setup")));

      m_gdbClientInstance = new AsyncRedirectProcess (m_gdbSetup.GdbToolPath, clientArguments);

      m_gdbClientInstance.Start (this);

      m_timeSinceLastOperation.Start ();

      uint timeout = 15000;

      bool responseSignaled = false;

      while ((!responseSignaled) && (m_timeSinceLastOperation.ElapsedMilliseconds < timeout))
      {
        responseSignaled = m_sessionStarted.WaitOne (0);

        if (!responseSignaled)
        {
          Thread.Sleep (100);
        }
      }

      if (!responseSignaled)
      {
        throw new TimeoutException ("Timed out waiting for GDB client to execute");
      }

      // 
      // Create asynchronous input and output job queue threads.
      // 

      if (m_asyncRecordWorkerThread == null)
      {
        m_asyncRecordWorkerThread = new Thread (AsyncOutputWorkerThreadBody);

        m_asyncRecordWorkerThread.Start ();
      }

      // 
      // Evaluate this client's GDB/MI support and capabilities. 
      // 

      try
      {
        SendCommand ("-list-features", delegate (MiResultRecord resultRecord)
        {
          MiResultRecord.RequireOk (resultRecord, "-list-features");

          if (resultRecord.HasField ("features"))
          {
            foreach (MiResultValue feature in resultRecord ["features"] [0].Values)
            {
              m_gdbSupportedClientMiFeatures.Add (feature.GetString ());
            }
          }
        });
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);

        throw;
      }

      // 
      // Evaluate available signals and their current 'should stop' status.
      // 

      try
      {
        string command = string.Format ("-interpreter-exec console \"info signals\"");

        SendCommand (command, delegate (MiResultRecord resultRecord)
        {
          MiResultRecord.RequireOk (resultRecord, command);

          string pattern = @"(?<sig>[^ ]+)[ ]+(?<stop>[^\\t]+)\\t(?<print>[^\\t]+)\\t(?<pass>[^\\t]+)\\t\\t(?<desc>[^\\]+)";

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

          for (int i = 2; i < resultRecord.Records.Count; ++i) // Skip the first rows (2) of headers
          {
            MiStreamRecord record = resultRecord.Records [i];

            Match regExLineMatch = regExMatcher.Match (record.Stream);

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

              bool stop = regExLineMatch.Result ("${stop}").Equals ("Yes");

              bool print = regExLineMatch.Result ("${print}").Equals ("Yes");

              bool passToProgram = regExLineMatch.Result ("${pass}").Equals ("Yes");

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

              Signal signal = new Signal (this, sig, desc, stop, passToProgram);

              lock (m_gdbSupportedClientSignals)
              {
                m_gdbSupportedClientSignals.Add (sig, signal);
              }
            }
          }
        });
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);

        throw;
      }
    }
Example #11
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public static AsyncRedirectProcess AdbCommandAsync (AndroidDevice target, string command, string arguments)
    {
      LoggingUtils.Print (string.Format ("[AndroidDevice] AdbCommandAsync: Target={0} Cmd={1} Args={2}", target.ID, command, arguments));

      AsyncRedirectProcess adbCommand = new AsyncRedirectProcess (AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", string.Format ("-s {0} {1} {2}", target.ID, command, arguments));

      return adbCommand;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int OnProgramDestroy (IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib)
    {
      LoggingUtils.PrintFunction ();

      try
      {
        if (m_adbLogcatProcess != null)
        {
          m_adbLogcatProcess.Kill ();

          m_adbLogcatProcess.Dispose ();

          m_adbLogcatProcess = null;
        }

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

        return VSConstants.E_FAIL;
      }
    }
Example #13
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public void ProcessExited (object sendingProcess, EventArgs args)
    {
      try
      {
        m_timeSinceLastOperation.Restart ();

        LoggingUtils.Print (string.Format ("[JdbClient] ProcessExited"));

        m_jdbClientInstance = null;

        // 
        // If we're waiting on a synchronous command, signal a finish to process termination.
        // 

        foreach (KeyValuePair<string, ManualResetEvent> syncKeyPair in m_syncCommandLocks)
        {
          syncKeyPair.Value.Set ();
        }
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);
      }
    }
Example #14
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    protected virtual void Dispose (bool disposing)
    {
      if (disposing)
      {
        if (m_gdbClientInstance != null)
        {
          m_gdbClientInstance.Dispose ();

          m_gdbClientInstance = null;
        }

        if (m_asyncRecordWorkerThreadSignal != null)
        {
          m_asyncRecordWorkerThreadSignal.Dispose ();

          m_asyncRecordWorkerThreadSignal = null;
        }

        if (m_sessionStarted != null)
        {
          m_sessionStarted.Dispose ();

          m_sessionStarted = null;
        }
      }
    }
Example #15
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void Start()
        {
            LoggingUtils.PrintFunction();

            //
            // Check the target 'gdbserver' binary exits on target device/emulator.
            //

            string gdbServerPath = string.Empty;

            List <string> potentialGdbServerPaths = new List <string> ();

            foreach (string libraryPath in m_gdbSetup.Process.NativeLibraryAbiPaths)
            {
                potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", libraryPath));
            }

            potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", m_gdbSetup.Process.NativeLibraryPath));

            foreach (string path in potentialGdbServerPaths)
            {
                try
                {
                    string ls = m_gdbSetup.Process.HostDevice.Shell("ls", path);

                    if (ls.ToLowerInvariant().Contains("no such file"))
                    {
                        throw new DirectoryNotFoundException(path);
                    }

                    gdbServerPath = path;

                    break;
                }
                catch (Exception)
                {
                    // Ignore.
                }
            }

            //
            // If we can't find a bundled 'gdbserver' binary, attempt to find one in the NDK.
            //

            if (string.IsNullOrWhiteSpace(gdbServerPath))
            {
                foreach (string path in m_gdbSetup.Process.NativeLibraryAbiPaths)
                {
                    try
                    {
                        string shortAbi = path.Substring(path.LastIndexOf('/') + 1);

                        string local = Path.Combine(AndroidSettings.NdkRoot, string.Format(@"prebuilt\android-{0}\gdbserver\gdbserver", shortAbi));

                        string remote = string.Format("/data/local/tmp/gdbserver-{0}", shortAbi);

                        m_gdbSetup.Process.HostDevice.Push(local, remote);
                    }
                    catch (Exception e)
                    {
                        LoggingUtils.HandleException(e);
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(gdbServerPath))
            {
                throw new InvalidOperationException(string.Format("Failed to locate required 'gdbserver' binary on device ({0}).", m_gdbSetup.Process.HostDevice.ID));
            }

            KillActiveGdbServerSessions();

            //
            // Construct a adaptive command line based on GdbSetup requirements.
            //

            StringBuilder commandLineArgumentsBuilder = new StringBuilder();

            commandLineArgumentsBuilder.AppendFormat("run-as {0} {1} ", m_gdbSetup.Process.Name, gdbServerPath);

            if (!string.IsNullOrWhiteSpace(m_gdbSetup.Socket))
            {
                commandLineArgumentsBuilder.AppendFormat("+{0} ", m_gdbSetup.Socket);
            }

            commandLineArgumentsBuilder.Append("--attach ");

            if (string.IsNullOrWhiteSpace(m_gdbSetup.Socket)) // Don't need a host if we have a bound socket?
            {
                commandLineArgumentsBuilder.AppendFormat("{0}:{1} ", m_gdbSetup.Host, m_gdbSetup.Port);
            }

            commandLineArgumentsBuilder.Append(m_gdbSetup.Process.Pid);

            //
            // Launch 'gdbserver' and wait for output to determine success.
            //

            Stopwatch waitForConnectionTimer = new Stopwatch();

            waitForConnectionTimer.Start();

            m_gdbServerAttached = new ManualResetEvent(false);

            m_gdbServerInstance = AndroidAdb.AdbCommandAsync(m_gdbSetup.Process.HostDevice, "shell", commandLineArgumentsBuilder.ToString());

            m_gdbServerInstance.Start(this);

            LoggingUtils.Print(string.Format("[GdbServer] Waiting to attach..."));

            uint timeout = 5000;

            bool responseSignaled = false;

            while ((!responseSignaled) && (waitForConnectionTimer.ElapsedMilliseconds < timeout))
            {
                responseSignaled = m_gdbServerAttached.WaitOne(0);

                if (!responseSignaled)
                {
                    Thread.Sleep(100);
                }
            }

            if (!responseSignaled)
            {
                throw new TimeoutException("Timed out waiting for GdbServer to execute.");
            }
        }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int OnDebuggerLogcatEvent (IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib)
    {
      LoggingUtils.PrintFunction ();

      try
      {
        DebugEngineEvent.DebuggerLogcatEvent debuggerLogcatEvent = pEvent as DebugEngineEvent.DebuggerLogcatEvent;

        using (SyncRedirectProcess command = AndroidAdb.AdbCommand (debuggerLogcatEvent.HostDevice, "logcat", "-c"))
        {
          command.StartAndWaitForExit ();
        }

        m_adbLogcatProcess = AndroidAdb.AdbCommandAsync (debuggerLogcatEvent.HostDevice, "logcat", "");

        m_adbLogcatListener = new DeviceLogcatListener ();

        if (m_adbLogcatProcess == null)
        {
          throw new InvalidOperationException ("Failed to launch logcat application.");
        }

        if (m_adbLogcatListener == null)
        {
          throw new InvalidOperationException ("Failed to launch logcat listener.");
        }

        m_adbLogcatProcess.Start (m_adbLogcatListener);

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

        return VSConstants.E_FAIL;
      }
    }
Example #17
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public void Start()
        {
            LoggingUtils.PrintFunction ();

              //
              // Check the target 'gdbserver' binary exits on target device/emulator.
              //

              string gdbServerPath = string.Empty;

              List<string> potentialGdbServerPaths = new List<string> ();

              foreach (string libraryPath in m_gdbSetup.Process.NativeLibraryAbiPaths)
              {
            potentialGdbServerPaths.Add (string.Format ("{0}/gdbserver", libraryPath));
              }

              potentialGdbServerPaths.Add (string.Format ("{0}/gdbserver", m_gdbSetup.Process.NativeLibraryPath));

              foreach (string path in potentialGdbServerPaths)
              {
            using (SyncRedirectProcess checkGdbServer = AndroidAdb.AdbCommand (m_gdbSetup.Process.HostDevice, "shell", "ls " + path))
            {
              int exitCode = checkGdbServer.StartAndWaitForExit (1000);

              if ((exitCode == 0) && !checkGdbServer.StandardOutput.ToLower ().Contains ("no such file"))
              {
            gdbServerPath = path;

            break;
              }
            }
              }

              if (string.IsNullOrWhiteSpace (gdbServerPath))
              {
            // TODO: Push the required gdbserver binary, so we can attach to any app.
            throw new InvalidOperationException (string.Format ("Failed to locate required 'gdbserver' binary on device ({0}).", m_gdbSetup.Process.HostDevice.ID));
              }

              KillActiveGdbServerSessions ();

              //
              // Construct a adaptive command line based on GdbSetup requirements.
              //

              StringBuilder commandLineArgumentsBuilder = new StringBuilder ();

              commandLineArgumentsBuilder.AppendFormat ("run-as {0} {1} ", m_gdbSetup.Process.Name, gdbServerPath);

              if (!string.IsNullOrWhiteSpace (m_gdbSetup.Socket))
              {
            commandLineArgumentsBuilder.AppendFormat ("+{0} ", m_gdbSetup.Socket);
              }

              commandLineArgumentsBuilder.Append ("--attach ");

              if (string.IsNullOrWhiteSpace (m_gdbSetup.Socket)) // Don't need a host if we have a bound socket?
              {
            commandLineArgumentsBuilder.AppendFormat ("{0}:{1} ", m_gdbSetup.Host, m_gdbSetup.Port);
              }

              commandLineArgumentsBuilder.Append (m_gdbSetup.Process.Pid);

              //
              // Launch 'gdbserver' and wait for output to determine success.
              //

              Stopwatch waitForConnectionTimer = new Stopwatch ();

              waitForConnectionTimer.Start ();

              m_gdbServerAttached = new ManualResetEvent (false);

              m_gdbServerInstance = AndroidAdb.AdbCommandAsync (m_gdbSetup.Process.HostDevice, "shell", commandLineArgumentsBuilder.ToString ());

              m_gdbServerInstance.Start (this);

              LoggingUtils.Print (string.Format ("[GdbServer] Waiting to attach..."));

              uint timeout = 5000;

              bool responseSignaled = false;

              while ((!responseSignaled) && (waitForConnectionTimer.ElapsedMilliseconds < timeout))
              {
            responseSignaled = m_gdbServerAttached.WaitOne (0);

            if (!responseSignaled)
            {
              Thread.Sleep (100);
            }
              }

              if (!responseSignaled)
              {
            throw new TimeoutException ("Timed out waiting for GdbServer to execute.");
              }
        }
Example #18
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void Start()
        {
            LoggingUtils.PrintFunction();

            //
            // Check the target 'gdbserver' binary exits on target device/emulator.
            //

            string gdbServerPath = string.Empty;

            List <string> potentialGdbServerPaths = new List <string> ();

            foreach (string libraryPath in m_gdbSetup.Process.NativeLibraryAbiPaths)
            {
                potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", libraryPath));
            }

            potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", m_gdbSetup.Process.NativeLibraryPath));

            foreach (string path in potentialGdbServerPaths)
            {
                using (SyncRedirectProcess checkGdbServer = AndroidAdb.AdbCommand(m_gdbSetup.Process.HostDevice, "shell", "ls " + path))
                {
                    int exitCode = checkGdbServer.StartAndWaitForExit(1000);

                    if ((exitCode == 0) && !checkGdbServer.StandardOutput.ToLower().Contains("no such file"))
                    {
                        gdbServerPath = path;

                        break;
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(gdbServerPath))
            {
                // TODO: Push the required gdbserver binary, so we can attach to any app.
                throw new InvalidOperationException(string.Format("Failed to locate required 'gdbserver' binary on device ({0}).", m_gdbSetup.Process.HostDevice.ID));
            }

            KillActiveGdbServerSessions();

            //
            // Construct a adaptive command line based on GdbSetup requirements.
            //

            StringBuilder commandLineArgumentsBuilder = new StringBuilder();

            commandLineArgumentsBuilder.AppendFormat("run-as {0} {1} ", m_gdbSetup.Process.Name, gdbServerPath);

            if (!string.IsNullOrWhiteSpace(m_gdbSetup.Socket))
            {
                commandLineArgumentsBuilder.AppendFormat("+{0} ", m_gdbSetup.Socket);
            }

            commandLineArgumentsBuilder.Append("--attach ");

            if (string.IsNullOrWhiteSpace(m_gdbSetup.Socket)) // Don't need a host if we have a bound socket?
            {
                commandLineArgumentsBuilder.AppendFormat("{0}:{1} ", m_gdbSetup.Host, m_gdbSetup.Port);
            }

            commandLineArgumentsBuilder.Append(m_gdbSetup.Process.Pid);

            //
            // Launch 'gdbserver' and wait for output to determine success.
            //

            Stopwatch waitForConnectionTimer = new Stopwatch();

            waitForConnectionTimer.Start();

            m_gdbServerAttached = new ManualResetEvent(false);

            m_gdbServerInstance = AndroidAdb.AdbCommandAsync(m_gdbSetup.Process.HostDevice, "shell", commandLineArgumentsBuilder.ToString());

            m_gdbServerInstance.Start(this);

            LoggingUtils.Print(string.Format("[GdbServer] Waiting to attach..."));

            uint timeout = 5000;

            bool responseSignaled = false;

            while ((!responseSignaled) && (waitForConnectionTimer.ElapsedMilliseconds < timeout))
            {
                responseSignaled = m_gdbServerAttached.WaitOne(0);

                if (!responseSignaled)
                {
                    Thread.Sleep(100);
                }
            }

            if (!responseSignaled)
            {
                throw new TimeoutException("Timed out waiting for GdbServer to execute.");
            }
        }
Example #19
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public void Start ()
    {
      LoggingUtils.PrintFunction ();

      // 
      // Export an execution script ('jdb.ini') for standard start-up properties.
      // 

      string [] execCommands = m_jdbSetup.CreateJdbExecutionScript ();

      using (StreamWriter writer = new StreamWriter (Path.Combine (m_jdbSetup.CacheDirectory, "jdb.ini"), false, Encoding.ASCII))
      {
        foreach (string command in execCommands)
        {
          writer.WriteLine (command);
        }
      }

      // 
      // Prepare a new JDB instance. Connections must be made on the command line, so delay this until an attach request.
      // 

      StringBuilder argumentBuilder = new StringBuilder ();

    #if DEBUG && false
      argumentBuilder.Append (string.Format ("-dbgtrace "));
    #endif

      argumentBuilder.Append (string.Format ("-connect com.sun.jdi.SocketAttach:hostname={0},port={1} ", m_jdbSetup.Host, m_jdbSetup.Port));

      m_jdbClientInstance = new AsyncRedirectProcess (Path.Combine (JavaSettings.JdkRoot, @"bin\jdb.exe"), argumentBuilder.ToString ());
    }