Exemplo n.º 1
0
        static void EnsureCreated()
        {
            lock (_lock)
            {
                if (_session != null)
                {
                    return;
                }

                _session             = new SoftDebuggerSession();
                _session.Breakpoints = BreakEvents;

                _session.ExceptionHandler = ex =>
                {
                    if (Configuration.Current.LogInternalErrors)
                    {
                        Log.Error("Internal debugger error:", ex.GetType());
                        Log.Error(ex.ToString());
                    }

                    return(true);
                };

                _session.LogWriter = (isStdErr, text) =>
                {
                    if (Configuration.Current.LogRuntimeSpew)
                    {
                        Log.NoticeSameLine("[Mono] {0}", text);                         // The string already has a line feed.
                    }
                };

                _session.OutputWriter = (isStdErr, text) =>
                {
                    //lock (Log.Lock)
                    //{
                    if (Callback != null)
                    {
                        Callback.Invoke(isStdErr ? "ErrorOutput" : "Output", null, text);
                    }
                    else
                    {
                        if (isStdErr)
                        {
                            Console.Error.Write(text);
                        }
                        else
                        {
                            Console.Write(text);
                        }
                    }
                    //}
                };

                _session.TypeResolverHandler += (identifier, location) =>
                {
                    // I honestly have no idea how correct this is. I suspect you
                    // could probably break it in some corner cases. It does make
                    // something like `p Android.Runtime.JNIEnv.Handle` work,
                    // though, which would otherwise have required `global::` to
                    // be explicitly prepended.

                    if (identifier == "__EXCEPTION_OBJECT__")
                    {
                        return(null);
                    }

                    foreach (var loc in ActiveFrame.GetAllLocals())
                    {
                        if (loc.Name == identifier)
                        {
                            return(null);
                        }
                    }

                    return(identifier);
                };

                _session.TargetEvent += (sender, e) =>
                {
                    Log.Debug("Event: '{0}'", e.Type);
                };

                _session.TargetStarted += (sender, e) =>
                {
                    _activeFrame = null;

                    /*
                     * if (_showResumeMessage)
                     *      Log.Notice("Inferior process '{0}' ('{1}') resumed",
                     *              ActiveProcess.Id, StringizeTarget());
                     */
                };

                _session.TargetReady += (sender, e) =>
                {
                    _activeProcess = _session.GetProcesses().SingleOrDefault();

                    // The inferior process has launched, so we can safely
                    // set our `SIGINT` handler without it interfering with
                    // the inferior.
                    CommandLine.SetControlCHandler();

                    /*
                     * Log.Notice("Inferior process '{0}' ('{1}') started",
                     *      ActiveProcess.Id, StringizeTarget());
                     */
                };

                _session.TargetStopped += (sender, e) =>
                {
                    //Log.Notice("Inferior process '{0}' ('{1}') suspended",
                    //	ActiveProcess.Id, StringizeTarget());
                    //Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true));

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetStopped", e.Thread, null);
                    }

                    CommandLine.ResumeEvent.Set();
                };

                _session.TargetInterrupted += (sender, e) =>
                {
                    Log.Notice("Inferior process '{0}' ('{1}') interrupted",
                               ActiveProcess.Id, StringizeTarget());
                    Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true));

                    CommandLine.ResumeEvent.Set();
                };

                _session.TargetHitBreakpoint += (sender, e) =>
                {
                    // var bp = e.BreakEvent as Breakpoint;
                    // var fbp = e.BreakEvent as FunctionBreakpoint;

                    /*
                     * if (fbp != null)
                     *      Log.Notice("Hit method breakpoint on '{0}'", fbp.FunctionName);
                     * else
                     * {
                     *      var cond = bp.ConditionExpression != null ?
                     *              string.Format(" (condition '{0}' met)", bp.ConditionExpression) :
                     *              string.Empty;
                     *
                     *      Log.Notice("Hit breakpoint at '{0}:{1}'{2}", bp.FileName, bp.Line, cond);
                     * }
                     *
                     * Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true));
                     */

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetHitBreakpoint", e.Thread, null);
                    }

                    CommandLine.ResumeEvent.Set();
                };

                _session.TargetExited += (sender, e) =>
                {
                    var p = ActiveProcess;

                    /*
                     * // Can happen when a remote connection attempt fails.
                     * if (p == null)
                     * {
                     *      if (_kind == SessionKind.Listening)
                     *              Log.Notice("Listening socket closed");
                     *      else if (_kind == SessionKind.Connected)
                     *              Log.Notice("Connection attempt terminated");
                     *      else
                     *              Log.Notice("Failed to connect to '{0}'", StringizeTarget());
                     * }
                     * else
                     *      Log.Notice("Inferior process '{0}' ('{1}') exited", ActiveProcess.Id, StringizeTarget());
                     */

                    // Make sure we clean everything up on a normal exit.
                    Kill();

                    _debuggeeKilled = true;
                    _kind           = SessionKind.Disconnected;

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetExited", null, null);
                    }

                    CommandLine.ResumeEvent.Set();
                };

                _session.TargetExceptionThrown += (sender, e) =>
                {
                    var ex = ActiveException;

                    //Log.Notice("Trapped first-chance exception of type '{0}'", ex.Type);
                    //Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true));

                    PrintException(ex);

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetExceptionThrown", e.Thread, null);
                    }

                    CommandLine.ResumeEvent.Set();
                };

                _session.TargetUnhandledException += (sender, e) =>
                {
                    var ex = ActiveException;

                    //Log.Notice("Trapped unhandled exception of type '{0}'", ex.Type);
                    //Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true));

                    PrintException(ex);

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetUnhandledException", e.Thread, null);
                    }

                    CommandLine.ResumeEvent.Set();
                };

                _session.TargetThreadStarted += (sender, e) =>
                {
                    //Log.Notice("Inferior thread '{0}' ('{1}') started",
                    //	e.Thread.Id, e.Thread.Name);

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetThreadStarted", e.Thread, null);
                    }
                };

                _session.TargetThreadStopped += (sender, e) =>
                {
                    //Log.Notice("Inferior thread '{0}' ('{1}') exited",
                    //	e.Thread.Id, e.Thread.Name);

                    if (Callback != null)
                    {
                        Callback.Invoke("TargetThreadStopped", e.Thread, null);
                    }
                };
            }
        }