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