Inheritance: TargetAccess, ITargetNotification, IDisposable
コード例 #1
0
ファイル: AddressBreakpoint.cs プロジェクト: baulig/debugger
        internal void Insert(Inferior inferior)
        {
            if (handle == null)
                handle = new AddressBreakpointHandle (this, address);

            handle.Insert (inferior);
        }
コード例 #2
0
ファイル: ThreadDB.cs プロジェクト: baulig/debugger
        public static ThreadDB Create(Process process, Inferior target)
        {
            ThreadDB db = new ThreadDB (process);
            if (!db.Initialize (target))
                return null;

            return db;
        }
コード例 #3
0
        public override NativeExecutableReader AddExecutableFile(Inferior inferior, string filename,
									  TargetAddress base_address, bool step_into,
									  bool is_loaded)
        {
            check_disposed ();
            Bfd bfd = (Bfd) bfd_hash [filename];
            if (bfd != null)
                return bfd;

            bfd = new Bfd (this, inferior.TargetMemoryInfo, filename, base_address, is_loaded);
            bfd_hash.Add (filename, bfd);
            check_loaded_library (inferior, bfd);
            return bfd;
        }
コード例 #4
0
ファイル: BreakpointManager.cs プロジェクト: baulig/debugger
        public void DomainUnload(Inferior inferior, int domain)
        {
            Lock ();
            try {
                int[] indices = new int [index_hash.Count];
                index_hash.Keys.CopyTo (indices, 0);

                for (int i = 0; i < indices.Length; i++) {
                    BreakpointEntry entry = (BreakpointEntry) index_hash [indices [i]];
                    if (entry.Domain != domain)
                        continue;
                    inferior.RemoveBreakpoint (indices [i]);
                    index_hash.Remove (indices [i]);
                }
            } finally {
                Unlock ();
            }
        }
コード例 #5
0
 internal abstract void UpdateSharedLibraries(Inferior inferior);
コード例 #6
0
        public abstract NativeExecutableReader AddExecutableFile(Inferior inferior, string filename,
									  TargetAddress base_address,
									  bool step_info, bool is_loaded);
コード例 #7
0
 internal abstract bool CheckForPendingMonoInit(Inferior inferior);
コード例 #8
0
ファイル: Process.cs プロジェクト: baulig/debugger
        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 ();
            }
        }
コード例 #9
0
            protected override EventResult DoProcessEvent(Inferior.ChildEvent cevent,
							       out TargetEventArgs args)
            {
                Report.Debug (DebugFlags.SSE,
                      "{0} stepped over breakpoint {1} at {2}: {3} {4}",
                      sse, Index, inferior.CurrentFrame, cevent, until);

                if ((cevent.Type == Inferior.ChildEventType.CHILD_HIT_BREAKPOINT) &&
                (cevent.Argument != Index)) {
                args = null;
                return EventResult.Completed;
                }

                if (!until.IsNull) {
                sse.do_continue (until);

                args = null;
                until = TargetAddress.Null;
                return EventResult.Running;
                }

                args = null;
                return EventResult.ResumeOperation;
            }
コード例 #10
0
ファイル: Process.cs プロジェクト: baulig/debugger
        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);
        }
コード例 #11
0
ファイル: Process.cs プロジェクト: baulig/debugger
        internal void InitializeMono(Inferior inferior, TargetAddress mdb_debug_info)
        {
            MonoRuntimeFound = true;
            mono_manager = MonoThreadManager.Initialize (this, inferior, mdb_debug_info, is_attached);

            InitializeThreads (inferior, !is_attached);

            if (mono_manager == null)
                return;

            mono_manager.InitializeThreads (inferior);

            if (is_attached)
                mono_manager.InitializeAfterAttach (inferior);
        }
コード例 #12
0
ファイル: Breakpoint.cs プロジェクト: baulig/debugger
 // <summary>
 //   Internal breakpoint handler.
 // </summary>
 // <remarks>
 //   The return value specifies whether we already dealt with the breakpoint; so you
 //   normally make it return `true' when overriding.
 // </remarks>
 internal virtual bool BreakpointHandler(Inferior inferior, out bool remain_stopped)
 {
     remain_stopped = false;
     return false;
 }
コード例 #13
0
ファイル: Instruction_X86_64.cs プロジェクト: baulig/debugger
        public override bool InterpretInstruction(Inferior inferior)
        {
            switch (InstructionType) {
            case Type.IndirectJump:
            case Type.Jump: {
                TargetAddress target = GetEffectiveAddress (inferior);
                Registers regs = inferior.GetRegisters ();
                regs [(int) X86_Register.RIP].SetValue (target);
                inferior.SetRegisters (regs);
                return true;
            }

            case Type.IndirectCall:
            case Type.Call: {
                TargetAddress target = GetEffectiveAddress (inferior);
                Registers regs = inferior.GetRegisters ();

                TargetAddress rip = new TargetAddress (
                    inferior.AddressDomain, regs [(int) X86_Register.RIP].Value);
                TargetAddress rsp = new TargetAddress (
                    inferior.AddressDomain, regs [(int) X86_Register.RSP].Value);

                inferior.WriteAddress (rsp - 8, rip + InstructionSize);

                regs [(int) X86_Register.RSP].SetValue (rsp - 8);
                regs [(int) X86_Register.RIP].SetValue (target);
                inferior.SetRegisters (regs);
                return true;
            }

            case Type.Ret: {
                Registers regs = inferior.GetRegisters ();

                TargetAddress rsp = new TargetAddress (
                    inferior.AddressDomain, regs [(int) X86_Register.RSP].Value);

                TargetAddress rip = inferior.ReadAddress (rsp);
                rsp += 8 + Displacement;

                regs [(int) X86_Register.RSP].SetValue (rsp);
                regs [(int) X86_Register.RIP].SetValue (rip);
                inferior.SetRegisters (regs);
                return true;
            }

            case Type.Interpretable: {
                Registers regs = inferior.GetRegisters ();

                TargetAddress rsp = new TargetAddress (
                    inferior.AddressDomain, regs [(int) X86_Register.RSP].Value);
                TargetAddress rbp = new TargetAddress (
                    inferior.AddressDomain, regs [(int) X86_Register.RBP].Value);
                TargetAddress rip = new TargetAddress (
                    inferior.AddressDomain, regs [(int) X86_Register.RIP].Value);

                if (Code [0] == 0x55) /* push %rbp */ {
                    inferior.WriteAddress (rsp - 8, rbp);
                    regs [(int) X86_Register.RSP].SetValue (rsp - 8);
                    regs [(int) X86_Register.RIP].SetValue (rip + 1);
                    inferior.SetRegisters (regs);
                    return true;
                }

                return false;
            }

            default:
                return false;
            }
        }
コード例 #14
0
            public void SetStopEvent(Inferior.ChildEvent stop_event)
            {
                if (StopEvent != null)
                    throw new InternalError ();

                StopEvent = stop_event;
                Stopped = true;
            }
コード例 #15
0
        public bool ProcessEvent(Inferior.ChildEvent cevent)
        {
            Report.Debug (DebugFlags.EventLoop, "{0} received event {1}",
                      this, cevent);

            if (killed) {
                if (cevent.Type == Inferior.ChildEventType.CHILD_INTERRUPTED) {
                    inferior.Continue ();
                    return true;
                } else if (cevent.Type != Inferior.ChildEventType.CHILD_EXITED) {
                    Report.Debug (DebugFlags.EventLoop,
                              "{0} received event {1} when already killed",
                              this, cevent);
                    return true;
                }
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_EXITED) ||
                (cevent.Type == Inferior.ChildEventType.CHILD_SIGNALED)) {
                Report.Debug (DebugFlags.EventLoop, "{0} received {1} while running {2}",
                          this, cevent, current_operation);
                // we can't remove the breakpoint anymore after
                // the target exited, but we need to clear this id.
                temp_breakpoint = null;
                dead = true;
            } else {
                string frame_text = "";
                Inferior.StackFrame iframe = inferior.GetCurrentFrame (true);
                if (iframe != null)
                    frame_text = " at " + iframe.Address.ToString ();

                string running_text;
                if (HasThreadLock)
                    running_text = String.Format ("being thread-locked ({0})", thread_lock);
                else
                    running_text = String.Format ("running {0}", current_operation);

                string event_text;
                if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION)
                    event_text = String.Format ("notification {0} ({1})", cevent, (NotificationType) cevent.Argument);
                else
                    event_text = "event " + cevent.ToString ();

                Report.Debug (DebugFlags.EventLoop, "{0} received {1}{2} while {3}",
                          this, event_text, frame_text, running_text);

                if (HasThreadLock) {
                    thread_lock.SetStopEvent (cevent);
                    return false;
                }
            }

            if (Process.IsAttached && !attach_initialized) {
                attach_initialized = true;

                if (cevent.Type == Inferior.ChildEventType.CHILD_INTERRUPTED)
                    cevent = new Inferior.ChildEvent (Inferior.ChildEventType.CHILD_STOPPED, 0, 0, 0);
            }

            bool resume_target;
            if (manager.HandleChildEvent (this, inferior, ref cevent, out resume_target)) {
                Report.Debug (DebugFlags.EventLoop,
                          "{0} done handling event: {1}{2}{3}{4}",
                          this, cevent, resume_target ? " resume-target" : "" ,
                          stop_requested ? " stop-requested" : "",
                          HasThreadLock ? " thread-lock" : "");
                if (stop_requested) {
                    OperationInterrupted ();
                } else if (resume_target) {
                    if (!current_operation.ResumeOperation ())
                        inferior.Continue ();
                }
                return true;
            }

            Inferior.ChildEventType message = cevent.Type;
            int arg = (int) cevent.Argument;

            switch (message) {
            case Inferior.ChildEventType.CHILD_INTERRUPTED:
                if (current_operation != null)
                    OperationInterrupted ();
                return true;
            case Inferior.ChildEventType.CHILD_SIGNALED:
                if (killed)
                    OperationCompleted (new TargetEventArgs (TargetEventType.TargetExited, 0));
                else
                    OperationCompleted (new TargetEventArgs (TargetEventType.TargetSignaled, arg));
                return true;

            case Inferior.ChildEventType.INTERNAL_ERROR:
                frame_changed (inferior.CurrentFrame, null);
                Report.Error ("{0} got {1} at {2} while executing {3}", this, message,
                          inferior.CurrentFrame, current_operation);
                OperationCompleted (new TargetEventArgs (TargetEventType.TargetSignaled, -1));
                return true;

            case Inferior.ChildEventType.CHILD_EXITED:
                OperationCompleted (new TargetEventArgs (TargetEventType.TargetExited, arg));
                return true;

            case Inferior.ChildEventType.CHILD_CALLBACK_COMPLETED:
                frame_changed (inferior.CurrentFrame, null);
                OperationCompleted (new TargetEventArgs (TargetEventType.TargetStopped, 0, current_frame));
                return true;

            case Inferior.ChildEventType.RUNTIME_INVOKE_DONE:
                OperationRuntimeInvoke rti = rti_stack.Pop ();
                if (rti.ID != cevent.Argument)
                    throw new InternalError ("{0} got unknown RUNTIME_INVOKE_DONE: {1} {2}", this, rti.ID, cevent);

                frame_changed (inferior.CurrentFrame, null);
                rti.Completed (cevent.Data1, cevent.Data2);

                if (rti.IsSuspended) {
                    InterruptibleOperation io = nested_break_stack.Pop ();
                    if (io != rti)
                        throw new InternalError ("{0} unexpected item on nested break state stack: {1}", this, io);
                    process.Debugger.OnLeaveNestedBreakState (thread);
                }

                if (current_operation != rti) {
                    OperationCommandResult result = current_operation.Result as OperationCommandResult;
                    if (result != null)
                        result.Completed (this, null);
                    current_operation.Result.Completed ();
                }
                current_operation = rti;

                TargetEventArgs args = rti.OperationCompleted (current_frame, false);
                OperationCompleted (args);
                return true;
            }

            if (stop_requested) {
                switch (message) {
                case Inferior.ChildEventType.CHILD_STOPPED:
                case Inferior.ChildEventType.CHILD_CALLBACK:
                case Inferior.ChildEventType.CHILD_HIT_BREAKPOINT:
                    OperationInterrupted ();
                    return true;

                case Inferior.ChildEventType.UNHANDLED_EXCEPTION:
                case Inferior.ChildEventType.THROW_EXCEPTION:
                case Inferior.ChildEventType.HANDLE_EXCEPTION:
                case Inferior.ChildEventType.CHILD_NOTIFICATION:
                    inferior.RestartNotification ();
                    OperationInterrupted ();
                    return true;

                default:
                    OperationInterrupted ();
                    return false;
                }
            }

            DoProcessEvent (cevent);
            return true;
        }
コード例 #16
0
 public void PopRegisters(Inferior inferior)
 {
     if (PushedRegisters)
         inferior.PopRegisters ();
     PushedRegisters = false;
 }
コード例 #17
0
 public ThreadLockData(bool stopped, Inferior.ChildEvent stop_event, bool pushed_regs)
 {
     this.Stopped = stopped;
     this.StopEvent = stop_event;
     this.PushedRegisters = pushed_regs;
 }
コード例 #18
0
            bool ReleaseThreadLock(Inferior.ChildEvent cevent)
            {
                if (!has_thread_lock)
                return true;

                Report.Debug (DebugFlags.SSE,
                      "{0} releasing thread lock at {1}",
                      sse, inferior.CurrentFrame);

                inferior.EnableBreakpoint (Index);
                sse.process.ReleaseGlobalThreadLock (sse);

                Report.Debug (DebugFlags.SSE,
                      "{0} done releasing thread lock at {1} - {2}",
                      sse, inferior.CurrentFrame, sse.HasThreadLock);

                has_thread_lock = false;

                if (sse.thread_lock == null)
                return true;

                sse.thread_lock.SetStopEvent (cevent);
                return false;
            }
コード例 #19
0
ファイル: Process.cs プロジェクト: baulig/debugger
        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);
        }
コード例 #20
0
ファイル: Architecture.cs プロジェクト: baulig/debugger
 //
 // This is a horrible hack - don't use !
 //
 //
 internal abstract void Hack_ReturnNull(Inferior inferior);
コード例 #21
0
ファイル: Process.cs プロジェクト: baulig/debugger
        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);
        }
コード例 #22
0
ファイル: AddressBreakpoint.cs プロジェクト: baulig/debugger
 internal void Remove(Inferior inferior)
 {
     if (handle != null) {
         handle.Remove (inferior);
         handle = null;
     }
 }
コード例 #23
0
ファイル: Process.cs プロジェクト: baulig/debugger
        internal SingleSteppingEngine GetEngineByTID(Inferior inferior, long tid)
        {
            foreach (SingleSteppingEngine engine in thread_hash.Values) {
                if (engine.TID == tid)
                    return engine;
            }

            if (thread_db == null) {
                Report.Error ("Failed to initialize thread_db on {0}: {1}",
                          start.CommandLine, start);
                return null;
            }

            SingleSteppingEngine result = null;
            thread_db.GetThreadInfo (inferior, delegate (int t_lwp, long t_tid) {
                if (tid != t_tid)
                    return;
                result = (SingleSteppingEngine) thread_hash [t_lwp];

            });

            if (result == null)
                Report.Error ("Cannot find thread {0:x} in {1}",
                          tid, start.CommandLine);

            return result;
        }
コード例 #24
0
            protected override EventResult DoProcessEvent(Inferior.ChildEvent cevent,
							       out TargetEventArgs args)
            {
                args = null;
                bool completed;
                if (cevent.Type == Inferior.ChildEventType.CHILD_INTERRUPTED)
                completed = !ResumeOperation ();
                else
                completed = DoProcessEvent ();

                return completed ? EventResult.Completed : EventResult.Running;
            }
コード例 #25
0
ファイル: Process.cs プロジェクト: baulig/debugger
        internal void InitializeThreads(Inferior inferior, bool resume_threads)
        {
            if (thread_db != null)
                return;

            thread_db = ThreadDB.Create (this, inferior);
            if (thread_db == null) {
                if (!IsManaged)
                    return;

                Report.Error ("Failed to initialize thread_db on {0}", start.CommandLine);
                throw new TargetException (TargetError.CannotStartTarget,
                               "Failed to initialize thread_db on {0}", start.CommandLine);
            }

            int[] threads = inferior.GetThreads ();
            foreach (int thread in threads) {
                if (thread_hash.Contains (thread))
                    continue;
                ThreadCreated (inferior, thread, Inferior.HasThreadEvents, resume_threads);
            }

            thread_db.GetThreadInfo (inferior, delegate (int lwp, long tid) {
                SingleSteppingEngine engine = (SingleSteppingEngine) thread_hash [lwp];
                if (engine == null) {
                    Report.Error ("Unknown thread {0} in {1}", lwp, start.CommandLine);
                    return;
                }
                engine.SetTID (tid);
            });
        }
コード例 #26
0
        internal override void Hack_ReturnNull(Inferior inferior)
        {
            Registers regs = inferior.GetRegisters ();
            TargetAddress rsp = new TargetAddress (
                inferior.AddressDomain, regs [(int) X86_Register.RSP].GetValue ());
            TargetAddress rip = inferior.ReadAddress (rsp);
            rsp += TargetAddressSize;

            regs [(int) X86_Register.RIP].SetValue (rip);
            regs [(int) X86_Register.RSP].SetValue (rsp);
            regs [(int) X86_Register.RAX].SetValue (TargetAddress.Null);

            inferior.SetRegisters (regs);
        }
コード例 #27
0
        void JitBreakpoint(Inferior inferior, int idx, TargetAddress data)
        {
            Method method = read_range_entry (inferior, data);
            if (method == null)
                return;

            MethodLoadedHandler handler = (MethodLoadedHandler) method_load_handlers [idx];
            if (handler != null)
                handler (inferior, method);
        }
コード例 #28
0
            public override EventResult ProcessEvent(Inferior.ChildEvent cevent,
							  out TargetEventArgs args)
            {
                if (((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) &&
                 (cevent.Argument == 0)) ||
                ((cevent.Type != Inferior.ChildEventType.CHILD_CALLBACK) &&
                 (cevent.Type != Inferior.ChildEventType.RUNTIME_INVOKE_DONE))) {
                if (!ReleaseThreadLock (cevent)) {
                    args = null;
                    return EventResult.Running;
                }
                }
                return base.ProcessEvent (cevent, out args);
            }
コード例 #29
0
ファイル: Instruction.cs プロジェクト: baulig/debugger
 public abstract bool InterpretInstruction(Inferior inferior);
コード例 #30
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;
        }