The single stepping engine is responsible for doing all the stepping operations. sse - short for single stepping engine. stepping operation - an operation which has been invoked by the user such as StepLine(), NextLine() etc. atomic operation - an operation which the sse invokes on the target such as stepping one machine instruction or resuming the target until a breakpoint is hit. step frame - an address range; the sse invokes atomic operations until the target hit a breakpoint, received a signal or stopped at an address outside this range. temporary breakpoint - a breakpoint which is automatically removed the next time the target stopped; it is used to step over method calls. source stepping op - stepping operation based on the program's source code, such as StepLine() or NextLine(). native stepping op - stepping operation based on the machine code such as StepInstruction() or NextInstruction(). The SingleSteppingEngine supports both synchronous and asynchronous operations; in synchronous mode, the engine waits until the child has stopped before returning. In either case, the step commands return true on success and false an error. Since the SingleSteppingEngine can be used from multiple threads at the same time, you can no longer safely use the `State' property to find out whether the target is stopped or not. It is safe to call all the step commands from multiple threads, but for obvious reasons only one command can run at a time. So if you attempt to issue a step command while the engine is still busy, the step command will return false to signal this error. The ThreadManager creates one SingleSteppingEngine instance for each thread in the target. The `SingleSteppingEngine' class is basically just responsible for whatever happens in the background thread: processing commands and events. Their methods are just meant to be called from the SingleSteppingEngine (since it's a protected nested class they can't actually be called from anywhere else). See the `Thread' class for the "user interface".
Inheritance: ThreadServant
Ejemplo n.º 1
0
 public Command(SingleSteppingEngine sse, TargetAccessDelegate func, object data)
 {
     this.Type = CommandType.TargetAccess;
     this.Engine = sse;
     this.Data1 = func;
     this.Data2 = data;
 }
Ejemplo n.º 2
0
            public OperationStepCompilerGenerated(SingleSteppingEngine sse, Method method,
						       Block block, CommandResult result)
                : base(sse, result)
            {
                this.method = method;
                this.block = block;
            }
Ejemplo n.º 3
0
        internal void ThreadCreated(Inferior inferior, int pid, bool do_attach, bool resume_thread)
        {
            Inferior new_inferior = inferior.CreateThread (pid, do_attach);

            SingleSteppingEngine new_thread = new SingleSteppingEngine (manager, this, new_inferior, pid);

            Report.Debug (DebugFlags.Threads, "Thread created: {0} {1} {2}", pid, new_thread, do_attach);

            if (mono_manager != null)
                mono_manager.ThreadCreated (new_thread);

            if (!do_attach && !is_execed)
                get_thread_info (inferior, new_thread);
            OnThreadCreatedEvent (new_thread);

            if (resume_thread) {
                CommandResult result = current_operation != null ?
                    current_operation : new ThreadCommandResult (new_thread.Thread);
                new_thread.StartThread (result);
            } else {
                new_thread.StartSuspended ();
            }
        }
Ejemplo n.º 4
0
        internal void StartGlobalOperation(ThreadingModel model, SingleSteppingEngine caller, OperationCommandResult operation)
        {
            if (!ThreadManager.InBackgroundThread)
                throw new InternalError ();

            if ((current_state != ProcessState.Stopped) && (current_state != ProcessState.SingleThreaded))
                throw new TargetException (TargetError.NotStopped);

            lock (this) {
                current_state = ProcessState.Running;
                stopped_event.Reset ();
                current_operation = operation;
            }

            ResumeUserThreads (model, caller);
        }
Ejemplo n.º 5
0
        internal void ReleaseGlobalThreadLock(SingleSteppingEngine caller)
        {
            Report.Debug (DebugFlags.Threads,
                      "Releasing global thread lock: {0}", caller);

            foreach (ThreadServant thread in thread_hash.Values) {
                if (thread == caller)
                    continue;
                thread.ReleaseThreadLock ();
            }
            has_thread_lock = false;
            thread_lock_mutex.Unlock ();
            Report.Debug (DebugFlags.Threads,
                      "Released global thread lock: {0}", caller);
        }
Ejemplo n.º 6
0
 internal void OnTargetEvent(SingleSteppingEngine sse, TargetEventArgs args)
 {
     Debugger.OnTargetEvent (sse.Client, args);
 }
Ejemplo n.º 7
0
        internal void ChildForked(Inferior inferior, int pid)
        {
            Process new_process = new Process (this, pid);
            new_process.ProcessStart.StopInMain = false;

            Inferior new_inferior = Inferior.CreateInferior (
                manager, new_process, new_process.ProcessStart);
            new_inferior.InitializeThread (pid);

            if (!manager.Debugger.Configuration.FollowFork) {
                new_inferior.DetachAfterFork ();
                return;
            }

            SingleSteppingEngine new_thread = new SingleSteppingEngine (
                manager, new_process, new_inferior, pid);

            Report.Debug (DebugFlags.Threads, "Child forked: {0} {1}", pid, new_thread);

            new_process.main_thread = new_thread;

            manager.Debugger.OnProcessCreatedEvent (new_process);
            new_process.OnThreadCreatedEvent (new_thread);

            CommandResult result = new_process.CloneParentOperation (new_thread);
            new_thread.StartForkedChild (result);
        }
Ejemplo n.º 8
0
        // <summary>
        //   Stop all currently running threads without sending any notifications.
        //   The threads are automatically resumed to their previos state when
        //   ReleaseGlobalThreadLock() is called.
        // </summary>
        internal void AcquireGlobalThreadLock(SingleSteppingEngine caller)
        {
            if (has_thread_lock)
                throw new InternalError ("Recursive thread lock");

            thread_lock_mutex.Lock ();
            Report.Debug (DebugFlags.Threads,
                      "Acquiring global thread lock: {0}", caller);
            has_thread_lock = true;
            foreach (ThreadServant thread in thread_hash.Values) {
                if (thread == caller)
                    continue;
                thread.AcquireThreadLock ();
            }
            Report.Debug (DebugFlags.Threads,
                      "Done acquiring global thread lock: {0}",
                      caller);
        }
Ejemplo n.º 9
0
        internal virtual void Completed(SingleSteppingEngine sse, TargetEventArgs args)
        {
            if ((args != null) && ((args.Type == TargetEventType.TargetExited) || (args.Type == TargetEventType.TargetSignaled))) {
                if ((sse.Thread.ThreadFlags & Thread.Flags.StopOnExit) == 0) {
                    Host.SendResult (sse, args);
                    return;
                }
            }

            if (!IsCompleted) {
                IsCompleted = true;
                if (args != null)
                    Host.SendResult (sse, args);
                Host.OperationCompleted (sse, args, ThreadingModel);
            }
        }
Ejemplo n.º 10
0
 internal override void OnExecd(SingleSteppingEngine new_thread)
 {
     Thread = new_thread.Thread;
 }
Ejemplo n.º 11
0
 internal override void Completed(SingleSteppingEngine sse, TargetEventArgs args)
 {
     Host.OperationCompleted (sse, args, ThreadingModel);
     if (args != null)
         Host.SendResult (sse, args);
 }
Ejemplo n.º 12
0
 void IOperationHost.OperationCompleted(SingleSteppingEngine sse, TargetEventArgs args, ThreadingModel model)
 {
 }
Ejemplo n.º 13
0
            public OperationWrapper(SingleSteppingEngine sse,
					 Method method, CommandResult result)
                : base(sse, result)
            {
                this.method = method;
            }
Ejemplo n.º 14
0
            public OperationStepOverBreakpoint(SingleSteppingEngine sse, int index,
						    TargetAddress until)
                : base(sse, null)
            {
                this.Index = index;
                this.until = until;
            }
Ejemplo n.º 15
0
 internal override void OnExecd(SingleSteppingEngine new_thread)
 {
     Process = new_thread.Process;
 }
Ejemplo n.º 16
0
 internal abstract void OnExecd(SingleSteppingEngine new_thread);
Ejemplo n.º 17
0
 public void Kill()
 {
     if (!Inferior.HasThreadEvents) {
         SingleSteppingEngine[] sses = new SingleSteppingEngine [thread_hash.Count];
         thread_hash.Values.CopyTo (sses, 0);
         foreach (SingleSteppingEngine sse in sses)
             sse.SetKilledFlag ();
         foreach (SingleSteppingEngine sse in sses)
             sse.Kill ();
     } else {
         main_thread.Kill ();
     }
 }
Ejemplo n.º 18
0
        public bool Notification(SingleSteppingEngine engine, Inferior inferior,
					  NotificationType type, TargetAddress data, long arg)
        {
            switch (type) {
            case NotificationType.InitializeCorlib:
                Report.Debug (DebugFlags.JitSymtab, "Initialize corlib");
                read_mono_debugger_info (inferior);
                read_symbol_table (inferior);
                read_builtin_types (inferior);
                break;

            case NotificationType.InitializeManagedCode:
                Report.Debug (DebugFlags.JitSymtab, "Initialize managed code");
                reached_main (inferior, data);
                break;

            case NotificationType.LoadModule: {
                MonoSymbolFile symfile = load_symfile (inferior, data);
                Report.Debug (DebugFlags.JitSymtab,
                          "Module load: {0} {1}", data, symfile);
                if (symfile == null)
                    break;
                engine.Process.Debugger.OnModuleLoadedEvent (symfile.Module);
                if ((builtin_types != null) && (symfile != null)) {
                    if (engine.OnModuleLoaded (symfile.Module))
                        return false;
                }
                break;
            }

            case NotificationType.UnloadModule: {
                Report.Debug (DebugFlags.JitSymtab,
                          "Module unload: {0} {1}", data, arg);

                MonoSymbolFile symfile = (MonoSymbolFile) symfile_by_index [(int) arg];
                if (symfile == null)
                    break;

                engine.Process.Debugger.OnModuleUnLoadedEvent (symfile.Module);
                close_symfile (symfile);
                break;
            }

            case NotificationType.JitBreakpoint:
                JitBreakpoint (inferior, (int) arg, data);
                break;

            case NotificationType.DomainCreate:
                Report.Debug (DebugFlags.JitSymtab,
                          "Domain create: {0}", data);
                add_data_table (inferior, data);
                break;

            case NotificationType.DomainUnload:
                Report.Debug (DebugFlags.JitSymtab,
                          "Domain unload: {0} {1:x}", data, arg);
                destroy_data_table ((int) arg, data);
                engine.Process.BreakpointManager.DomainUnload (inferior, (int) arg);
                break;

            case NotificationType.ClassInitialized:
                break;

            case NotificationType.CreateAppDomain:
                create_appdomain (inferior, data);
                break;

            case NotificationType.UnloadAppDomain:
                unload_appdomain ((int) arg);
                break;

            default:
                Console.WriteLine ("Received unknown notification {0:x} / {1} {2:x}",
                           (int) type, data, arg);
                break;
            }

            return true;
        }
Ejemplo n.º 19
0
        internal void ChildExecd(SingleSteppingEngine engine, Inferior inferior)
        {
            is_execed = true;

            if (!is_forked) {
                if (mono_language != null)
                    mono_language.Dispose();

                if (native_language != null)
                    native_language.Dispose ();

                if (os != null)
                    os.Dispose ();

                if (symtab_manager != null)
                    symtab_manager.Dispose ();
            }

            if (breakpoint_manager != null)
                breakpoint_manager.Dispose ();

            session.OnProcessExecd (this);

            breakpoint_manager = new BreakpointManager ();

            exception_handlers = new Dictionary<int,ExceptionCatchPoint> ();

            symtab_manager = new SymbolTableManager (session);

            os = Inferior.CreateOperatingSystemBackend (this);
            native_language = new NativeLanguage (this, os, target_info);

            Inferior new_inferior = Inferior.CreateInferior (manager, this, start);
            try {
                new_inferior.InitializeAfterExec (inferior.PID);
            } catch (Exception ex) {
                if ((ex is TargetException) && (((TargetException) ex).Type == TargetError.PermissionDenied)) {
                    Report.Error ("Permission denied when trying to debug exec()ed child {0}, detaching!",
                              inferior.PID);
                } else {
                    Report.Error ("InitializeAfterExec() failed on pid {0}: {1}", inferior.PID, ex);
                }
                new_inferior.DetachAfterFork ();
                return;
            }

            SingleSteppingEngine new_thread = new SingleSteppingEngine (
                manager, this, new_inferior, inferior.PID);

            ThreadServant[] threads;
            lock (thread_hash.SyncRoot) {
                threads = new ThreadServant [thread_hash.Count];
                thread_hash.Values.CopyTo (threads, 0);
            }

            for (int i = 0; i < threads.Length; i++) {
                if (threads [i].PID != inferior.PID)
                    threads [i].Kill ();
            }

            thread_hash [inferior.PID] = new_thread;

            inferior.Dispose ();
            inferior = null;

            manager.Debugger.OnProcessExecdEvent (this);
            manager.Debugger.OnThreadCreatedEvent (new_thread.Thread);
            initialized = is_forked = false;
            main_thread = new_thread;

            if ((engine.Thread.ThreadFlags & Thread.Flags.StopOnExit) != 0)
                new_thread.Thread.ThreadFlags |= Thread.Flags.StopOnExit;

            CommandResult result = engine.OnExecd (new_thread);
            new_thread.StartExecedChild (result);
        }
Ejemplo n.º 20
0
        void get_thread_info(Inferior inferior, SingleSteppingEngine engine)
        {
            if (thread_db == null) {
                if (mono_manager == null)
                    return;
                Report.Error ("Failed to initialize thread_db on {0}: {1} {2}",
                          start.CommandLine, start, Environment.StackTrace);
                throw new InternalError ();
            }

            bool found = false;
            thread_db.GetThreadInfo (inferior, delegate (int lwp, long tid) {
                if (lwp != engine.PID)
                    return;

                engine.SetTID (tid);
                found = true;
            });

            if (!found)
                Report.Error ("Cannot find thread {0:x} in {1}",
                          engine.PID, start.CommandLine);
        }
Ejemplo n.º 21
0
 internal void OnLeaveNestedBreakState(SingleSteppingEngine sse)
 {
     Debugger.OnLeaveNestedBreakState (sse.Client);
 }
Ejemplo n.º 22
0
        void ResumeUserThreads(ThreadingModel model, SingleSteppingEngine caller)
        {
            Report.Debug (DebugFlags.Threads,
                      "Resuming user threads: {0}", caller);

            foreach (SingleSteppingEngine engine in thread_hash.Values) {
                if (engine == caller)
                    continue;
                if ((engine.Thread.ThreadFlags & Thread.Flags.AutoRun) == 0)
                    continue;
                if (((engine.Thread.ThreadFlags & Thread.Flags.Immutable) != 0) &&
                    ((model & ThreadingModel.StopImmutableThreads) == 0))
                    continue;
                if (((engine.Thread.ThreadFlags & Thread.Flags.Daemon) != 0) &&
                    ((model & ThreadingModel.StopDaemonThreads) == 0))
                    continue;

                CommandResult result;
                if (current_operation != null)
                    result = current_operation;
                else
                    result = new ThreadCommandResult (engine.Thread);

                engine.ResumeUserThread (result);
            }

            Report.Debug (DebugFlags.Threads,
                      "Resumed user threads: {0}", caller);
        }
Ejemplo n.º 23
0
        internal void OperationCompleted(SingleSteppingEngine caller, TargetEventArgs result, ThreadingModel model)
        {
            if (!ThreadManager.InBackgroundThread && Inferior.HasThreadEvents)
                throw new InternalError ();

            if (current_state == ProcessState.Stopping)
                return;
            else if (current_state != ProcessState.Running)
                throw new InternalError ();

            if ((result != null) && (caller != main_thread) &&
                ((result.Type == TargetEventType.TargetExited) || (result.Type == TargetEventType.TargetSignaled)))
                return;

            current_state = ProcessState.Stopping;
            SuspendUserThreads (model, caller);

            lock (this) {
                current_state = ProcessState.Stopped;
                current_operation.Completed ();
                current_operation = null;
                stopped_event.Set ();
            }
        }
Ejemplo n.º 24
0
        void SuspendUserThreads(ThreadingModel model, SingleSteppingEngine caller)
        {
            Report.Debug (DebugFlags.Threads,
                      "Suspending user threads: {0} {1}", model, caller);

            foreach (SingleSteppingEngine engine in thread_hash.Values) {
                Report.Debug (DebugFlags.Threads, "  check user thread: {0} {1}",
                          engine, engine.Thread.ThreadFlags);
                if (engine == caller)
                    continue;
                if (((engine.Thread.ThreadFlags & Thread.Flags.Immutable) != 0) &&
                    ((model & ThreadingModel.StopImmutableThreads) == 0))
                    continue;
                if (((engine.Thread.ThreadFlags & Thread.Flags.Daemon) != 0) &&
                    ((model & ThreadingModel.StopDaemonThreads) == 0))
                    continue;
                engine.SuspendUserThread ();
            }

            Report.Debug (DebugFlags.Threads,
                      "Done suspending user threads: {0} {1}", model, caller);
        }
Ejemplo n.º 25
0
        internal CommandResult StartApplication()
        {
            SingleSteppingEngine engine = new SingleSteppingEngine (manager, this, start);

            initialized = true;

            this.main_thread = engine;
            engine.Thread.ThreadFlags |= Thread.Flags.StopOnExit;

            if (thread_hash.Contains (engine.PID))
                thread_hash [engine.PID] = engine;
            else
                thread_hash.Add (engine.PID, engine);
            session.MainThreadGroup.AddThread (engine.Thread.ID);

            session.OnMainProcessCreated (this);
            manager.Debugger.OnMainProcessCreatedEvent (this);

            CommandResult result = Debugger.StartOperation (start.Session.Config.ThreadingModel, engine);
            return engine.StartApplication (result);
        }
Ejemplo n.º 26
0
 void IOperationHost.OperationCompleted(SingleSteppingEngine caller, TargetEventArgs result, ThreadingModel model)
 {
     Process.OperationCompleted (caller, result, model);
 }
Ejemplo n.º 27
0
        internal CommandResult StartOperation(ThreadingModel model, SingleSteppingEngine caller)
        {
            if (!ThreadManager.InBackgroundThread)
                throw new InternalError ();

            if ((current_state != ProcessState.Stopped) && (current_state != ProcessState.SingleThreaded))
                throw new TargetException (TargetError.NotStopped);

            if ((model & ThreadingModel.ThreadingMode) == ThreadingModel.Single) {
                current_state = ProcessState.SingleThreaded;
                if ((model & ThreadingModel.ResumeThreads) != 0)
                    ResumeUserThreads (model, caller);
                return new ThreadCommandResult (caller.Thread);
            } else if ((model & ThreadingModel.ThreadingMode) != ThreadingModel.Process) {
                throw new ArgumentException ();
            }

            lock (this) {
                current_state = ProcessState.Running;
                stopped_event.Reset ();
                current_operation = new ProcessCommandResult (this, model);
            }

            ResumeUserThreads (model, caller);
            return current_operation;
        }
Ejemplo n.º 28
0
 void IOperationHost.SendResult(SingleSteppingEngine sse, TargetEventArgs args)
 {
     Process.Debugger.OnTargetEvent (sse.Client, args);
 }
Ejemplo n.º 29
0
        CommandResult CloneParentOperation(SingleSteppingEngine new_thread)
        {
            if (parent.current_state == ProcessState.SingleThreaded) {
                current_state = ProcessState.SingleThreaded;
                return new ThreadCommandResult (new_thread.Thread);
            }

            if (parent.current_state != ProcessState.Running)
                throw new InternalError ();

            current_state = ProcessState.Running;
            if ((parent.current_operation.ThreadingModel & ThreadingModel.ThreadingMode) == ThreadingModel.Global)
                current_operation = parent.current_operation;
            else if ((parent.current_operation.ThreadingModel & ThreadingModel.ThreadingMode) == ThreadingModel.Process)
                current_operation = new ProcessCommandResult (this, parent.current_operation.ThreadingModel);
            else
                throw new InternalError ();

            return current_operation;
        }
Ejemplo n.º 30
0
 protected OperationStepBase(SingleSteppingEngine sse, CommandResult result)
     : base(sse, result)
 {
 }