Пример #1
0
        private static bool GetManagedTypeInfoForCLSID(HostConfigurationStore configStore, Guid clsid, out string assembly, out string className, out string codeBase)
        {
            assembly = null;
            className = null;
            codeBase = null;

            string keyPath = configStore.RegistryRoot + @"\CLSID\" + clsid.ToString("B");
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(keyPath))
            {
                if (key == null)
                    return false;

                object oAssembly = key.GetValue("Assembly");
                object oClassName = key.GetValue("Class");
                object oCodeBase = key.GetValue("CodeBase");

                if (oAssembly == null || !(oAssembly is string))
                    return false;
                if (oClassName == null || !(oClassName is string))
                    return false;

                // CodeBase is not required, but it is an error if it isn't a string
                if (oCodeBase != null && !(oCodeBase is string))
                    return false;

                assembly = (string)oAssembly;
                className = (string)oClassName;
                codeBase = (string)oCodeBase;

                return true;
            }
        }
Пример #2
0
        void IPlatformAppLauncher.Initialize(HostConfigurationStore configStore, IDeviceAppLauncherEventCallback eventCallback)
        {
            if (configStore == null)
                throw new ArgumentNullException("configStore");
            if (eventCallback == null)
                throw new ArgumentNullException("eventCallback");

            _eventCallback = eventCallback;
            RegistryRoot.Set(configStore.RegistryRoot);
        }
Пример #3
0
 public static void LoadMIDebugLogger(HostConfigurationStore configStore)
 {
     if (s_logger == null)
     {
         s_logger = configStore.GetLogger("EnableMIDebugLogger", "Microsoft.MIDebug.log");
         if (s_logger != null)
         {
             s_isEnabled = true;
         }
     }
 }
Пример #4
0
 public static void LoadMIDebugLogger(HostConfigurationStore configStore)
 {
     if (s_logger == null)
     { 
         if (CmdLogInfo.enabled)
         {   // command configured log file
             s_logger = HostLogger.GetLoggerFromCmd(CmdLogInfo.logFile, CmdLogInfo.logToOutput);
         }
         else
         {   // use default logging
             s_logger = configStore.GetLogger("EnableMIDebugLogger", "Microsoft.MIDebug.log");
         }
         if (s_logger != null)
         {
             s_isEnabled = true;
         }
     }
 }
Пример #5
0
        public static Logger EnsureInitialized(HostConfigurationStore configStore)
        {
            Logger res = new Logger();
            if (!s_isInitialized)
            {
                s_isInitialized = true;
                s_initTime = DateTime.Now;

                LoadMIDebugLogger(configStore);
                res.WriteLine("Initialized log at: " + s_initTime);
            }

            #if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                s_isEnabled = true;
            }
            #endif
            return res;
        }
Пример #6
0
        public static void EnsureInitialized(HostConfigurationStore configStore)
        {
            if (!s_isInitialized)
            {
                s_isInitialized = true;
                s_initTime = DateTime.Now;

                s_logger = configStore.GetLogger("EnableMIDebugLogger", "Microsoft.MIDebug.log");
                if (s_logger != null)
                {
                    s_isEnabled = true;
                }
                WriteLine("Initialized log at: " + s_initTime);
            }

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                s_isEnabled = true;
            }
#endif
        }
Пример #7
0
        /// <summary>
        /// Looks up the specified CLSID in the VS registry and loads it
        /// </summary>
        /// <param name="configStore">Registry root to lookup the type</param>
        /// <param name="clsid">CLSID to CoCreate</param>
        /// <returns>[Optional] loaded object. Null if the type is not registered, or points to a type that doesn't exist</returns>
        public static object VsCoCreateManagedObject(HostConfigurationStore configStore, Guid clsid)
        {
            string assemblyNameString, className, codeBase;
            if (!GetManagedTypeInfoForCLSID(configStore, clsid, out assemblyNameString, out className, out codeBase))
            {
                return null;
            }

            if (codeBase != null && !File.Exists(codeBase))
            {
                return null;
            }

            AssemblyName assemblyName = new AssemblyName(assemblyNameString);
            if (codeBase != null)
            {
                assemblyName.CodeBase = "file:///" + codeBase;
            }

            Assembly assemblyObject = Assembly.Load(assemblyName);
            return assemblyObject.CreateInstance(className);
        }
Пример #8
0
        private static LaunchOptions ExecuteLauncher(HostConfigurationStore configStore, Guid clsidLauncher, string exePath, string args, string dir, object launcherXmlOptions, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine)
        {
            var deviceAppLauncher = (IPlatformAppLauncher)HostLoader.VsCoCreateManagedObject(configStore, clsidLauncher);
            if (deviceAppLauncher == null)
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_LauncherNotFound, clsidLauncher.ToString("B")));
            }

            bool success = false;

            try
            {
                try
                {
                    deviceAppLauncher.Initialize(configStore, eventCallback);
                    deviceAppLauncher.SetLaunchOptions(exePath, args, dir, launcherXmlOptions, targetEngine);
                }
                catch (Exception e) when (!(e is InvalidLaunchOptionsException))
                {
                    throw new InvalidLaunchOptionsException(e.Message);
                }

                LaunchOptions debuggerLaunchOptions;
                deviceAppLauncher.SetupForDebugging(out debuggerLaunchOptions);
                debuggerLaunchOptions.DeviceAppLauncher = deviceAppLauncher;

                success = true;
                return debuggerLaunchOptions;
            }
            finally
            {
                if (!success)
                {
                    deviceAppLauncher.Dispose();
                }
            }
        }
Пример #9
0
        public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, HostConfigurationStore configStore, HostWaitLoop waitLoop = null) : base(launchOptions, engine.Logger)
        {
            uint processExitCode = 0;
            _pendingMessages = new StringBuilder(400);
            _worker = worker;
            _breakpointManager = bpman;
            Engine = engine;
            _libraryLoaded = new List<string>();
            _loadOrder = 0;
            MICommandFactory = MICommandFactory.GetInstance(launchOptions.DebuggerMIMode, this);
            _waitDialog = (MICommandFactory.SupportsStopOnDynamicLibLoad() && launchOptions.WaitDynamicLibLoad) ? new HostWaitDialog(ResourceStrings.LoadingSymbolMessage, ResourceStrings.LoadingSymbolCaption) : null;
            Natvis = new Natvis.Natvis(this, launchOptions.ShowDisplayString);

            // we do NOT have real Win32 process IDs, so we use a guid
            AD_PROCESS_ID pid = new AD_PROCESS_ID();
            pid.ProcessIdType = (int)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID;
            pid.guidProcessId = Guid.NewGuid();
            this.Id = pid;

            SourceLineCache = new SourceLineCache(this);

            _callback = callback;
            _moduleList = new List<DebuggedModule>();
            ThreadCache = new ThreadCache(callback, this);
            Disassembly = new Disassembly(this);
            ExceptionManager = new ExceptionManager(MICommandFactory, _worker, _callback, configStore);

            VariablesToDelete = new List<string>();
            this.ActiveVariables = new List<IVariableInformation>();
            _fileTimestampWarnings = new HashSet<Tuple<string, string>>();

            OutputStringEvent += delegate (object o, string message)
            {
                // We can get messages before we have started the process
                // but we can't send them on until it is
                if (_connected)
                {
                    _callback.OnOutputString(message);
                }
                else
                {
                    _pendingMessages.Append(message);
                }
            };

            LibraryLoadEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs results = args as MICore.Debugger.ResultEventArgs;
                string file = results.Results.TryFindString("host-name");
                if (!string.IsNullOrEmpty(file) && MICommandFactory.SupportsStopOnDynamicLibLoad())
                {
                    _libraryLoaded.Add(file);
                    if (_waitDialog != null)
                    {
                        _waitDialog.ShowWaitDialog(file);
                    }
                }
                else if (this.MICommandFactory.Mode == MIMode.Clrdbg)
                {
                    string id = results.Results.FindString("id");
                    ulong baseAddr = results.Results.FindAddr("base-address");
                    uint size = results.Results.FindUint("size");
                    bool symbolsLoaded = results.Results.FindInt("symbols-loaded") != 0;
                    var module = new DebuggedModule(id, file, baseAddr, size, symbolsLoaded, string.Empty, _loadOrder++);
                    lock (_moduleList)
                    {
                        _moduleList.Add(module);
                    }
                    _callback.OnModuleLoad(module);
                }
                else if (!string.IsNullOrEmpty(file))
                {
                    string addr = results.Results.TryFindString("loaded_addr");
                    if (string.IsNullOrEmpty(addr) || addr == "-")
                    {
                        return; // identifies the exe, not a real load
                    }
                    // generate module 
                    string id = results.Results.TryFindString("name");
                    bool symsLoaded = true;
                    string symPath = null;
                    if (results.Results.Contains("symbols-path"))
                    {
                        symPath = results.Results.FindString("symbols-path");
                        if (string.IsNullOrEmpty(symPath))
                        {
                            symsLoaded = false;
                        }
                    }
                    else
                    {
                        symPath = file;
                    }
                    ulong loadAddr = results.Results.FindAddr("loaded_addr");

                    uint size = results.Results.FindUint("size");
                    if (String.IsNullOrEmpty(id))
                    {
                        id = file;
                    }
                    var module = FindModule(id);
                    if (module == null)
                    {
                        module = new DebuggedModule(id, file, loadAddr, size, symsLoaded, symPath, _loadOrder++);
                        lock (_moduleList)
                        {
                            _moduleList.Add(module);
                        }
                        _callback.OnModuleLoad(module);
                    }
                }
            };

            if (_launchOptions is LocalLaunchOptions)
            {
                LocalLaunchOptions localLaunchOptions = (LocalLaunchOptions)_launchOptions;

                if (!localLaunchOptions.IsValidMiDebuggerPath())
                {
                    throw new Exception(MICoreResources.Error_InvalidMiDebuggerPath);
                }

                if (PlatformUtilities.IsOSX() &&
                    localLaunchOptions.DebuggerMIMode != MIMode.Clrdbg &&
                    localLaunchOptions.DebuggerMIMode != MIMode.Lldb &&
                    !UnixUtilities.IsBinarySigned(localLaunchOptions.MIDebuggerPath))
                {
                    string message = String.Format(CultureInfo.CurrentCulture, ResourceStrings.Warning_DarwinDebuggerUnsigned, localLaunchOptions.MIDebuggerPath);
                    _callback.OnOutputMessage(new OutputMessage(
                        message + Environment.NewLine,
                        enum_MESSAGETYPE.MT_MESSAGEBOX,
                        OutputMessage.Severity.Warning));
                }

                ITransport localTransport = null;
                // For local Linux and OS X launch, use the local Unix transport which creates a new terminal and
                // uses fifos for debugger (e.g., gdb) communication.
                if (this.MICommandFactory.UseExternalConsoleForLocalLaunch(localLaunchOptions) &&
                    (PlatformUtilities.IsLinux() || (PlatformUtilities.IsOSX() && localLaunchOptions.DebuggerMIMode != MIMode.Lldb)))
                {
                    localTransport = new LocalUnixTerminalTransport();

                    // Only need to clear terminal for Linux and OS X local launch
                    _needTerminalReset = (localLaunchOptions.ProcessId == 0 && _launchOptions.DebuggerMIMode == MIMode.Gdb);
                }
                else
                {
                    localTransport = new LocalTransport();
                }

                if (localLaunchOptions.ShouldStartServer())
                {
                    this.Init(
                        new MICore.ClientServerTransport(
                            localTransport,
                            new ServerTransport(killOnClose: true, filterStdout: localLaunchOptions.FilterStdout, filterStderr: localLaunchOptions.FilterStderr)
                        ),
                        _launchOptions);
                }
                else
                {
                    this.Init(localTransport, _launchOptions);
                }

                // Only need to know the debugger pid on Linux and OS X local launch to detect whether
                // the debugger is closed. If the debugger is not running anymore, the response (^exit)
                // to the -gdb-exit command is faked to allow MIEngine to shut down.
                SetDebuggerPid(localTransport.DebuggerPid);
            }
            else if (_launchOptions is PipeLaunchOptions)
            {
                this.Init(new MICore.PipeTransport(), _launchOptions);
            }
            else if (_launchOptions is TcpLaunchOptions)
            {
                this.Init(new MICore.TcpTransport(), _launchOptions);
            }
            else if (_launchOptions is UnixShellPortLaunchOptions)
            {
                this.Init(new MICore.UnixShellPortTransport(), _launchOptions, waitLoop);
            }
            else
            {
                throw new ArgumentOutOfRangeException("LaunchInfo.options");
            }

            MIDebugCommandDispatcher.AddProcess(this);

            // When the debuggee exits, we need to exit the debugger
            ProcessExitEvent += delegate (object o, EventArgs args)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                ResultEventArgs results = args as MICore.Debugger.ResultEventArgs;

                if (results.Results.Contains("exit-code"))
                {
                    // GDB sometimes returns exit codes, which don't fit into uint, like "030000000472".
                    // And we can't throw from here, because it crashes VS.
                    // Full exit code will still usually be reported in the Output window,
                    // but here let's return "uint.MaxValue" just to indicate that something went wrong.
                    if (!uint.TryParse(results.Results.FindString("exit-code"), out processExitCode))
                    {
                        processExitCode = uint.MaxValue;
                    }
                }

                // quit MI Debugger
                if (!this.IsClosed)
                {
                    _worker.PostOperation(CmdExitAsync);
                }
                else
                {
                    // If we are already closed, make sure that something sends program destroy
                    _callback.OnProcessExit(processExitCode);
                }

                if (_waitDialog != null)
                {
                    _waitDialog.EndWaitDialog();
                }
            };

            // When the debugger exits, we tell AD7 we are done
            DebuggerExitEvent += delegate (object o, EventArgs args)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                // this is the last AD7 Event we can ever send
                // Also the transport is closed when this returns
                _callback.OnProcessExit(processExitCode);

                Dispose();
            };

            DebuggerAbortedEvent += delegate (object o, DebuggerAbortedEventArgs eventArgs)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                // The MI debugger process unexpectedly exited.
                _worker.PostOperation(() =>
                    {
                        _engineTelemetry.SendDebuggerAborted(MICommandFactory, GetLastSentCommandName(), eventArgs.ExitCode);

                        // If the MI Debugger exits before we get a resume call, we have no way of sending program destroy. So just let start debugging fail.
                        if (!_connected)
                        {
                            return;
                        }

                        _callback.OnError(string.Concat(eventArgs.Message, " ", ResourceStrings.DebuggingWillAbort));
                        _callback.OnProcessExit(uint.MaxValue);

                        Dispose();
                    });
            };

            ModuleLoadEvent += async delegate (object o, EventArgs args)
            {
                // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported

                if (_needTerminalReset)
                {
                    _needTerminalReset = false;

                    // This is to work around a GDB bug of warning "Failed to set controlling terminal: Operation not permitted"
                    // Reset debuggee terminal after the first module load.
                    await ResetConsole();
                }

                if (this.MICommandFactory.SupportsStopOnDynamicLibLoad() && !_launchOptions.WaitDynamicLibLoad)
                {
                    await CmdAsync("-gdb-set stop-on-solib-events 0", ResultClass.None);
                }

                await this.EnsureModulesLoaded();


                if (_waitDialog != null)
                {
                    _waitDialog.EndWaitDialog();
                }
                if (MICommandFactory.SupportsStopOnDynamicLibLoad())
                {
                    // Do not continue if debugging core dump
                    if (!this.IsCoreDump)
                    {
                        CmdContinueAsync();
                    }
                }
            };

            // When we break we need to gather information
            BreakModeEvent += async delegate (object o, EventArgs args)
            {
                // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported

                StoppingEventArgs results = args as MICore.Debugger.StoppingEventArgs;
                if (_waitDialog != null)
                {
                    _waitDialog.EndWaitDialog();
                }

                if (!this._connected)
                {
                    _initialBreakArgs = results;
                    return;
                }

                try
                {
                    await HandleBreakModeEvent(results, results.AsyncRequest);
                }
                catch (Exception e) when (ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true))
                {
                    if (this.IsStopDebuggingInProgress)
                    {
                        return; // ignore exceptions after the process has exited
                    }

                    string exceptionDescription = EngineUtils.GetExceptionDescription(e);
                    string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_FailedToEnterBreakState, exceptionDescription);
                    _callback.OnError(message);

                    Terminate();
                }
            };

            ErrorEvent += delegate (object o, EventArgs args)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                ResultEventArgs result = (ResultEventArgs)args;
                _callback.OnError(result.Results.FindString("msg"));
            };

            ThreadCreatedEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs result = (ResultEventArgs)args;
                ThreadCache.ThreadCreatedEvent(result.Results.FindInt("id"), result.Results.TryFindString("group-id"));
                _childProcessHandler?.ThreadCreatedEvent(result.Results);
            };

            ThreadExitedEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs result = (ResultEventArgs)args;
                ThreadCache.ThreadExitedEvent(result.Results.FindInt("id"));
            };

            ThreadGroupExitedEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs result = (ResultEventArgs)args;
                ThreadCache.ThreadGroupExitedEvent(result.Results.FindString("id"));
            };

            MessageEvent += (object o, ResultEventArgs args) =>
            {
                OutputMessage outputMessage = DecodeOutputEvent(args.Results);
                if (outputMessage != null)
                {
                    _callback.OnOutputMessage(outputMessage);
                }
            };

            TelemetryEvent += (object o, ResultEventArgs args) =>
            {
                string eventName;
                KeyValuePair<string, object>[] properties;
                if (_engineTelemetry.DecodeTelemetryEvent(args.Results, out eventName, out properties))
                {
                    HostTelemetry.SendEvent(eventName, properties);
                }
            };

            BreakChangeEvent += _breakpointManager.BreakpointModified;
        }
Пример #10
0
        public static LaunchOptions GetInstance(HostConfigurationStore configStore, string exePath, string args, string dir, string options, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine, Logger logger)
        {
            if (string.IsNullOrWhiteSpace(exePath))
            {
                throw new ArgumentNullException("exePath");
            }

            if (string.IsNullOrWhiteSpace(options))
            {
                throw new InvalidLaunchOptionsException(MICoreResources.Error_StringIsNullOrEmpty);
            }

            logger?.WriteTextBlock("LaunchOptions", options);

            LaunchOptions launchOptions      = null;
            Guid          clsidLauncher      = Guid.Empty;
            object        launcherXmlOptions = null;

            try
            {
                XmlSerializer serializer;
                using (XmlReader reader = OpenXml(options))
                {
                    switch (reader.LocalName)
                    {
                    case "LocalLaunchOptions":
                    {
                        serializer = GetXmlSerializer(typeof(Xml.LaunchOptions.LocalLaunchOptions));
                        var xmlLaunchOptions = (Xml.LaunchOptions.LocalLaunchOptions)Deserialize(serializer, reader);
                        launchOptions             = LocalLaunchOptions.CreateFromXml(xmlLaunchOptions);
                        launchOptions.BaseOptions = xmlLaunchOptions;
                    }
                    break;

                    case "PipeLaunchOptions":
                    {
                        serializer = GetXmlSerializer(typeof(Xml.LaunchOptions.PipeLaunchOptions));
                        var xmlLaunchOptions = (Xml.LaunchOptions.PipeLaunchOptions)Deserialize(serializer, reader);
                        launchOptions             = PipeLaunchOptions.CreateFromXml(xmlLaunchOptions);
                        launchOptions.BaseOptions = xmlLaunchOptions;
                    }
                    break;

                    case "TcpLaunchOptions":
                    {
                        serializer = GetXmlSerializer(typeof(Xml.LaunchOptions.TcpLaunchOptions));
                        var xmlLaunchOptions = (Xml.LaunchOptions.TcpLaunchOptions)Deserialize(serializer, reader);
                        launchOptions             = TcpLaunchOptions.CreateFromXml(xmlLaunchOptions);
                        launchOptions.BaseOptions = xmlLaunchOptions;
                    }
                    break;

                    case "IOSLaunchOptions":
                    {
                        serializer         = GetXmlSerializer(typeof(IOSLaunchOptions));
                        launcherXmlOptions = Deserialize(serializer, reader);
                        clsidLauncher      = new Guid("316783D1-1824-4847-B3D3-FB048960EDCF");
                    }
                    break;

                    case "AndroidLaunchOptions":
                    {
                        serializer         = GetXmlSerializer(typeof(AndroidLaunchOptions));
                        launcherXmlOptions = Deserialize(serializer, reader);
                        clsidLauncher      = new Guid("C9A403DA-D3AA-4632-A572-E81FF6301E9B");
                    }
                    break;

                    default:
                    {
                        throw new XmlException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_UnknownXmlElement, reader.LocalName));
                    }
                    }

                    // Read any remaining bits of XML to catch other errors
                    while (reader.NodeType != XmlNodeType.None)
                    {
                        reader.Read();
                    }
                }
            }
            catch (XmlException e)
            {
                throw new InvalidLaunchOptionsException(e.Message);
            }

            if (clsidLauncher != Guid.Empty)
            {
                launchOptions = ExecuteLauncher(configStore, clsidLauncher, exePath, args, dir, launcherXmlOptions, eventCallback, targetEngine, logger);
            }

            if (targetEngine == TargetEngine.Native)
            {
                if (launchOptions.ExePath == null)
                {
                    launchOptions.ExePath = exePath;
                }
            }

            if (string.IsNullOrEmpty(launchOptions.ExeArguments))
            {
                launchOptions.ExeArguments = args;
            }

            if (string.IsNullOrEmpty(launchOptions.WorkingDirectory))
            {
                launchOptions.WorkingDirectory = dir;
            }

            if (launchOptions._setupCommands == null)
            {
                launchOptions._setupCommands = new List <LaunchCommand>(capacity: 0).AsReadOnly();
            }

            launchOptions._initializationComplete = true;
            return(launchOptions);
        }
Пример #11
0
        public static LaunchOptions GetInstance(HostConfigurationStore configStore, string exePath, string args, string dir, string options, bool noDebug, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine, Logger logger)
        {
            if (string.IsNullOrWhiteSpace(exePath))
                throw new ArgumentNullException("exePath");

            if (string.IsNullOrWhiteSpace(options))
                throw new InvalidLaunchOptionsException(MICoreResources.Error_StringIsNullOrEmpty);

            logger?.WriteTextBlock("LaunchOptions", options);

            LaunchOptions launchOptions = null;
            Guid clsidLauncher = Guid.Empty;
            object launcher = null;
            object launcherXmlOptions = null;

            try
            {
                XmlSerializer serializer;
                using (XmlReader reader = OpenXml(options))
                {
                    switch (reader.LocalName)
                    {
                        case "LocalLaunchOptions":
                            {
                                serializer = GetXmlSerializer(typeof(Xml.LaunchOptions.LocalLaunchOptions));
                                var xmlLaunchOptions = (Xml.LaunchOptions.LocalLaunchOptions)Deserialize(serializer, reader);
                                launchOptions = LocalLaunchOptions.CreateFromXml(xmlLaunchOptions);
                                launchOptions.BaseOptions = xmlLaunchOptions;
                            }
                            break;

                        case "PipeLaunchOptions":
                            {
                                serializer = GetXmlSerializer(typeof(Xml.LaunchOptions.PipeLaunchOptions));
                                var xmlLaunchOptions = (Xml.LaunchOptions.PipeLaunchOptions)Deserialize(serializer, reader);
                                launchOptions = PipeLaunchOptions.CreateFromXml(xmlLaunchOptions);
                                launchOptions.BaseOptions = xmlLaunchOptions;
                            }
                            break;

                        case "TcpLaunchOptions":
                            {
                                serializer = GetXmlSerializer(typeof(Xml.LaunchOptions.TcpLaunchOptions));
                                var xmlLaunchOptions = (Xml.LaunchOptions.TcpLaunchOptions)Deserialize(serializer, reader);
                                launchOptions = TcpLaunchOptions.CreateFromXml(xmlLaunchOptions);
                                launchOptions.BaseOptions = xmlLaunchOptions;
                            }
                            break;

                        case "IOSLaunchOptions":
                            {
                                serializer = GetXmlSerializer(typeof(IOSLaunchOptions));
                                launcherXmlOptions = Deserialize(serializer, reader);
                                clsidLauncher = new Guid("316783D1-1824-4847-B3D3-FB048960EDCF");
                            }
                            break;

                        case "AndroidLaunchOptions":
                            {
                                serializer = GetXmlSerializer(typeof(AndroidLaunchOptions));
                                launcherXmlOptions = Deserialize(serializer, reader);
                                clsidLauncher = new Guid("C9A403DA-D3AA-4632-A572-E81FF6301E9B");
                            }
                            break;

                        case "SSHLaunchOptions":
                            {
                                serializer = GetXmlSerializer(typeof(SSHLaunchOptions));
                                launcherXmlOptions = Deserialize(serializer, reader);
                                clsidLauncher = new Guid("7E3052B2-FB42-4E38-B22C-1FD281BD4413");
                            }
                            break;

                        default:
                            {
                                launcher = configStore?.GetCustomLauncher(reader.LocalName);
                                if (launcher == null)
                                {
                                    throw new XmlException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_UnknownXmlElement, reader.LocalName));
                                }
                                if (launcher as IPlatformAppLauncher == null)
                                {
                                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_LauncherNotFound, reader.LocalName));
                                }
                                var deviceAppLauncher = (IPlatformAppLauncherSerializer)launcher;
                                if (deviceAppLauncher == null)
                                {
                                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_LauncherSerializerNotFound, clsidLauncher.ToString("B")));
                                }
                                serializer = deviceAppLauncher.GetXmlSerializer(reader.LocalName);
                                launcherXmlOptions = Deserialize(serializer, reader);
                            }
                            break;
                    }

                    // Read any remaining bits of XML to catch other errors
                    while (reader.NodeType != XmlNodeType.None)
                        reader.Read();
                }
            }
            catch (XmlException e)
            {
                throw new InvalidLaunchOptionsException(e.Message);
            }

            if (clsidLauncher != Guid.Empty)
            {
                launchOptions = ExecuteLauncher(configStore, clsidLauncher, exePath, args, dir, launcherXmlOptions, eventCallback, targetEngine, logger);
            }
            else if (launcher != null)
            {
                launchOptions = ExecuteLauncher(configStore, (IPlatformAppLauncher)launcher, exePath, args, dir, launcherXmlOptions, eventCallback, targetEngine, logger);
            }

            if (targetEngine == TargetEngine.Native)
            {
                if (launchOptions.ExePath == null)
                    launchOptions.ExePath = exePath;
            }

            if (string.IsNullOrEmpty(launchOptions.ExeArguments))
                launchOptions.ExeArguments = args;

            if (string.IsNullOrEmpty(launchOptions.WorkingDirectory))
                launchOptions.WorkingDirectory = dir;

            launchOptions.NoDebug = noDebug;

            if (launchOptions._setupCommands == null)
                launchOptions._setupCommands = new List<LaunchCommand>(capacity: 0).AsReadOnly();

            launchOptions.SetInitializationComplete();
            return launchOptions;
        }
Пример #12
0
 void IPlatformAppLauncher.Initialize(HostConfigurationStore configStore, IDeviceAppLauncherEventCallback eventCallback)
 {
     _callback = eventCallback;
 }
Пример #13
0
 // Kofe debugger depends on this method to generate LaunchOptions
 public static LaunchOptions GetInstance(HostConfigurationStore configStore, string exePath, string args, string dir, string options, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine)
 {
     return GetInstance(configStore, exePath, args, dir, options, eventCallback, targetEngine, null);
 }
Пример #14
0
 // Sets the registry root currently in use by the DE. Different installations of Visual Studio can change where their registry information is stored
 // This allows the debugger to tell the engine where that location is.
 public int SetRegistryRoot(string registryRoot)
 {
     _configStore = new HostConfigurationStore(registryRoot);
     Logger       = Logger.EnsureInitialized(_configStore);
     return(Constants.S_OK);
 }
Пример #15
0
 private static LaunchOptions ExecuteLauncher(HostConfigurationStore configStore, Guid clsidLauncher, string exePath, string args, string dir, object launcherXmlOptions, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine, Logger logger)
 {
     var deviceAppLauncher = (IPlatformAppLauncher)HostLoader.VsCoCreateManagedObject(configStore, clsidLauncher);
     if (deviceAppLauncher == null)
     {
         throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_LauncherNotFound, clsidLauncher.ToString("B")));
     }
     return ExecuteLauncher(configStore, deviceAppLauncher, exePath, args, dir, launcherXmlOptions, eventCallback, targetEngine, logger);
 }
Пример #16
0
        private static LaunchOptions ExecuteLauncher(HostConfigurationStore configStore, IPlatformAppLauncher deviceAppLauncher, string exePath, string args, string dir, object launcherXmlOptions, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine, Logger logger)
        {
            bool success = false;

            try
            {
                try
                {
                    deviceAppLauncher.Initialize(configStore, eventCallback);
                    deviceAppLauncher.SetLaunchOptions(exePath, args, dir, launcherXmlOptions, targetEngine);
                }
                catch (Exception e) when (!(e is InvalidLaunchOptionsException) && ExceptionHelper.BeforeCatch(e, logger, reportOnlyCorrupting: true))
                {
                    throw new InvalidLaunchOptionsException(e.Message);
                }

                LaunchOptions debuggerLaunchOptions;
                deviceAppLauncher.SetupForDebugging(out debuggerLaunchOptions);
                debuggerLaunchOptions.DeviceAppLauncher = deviceAppLauncher;

                success = true;
                return debuggerLaunchOptions;
            }
            finally
            {
                if (!success)
                {
                    deviceAppLauncher.Dispose();
                }
            }
        }
Пример #17
0
        public ExceptionManager(MICommandFactory commandFactory, WorkerThread worker, ISampleEngineCallback callback, /*OPTIONAL*/ HostConfigurationStore configStore)
        {
            Debug.Assert(commandFactory != null, "Missing commandFactory");
            Debug.Assert(worker != null, "Missing worker");
            Debug.Assert(callback != null, "Missing callback");

            _commandFactory = commandFactory;
            _worker = worker;
            _callback = callback;
            _categoryMap = ReadDefaultSettings(configStore);
        }
Пример #18
0
        private ReadOnlyDictionary<Guid, ExceptionCategorySettings> ReadDefaultSettings(HostConfigurationStore configStore)
        {
            Dictionary<Guid, ExceptionCategorySettings> categoryMap = new Dictionary<Guid, ExceptionCategorySettings>();

            IEnumerable<Guid> categories = _commandFactory.GetSupportedExceptionCategories();
            foreach (Guid categoryId in categories)
            {
                string categoryName;
                HostConfigurationSection categoryConfigSection;
                configStore.GetExceptionCategorySettings(categoryId, out categoryConfigSection, out categoryName);

                using (categoryConfigSection)
                {
                    ExceptionCategorySettings categorySettings = new ExceptionCategorySettings(this, categoryConfigSection, categoryName);
                    categoryMap.Add(categoryId, categorySettings);
                }
            }

            return new ReadOnlyDictionary<Guid, ExceptionCategorySettings>(categoryMap);
        }
Пример #19
0
        public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, HostConfigurationStore configStore) : base(launchOptions)
        {
            uint processExitCode = 0;
            _pendingMessages = new StringBuilder(400);
            _worker = worker;
            _breakpointManager = bpman;
            Engine = engine;
            _libraryLoaded = new List<string>();
            _loadOrder = 0;
            MICommandFactory = MICommandFactory.GetInstance(launchOptions.DebuggerMIMode, this);
            _waitDialog = MICommandFactory.SupportsStopOnDynamicLibLoad() ? new HostWaitDialog(ResourceStrings.LoadingSymbolMessage, ResourceStrings.LoadingSymbolCaption) : null;
            Natvis = new Natvis.Natvis(this, launchOptions.ShowDisplayString);

            // we do NOT have real Win32 process IDs, so we use a guid
            AD_PROCESS_ID pid = new AD_PROCESS_ID();
            pid.ProcessIdType = (int)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID;
            pid.guidProcessId = Guid.NewGuid();
            this.Id = pid;

            SourceLineCache = new SourceLineCache(this);

            _callback = callback;
            _moduleList = new List<DebuggedModule>();
            ThreadCache = new ThreadCache(callback, this);
            Disassembly = new Disassembly(this);
            ExceptionManager = new ExceptionManager(MICommandFactory, _worker, _callback, configStore);

            VariablesToDelete = new List<string>();

            OutputStringEvent += delegate (object o, string message)
            {
                // We can get messages before we have started the process
                // but we can't send them on until it is
                if (_connected)
                {
                    _callback.OnOutputString(message);
                }
                else
                {
                    _pendingMessages.Append(message);
                }
            };

            LibraryLoadEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs results = args as MICore.Debugger.ResultEventArgs;
                string file = results.Results.TryFindString("host-name");
                if (!string.IsNullOrEmpty(file) && MICommandFactory.SupportsStopOnDynamicLibLoad())
                {
                    _libraryLoaded.Add(file);
                    if (_waitDialog != null)
                    {
                        _waitDialog.ShowWaitDialog(file);
                    }
                }
                else if (this.MICommandFactory.Mode == MIMode.Clrdbg)
                {
                    string id = results.Results.FindString("id");
                    ulong baseAddr = results.Results.FindAddr("base-address");
                    uint size = results.Results.FindUint("size");
                    bool symbolsLoaded = results.Results.FindInt("symbols-loaded") != 0;
                    var module = new DebuggedModule(id, file, baseAddr, size, symbolsLoaded, string.Empty, _loadOrder++);
                    lock (_moduleList)
                    {
                        _moduleList.Add(module);
                    }
                    _callback.OnModuleLoad(module);
                }
                else if (!string.IsNullOrEmpty(file))
                {
                    string addr = results.Results.TryFindString("loaded_addr");
                    if (string.IsNullOrEmpty(addr) || addr == "-")
                    {
                        return; // identifies the exe, not a real load
                    }
                    // generate module 
                    string id = results.Results.TryFindString("name");
                    bool symsLoaded = true;
                    string symPath = null;
                    if (results.Results.Contains("symbols-path"))
                    {
                        symPath = results.Results.FindString("symbols-path");
                        if (string.IsNullOrEmpty(symPath))
                        {
                            symsLoaded = false;
                        }
                    }
                    else
                    {
                        symPath = file;
                    }
                    ulong loadAddr = results.Results.FindAddr("loaded_addr");

                    uint size = results.Results.FindUint("size");
                    if (String.IsNullOrEmpty(id))
                    {
                        id = file;
                    }
                    var module = FindModule(id);
                    if (module == null)
                    {
                        module = new DebuggedModule(id, file, loadAddr, size, symsLoaded, symPath, _loadOrder++);
                        lock (_moduleList)
                        {
                            _moduleList.Add(module);
                        }
                        _callback.OnModuleLoad(module);
                    }
                }
            };

            if (_launchOptions is LocalLaunchOptions)
            {
                LocalLaunchOptions localLaunchOptions = (LocalLaunchOptions)_launchOptions;
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) &&
                    _launchOptions.DebuggerMIMode == MIMode.Gdb &&
                    String.IsNullOrEmpty(localLaunchOptions.MIDebuggerServerAddress)
                    )
                {
                    // For local linux launch, use the local linux transport which creates a new terminal and uses fifos for gdb communication.
                    // CONSIDER: add new flag and only do this if new terminal is true? Note that setting this to false on linux will cause a deadlock
                    // during debuggee launch
                    if (localLaunchOptions.ShouldStartServer())
                    {
                        this.Init(new MICore.ClientServerTransport
                            (
                                        new LocalLinuxTransport(),
                                        new ServerTransport(killOnClose: true, filterStdout: localLaunchOptions.FilterStdout, filterStderr: localLaunchOptions.FilterStderr)
                                  ), _launchOptions
                            );
                    }
                    else
                    {
                        this.Init(new MICore.LocalLinuxTransport(), _launchOptions);
                    }
                }
                else
                {
                    if (localLaunchOptions.ShouldStartServer())
                    {
                        this.Init(new MICore.ClientServerTransport
                            (
                                        new LocalTransport(),
                                        new ServerTransport(killOnClose: true, filterStdout: localLaunchOptions.FilterStdout, filterStderr: localLaunchOptions.FilterStderr)
                                  ), _launchOptions
                            );
                    }
                    else
                    {
                        this.Init(new MICore.LocalTransport(), _launchOptions);
                    }
                }
            }
            else if (_launchOptions is PipeLaunchOptions)
            {
                this.Init(new MICore.PipeTransport(), _launchOptions);
            }
            else if (_launchOptions is TcpLaunchOptions)
            {
                this.Init(new MICore.TcpTransport(), _launchOptions);
            }
            else
            {
                throw new ArgumentOutOfRangeException("LaunchInfo.options");
            }

            MIDebugCommandDispatcher.AddProcess(this);

            // When the debuggee exits, we need to exit the debugger
            ProcessExitEvent += delegate (object o, EventArgs args)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                ResultEventArgs results = args as MICore.Debugger.ResultEventArgs;

                if (results.Results.Contains("exit-code"))
                {
                    // GDB sometimes returns exit codes, which don't fit into uint, like "030000000472".
                    // And we can't throw from here, because it crashes VS.
                    // Full exit code will still usually be reported in the Output window,
                    // but here let's return "uint.MaxValue" just to indicate that something went wrong.
                    if (!uint.TryParse(results.Results.FindString("exit-code"), out processExitCode))
                    {
                        processExitCode = uint.MaxValue;
                    }
                }

                // quit MI Debugger
                _worker.PostOperation(CmdExitAsync);
                if (_waitDialog != null)
                {
                    _waitDialog.EndWaitDialog();
                }
            };

            // When the debugger exits, we tell AD7 we are done
            DebuggerExitEvent += delegate (object o, EventArgs args)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                // this is the last AD7 Event we can ever send
                // Also the transport is closed when this returns
                _callback.OnProcessExit(processExitCode);

                Dispose();
            };

            DebuggerAbortedEvent += delegate (object o, /*OPTIONAL*/ string debuggerExitCode)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                // The MI debugger process unexpectedly exited.
                _worker.PostOperation(() =>
                    {
                        // If the MI Debugger exits before we get a resume call, we have no way of sending program destroy. So just let start debugging fail.
                        if (!_connected)
                        {
                            return;
                        }

                        string message;
                        if (string.IsNullOrEmpty(debuggerExitCode))
                            message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_MIDebuggerExited_UnknownCode, MICommandFactory.Name);
                        else
                            message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_MIDebuggerExited_WithCode, MICommandFactory.Name, debuggerExitCode);

                        _callback.OnError(message);
                        _callback.OnProcessExit(uint.MaxValue);

                        Dispose();
                    });
            };

            ModuleLoadEvent += async delegate (object o, EventArgs args)
            {
                // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported

                if (_libraryLoaded.Count != 0)
                {
                    string moduleNames = string.Join(", ", _libraryLoaded);

                    try
                    {
                        _libraryLoaded.Clear();
                        SourceLineCache.OnLibraryLoad();

                        await _breakpointManager.BindAsync();
                        await CheckModules();

                        _bLastModuleLoadFailed = false;
                    }
                    catch (Exception e)
                    {
                        if (this.ProcessState == MICore.ProcessState.Exited)
                        {
                            return; // ignore exceptions after the process has exited
                        }

                        string exceptionDescription = EngineUtils.GetExceptionDescription(e);
                        string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_ExceptionProcessingModules, moduleNames, exceptionDescription);

                        // to avoid spamming the user, if the last module failed, we send the next failure to the output windiw instead of a message box
                        if (!_bLastModuleLoadFailed)
                        {
                            _callback.OnError(message);
                            _bLastModuleLoadFailed = true;
                        }
                        else
                        {
                            _callback.OnOutputMessage(new OutputMessage(message, enum_MESSAGETYPE.MT_OUTPUTSTRING, OutputMessage.Severity.Warning));
                        }
                    }
                }
                if (_waitDialog != null)
                {
                    _waitDialog.EndWaitDialog();
                }
                if (MICommandFactory.SupportsStopOnDynamicLibLoad())
                {
                    CmdContinueAsync();
                }
            };

            // When we break we need to gather information
            BreakModeEvent += async delegate (object o, EventArgs args)
            {
                // NOTE: This is an async void method, so make sure exceptions are caught and somehow reported

                ResultEventArgs results = args as MICore.Debugger.ResultEventArgs;
                if (_waitDialog != null)
                {
                    _waitDialog.EndWaitDialog();
                }

                if (!this._connected)
                {
                    _initialBreakArgs = results;
                    return;
                }

                try
                {
                    await HandleBreakModeEvent(results);
                }
                catch (Exception e)
                {
                    if (this.ProcessState == MICore.ProcessState.Exited)
                    {
                        return; // ignore exceptions after the process has exited
                    }

                    string exceptionDescription = EngineUtils.GetExceptionDescription(e);
                    string message = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_FailedToEnterBreakState, exceptionDescription);
                    _callback.OnError(message);

                    Terminate();
                }
            };

            ErrorEvent += delegate (object o, EventArgs args)
            {
                // NOTE: Exceptions leaked from this method may cause VS to crash, be careful

                ResultEventArgs result = (ResultEventArgs)args;
                _callback.OnError(result.Results.FindString("msg"));
            };

            ThreadCreatedEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs result = (ResultEventArgs)args;
                ThreadCache.ThreadEvent(result.Results.FindInt("id"), /*deleted */false);
            };

            ThreadExitedEvent += delegate (object o, EventArgs args)
            {
                ResultEventArgs result = (ResultEventArgs)args;
                ThreadCache.ThreadEvent(result.Results.FindInt("id"), /*deleted*/true);
            };

            MessageEvent += (object o, ResultEventArgs args) =>
            {
                OutputMessage outputMessage = DecodeOutputEvent(args.Results);
                if (outputMessage != null)
                {
                    _callback.OnOutputMessage(outputMessage);
                }
            };

            TelemetryEvent += (object o, ResultEventArgs args) =>
            {
                string eventName;
                KeyValuePair<string, object>[] properties;
                if (DecodeTelemetryEvent(args.Results, out eventName, out properties))
                {
                    HostTelemetry.SendEvent(eventName, properties);
                }
            };

            BreakChangeEvent += _breakpointManager.BreakpointModified;
        }
Пример #20
0
 // Sets the registry root currently in use by the DE. Different installations of Visual Studio can change where their registry information is stored
 // This allows the debugger to tell the engine where that location is.
 int IDebugEngine2.SetRegistryRoot(string registryRoot)
 {
     _configStore = new HostConfigurationStore(registryRoot, EngineConstants.EngineId);
     Logger = Logger.EnsureInitialized(_configStore);
     return Constants.S_OK;
 }
Пример #21
0
 // Kofe debugger depends on this method to generate LaunchOptions
 public static LaunchOptions GetInstance(HostConfigurationStore configStore, string exePath, string args, string dir, string options, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine)
 {
     return(GetInstance(configStore, exePath, args, dir, options, eventCallback, targetEngine, null));
 }