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

        public string Push(string localPath, string remotePath)
        {
            LoggingUtils.PrintFunction();

            try
            {
                int exitCode = -1;

                using (SyncRedirectProcess process = AndroidAdb.AdbCommand(this, "push", string.Format("{0} {1}", PathUtils.QuoteIfNeeded(localPath), remotePath)))
                {
                    exitCode = process.StartAndWaitForExit();

                    if (exitCode != 0)
                    {
                        throw new InvalidOperationException(string.Format("[push] returned error code: {0}", exitCode));
                    }

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

                throw new InvalidOperationException("[push] failed", e);
            }
        }
Example #2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public string Shell(string command, string arguments, int timeout = 30000)
        {
            LoggingUtils.PrintFunction();

            try
            {
                int exitCode = -1;

                using (SyncRedirectProcess process = AndroidAdb.AdbCommand(this, "shell", string.Format("{0} {1}", command, arguments)))
                {
                    exitCode = process.StartAndWaitForExit(timeout);

                    if (exitCode != 0)
                    {
                        throw new InvalidOperationException(string.Format("[shell:{0}] returned error code: {1}", command, exitCode));
                    }

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

                throw new InvalidOperationException(string.Format("[shell:{0}] failed", command), e);
            }
        }
Example #3
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public void SetupPortForwarding ()
    {
      // 
      // Setup network redirection.
      // 

      LoggingUtils.PrintFunction ();

      StringBuilder forwardArgsBuilder = new StringBuilder ();

      forwardArgsBuilder.AppendFormat ("tcp:{0} ", Port);

      if (!string.IsNullOrWhiteSpace (Socket))
      {
        forwardArgsBuilder.AppendFormat ("localfilesystem:{0}/{1}", Process.DataDirectory, Socket);
      }
      else
      {
        forwardArgsBuilder.AppendFormat ("tcp:{0} ", Port);
      }

      using (SyncRedirectProcess adbPortForward = AndroidAdb.AdbCommand (Process.HostDevice, "forward", forwardArgsBuilder.ToString ()))
      {
        adbPortForward.StartAndWaitForExit ();
      }
    }
Example #4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

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

            return(adbCommand);
        }
Example #5
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static SyncRedirectProcess AdbCommand(string command, string arguments)
        {
            LoggingUtils.Print(string.Format("[AndroidDevice] AdbCommand: Cmd={0} Args={1}", command, arguments));

            var adbCommand = new SyncRedirectProcess(AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", string.Format("{0} {1}", command, arguments));

            return(adbCommand);
        }
Example #6
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public static SyncRedirectProcess AdbCommand(AndroidDevice target, string command, string arguments)
        {
            LoggingUtils.Print (string.Format ("[AndroidDevice] AdbCommand: Target={0} Cmd={1} Args={2}", target.ID, command, arguments));

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

              return adbCommand;
        }
Example #7
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void ClearPortForwarding()
        {
            //
            // Clear network redirection.
            //

            LoggingUtils.PrintFunction();

            StringBuilder forwardArgsBuilder = new StringBuilder();

            forwardArgsBuilder.AppendFormat("--remove tcp:{0}", Port);

            using SyncRedirectProcess adbPortForward = AndroidAdb.AdbCommand(Process.HostDevice, "forward", forwardArgsBuilder.ToString());

            adbPortForward.StartAndWaitForExit(1000);
        }
Example #8
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void SetupPortForwarding()
        {
            //
            // Setup network redirection.
            //

            LoggingUtils.PrintFunction();

            StringBuilder forwardArgsBuilder = new StringBuilder();

            forwardArgsBuilder.AppendFormat("tcp:{0} jdwp:{1}", Port, Process.Pid);

            using (SyncRedirectProcess adbPortForward = AndroidAdb.AdbCommand(Process.HostDevice, "forward", forwardArgsBuilder.ToString()))
            {
                adbPortForward.StartAndWaitForExit(1000);
            }
        }
Example #9
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static string GetElfSectionData(string objDumpTool, string elfBinary, string sectionName)
        {
            if (string.IsNullOrWhiteSpace(objDumpTool) || !File.Exists(objDumpTool))
            {
                throw new ArgumentException("Could not find required objdump tool. Expected: " + objDumpTool);
            }

            if (string.IsNullOrWhiteSpace(elfBinary) || !File.Exists(elfBinary))
            {
                throw new ArgumentException("Could not find required ELF binary. Expected: " + elfBinary);
            }

            if (string.IsNullOrWhiteSpace(sectionName))
            {
                throw new ArgumentNullException("sectionName");
            }

            using (SyncRedirectProcess dumpSection = new SyncRedirectProcess(objDumpTool, string.Format("-s -j {0} {1}", sectionName, elfBinary)))
            {
                int exitCode = dumpSection.StartAndWaitForExit();

                if (exitCode == 0)
                {
                    StringBuilder dumpContent = new StringBuilder();

                    string dumpRegExPattern = " ([0-9a-fA-F]+) (?<block_a>[0-9a-fA-F]*) (?<block_b>[0-9a-fA-F]*) (?<block_c>[0-9a-fA-F]*) (?<block_d>[0-9a-fA-F]*)";

                    Regex regExMatcher = new Regex(dumpRegExPattern, RegexOptions.Compiled);

                    MatchCollection regExMatches = regExMatcher.Matches(dumpSection.StandardOutput);

                    string [] blockIds =
                    {
                        "${block_a}",
                        "${block_b}",
                        "${block_c}",
                        "${block_d}"
                    };

                    foreach (Match match in regExMatches)
                    {
                        foreach (string block in blockIds)
                        {
                            string blockData = match.Result(block);

                            if (!string.IsNullOrWhiteSpace(blockData))
                            {
                                for (int i = 0; i < blockData.Length; i += 2)
                                {
                                    string hexComponent = blockData.Substring(i, 2);

                                    dumpContent.Append(Convert.ToChar(Convert.ToUInt32(hexComponent, 16)));
                                }
                            }
                        }
                    }

                    return(dumpContent.ToString());
                }
            }

            return(null);
        }
Example #10
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public GdbSetup (AndroidProcess process, string gdbToolPath)
    {
      LoggingUtils.PrintFunction ();

      Process = process;

      Host = "localhost";

      Port = 5039;

      if (!Process.HostDevice.IsOverWiFi)
      {
        Socket = "debug-socket";
      }

      string sanitisedDeviceId = Process.HostDevice.ID.Replace (':', '-');

      CacheDirectory = string.Format (@"{0}\Android++\Cache\{1}\{2}", Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), sanitisedDeviceId, Process.Name);

      Directory.CreateDirectory (CacheDirectory);

      CacheSysRoot = Path.Combine (CacheDirectory, "sysroot");

      Directory.CreateDirectory (CacheSysRoot);

      SymbolDirectories = new HashSet<string> ();

      GdbToolPath = gdbToolPath;

      GdbToolArguments = "--interpreter=mi ";

      if (!File.Exists (gdbToolPath))
      {
        throw new FileNotFoundException ("Could not find requested GDB instance. Expected: " + gdbToolPath);
      }

      // 
      // Spawn an initial GDB instance to evaluate the client version.
      // 

      GdbToolVersionMajor = 1;

      GdbToolVersionMinor = 0;

      using (SyncRedirectProcess gdbProcess = new SyncRedirectProcess (GdbToolPath, "--version"))
      {
        gdbProcess.StartAndWaitForExit ();

        string [] versionDetails = gdbProcess.StandardOutput.Replace ("\r", "").Split (new char [] { '\n' });

        string versionPrefix = "GNU gdb (GDB) ";

        for (int i = 0; i < versionDetails.Length; ++i)
        {
          if (versionDetails [i].StartsWith (versionPrefix))
          {
            string gdbVersion = versionDetails [i].Substring (versionPrefix.Length); ;

            string [] gdbVersionComponents = gdbVersion.Split ('.');

            if (gdbVersionComponents.Length > 0)
            {
              GdbToolVersionMajor = int.Parse (gdbVersionComponents [0]);
            }

            if (gdbVersionComponents.Length > 1)
            {
              GdbToolVersionMinor = int.Parse (gdbVersionComponents [1]);
            }

            break;
          }
        }
      }
    }
        public LaunchConfiguration GetLaunchConfigurationFromProjectProperties(IDictionary<string, string> projectProperties)
        {
            LoggingUtils.PrintFunction ();

              //
              // Retrieve standard project macro values, and determine the preferred debugger configuration.
              //

              string projectTargetName = EvaluateProjectProperty (projectProperties, "ConfigurationGeneral", "TargetName");

              string projectProjectDir = EvaluateProjectProperty (projectProperties, "ConfigurationGeneral", "ProjectDir");

              string debuggerMode = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigMode");

              string debuggerTargetApk = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigTargetApk");

              string debuggerUpToDateCheck = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigUpToDateCheck");

              string debuggerLaunchActivity = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigLaunchActivity");

              string debuggerDebugMode = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigDebugMode");

              string debuggerOpenGlTrace = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigOpenGlTrace");

              string debuggerKeepAppData = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigKeepAppData");

              string debuggerInstallerPackage = EvaluateProjectProperty (projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigInstallerPackage");

              if (string.IsNullOrEmpty (debuggerMode))
              {
            debuggerMode = "Custom";
              }
              else if (debuggerMode.Equals ("vs-android"))
              {
            //
            // Support for vs-android.
            //

            string antBuildPath = EvaluateProjectProperty (projectProperties, "AntBuild", "AntBuildPath");

            string antBuildType = EvaluateProjectProperty (projectProperties, "AntBuild", "AntBuildType");

            string antBuildXml = Path.Combine (antBuildPath, "build.xml");

            XmlDocument buildXmlDocument = new XmlDocument ();

            buildXmlDocument.Load (antBuildXml);

            string antBuildXmlProjectName = buildXmlDocument.DocumentElement.GetAttribute ("name");

            debuggerTargetApk = Path.Combine (antBuildPath, "bin", string.Format (CultureInfo.InvariantCulture, "{0}-{1}.apk", antBuildXmlProjectName, antBuildType));
              }

              //
              // Ensure the provided target APK is found and absolute.
              //

              if (string.IsNullOrEmpty (debuggerTargetApk))
              {
            throw new FileNotFoundException ("Could not locate target application. Empty path provided.");
              }
              else if (!Path.IsPathRooted (debuggerTargetApk) && !string.IsNullOrWhiteSpace (projectProjectDir))
              {
            debuggerTargetApk = Path.Combine (projectProjectDir, debuggerTargetApk);
              }

              if (!Path.IsPathRooted (debuggerTargetApk))
              {
            throw new InvalidOperationException ("Could not evaluate an absolute path to the target application. Tried: " + debuggerTargetApk);
              }

              debuggerTargetApk = Path.GetFullPath (debuggerTargetApk); // normalises relative paths.

              if (!File.Exists (debuggerTargetApk))
              {
            throw new FileNotFoundException ("Could not find required target application. Expected: " + debuggerTargetApk);
              }

              //
              // Find the selected Android SDK (and associated build-tools) deployment.
              //

              string androidSdkRoot = EvaluateProjectProperty (projectProperties, "ConfigurationGeneral", "AndroidSdkRoot");

              if (string.IsNullOrWhiteSpace (androidSdkRoot))
              {
            throw new DirectoryNotFoundException ("Could not locate Android SDK. \"AndroidSdkRoot\" property is empty.");
              }
              else if (!Directory.Exists (androidSdkRoot))
              {
            throw new DirectoryNotFoundException ("Could not locate Android SDK. \"AndroidSdkRoot\" property references a directory which does not exist. Expected: " + androidSdkRoot);
              }

              string androidSdkBuildToolsVersion = EvaluateProjectProperty (projectProperties, "ConfigurationGeneral", "AndroidSdkBuildToolsVersion");

              string androidSdkBuildToolsPath = Path.Combine (androidSdkRoot, "build-tools", androidSdkBuildToolsVersion);

              if (!Directory.Exists (androidSdkBuildToolsPath))
              {
            throw new DirectoryNotFoundException (string.Format (CultureInfo.CurrentCulture, "Could not locate Android SDK build-tools (v{0}). Expected: {1}", androidSdkBuildToolsVersion, androidSdkBuildToolsPath));
              }

              //
              // Spawn a AAPT.exe instance to gain some extra information about the APK we are trying to load.
              //

              string applicationPackageName = string.Empty;

              string applicationLaunchActivity = string.Empty;

              string aaptToolPath = Path.Combine (androidSdkBuildToolsPath, "aapt.exe");

              if (!File.Exists (aaptToolPath))
              {
            throw new FileNotFoundException ("Could not locate AAPT tool (under Android SDK build-tools).", aaptToolPath);
              }

              using (SyncRedirectProcess getApkDetails = new SyncRedirectProcess (aaptToolPath, "dump --values badging " + PathUtils.SantiseWindowsPath (debuggerTargetApk)))
              {
            int exitCode = getApkDetails.StartAndWaitForExit ();

            if (exitCode != 0)
            {
              throw new InvalidOperationException ("AAPT failed to dump required application badging information. Exit-code: " + exitCode);
            }

            string [] apkDetails = getApkDetails.StandardOutput.Replace ("\r", "").Split (new char [] { '\n' });

            foreach (string singleLine in apkDetails)
            {
              if (singleLine.StartsWith ("package: ", StringComparison.OrdinalIgnoreCase))
              {
            //
            // Retrieve package name from format: "package: name='com.example.hellogdbserver' versionCode='1' versionName='1.0'"
            //

            string [] packageData = singleLine.Substring ("package: ".Length).Split (' ');

            foreach (string data in packageData)
            {
              if (data.StartsWith ("name=", StringComparison.OrdinalIgnoreCase))
              {
                applicationPackageName = data.Substring ("name=".Length).Trim ('\'');
              }
            }
              }
              else if (singleLine.StartsWith ("launchable-activity: ", StringComparison.OrdinalIgnoreCase))
              {
            string [] launchActivityData = singleLine.Substring ("launchable-activity: ".Length).Split (' ');

            foreach (string data in launchActivityData)
            {
              if (data.StartsWith ("name=", StringComparison.OrdinalIgnoreCase))
              {
                applicationLaunchActivity = data.Substring ("name=".Length).Trim ('\'');
              }
            }
              }
            }
              }

              //
              // If a specific launch activity was not requested, ensure that the default one is referenced.
              //

              if (string.IsNullOrEmpty (debuggerLaunchActivity))
              {
            debuggerLaunchActivity = applicationLaunchActivity;
              }

              LaunchConfiguration launchConfig = new LaunchConfiguration ();

              launchConfig ["TargetApk"] = debuggerTargetApk;

              launchConfig ["UpToDateCheck"] = debuggerUpToDateCheck;

              launchConfig ["PackageName"] = applicationPackageName;

              launchConfig ["LaunchActivity"] = debuggerLaunchActivity;

              launchConfig ["DebugMode"] = debuggerDebugMode;

              launchConfig ["OpenGlTrace"] = debuggerOpenGlTrace;

              launchConfig ["KeepAppData"] = debuggerKeepAppData;

              launchConfig ["InstallerPackage"] = debuggerInstallerPackage;

              return launchConfig;
        }
Example #12
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public GdbSetup(AndroidProcess process, string gdbToolPath)
        {
            LoggingUtils.PrintFunction ();

              Process = process;

              Host = "localhost";

              Port = 5039;

              if (!Process.HostDevice.IsOverWiFi)
              {
            Socket = "debug-socket";
              }

              string sanitisedDeviceId = Process.HostDevice.ID.Replace (':', '-');

              CacheDirectory = string.Format (@"{0}\Android++\Cache\{1}\{2}", Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), sanitisedDeviceId, Process.Name);

              Directory.CreateDirectory (CacheDirectory);

              CacheSysRoot = Path.Combine (CacheDirectory, "sysroot");

              Directory.CreateDirectory (CacheSysRoot);

              SymbolDirectories = new HashSet<string> ();

              GdbToolPath = gdbToolPath;

              GdbToolArguments = "--interpreter=mi ";

              if (!File.Exists (gdbToolPath))
              {
            throw new FileNotFoundException ("Could not find requested GDB instance. Expected: " + gdbToolPath);
              }

              //
              // Spawn an initial GDB instance to evaluate the client version.
              //

              GdbToolVersionMajor = 1;

              GdbToolVersionMinor = 0;

              using (SyncRedirectProcess gdbProcess = new SyncRedirectProcess (GdbToolPath, "--version"))
              {
            gdbProcess.StartAndWaitForExit ();

            string [] versionDetails = gdbProcess.StandardOutput.Replace ("\r", "").Split (new char [] { '\n' });

            string versionPrefix = "GNU gdb (GDB) ";

            for (int i = 0; i < versionDetails.Length; ++i)
            {
              if (versionDetails [i].StartsWith (versionPrefix))
              {
            string gdbVersion = versionDetails [i].Substring (versionPrefix.Length); ;

            string [] gdbVersionComponents = gdbVersion.Split ('.');

            if (gdbVersionComponents.Length > 0)
            {
              GdbToolVersionMajor = int.Parse (gdbVersionComponents [0]);
            }

            if (gdbVersionComponents.Length > 1)
            {
              GdbToolVersionMinor = int.Parse (gdbVersionComponents [1]);
            }

            break;
              }
            }
              }
        }
Example #13
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 #14
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public static void Refresh ()
    {
      LoggingUtils.PrintFunction ();

      lock (m_updateLockMutex)
      {
        // 
        // Start an ADB instance, if required.
        // 

        using (SyncRedirectProcess adbStartServer = new SyncRedirectProcess (AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", "start-server"))
        {
          adbStartServer.StartAndWaitForExit (30000);
        }

        using (SyncRedirectProcess adbDevices = new SyncRedirectProcess (AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", "devices"))
        {
          adbDevices.StartAndWaitForExit (30000);

          // 
          // Parse 'devices' output, skipping headers and potential 'start-server' output.
          // 

          Dictionary<string, string> currentAdbDevices = new Dictionary<string, string> ();

          LoggingUtils.Print (string.Format ("[AndroidAdb] Devices output: {0}", adbDevices.StandardOutput));

          if (!String.IsNullOrEmpty (adbDevices.StandardOutput))
          {
            string [] deviceOutputLines = adbDevices.StandardOutput.Replace ("\r", "").Split (new char [] { '\n' });

            foreach (string line in deviceOutputLines)
            {
              if (Regex.IsMatch (line, "^[A-Za-z0-9.:\\-]+[\t][a-z]+$"))
              {
                string [] segments = line.Split (new char [] { '\t' });

                string deviceName = segments [0];

                string deviceType = segments [1];

                currentAdbDevices.Add (deviceName, deviceType);
              }
            }
          }

          // 
          // First identify any previously tracked devices which aren't in 'devices' output.
          // 

          HashSet<string> disconnectedDevices = new HashSet<string> ();

          foreach (string key in m_connectedDevices.Keys)
          {
            string deviceName = (string) key;

            if (!currentAdbDevices.ContainsKey (deviceName))
            {
              disconnectedDevices.Add (deviceName);
            }
          }

          // 
          // Identify whether any devices have changed state; connected/persisted/disconnected.
          // 

          foreach (KeyValuePair <string, string> devicePair in currentAdbDevices)
          {
            string deviceName = devicePair.Key;

            string deviceType = devicePair.Value;

            if (deviceType.Equals ("offline"))
            {
              disconnectedDevices.Add (deviceName);
            }
            else if (deviceType.Equals ("unauthorized"))
            {
              // User needs to allow USB debugging.
            }
            else
            {
              AndroidDevice connectedDevice;

              if (m_connectedDevices.TryGetValue (deviceName, out connectedDevice))
              {
                // 
                // Device is pervasive. Refresh internal properties.
                // 

                LoggingUtils.Print (string.Format ("[AndroidAdb] Device pervaded: {0} - {1}", deviceName, deviceType));

                connectedDevice.Refresh ();

                foreach (IStateListener deviceListener in m_registeredDeviceStateListeners)
                {
                  deviceListener.DevicePervasive (connectedDevice);
                }
              }
              else
              {
                // 
                // Device connected.
                // 

                LoggingUtils.Print (string.Format ("[AndroidAdb] Device connected: {0} - {1}", deviceName, deviceType));

                connectedDevice = new AndroidDevice (deviceName);

                connectedDevice.Refresh ();

                m_connectedDevices.Add (deviceName, connectedDevice);

                foreach (IStateListener deviceListener in m_registeredDeviceStateListeners)
                {
                  deviceListener.DeviceConnected (connectedDevice);
                }
              }
            }
          }

          // 
          // Finally, handle device disconnection.
          // 

          foreach (string deviceName in disconnectedDevices)
          {
            AndroidDevice disconnectedDevice;

            if (m_connectedDevices.TryGetValue (deviceName, out disconnectedDevice))
            {
              LoggingUtils.Print (string.Format ("[AndroidAdb] Device disconnected: {0}", deviceName));

              m_connectedDevices.Remove (deviceName);

              foreach (IStateListener deviceListener in m_registeredDeviceStateListeners)
              {
                deviceListener.DeviceDisconnected (disconnectedDevice);
              }
            }
          }
        }
      }
    }
Example #15
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static void Refresh()
        {
            LoggingUtils.PrintFunction();

            lock (m_updateLockMutex)
            {
                //
                // Start an ADB instance, if required.
                //

                using (SyncRedirectProcess adbStartServer = new SyncRedirectProcess(AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", "start-server"))
                {
                    adbStartServer.StartAndWaitForExit(30000);
                }

                using (SyncRedirectProcess adbDevices = new SyncRedirectProcess(AndroidSettings.SdkRoot + @"\platform-tools\adb.exe", "devices"))
                {
                    adbDevices.StartAndWaitForExit(30000);

                    //
                    // Parse 'devices' output, skipping headers and potential 'start-server' output.
                    //

                    Dictionary <string, string> currentAdbDevices = new Dictionary <string, string> ();

                    LoggingUtils.Print(string.Concat("[AndroidAdb] Devices output: ", adbDevices.StandardOutput));

                    if (!String.IsNullOrEmpty(adbDevices.StandardOutput))
                    {
                        string [] deviceOutputLines = adbDevices.StandardOutput.Replace("\r", "").Split(new char [] { '\n' });

                        foreach (string line in deviceOutputLines)
                        {
                            if (Regex.IsMatch(line, "^[A-Za-z0-9.:\\-]+[\t][A-Za-z]+$"))
                            {
                                string [] segments = line.Split(new char [] { '\t' });

                                string deviceName = segments [0];

                                string deviceType = segments [1];

                                currentAdbDevices.Add(deviceName, deviceType);
                            }
                        }
                    }

                    //
                    // First identify any previously tracked devices which aren't in 'devices' output.
                    //

                    HashSet <string> disconnectedDevices = new HashSet <string> ();

                    foreach (string key in m_connectedDevices.Keys)
                    {
                        string deviceName = (string)key;

                        if (!currentAdbDevices.ContainsKey(deviceName))
                        {
                            disconnectedDevices.Add(deviceName);
                        }
                    }

                    //
                    // Identify whether any devices have changed state; connected/persisted/disconnected.
                    //

                    foreach (KeyValuePair <string, string> devicePair in currentAdbDevices)
                    {
                        string deviceName = devicePair.Key;

                        string deviceType = devicePair.Value;

                        if (deviceType.Equals("offline", StringComparison.InvariantCultureIgnoreCase))
                        {
                            disconnectedDevices.Add(deviceName);
                        }
                        else if (deviceType.Equals("unauthorized", StringComparison.InvariantCultureIgnoreCase))
                        {
                            // User needs to allow USB debugging.
                        }
                        else
                        {
                            AndroidDevice connectedDevice;

                            if (m_connectedDevices.TryGetValue(deviceName, out connectedDevice))
                            {
                                //
                                // Device is pervasive. Refresh internal properties.
                                //

                                LoggingUtils.Print(string.Format("[AndroidAdb] Device pervaded: {0} - {1}", deviceName, deviceType));

                                connectedDevice.Refresh();

                                foreach (IStateListener deviceListener in m_registeredDeviceStateListeners)
                                {
                                    deviceListener.DevicePervasive(connectedDevice);
                                }
                            }
                            else
                            {
                                //
                                // Device connected.
                                //

                                LoggingUtils.Print(string.Format("[AndroidAdb] Device connected: {0} - {1}", deviceName, deviceType));

                                connectedDevice = new AndroidDevice(deviceName);

                                connectedDevice.Refresh();

                                m_connectedDevices.Add(deviceName, connectedDevice);

                                foreach (IStateListener deviceListener in m_registeredDeviceStateListeners)
                                {
                                    deviceListener.DeviceConnected(connectedDevice);
                                }
                            }
                        }
                    }

                    //
                    // Finally, handle device disconnection.
                    //

                    foreach (string deviceName in disconnectedDevices)
                    {
                        AndroidDevice disconnectedDevice;

                        if (m_connectedDevices.TryGetValue(deviceName, out disconnectedDevice))
                        {
                            LoggingUtils.Print(string.Concat("[AndroidAdb] Device disconnected: ", deviceName));

                            m_connectedDevices.Remove(deviceName);

                            foreach (IStateListener deviceListener in m_registeredDeviceStateListeners)
                            {
                                deviceListener.DeviceDisconnected(disconnectedDevice);
                            }
                        }
                    }
                }
            }
        }
Example #16
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public string Pull(string remotePath, string localPath)
        {
            LoggingUtils.PrintFunction();

            try
            {
                //
                // Check if the remote path is a symbolic link, and adjust the target file.
                // (ADB Pull doesn't follow these links)
                //

                try
                {
                    string readlink = Shell("readlink", remotePath).Replace("\r", "").Replace("\n", "");

                    if (readlink.StartsWith("/")) // absolute path link
                    {
                        remotePath = readlink;
                    }
                    else // relative path link
                    {
                        int i = remotePath.LastIndexOf('/');

                        if (i != -1)
                        {
                            string parentPath = remotePath.Substring(0, i);

                            string file = remotePath.Substring(i + 1);

                            remotePath = parentPath + '/' + file;
                        }
                    }
                }
                catch (Exception)
                {
                    // Ignore. Not a relative link.
                }

                //
                // Pull the requested file.
                //

                int exitCode = -1;

                using (SyncRedirectProcess process = AndroidAdb.AdbCommand(this, "pull", string.Format("{0} {1}", remotePath, PathUtils.QuoteIfNeeded(localPath))))
                {
                    exitCode = process.StartAndWaitForExit();

                    if (exitCode != 0)
                    {
                        throw new InvalidOperationException(string.Format("[pull] returned error code: {0}", exitCode));
                    }

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

                throw new InvalidOperationException("[pull] failed", e);
            }
        }
Example #17
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public static string GetElfSectionData (string objDumpTool, string elfBinary, string sectionName)
    {
      if (string.IsNullOrWhiteSpace (objDumpTool) || !File.Exists (objDumpTool))
      {
        throw new ArgumentException ("Could not find required objdump tool. Expected: " + objDumpTool);
      }

      if (string.IsNullOrWhiteSpace (elfBinary) || !File.Exists (elfBinary))
      {
        throw new ArgumentException ("Could not find required ELF binary. Expected: " + elfBinary);
      }

      if (string.IsNullOrWhiteSpace (sectionName))
      {
        throw new ArgumentNullException ("sectionName");
      }

      using (SyncRedirectProcess dumpSection = new SyncRedirectProcess (objDumpTool, string.Format ("-s -j {0} {1}", sectionName, elfBinary)))
      {
        int exitCode = dumpSection.StartAndWaitForExit ();

        if (exitCode == 0)
        {
          StringBuilder dumpContent = new StringBuilder ();

          string dumpRegExPattern = " ([0-9a-fA-F]+) (?<block_a>[0-9a-fA-F]*) (?<block_b>[0-9a-fA-F]*) (?<block_c>[0-9a-fA-F]*) (?<block_d>[0-9a-fA-F]*)";

          Regex regExMatcher = new Regex (dumpRegExPattern, RegexOptions.Compiled);

          MatchCollection regExMatches = regExMatcher.Matches (dumpSection.StandardOutput);

          string [] blockIds = 
          {
            "${block_a}",
            "${block_b}",
            "${block_c}",
            "${block_d}"
          };

          foreach (Match match in regExMatches)
          {
            foreach (string block in blockIds)
            {
              string blockData = match.Result (block);

              if (!string.IsNullOrWhiteSpace (blockData))
              {
                for (int i = 0; i < blockData.Length; i += 2)
                {
                  string hexComponent = blockData.Substring (i, 2);

                  dumpContent.Append (Convert.ToChar (Convert.ToUInt32 (hexComponent, 16)));
                }
              }
            }
          }

          return dumpContent.ToString ();
        }
      }

      return null;
    }