Esempio n. 1
0
        public string MapCygwinToWindows(string origCygwinPath)
        {
            if (!(_debuggedProcess.LaunchOptions is LocalLaunchOptions))
            {
                return(origCygwinPath);
            }

            LocalLaunchOptions localLaunchOptions = (LocalLaunchOptions)_debuggedProcess.LaunchOptions;

            string cygwinPath = origCygwinPath.Replace('\\', '/');

            string windowsPath = cygwinPath;

            lock (_cygwinToWindows)
            {
                if (!_cygwinToWindows.TryGetValue(cygwinPath, out windowsPath))
                {
                    if (!LaunchCygPathAndReadResult(cygwinPath, localLaunchOptions.MIDebuggerPath, out windowsPath))
                    {
                        return(origCygwinPath);
                    }

                    _cygwinToWindows.Add(cygwinPath, windowsPath);
                }
            }

            return(windowsPath);
        }
Esempio n. 2
0
        /// <summary>
        /// Compilation test, do not execute.
        /// Verify that types relied upon by launcher extensions are exported by MIEngine in current build.
        /// Don't change this test without checking with C++ team.
        /// </summary>
        public void VerifyCoreApisPresent()
        {
            LaunchOptions launchOptions = new LocalLaunchOptions("/usr/bin/gdb", "10.10.10.10:2345");

            launchOptions.ExePath = @"c:\users\me\myapp.out";
            launchOptions.AdditionalSOLibSearchPath = @"c:\temp;e:\foo\bar";
            launchOptions.TargetArchitecture        = TargetArchitecture.ARM;
            launchOptions.WorkingDirectory          = "/home/user";
            launchOptions.DebuggerMIMode            = MIMode.Gdb;
            launchOptions.WaitDynamicLibLoad        = false;
            launchOptions.VisualizerFile            = @"c:\myproject\file.natvis";
            launchOptions.SourceMap   = new ReadOnlyCollection <SourceMapEntry>(new List <SourceMapEntry>());
            launchOptions.Environment = new ReadOnlyCollection <EnvironmentEntry>(new List <EnvironmentEntry>());
            Microsoft.DebugEngineHost.HostConfigurationStore configStore = null;
            IDeviceAppLauncherEventCallback eventCallback = null;
            IPlatformAppLauncher            iLauncher     = null;
            IPlatformAppLauncherSerializer  iSerializer   = null;

            iLauncher.Initialize(configStore, eventCallback);
            iLauncher.OnResume();
            iLauncher.SetLaunchOptions(string.Empty, string.Empty, string.Empty, (object)null, TargetEngine.Native);
            iLauncher.SetupForDebugging(out launchOptions);
            iLauncher.Dispose();
            XmlSerializer serializer = iSerializer.GetXmlSerializer("foobar");
        }
Esempio n. 3
0
        void IPlatformAppLauncher.SetupForDebugging(out LaunchOptions result)
        {
            if (_launchOptions == null)
            {
                Debug.Fail("Why is SetupForDebugging being called before ParseLaunchOptions?");
                throw new InvalidOperationException();
            }

            ManualResetEvent doneEvent  = new ManualResetEvent(false);
            var cancellationTokenSource = new CancellationTokenSource();
            ExceptionDispatchInfo exceptionDispatchInfo = null;
            LocalLaunchOptions    localLaunchOptions    = null;

            _waitLoop = new MICore.WaitLoop(LauncherResources.WaitDialogText);

            // Do the work on a worker thread to avoid blocking the UI. Use ThreadPool.QueueUserWorkItem instead
            // of Task.Run to avoid needing to unwrap the AggregateException.
            ThreadPool.QueueUserWorkItem((object o) =>
            {
                string launchErrorTelemetryResult = null;

                try
                {
                    localLaunchOptions         = SetupForDebuggingWorker(cancellationTokenSource.Token);
                    launchErrorTelemetryResult = "None";
                }
                catch (Exception e)
                {
                    exceptionDispatchInfo = ExceptionDispatchInfo.Capture(e);
                    if (!(e is OperationCanceledException))
                    {
                        launchErrorTelemetryResult = Telemetry.GetLaunchErrorResultValue(e);
                    }
                }

                doneEvent.Set();

                if (launchErrorTelemetryResult != null)
                {
                    Telemetry.SendLaunchError(launchErrorTelemetryResult);
                }
            }
                                         );

            _waitLoop.Wait(doneEvent, cancellationTokenSource);

            if (exceptionDispatchInfo != null)
            {
                exceptionDispatchInfo.Throw();
            }
            if (localLaunchOptions == null)
            {
                Debug.Fail("No result provided? Should be impossible.");
                throw new InvalidOperationException();
            }

            result = localLaunchOptions;
        }
Esempio n. 4
0
        public override async Task LaunchAsync(DebugLaunchOptions launchOptions)
        {
            // The properties that are available via DebuggerProperties are determined by the property XAML files in your project.
            var debuggerProperties = await this.DebuggerProperties.GetMocheDebuggerPropertiesAsync();

            LocalLaunchOptions llo = new LocalLaunchOptions();

            llo.ExePath = await debuggerProperties.LocalDebuggerCommand.GetEvaluatedValueAtEndAsync();

            llo.ExeArguments = await debuggerProperties.LocalDebuggerCommandArguments.GetEvaluatedValueAtEndAsync();

            llo.WorkingDirectory = await debuggerProperties.LocalDebuggerWorkingDirectory.GetEvaluatedValueAtEndAsync();

            llo.MIDebuggerPath = await debuggerProperties.LocalDebuggerPath.GetEvaluatedValueAtEndAsync();

            MIMode miMode;

            if (Enum.TryParse(await debuggerProperties.LocalDebuggerType.GetEvaluatedValueAtEndAsync(), out miMode))
            {
                llo.MIMode          = miMode;
                llo.MIModeSpecified = true;
            }
            if (llo.ExePath == null)
            {
                var generalProperties = await this.DebuggerProperties.GetConfigurationGeneralPropertiesAsync();

                llo.ExePath = await generalProperties.TargetPath.GetEvaluatedValueAtEndAsync();
            }

            IVsDebugger4 debugger = (IVsDebugger4)ServiceProvider.GetService(typeof(IVsDebugger));

            VsDebugTargetInfo4[] debugTargets = new VsDebugTargetInfo4[1];
            debugTargets[0].dlo     = (uint)DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;
            debugTargets[0].bstrExe = llo.MIDebuggerPath;
            using (MemoryStream s = new MemoryStream())
            {
                new System.Xml.Serialization.XmlSerializer(typeof(LocalLaunchOptions)).Serialize(s, llo);
                s.Flush();
                s.Seek(0, SeekOrigin.Begin);
                debugTargets[0].bstrOptions = await new StreamReader(s).ReadToEndAsync();
            }
            debugTargets[0].guidLaunchDebugEngine = Microsoft.MIDebugEngine.EngineConstants.EngineId;
            VsDebugTargetProcessInfo[] processInfo = new VsDebugTargetProcessInfo[debugTargets.Length];

            debugger.LaunchDebugTargets4(1, debugTargets, processInfo);
        }
Esempio n. 5
0
        static internal LocalLaunchOptions CreateFromXml(Xml.LaunchOptions.LocalLaunchOptions source)
        {
            string miDebuggerPath = source.MIDebuggerPath;

            // If no path to the debugger was specified, look for the proper binary in the user's $PATH
            if (String.IsNullOrEmpty(miDebuggerPath))
            {
                string debuggerBinary = null;
                switch (source.MIMode)
                {
                    case Xml.LaunchOptions.MIMode.gdb:
                        debuggerBinary = "gdb";
                        break;

                    case Xml.LaunchOptions.MIMode.lldb:
                        debuggerBinary = "lldb-mi";
                        break;
                }

                if (!String.IsNullOrEmpty(debuggerBinary))
                {
                    miDebuggerPath = LocalLaunchOptions.ResolveFromPath(debuggerBinary);
                }

                if (String.IsNullOrEmpty(miDebuggerPath))
                {
                    throw new InvalidLaunchOptionsException(MICoreResources.Error_NoMiDebuggerPath);
                }
            }

            var options = new LocalLaunchOptions(
                RequireAttribute(miDebuggerPath, "MIDebuggerPath"),
                source.MIDebuggerServerAddress,
                source.Environment);
            options.InitializeCommonOptions(source);
            options.InitializeServerOptions(source);
            options._useExternalConsole = source.ExternalConsole;

            // when using local options the core dump path must check out
            if (options.IsCoreDump && !LocalLaunchOptions.CheckFilePath(options.CoreDumpPath))
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, MICoreResources.Error_InvalidLocalExePath, options.CoreDumpPath));

            return options;
        }
Esempio n. 6
0
        static internal LocalLaunchOptions CreateFromXml(Xml.LaunchOptions.LocalLaunchOptions source)
        {
            var options = new LocalLaunchOptions(
                RequireAttribute(source.MIDebuggerPath, "MIDebuggerPath"),
                source.MIDebuggerServerAddress,
                source.ProcessId,
                source.Environment);
            options.InitializeCommonOptions(source);

            return options;
        }
Esempio n. 7
0
        private LaunchOptions SetupForDebuggingWorker(CancellationToken token)
        {
            CancellationTokenRegistration onCancelRegistration = token.Register(() =>
            {
                _gdbServerExecCancellationSource.Cancel();
            });

            using (onCancelRegistration)
            {
                // TODO: Adb exception messages should be improved. Example, if ADB is not started, this is returned:
                //    +		[libadb.AdbException]	{"Could not connect to the adb.exe server. See InnerException for details."}	libadb.AdbException
                // 'See InnerException for details.' should not be there. It should just add the inner exception message:
                //    [System.Net.Sockets.SocketException]	{"No connection could be made because the target machine actively refused it 127.0.0.1:5037"}	System.Net.Sockets.SocketException

                Device device                     = null;
                string workingDirectory           = null;
                string gdbServerRemotePath        = null;
                string gdbServerSocketDescription = null;
                string exePath                    = null;
                Task   taskGdbServer              = null;
                int    gdbPortNumber              = 0;
                int    progressCurrentIndex       = 0;
                int    progressStepCount          = 0;

                List <NamedAction> actions = new List <NamedAction>();

                actions.Add(new NamedAction(LauncherResources.Step_ResolveInstallPaths, () =>
                {
                    _installPaths = InstallPaths.Resolve(token, _launchOptions);
                }));

                actions.Add(new NamedAction(LauncherResources.Step_ConnectToDevice, () =>
                {
                    Adb adb;
                    try
                    {
                        adb = new Adb(_installPaths.SDKRoot);
                    }
                    catch (ArgumentException)
                    {
                        throw new LauncherException(Telemetry.LaunchFailureCode.InvalidAndroidSDK, string.Format(CultureInfo.CurrentCulture, LauncherResources.Error_InvalidAndroidSDK, _installPaths.SDKRoot));
                    }

                    try
                    {
                        adb.Start();
                        device = adb.GetDeviceById(_launchOptions.DeviceId);

                        // There is a rare case, which we have seen it a few times now with the Android emulator where the device will be initially
                        // in the offline state. But after a very short amount of time it comes online. Retry waiting for this.
                        if (device.GetState().HasFlag(DeviceState.Offline))
                        {
                            // Add in an extra progress step and update the dialog
                            progressStepCount++;

                            _waitLoop.SetProgress(progressStepCount, progressCurrentIndex, LauncherResources.Step_WaitingForDeviceToComeOnline);
                            progressCurrentIndex++;

                            const int waitTimePerIteration = 50;
                            const int maxTries             = 5000 / waitTimePerIteration; // We will wait for up to 5 seconds

                            // NOTE: libadb has device discovery built in which we could allegedly use instead of a retry loop,
                            // but I couldn't get this to work (though the problem is so rare, I had a lot of trouble testing it), so just using
                            // a retry loop.
                            for (int cTry = 0; true; cTry++)
                            {
                                if (cTry == maxTries)
                                {
                                    throw new LauncherException(Telemetry.LaunchFailureCode.DeviceOffline, LauncherResources.Error_DeviceOffline);
                                }

                                // Sleep for a little while unless this operation is canceled
                                if (token.WaitHandle.WaitOne(waitTimePerIteration))
                                {
                                    throw new OperationCanceledException();
                                }

                                if (!device.GetState().HasFlag(DeviceState.Offline))
                                {
                                    break; // we are no longer offline
                                }
                            }
                        }
                    }
                    catch (AdbException)
                    {
                        throw new LauncherException(Telemetry.LaunchFailureCode.DeviceNotResponding, LauncherResources.Error_DeviceNotResponding);
                    }
                }));

                actions.Add(new NamedAction(LauncherResources.Step_InspectingDevice, () =>
                {
                    try
                    {
                        DeviceAbi[] allowedAbis;
                        switch (_launchOptions.TargetArchitecture)
                        {
                        case TargetArchitecture.ARM:
                            allowedAbis = new DeviceAbi[] { DeviceAbi.armeabi, DeviceAbi.armeabiv7a };
                            break;

                        case TargetArchitecture.ARM64:
                            allowedAbis = new DeviceAbi[] { DeviceAbi.arm64v8a };
                            break;

                        case TargetArchitecture.X86:
                            allowedAbis = new DeviceAbi[] { DeviceAbi.x86 };
                            break;

                        case TargetArchitecture.X64:
                            allowedAbis = new DeviceAbi[] { DeviceAbi.x64 };
                            break;

                        default:
                            Debug.Fail("New target architucture support added without updating this code???");
                            throw new InvalidOperationException();
                        }

                        if (!DoesDeviceSupportAnyAbi(device, allowedAbis))
                        {
                            throw GetBadDeviceAbiException(device.Abi);
                        }

                        if (_launchOptions.TargetArchitecture == TargetArchitecture.ARM && device.IsEmulator)
                        {
                            _isUsingArmEmulator = true;
                        }

                        _shell = device.Shell;
                    }
                    catch (AdbException)
                    {
                        throw new LauncherException(Telemetry.LaunchFailureCode.DeviceNotResponding, LauncherResources.Error_DeviceNotResponding);
                    }

                    VerifySdkVersion();

                    if (_targetEngine == TargetEngine.Native)
                    {
                        string pwdCommand = string.Concat("run-as ", _launchOptions.Package, " /system/bin/sh -c pwd");
                        ExecCommand(pwdCommand);
                        workingDirectory    = PwdOutputParser.ExtractWorkingDirectory(_shell.Out, _launchOptions.Package);
                        gdbServerRemotePath = GetGdbServerPath(workingDirectory);

                        KillOldInstances(gdbServerRemotePath);
                    }
                }));

                if (!_launchOptions.IsAttach)
                {
                    actions.Add(new NamedAction(LauncherResources.Step_StartingApp, () =>
                    {
                        string activateCommand = string.Concat("am start -D -n ", _launchOptions.Package, "/", _launchOptions.LaunchActivity);
                        ExecCommand(activateCommand);
                        ValidateActivityManagerOutput(activateCommand, _shell.Out);
                    }));
                }

                actions.Add(new NamedAction(LauncherResources.Step_GettingAppProcessId, () =>
                {
                    _appProcessId = GetAppProcessId();
                }));

                if (_targetEngine == TargetEngine.Native)
                {
                    actions.Add(new NamedAction(LauncherResources.Step_StartGDBServer, () =>
                    {
                        // We will default to using a unix socket with gdbserver as this is what the ndk-gdb script uses. Though we have seen
                        // some machines where this doesn't work and we fall back to TCP instead.
                        const bool useUnixSocket = true;

                        taskGdbServer = StartGdbServer(gdbServerRemotePath, workingDirectory, useUnixSocket, out gdbServerSocketDescription);
                    }));
                }

                actions.Add(new NamedAction(LauncherResources.Step_PortForwarding, () =>
                {
                    // TODO: Use a dynamic socket
                    gdbPortNumber  = 5039;
                    _jdbPortNumber = 65534;

                    if (_targetEngine == TargetEngine.Native)
                    {
                        device.Forward(string.Format(CultureInfo.InvariantCulture, "tcp:{0}", gdbPortNumber), gdbServerSocketDescription);
                    }


                    device.Forward(string.Format(CultureInfo.InvariantCulture, "tcp:{0}", _jdbPortNumber), string.Format(CultureInfo.InvariantCulture, "jdwp:{0}", _appProcessId));
                }));

                if (_targetEngine == TargetEngine.Native)
                {
                    actions.Add(new NamedAction(LauncherResources.Step_DownloadingFiles, () =>
                    {
                        //pull binaries from the emulator/device
                        var fileSystem = device.FileSystem;

                        string app_process_suffix = String.Empty;
                        switch (_launchOptions.TargetArchitecture)
                        {
                        case TargetArchitecture.X86:
                        case TargetArchitecture.ARM:
                            app_process_suffix = "32";
                            break;

                        case TargetArchitecture.X64:
                        case TargetArchitecture.ARM64:
                            app_process_suffix = "64";
                            break;

                        default:
                            Debug.Fail("Unsupported Target Architecture!");
                            break;
                        }

                        string app_process = String.Concat("app_process", app_process_suffix);
                        exePath            = Path.Combine(_launchOptions.IntermediateDirectory, app_process);

                        bool retry = false;
                        try
                        {
                            fileSystem.Download(@"/system/bin/" + app_process, exePath, true);
                        }
                        catch (AdbException) when(String.Compare(app_process_suffix, "32", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // Older devices don't have an 'app_process32', only an 'app_process', so retry
                            // NOTE: libadb doesn't have an error code property to verify that this is caused
                            // by the file not being found.
                            retry = true;
                        }

                        if (retry)
                        {
                            app_process = "app_process";
                            exePath     = Path.Combine(_launchOptions.IntermediateDirectory, app_process);
                            fileSystem.Download(@"/system/bin/app_process", exePath, true);
                        }

                        //on 64 bit, 'linker64' is the 64bit version and 'linker' is the 32 bit version
                        string suffix64bit = String.Empty;
                        if (_launchOptions.TargetArchitecture == TargetArchitecture.X64 || _launchOptions.TargetArchitecture == TargetArchitecture.ARM64)
                        {
                            suffix64bit = "64";
                        }

                        string linker = String.Concat("linker", suffix64bit);
                        fileSystem.Download(String.Concat(@"/system/bin/", linker), Path.Combine(_launchOptions.IntermediateDirectory, linker), true);

                        //on 64 bit, libc.so lives in /system/lib64/, on 32 bit it lives in simply /system/lib/
                        fileSystem.Download(@"/system/lib" + suffix64bit + "/libc.so", Path.Combine(_launchOptions.IntermediateDirectory, "libc.so"), true);
                    }));
                }

                progressStepCount = actions.Count;

                foreach (NamedAction namedAction in actions)
                {
                    token.ThrowIfCancellationRequested();

                    _waitLoop.SetProgress(progressStepCount, progressCurrentIndex, namedAction.Name);
                    progressCurrentIndex++;
                    namedAction.Action();
                }

                _waitLoop.SetProgress(progressStepCount, progressStepCount, string.Empty);

                if (_targetEngine == TargetEngine.Native && taskGdbServer.IsCompleted)
                {
                    token.ThrowIfCancellationRequested();
                    throw new LauncherException(Telemetry.LaunchFailureCode.GDBServerFailed, LauncherResources.Error_GDBServerFailed);
                }

                if (_launchOptions.LogcatServiceId != Guid.Empty)
                {
                    _eventCallback.OnCustomDebugEvent(_launchOptions.LogcatServiceId, new Guid(LogcatServiceMessage_SourceId), LogcatServiceMessage_NewProcess, _appProcessId, null);
                }

                LaunchOptions launchOptions = null;
                if (_targetEngine == TargetEngine.Native)
                {
                    launchOptions         = new LocalLaunchOptions(_installPaths.GDBPath, string.Format(CultureInfo.InvariantCulture, ":{0}", gdbPortNumber));
                    launchOptions.ExePath = exePath;
                }
                else
                {
                    launchOptions = new JavaLaunchOptions(_launchOptions.JVMHost, _launchOptions.JVMPort, _launchOptions.SourceRoots, _launchOptions.Package);
                }

                launchOptions.AdditionalSOLibSearchPath = _launchOptions.AdditionalSOLibSearchPath;
                launchOptions.TargetArchitecture        = _launchOptions.TargetArchitecture;
                launchOptions.WorkingDirectory          = _launchOptions.IntermediateDirectory;

                launchOptions.DebuggerMIMode = MIMode.Gdb;

                launchOptions.VisualizerFile = "Microsoft.Android.natvis";

                return(launchOptions);
            }
        }
Esempio n. 8
0
        internal static LocalLaunchOptions CreateFromXml(Xml.LaunchOptions.LocalLaunchOptions source)
        {
            string miDebuggerPath = source.MIDebuggerPath;

            // If no path to the debugger was specified, look for the proper binary in the user's $PATH
            if (String.IsNullOrEmpty(miDebuggerPath))
            {
                string debuggerBinary = null;
                switch (source.MIMode)
                {
                    case Xml.LaunchOptions.MIMode.gdb:
                        debuggerBinary = "gdb";
                        break;

                    case Xml.LaunchOptions.MIMode.lldb:
                        debuggerBinary = "lldb-mi";
                        break;
                }

                if (!String.IsNullOrEmpty(debuggerBinary))
                {
                    miDebuggerPath = LocalLaunchOptions.ResolveFromPath(debuggerBinary);
                }

                if (String.IsNullOrEmpty(miDebuggerPath))
                {
                    throw new InvalidLaunchOptionsException(MICoreResources.Error_NoMiDebuggerPath);
                }
            }

            var options = new LocalLaunchOptions(
                RequireAttribute(miDebuggerPath, "MIDebuggerPath"),
                source.MIDebuggerServerAddress,
                source.ProcessId,
                source.Environment);
            options.InitializeCommonOptions(source);
            options.InitializeServerOptions(source);
            options.CoreDumpPath = source.CoreDumpPath;
            options._useExternalConsole = source.ExternalConsole;

            // Ensure that CoreDumpPath and ProcessId are not specified at the same time
            if (!String.IsNullOrEmpty(source.CoreDumpPath) && source.ProcessId != 0)
                throw new InvalidLaunchOptionsException(String.Format(CultureInfo.InvariantCulture, MICoreResources.Error_CannotSpecifyBoth, nameof(source.CoreDumpPath), nameof(source.ProcessId)));

            return options;
        }
Esempio n. 9
0
        static internal LocalLaunchOptions CreateFromXml(Xml.LaunchOptions.LocalLaunchOptions source)
        {
            var options = new LocalLaunchOptions(
                RequireAttribute(source.MIDebuggerPath, "MIDebuggerPath"),
                source.MIDebuggerServerAddress,
                source.ProcessId,
                source.Environment);
            options.InitializeCommonOptions(source);
            options.InitializeServerOptions(source);
            options.CoreDumpPath = source.CoreDumpPath;

            // Ensure that CoreDumpPath and ProcessId are not specified at the same time
            if (!String.IsNullOrEmpty(source.CoreDumpPath) && source.ProcessId != 0)
                throw new InvalidLaunchOptionsException(String.Format(CultureInfo.InvariantCulture, MICoreResources.Error_CannotSpecifyBoth, nameof(source.CoreDumpPath), nameof(source.ProcessId)));

            return options;
        }