void check_for_mono_runtime(Inferior inferior, Bfd bfd) { TargetAddress info = bfd.GetSectionAddress(".mdb_debug_info"); if (info.IsNull) { return; } TargetAddress data = inferior.ReadAddress(info); if (data.IsNull) { // // See CheckForPendingMonoInit() below - this should only happen when // the Mono runtime is embedded - for instance Moonlight inside Firefox. // // Note that we have to do a symbol lookup for it because we do not know // whether the mono runtime is recent enough to have this variable. // data = bfd.LookupSymbol("MONO_DEBUGGER__using_debugger"); if (data.IsNull) { Report.Error("Failed to initialize the Mono runtime!"); return; } inferior.WriteInteger(data, 1); pending_mono_init = info; return; } Process.InitializeMono(inferior, data); }
internal Queue <ManagedCallbackData> ClearManagedCallbacks(Inferior inferior) { inferior.WriteInteger(MonoDebuggerInfo.InterruptionRequest, 0); Queue <ManagedCallbackData> retval = managed_callbacks; managed_callbacks = new Queue <ManagedCallbackData> (); return(retval); }
protected MonoThreadManager(Process process, Inferior inferior, MonoDebuggerInfo debugger_info) { this.process = process; this.debugger_info = debugger_info; inferior.WriteInteger(debugger_info.UsingMonoDebugger, 1); notification_bpt = new InitializeBreakpoint(this, debugger_info.Initialize); notification_bpt.Insert(inferior); }
void check_for_mono_runtime(Inferior inferior, Bfd bfd) { TargetAddress info = bfd.LookupSymbol("MONO_DEBUGGER__debugger_info_ptr"); if (info.IsNull) { return; } TargetAddress data = inferior.ReadAddress(info); if (data.IsNull) { // // See CheckForPendingMonoInit() below - this should only happen when // the Mono runtime is embedded - for instance Moonlight inside Firefox. // // Note that we have to do a symbol lookup for it because we do not know // whether the mono runtime is recent enough to have this variable. // data = bfd.LookupSymbol("MONO_DEBUGGER__using_debugger"); if (data.IsNull) { Report.Error("Failed to initialize the Mono runtime!"); return; } inferior.WriteInteger(data, 1); pending_mono_init = info; // Add a breakpoint in mini_debugger_init, to make sure that InitializeMono() // gets called in time to set the breakpoint at debugger_initialize, needed to // initialize the notifications. TargetAddress mini_debugger_init = bfd.LookupSymbol("mini_debugger_init"); if (!mini_debugger_init.IsNull) { Instruction insn = inferior.Architecture.ReadInstruction(inferior, mini_debugger_init); if ((insn == null) || !insn.CanInterpretInstruction) { throw new InternalError("Unknown dynlink breakpoint: {0}", mini_debugger_init); } DynlinkBreakpoint init_breakpoint = new DynlinkBreakpoint(this, insn); init_breakpoint.Insert(inferior); } return; } Process.InitializeMono(inferior, data); }
internal bool InitializeAfterAttach(Inferior inferior) { initialize_notifications(inferior); inferior.WriteAddress(debugger_info.ThreadVTablePtr, debugger_info.ThreadVTable); inferior.WriteAddress(debugger_info.EventHandlerPtr, debugger_info.EventHandler); inferior.WriteInteger(debugger_info.UsingMonoDebugger, 1); csharp_language = inferior.Process.CreateMonoLanguage(debugger_info); csharp_language.InitializeAttach(inferior); return(true); }
internal bool InitializeAfterAttach(Inferior inferior) { initialize_notifications (inferior); inferior.WriteAddress (debugger_info.ThreadVTablePtr, debugger_info.ThreadVTable); inferior.WriteAddress (debugger_info.EventHandlerPtr, debugger_info.EventHandler); inferior.WriteInteger (debugger_info.UsingMonoDebugger, 1); csharp_language = inferior.Process.CreateMonoLanguage (debugger_info); csharp_language.InitializeAttach (inferior); return true; }
internal bool HandleChildEvent(SingleSteppingEngine engine, Inferior inferior, ref Inferior.ChildEvent cevent, out bool resume_target) { if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION) { NotificationType type = (NotificationType) cevent.Argument; Report.Debug (DebugFlags.EventLoop, "{0} received notification {1}: {2}", engine, type, cevent); switch (type) { case NotificationType.AcquireGlobalThreadLock: Report.Debug (DebugFlags.Threads, "{0} received notification {1}", engine, type); engine.Process.AcquireGlobalThreadLock (engine); break; case NotificationType.ReleaseGlobalThreadLock: Report.Debug (DebugFlags.Threads, "{0} received notification {1}", engine, type); engine.Process.ReleaseGlobalThreadLock (engine); break; case NotificationType.ThreadCreated: { TargetAddress data = new TargetAddress ( inferior.AddressDomain, cevent.Data2); TargetAddress lmf = inferior.ReadAddress (data + 8); engine.SetManagedThreadData (lmf, data + 24); if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3)) { int flags_offset = 56 + inferior.TargetAddressSize; ThreadFlags flags = (ThreadFlags) inferior.ReadInteger (data + flags_offset); check_thread_flags (engine, flags); } Report.Debug (DebugFlags.Threads, "{0} managed thread created: {1:x} {2} {3} - {4}", engine, cevent.Data1, data, lmf, engine.LMFAddress); break; } case NotificationType.ThreadCleanup: { TargetAddress data = new TargetAddress ( inferior.AddressDomain, cevent.Data1); Report.Debug (DebugFlags.Threads, "{0} managed thread cleanup: {1:x} {2}", engine, cevent.Data2, data); break; } case NotificationType.GcThreadCreated: { TargetAddress data = new TargetAddress ( inferior.AddressDomain, cevent.Data1); long tid = cevent.Data2; Report.Debug (DebugFlags.Threads, "{0} created gc thread: {1:x} {2}", engine, tid, data); engine = engine.Process.GetEngineByTID (inferior, tid); if (engine == null) throw new InternalError (); engine.OnManagedThreadCreated (data); break; } case NotificationType.GcThreadExited: Report.Debug (DebugFlags.Threads, "{0} gc thread exited", engine); engine.OnManagedThreadExited (); try { inferior.Continue (); } catch { // Ignore errors; for some reason, the thread may have died // already by the time get this notification. } resume_target = false; return true; case NotificationType.InitializeThreadManager: csharp_language = inferior.Process.CreateMonoLanguage ( debugger_info); if (engine.Process.IsAttached) csharp_language.InitializeAttach (inferior); else csharp_language.Initialize (inferior); break; case NotificationType.ReachedMain: { Inferior.StackFrame iframe = inferior.GetCurrentFrame (false); engine.SetMainReturnAddress (iframe.StackPointer); engine.Process.OnProcessReachedMainEvent (); resume_target = !engine.InitializeBreakpoints (); return true; } case NotificationType.WrapperMain: break; case NotificationType.MainExited: engine.SetMainReturnAddress (TargetAddress.Null); break; case NotificationType.UnhandledException: cevent = new Inferior.ChildEvent ( Inferior.ChildEventType.UNHANDLED_EXCEPTION, 0, cevent.Data1, cevent.Data2); resume_target = false; return false; case NotificationType.HandleException: cevent = new Inferior.ChildEvent ( Inferior.ChildEventType.HANDLE_EXCEPTION, 0, cevent.Data1, cevent.Data2); resume_target = false; return false; case NotificationType.ThrowException: cevent = new Inferior.ChildEvent ( Inferior.ChildEventType.THROW_EXCEPTION, 0, cevent.Data1, cevent.Data2); resume_target = false; return false; case NotificationType.FinalizeManagedCode: mono_debugger_server_finalize_mono_runtime (mono_runtime_info); mono_runtime_info = IntPtr.Zero; csharp_language = null; break; case NotificationType.OldTrampoline: case NotificationType.Trampoline: resume_target = false; return false; case NotificationType.ClassInitialized: break; case NotificationType.InterruptionRequest: inferior.WriteInteger (MonoDebuggerInfo.InterruptionRequest, 0); var callbacks = managed_callbacks; managed_callbacks = new Queue<ManagedCallbackData> (); resume_target = !engine.OnManagedCallback (callbacks); return true; default: { TargetAddress data = new TargetAddress ( inferior.AddressDomain, cevent.Data1); resume_target = csharp_language.Notification ( engine, inferior, type, data, cevent.Data2); return true; } } resume_target = true; return true; } if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument == thread_abort_signal)) { resume_target = true; return true; } if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument != 0) && ! engine.Process.Session.Config.StopOnManagedSignals) { if (inferior.IsManagedSignal ((int) cevent.Argument)) { resume_target = true; return true; } } resume_target = false; return false; }
internal void Detach(Inferior inferior) { inferior.WriteAddress (debugger_info.ThreadVTablePtr, TargetAddress.Null); inferior.WriteAddress (debugger_info.EventHandler, TargetAddress.Null); inferior.WriteInteger (debugger_info.UsingMonoDebugger, 0); }
internal Queue<ManagedCallbackData> ClearManagedCallbacks(Inferior inferior) { inferior.WriteInteger (MonoDebuggerInfo.InterruptionRequest, 0); Queue<ManagedCallbackData> retval = managed_callbacks; managed_callbacks = new Queue<ManagedCallbackData> (); return retval; }
internal void AddManagedCallback(Inferior inferior, ManagedCallbackData data) { inferior.WriteInteger (MonoDebuggerInfo.InterruptionRequest, 1); managed_callbacks.Enqueue (data); }
protected MonoThreadManager(Process process, Inferior inferior, MonoDebuggerInfo debugger_info) { this.process = process; this.debugger_info = debugger_info; inferior.WriteInteger (debugger_info.UsingMonoDebugger, 1); notification_bpt = new InitializeBreakpoint (this, debugger_info.Initialize); notification_bpt.Insert (inferior); }
internal bool HandleChildEvent(SingleSteppingEngine engine, Inferior inferior, ref Inferior.ChildEvent cevent, out bool resume_target) { if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION) { NotificationType type = (NotificationType)cevent.Argument; Report.Debug(DebugFlags.EventLoop, "{0} received notification {1}: {2}", engine, type, cevent); switch (type) { case NotificationType.AcquireGlobalThreadLock: Report.Debug(DebugFlags.Threads, "{0} received notification {1}", engine, type); engine.Process.AcquireGlobalThreadLock(engine); break; case NotificationType.ReleaseGlobalThreadLock: Report.Debug(DebugFlags.Threads, "{0} received notification {1}", engine, type); engine.Process.ReleaseGlobalThreadLock(engine); break; case NotificationType.ThreadCreated: { TargetAddress data = new TargetAddress( inferior.AddressDomain, cevent.Data2); TargetAddress lmf = inferior.ReadAddress(data + 8); engine.SetManagedThreadData(lmf, data + 24); if (MonoDebuggerInfo.CheckRuntimeVersion(81, 3)) { int flags_offset = 56 + inferior.TargetAddressSize; ThreadFlags flags = (ThreadFlags)inferior.ReadInteger(data + flags_offset); check_thread_flags(engine, flags); } Report.Debug(DebugFlags.Threads, "{0} managed thread created: {1:x} {2} {3} - {4}", engine, cevent.Data1, data, lmf, engine.LMFAddress); break; } case NotificationType.ThreadCleanup: { TargetAddress data = new TargetAddress( inferior.AddressDomain, cevent.Data1); Report.Debug(DebugFlags.Threads, "{0} managed thread cleanup: {1:x} {2}", engine, cevent.Data2, data); break; } case NotificationType.GcThreadCreated: { TargetAddress data = new TargetAddress( inferior.AddressDomain, cevent.Data1); long tid = cevent.Data2; Report.Debug(DebugFlags.Threads, "{0} created gc thread: {1:x} {2}", engine, tid, data); engine = engine.Process.GetEngineByTID(inferior, tid); if (engine == null) { throw new InternalError(); } engine.OnManagedThreadCreated(data); break; } case NotificationType.GcThreadExited: Report.Debug(DebugFlags.Threads, "{0} gc thread exited", engine); engine.OnManagedThreadExited(); try { inferior.Continue(); } catch { // Ignore errors; for some reason, the thread may have died // already by the time get this notification. } resume_target = false; return(true); case NotificationType.InitializeThreadManager: csharp_language = inferior.Process.CreateMonoLanguage( debugger_info); if (engine.Process.IsAttached) { csharp_language.InitializeAttach(inferior); } else { csharp_language.Initialize(inferior); } break; case NotificationType.ReachedMain: { Inferior.StackFrame iframe = inferior.GetCurrentFrame(false); engine.SetMainReturnAddress(iframe.StackPointer); engine.Process.OnProcessReachedMainEvent(); resume_target = !engine.InitializeBreakpoints(); return(true); } case NotificationType.WrapperMain: break; case NotificationType.MainExited: engine.SetMainReturnAddress(TargetAddress.Null); break; case NotificationType.UnhandledException: cevent = new Inferior.ChildEvent( Inferior.ChildEventType.UNHANDLED_EXCEPTION, 0, cevent.Data1, cevent.Data2); resume_target = false; return(false); case NotificationType.HandleException: cevent = new Inferior.ChildEvent( Inferior.ChildEventType.HANDLE_EXCEPTION, 0, cevent.Data1, cevent.Data2); resume_target = false; return(false); case NotificationType.ThrowException: cevent = new Inferior.ChildEvent( Inferior.ChildEventType.THROW_EXCEPTION, 0, cevent.Data1, cevent.Data2); resume_target = false; return(false); case NotificationType.FinalizeManagedCode: mono_debugger_server_finalize_mono_runtime(mono_runtime_info); mono_runtime_info = IntPtr.Zero; csharp_language = null; break; case NotificationType.OldTrampoline: case NotificationType.Trampoline: resume_target = false; return(false); case NotificationType.ClassInitialized: break; case NotificationType.InterruptionRequest: inferior.WriteInteger(MonoDebuggerInfo.InterruptionRequest, 0); var callbacks = managed_callbacks; managed_callbacks = new Queue <ManagedCallbackData> (); resume_target = !engine.OnManagedCallback(callbacks); return(true); default: { TargetAddress data = new TargetAddress( inferior.AddressDomain, cevent.Data1); resume_target = csharp_language.Notification( engine, inferior, type, data, cevent.Data2); return(true); } } resume_target = true; return(true); } if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument == thread_abort_signal)) { resume_target = true; return(true); } if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument != 0) && ! engine.Process.Session.Config.StopOnManagedSignals) { if (inferior.IsManagedSignal((int)cevent.Argument)) { resume_target = true; return(true); } } resume_target = false; return(false); }
internal void AddManagedCallback(Inferior inferior, ManagedCallbackData data) { inferior.WriteInteger(MonoDebuggerInfo.InterruptionRequest, 1); managed_callbacks.Enqueue(data); }
internal void Detach(Inferior inferior) { inferior.WriteAddress(debugger_info.ThreadVTablePtr, TargetAddress.Null); inferior.WriteAddress(debugger_info.EventHandler, TargetAddress.Null); inferior.WriteInteger(debugger_info.UsingMonoDebugger, 0); }