internal void InitializeThreads(Inferior inferior) { TargetAddress ptr = inferior.ReadAddress(MonoDebuggerInfo.ThreadTable); while (!ptr.IsNull) { int size; if (MonoDebuggerInfo.CheckRuntimeVersion(81, 3)) { size = 60 + inferior.TargetMemoryInfo.TargetAddressSize; } else { size = 32 + inferior.TargetMemoryInfo.TargetAddressSize; } TargetReader reader = new TargetReader(inferior.ReadMemory(ptr, size)); long tid = reader.ReadLongInteger(); TargetAddress lmf_addr = reader.ReadAddress(); TargetAddress end_stack = reader.ReadAddress(); TargetAddress extended_notifications_addr = ptr + 24; if (inferior.TargetMemoryInfo.TargetAddressSize == 4) { tid &= 0x00000000ffffffffL; } reader.Offset += 8; ptr = reader.ReadAddress(); ThreadFlags flags = ThreadFlags.None; if (MonoDebuggerInfo.CheckRuntimeVersion(81, 3)) { reader.Offset = 56 + inferior.TargetAddressSize; flags = (ThreadFlags)reader.ReadInteger(); } bool found = false; foreach (SingleSteppingEngine engine in process.Engines) { if (engine.TID != tid) { continue; } engine.SetManagedThreadData(lmf_addr, extended_notifications_addr); engine.OnManagedThreadCreated(end_stack); check_thread_flags(engine, flags); found = true; break; } if (!found) { Report.Error("Cannot find thread {0:x} in {1}", tid, process.ProcessStart.CommandLine); } } }
protected void initialize_notifications(Inferior inferior) { TargetAddress executable_code_buffer = inferior.ReadAddress( debugger_info.ExecutableCodeBuffer); HasCodeBuffer = !executable_code_buffer.IsNull; mono_runtime_info = mono_debugger_server_initialize_mono_runtime( inferior.TargetAddressSize, debugger_info.NotificationAddress.Address, executable_code_buffer.Address, debugger_info.ExecutableCodeBufferSize, debugger_info.BreakpointInfo.Address, debugger_info.BreakpointInfoIndex.Address, debugger_info.BreakpointArraySize); inferior.SetRuntimeInfo(mono_runtime_info); debugger_version = inferior.ReadInteger(debugger_info.DebuggerVersion); if (notification_bpt != null) { notification_bpt.Remove(inferior); notification_bpt = null; } if (debugger_info.HasThreadAbortSignal) { thread_abort_signal = inferior.ReadInteger(debugger_info.ThreadAbortSignal); } else { thread_abort_signal = inferior.MonoThreadAbortSignal; } }
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); }
void check_nptl_setxid(Inferior inferior, Bfd bfd) { if (setxid_breakpoint != null) { return; } TargetAddress vtable = bfd.LookupSymbol("__libc_pthread_functions"); if (vtable.IsNull) { return; } /* * Big big hack to allow debugging gnome-vfs: * We intercept any calls to __nptl_setxid() and make it * return 0. This is safe to do since we do not allow * debugging setuid programs or running as root, so setxid() * will always be a no-op anyways. */ TargetAddress nptl_setxid = inferior.ReadAddress(vtable + 51 * inferior.TargetAddressSize); if (!nptl_setxid.IsNull) { setxid_breakpoint = new SetXidBreakpoint(this, nptl_setxid); setxid_breakpoint.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 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); }
internal override bool CheckForPendingMonoInit(Inferior inferior) { if (pending_mono_init.IsNull) { return(false); } TargetAddress data = inferior.ReadAddress(pending_mono_init); if (data.IsNull) { return(false); } pending_mono_init = TargetAddress.Null; Process.InitializeMono(inferior, data); return(true); }
protected void initialize_notifications(Inferior inferior) { TargetAddress executable_code_buffer = inferior.ReadAddress ( debugger_info.ExecutableCodeBuffer); HasCodeBuffer = !executable_code_buffer.IsNull; mono_runtime_info = mono_debugger_server_initialize_mono_runtime ( inferior.TargetAddressSize, debugger_info.NotificationAddress.Address, executable_code_buffer.Address, debugger_info.ExecutableCodeBufferSize, debugger_info.BreakpointInfo.Address, debugger_info.BreakpointInfoIndex.Address, debugger_info.BreakpointArraySize); inferior.SetRuntimeInfo (mono_runtime_info); debugger_version = inferior.ReadInteger (debugger_info.DebuggerVersion); if (notification_bpt != null) { notification_bpt.Remove (inferior); notification_bpt = null; } if (debugger_info.HasThreadAbortSignal) thread_abort_signal = inferior.ReadInteger (debugger_info.ThreadAbortSignal); else thread_abort_signal = inferior.MonoThreadAbortSignal; }
internal void InitializeThreads(Inferior inferior) { TargetAddress ptr = inferior.ReadAddress (MonoDebuggerInfo.ThreadTable); while (!ptr.IsNull) { int size; if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3)) size = 60 + inferior.TargetMemoryInfo.TargetAddressSize; else size = 32 + inferior.TargetMemoryInfo.TargetAddressSize; TargetReader reader = new TargetReader (inferior.ReadMemory (ptr, size)); long tid = reader.ReadLongInteger (); TargetAddress lmf_addr = reader.ReadAddress (); TargetAddress end_stack = reader.ReadAddress (); TargetAddress extended_notifications_addr = ptr + 24; if (inferior.TargetMemoryInfo.TargetAddressSize == 4) tid &= 0x00000000ffffffffL; reader.Offset += 8; ptr = reader.ReadAddress (); ThreadFlags flags = ThreadFlags.None; if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3)) { reader.Offset = 56 + inferior.TargetAddressSize; flags = (ThreadFlags) reader.ReadInteger (); } bool found = false; foreach (SingleSteppingEngine engine in process.Engines) { if (engine.TID != tid) continue; engine.SetManagedThreadData (lmf_addr, extended_notifications_addr); engine.OnManagedThreadCreated (end_stack); check_thread_flags (engine, flags); found = true; break; } if (!found) Report.Error ("Cannot find thread {0:x} in {1}", tid, process.ProcessStart.CommandLine); } }
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; }
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); } }
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); }