/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A variable to be passed to the thread function.</param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread"/> class.</returns> public RemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { // Marshal the parameter var marshalledParameter = MarshalValue.Marshal(MemorySharp, parameter); //Create the thread var ret = ThreadCore.NtQueryInformationThread( ThreadCore.CreateRemoteThread(MemorySharp.Handle, address, marshalledParameter.Reference, ThreadCreationFlags.Suspended)); // Find the managed object corresponding to this thread var result = new RemoteThread(MemorySharp, MemorySharp.Threads.NativeThreads.First(t => t.Id == ret.ThreadId), marshalledParameter); // If the thread must be started if (isStarted) result.Resume(); return result; }
/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread"/> class.</returns> public RemoteThread Create(IntPtr address, bool isStarted = true) { //Create the thread var ret = ThreadCore.NtQueryInformationThread( ThreadCore.CreateRemoteThread(MemorySharp.Handle, address, IntPtr.Zero, ThreadCreationFlags.Suspended)); // Find the managed object corresponding to this thread var result = new RemoteThread(MemorySharp, MemorySharp.Threads.NativeThreads.First(t => t.Id == ret.ThreadId)); // If the thread must be started if (isStarted) result.Resume(); return result; }
/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread"/> class.</returns> public RemoteThread Create(IntPtr address, bool isStarted = true) { // Create the thread var ret = ThreadCore.NtQueryInformationThread( ThreadCore.CreateRemoteThread(MemorySharp.Handle, address, IntPtr.Zero, ThreadCreationFlags.Suspended)); // Get the native thread previously created // Loop until the native thread is retrieved ProcessThread nativeThread; do { nativeThread = MemorySharp.Threads.NativeThreads.FirstOrDefault(t => t.Id == ret.ThreadId); } while (nativeThread == null); // Wrap the native thread in an object of the library var result = new RemoteThread(MemorySharp, nativeThread); // If the thread must be started if (isStarted) result.Resume(); return result; }
/// <summary> /// Initializes a new instance of the <see cref="FrozenThread"/> class. /// </summary> /// <param name="thread">The frozen thread.</param> internal FrozenThread(RemoteThread thread) { // Save the parameter Thread = thread; }
/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A variable to be passed to the thread function.</param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread"/> class.</returns> public RemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { // Marshal the parameter var marshalledParameter = MarshalValue.Marshal(MemorySharp, parameter); //Create the thread var ret = ThreadCore.NtQueryInformationThread( ThreadCore.CreateRemoteThread(MemorySharp.Handle, address, marshalledParameter.Reference, ThreadCreationFlags.Suspended)); // Get the native thread previously created // Loop until the native thread is retrieved ProcessThread nativeThread; do { nativeThread = MemorySharp.Threads.NativeThreads.FirstOrDefault(t => t.Id == ret.ThreadId); } while (nativeThread == null); // Find the managed object corresponding to this thread var result = new RemoteThread(MemorySharp, nativeThread, marshalledParameter); // If the thread must be started if (isStarted) result.Resume(); return result; }
DebugThreadAsync(ITaskExecutor taskExecutor, FrameEnumFactory frameEnumFactory, StackFramesProvider stackFramesProvider, RemoteThread lldbThread) : base( taskExecutor, frameEnumFactory, stackFramesProvider, lldbThread) { }
/// <summary> /// Creator for unit tests. /// </summary> /// <param name="stackFramesProvider"></param> /// <param name="lldbThread"></param> /// <returns></returns> public virtual IDebugThreadAsync CreateForTesting( StackFramesProvider stackFramesProvider, RemoteThread lldbThread) => new DebugThreadAsync(_taskExecutor, _frameEnumFactory, stackFramesProvider, lldbThread);
// Called when we receive a state changed LLDB event. void OnStateChangedEvent(SbEvent sbEvent) { if (sbEvent == null) { return; } var type = sbEvent.GetStateType(); Debug.WriteLine("Received LLDB event: " + Enum.GetName(type.GetType(), type)); switch (type) { case StateType.STOPPED: if (sbEvent.GetProcessRestarted()) { break; } var currentThread = _lldbProcess.GetSelectedThread(); var currentStopReason = StopReason.INVALID; if (currentThread != null) { currentStopReason = currentThread.GetStopReason(); } // When stopping pick the most relevant thread based on the stop reason. if (currentThread == null || currentStopReason == StopReason.INVALID || currentStopReason == StopReason.NONE) { int numThreads = _lldbProcess.GetNumThreads(); RemoteThread planThread = null; RemoteThread otherThread = null; for (int i = 0; i < numThreads; ++i) { RemoteThread thread = _lldbProcess.GetThreadAtIndex(i); switch (thread.GetStopReason()) { case StopReason.INVALID: // fall-through case StopReason.NONE: break; case StopReason.SIGNAL: if (otherThread == null) { var signalNumber = thread.GetStopReasonDataAtIndex(0); var unixSignals = _lldbProcess.GetUnixSignals(); if (unixSignals != null && unixSignals.GetShouldStop((int)signalNumber)) { otherThread = thread; } } break; case StopReason.TRACE: // fall-through case StopReason.BREAKPOINT: // fall-through case StopReason.WATCHPOINT: // fall-through case StopReason.EXCEPTION: // fall-through case StopReason.EXEC: // fall-through case StopReason.EXITING: // fall-through case StopReason.INSTRUMENTATION: if (otherThread == null) { otherThread = thread; } break; case StopReason.PLAN_COMPLETE: if (planThread == null) { planThread = thread; } break; } } if (planThread != null) { currentThread = planThread; } else if (otherThread != null) { currentThread = otherThread; } else if (currentThread == null) { currentThread = _lldbProcess.GetThreadAtIndex(0); } if (currentThread == null) { Trace.WriteLine("Error: Cannot handle event. No thread found."); return; } _lldbProcess.SetSelectedThreadById(currentThread.GetThreadId()); currentStopReason = currentThread.GetStopReason(); } // Log specific information about the stop event. string message = "Received stop event. Reason: " + currentStopReason; var stopReasonDataCount = currentThread.GetStopReasonDataCount(); if (stopReasonDataCount > 0) { message += " Data:"; for (uint i = 0; i < stopReasonDataCount; i++) { message += " " + currentThread.GetStopReasonDataAtIndex(i); } } Trace.WriteLine(message); _taskContext.Factory.Run(async() => { // We run the event resolution on the main thread to make sure // we do not race with concurrent modifications in the breakpoint // manager class (we could just have hit breakpoint that is being // added by the main thread!). await _taskContext.Factory.SwitchToMainThreadAsync(); DebugEvent eventToSend = null; switch (currentStopReason) { case StopReason.BREAKPOINT: eventToSend = HandleBreakpointStop(currentThread); break; case StopReason.WATCHPOINT: eventToSend = HandleWatchpointStop(currentThread); break; case StopReason.SIGNAL: eventToSend = HandleSignalStop(currentThread); break; case StopReason.PLAN_COMPLETE: eventToSend = new StepCompleteEvent(); break; default: break; } if (eventToSend == null) { eventToSend = new BreakEvent(); } _debugEngineHandler.SendEvent(eventToSend,_program,currentThread); }); break; case StateType.EXITED: { // There are two ways to exit a debug session without an error: // - We call program.Terminate, which causes LLDB to send this event. // - Program exits by itself, resulting in this event. // We distinguish these events by checking if we called Terminate. ExitReason exitReason = _program.TerminationRequested ? ExitReason.DebuggerTerminated : ExitReason.ProcessExited; _debugEngineHandler.Abort(_program,ExitInfo.Normal(exitReason)); } break; case StateType.DETACHED: { // Normally the only way to detach the process is by program.Detach. // However, this check was retained to mirror the EXITED case and to // record unexpected instances of detaching through some other path. ExitReason exitReason = _program.DetachRequested ? ExitReason.DebuggerDetached : ExitReason.ProcessDetached; _debugEngineHandler.Abort(_program,ExitInfo.Normal(exitReason)); } break; } }
public int SendEvent(DebugEvent evnt, IGgpDebugProgram program, RemoteThread thread) => SendEvent(evnt, program, program.GetDebugThread(thread));