internal void Insert(Inferior inferior) { if (handle == null) handle = new AddressBreakpointHandle (this, address); handle.Insert (inferior); }
public static ThreadDB Create(Process process, Inferior target) { ThreadDB db = new ThreadDB (process); if (!db.Initialize (target)) return null; return db; }
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; }
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 (); } }
internal abstract void UpdateSharedLibraries(Inferior inferior);
public abstract NativeExecutableReader AddExecutableFile(Inferior inferior, string filename, TargetAddress base_address, bool step_info, bool is_loaded);
internal abstract bool CheckForPendingMonoInit(Inferior inferior);
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 (); } }
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; }
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); }
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); }
// <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; }
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; } }
public void SetStopEvent(Inferior.ChildEvent stop_event) { if (StopEvent != null) throw new InternalError (); StopEvent = stop_event; Stopped = true; }
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; }
public void PopRegisters(Inferior inferior) { if (PushedRegisters) inferior.PopRegisters (); PushedRegisters = false; }
public ThreadLockData(bool stopped, Inferior.ChildEvent stop_event, bool pushed_regs) { this.Stopped = stopped; this.StopEvent = stop_event; this.PushedRegisters = pushed_regs; }
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; }
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); }
// // This is a horrible hack - don't use ! // // internal abstract void Hack_ReturnNull(Inferior inferior);
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); }
internal void Remove(Inferior inferior) { if (handle != null) { handle.Remove (inferior); handle = null; } }
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; }
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; }
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); }); }
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); }
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); }
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); }
public abstract bool InterpretInstruction(Inferior inferior);
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; }