mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-27 22:06:24 +02:00
gdb: Support continue specific threads
This commit is contained in:
parent
b932905053
commit
625ca3f934
3 changed files with 45 additions and 7 deletions
|
@ -411,13 +411,13 @@ namespace Ryujinx.HLE.Debugger
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DebugProcess.GetDebugState() == DebugState.Stopped)
|
if (DebugProcess.IsThreadPaused(DebugProcess.GetThread(threadId.Value)))
|
||||||
{
|
{
|
||||||
Reply(ToHex("Stopped"));
|
Reply(ToHex("Paused"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reply(ToHex("Not stopped"));
|
Reply(ToHex("Running"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -625,6 +625,8 @@ namespace Ryujinx.HLE.Debugger
|
||||||
threadActionMap[thread.ThreadUid] = new VContPendingAction(VContAction.None);
|
threadActionMap[thread.ThreadUid] = new VContPendingAction(VContAction.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VContAction defaultAction = VContAction.None;
|
||||||
|
|
||||||
// For each inferior thread, the *leftmost* action with a matching thread-id is applied.
|
// For each inferior thread, the *leftmost* action with a matching thread-id is applied.
|
||||||
for (int i = rawActions.Length - 1; i >= 0; i--)
|
for (int i = rawActions.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
@ -642,6 +644,7 @@ namespace Ryujinx.HLE.Debugger
|
||||||
_ => VContAction.None
|
_ => VContAction.None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Note: We don't support signals yet.
|
||||||
ushort? signal = null;
|
ushort? signal = null;
|
||||||
if (cmd == 'C' || cmd == 'S')
|
if (cmd == 'C' || cmd == 'S')
|
||||||
{
|
{
|
||||||
|
@ -666,12 +669,17 @@ namespace Ryujinx.HLE.Debugger
|
||||||
{
|
{
|
||||||
threadActionMap[row.Key] = new VContPendingAction(action, signal);
|
threadActionMap[row.Key] = new VContPendingAction(action, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action == VContAction.Continue) {
|
||||||
|
defaultAction = action;
|
||||||
|
} else {
|
||||||
|
Logger.Warning?.Print(LogClass.GdbStub, $"Received vCont command with unsupported default action: {rawAction}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
|
|
||||||
// TODO: We don't support stop or continue yet, and we don't support signals.
|
|
||||||
foreach (var (threadUid, action) in threadActionMap)
|
foreach (var (threadUid, action) in threadActionMap)
|
||||||
{
|
{
|
||||||
if (action.Action == VContAction.Step)
|
if (action.Action == VContAction.Step)
|
||||||
|
@ -683,10 +691,20 @@ namespace Ryujinx.HLE.Debugger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all threads are set to continue, continue the process.
|
// If we receive "vCont;c", just continue the process.
|
||||||
|
// If we receive something like "vCont;c:2e;c:2f" (IDA Pro will send commands like this), continue these threads.
|
||||||
|
// For "vCont;s:2f;c", we only step thread 2f, and do not continue other threads. (Is this correct?)
|
||||||
if (threadActionMap.Values.All(a => a.Action == VContAction.Continue))
|
if (threadActionMap.Values.All(a => a.Action == VContAction.Continue))
|
||||||
{
|
{
|
||||||
DebugProcess.DebugContinue();
|
DebugProcess.DebugContinue();
|
||||||
|
} else if (defaultAction == VContAction.None) {
|
||||||
|
foreach (var (threadUid, action) in threadActionMap)
|
||||||
|
{
|
||||||
|
if (action.Action == VContAction.Continue)
|
||||||
|
{
|
||||||
|
DebugProcess.DebugContinue(DebugProcess.GetThread(threadUid));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasError)
|
if (hasError)
|
||||||
|
@ -716,7 +734,7 @@ namespace Ryujinx.HLE.Debugger
|
||||||
foreach (var thread in GetThreads())
|
foreach (var thread in GetThreads())
|
||||||
{
|
{
|
||||||
string threadName = System.Security.SecurityElement.Escape(thread.GetThreadName());
|
string threadName = System.Security.SecurityElement.Escape(thread.GetThreadName());
|
||||||
sb.Append($"<thread id=\"{thread.ThreadUid:x}\" name=\"{threadName}\" />\n");
|
sb.Append($"<thread id=\"{thread.ThreadUid:x}\" name=\"{threadName}\">{(DebugProcess.IsThreadPaused(thread) ? "Paused" : "Running")}</thread>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.Append("</threads>");
|
sb.Append("</threads>");
|
||||||
|
|
|
@ -8,9 +8,11 @@ namespace Ryujinx.HLE.Debugger
|
||||||
{
|
{
|
||||||
void DebugStop();
|
void DebugStop();
|
||||||
void DebugContinue();
|
void DebugContinue();
|
||||||
|
void DebugContinue(KThread thread);
|
||||||
bool DebugStep(KThread thread);
|
bool DebugStep(KThread thread);
|
||||||
KThread GetThread(ulong threadUid);
|
KThread GetThread(ulong threadUid);
|
||||||
DebugState GetDebugState();
|
DebugState GetDebugState();
|
||||||
|
bool IsThreadPaused(KThread thread);
|
||||||
ulong[] GetThreadUids();
|
ulong[] GetThreadUids();
|
||||||
public void DebugInterruptHandler(IExecutionContext ctx);
|
public void DebugInterruptHandler(IExecutionContext ctx);
|
||||||
IVirtualMemoryManager CpuMemory { get; }
|
IVirtualMemoryManager CpuMemory { get; }
|
||||||
|
|
|
@ -1257,12 +1257,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
_kernelContext.CriticalSection.Leave();
|
_kernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DebugContinue(KThread target)
|
||||||
|
{
|
||||||
|
Interlocked.Exchange(ref _parent.debugState, (int)DebugState.Running);
|
||||||
|
|
||||||
|
_kernelContext.CriticalSection.Enter();
|
||||||
|
lock (_parent._threadingLock)
|
||||||
|
{
|
||||||
|
target.Resume(ThreadSchedState.ThreadPauseFlag);
|
||||||
|
}
|
||||||
|
_kernelContext.CriticalSection.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
public bool DebugStep(KThread target)
|
public bool DebugStep(KThread target)
|
||||||
{
|
{
|
||||||
if (_parent.debugState != (int)DebugState.Stopped)
|
if (!IsThreadPaused(target))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_kernelContext.CriticalSection.Enter();
|
_kernelContext.CriticalSection.Enter();
|
||||||
steppingThread = target;
|
steppingThread = target;
|
||||||
bool waiting = target.MutexOwner != null || target.WaitingSync || target.WaitingInArbitration;
|
bool waiting = target.MutexOwner != null || target.WaitingSync || target.WaitingInArbitration;
|
||||||
|
@ -1322,6 +1335,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return (DebugState)_parent.debugState;
|
return (DebugState)_parent.debugState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsThreadPaused(KThread target)
|
||||||
|
{
|
||||||
|
return (target.SchedFlags & ThreadSchedState.ThreadPauseFlag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public ulong[] GetThreadUids()
|
public ulong[] GetThreadUids()
|
||||||
{
|
{
|
||||||
lock (_parent._threadingLock)
|
lock (_parent._threadingLock)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue