mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-27 19:56:23 +02:00
gdb: Implement vCont to support step on AArch32
This commit is contained in:
parent
44f4e9af51
commit
7d5f7bc479
1 changed files with 123 additions and 2 deletions
|
@ -6,6 +6,7 @@ using Ryujinx.HLE.HOS.Kernel.Threading;
|
|||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
@ -230,6 +231,7 @@ namespace Ryujinx.HLE.Debugger
|
|||
|
||||
case ThreadBreakMessage { Context: var ctx }:
|
||||
DebugProcess.DebugStop();
|
||||
gThread = cThread = ctx.ThreadUid;
|
||||
Reply($"T05thread:{ctx.ThreadUid:x};");
|
||||
break;
|
||||
|
||||
|
@ -370,7 +372,7 @@ namespace Ryujinx.HLE.Debugger
|
|||
|
||||
if (ss.ConsumePrefix("Supported:") || ss.ConsumeRemaining("Supported"))
|
||||
{
|
||||
Reply("PacketSize=10000;qXfer:features:read+;qXfer:threads:read+");
|
||||
Reply("PacketSize=10000;qXfer:features:read+;qXfer:threads:read+;vContSupported+");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -490,6 +492,22 @@ namespace Ryujinx.HLE.Debugger
|
|||
break;
|
||||
}
|
||||
case 'v':
|
||||
if (ss.ConsumePrefix("Cont"))
|
||||
{
|
||||
if (ss.ConsumeRemaining("?"))
|
||||
{
|
||||
Reply("vCont;c;C;s;S");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ss.ConsumePrefix(";"))
|
||||
{
|
||||
HandleVContCommand(ss);
|
||||
break;
|
||||
}
|
||||
|
||||
goto unknownCommand;
|
||||
}
|
||||
if (ss.ConsumeRemaining("MustReplyEmpty"))
|
||||
{
|
||||
Reply("");
|
||||
|
@ -504,6 +522,109 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
enum VContAction
|
||||
{
|
||||
None,
|
||||
Continue,
|
||||
Stop,
|
||||
Step
|
||||
}
|
||||
|
||||
record VContPendingAction(VContAction Action, ushort? Signal = null);
|
||||
|
||||
private void HandleVContCommand(StringStream ss)
|
||||
{
|
||||
string[] rawActions = ss.ReadRemaining().Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var threadActionMap = new Dictionary<ulong, VContPendingAction>();
|
||||
foreach (var thread in GetThreads())
|
||||
{
|
||||
threadActionMap[thread.ThreadUid] = new VContPendingAction(VContAction.None);
|
||||
}
|
||||
|
||||
// For each inferior thread, the *leftmost* action with a matching thread-id is applied.
|
||||
for (int i = rawActions.Length - 1; i >= 0; i--)
|
||||
{
|
||||
var rawAction = rawActions[i];
|
||||
var stream = new StringStream(rawAction);
|
||||
|
||||
char cmd = stream.ReadChar();
|
||||
VContAction action = cmd switch
|
||||
{
|
||||
'c' => VContAction.Continue,
|
||||
'C' => VContAction.Continue,
|
||||
's' => VContAction.Step,
|
||||
'S' => VContAction.Step,
|
||||
't' => VContAction.Stop,
|
||||
_ => VContAction.None
|
||||
};
|
||||
|
||||
ushort? signal = null;
|
||||
if (cmd == 'C' || cmd == 'S')
|
||||
{
|
||||
signal = (ushort)stream.ReadLengthAsHex(2);
|
||||
}
|
||||
|
||||
ulong? threadId = null;
|
||||
if (stream.ConsumePrefix(":"))
|
||||
{
|
||||
threadId = stream.ReadRemainingAsThreadUid();
|
||||
}
|
||||
|
||||
if (threadId.HasValue)
|
||||
{
|
||||
if (threadActionMap.ContainsKey(threadId.Value)) {
|
||||
threadActionMap[threadId.Value] = new VContPendingAction(action, signal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var row in threadActionMap.ToList())
|
||||
{
|
||||
threadActionMap[row.Key] = new VContPendingAction(action, signal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool hasError = false;
|
||||
|
||||
// TODO: We don't support stop or continue yet, and we don't support signals.
|
||||
foreach (var (threadUid, action) in threadActionMap)
|
||||
{
|
||||
if (action.Action == VContAction.Step)
|
||||
{
|
||||
var thread = DebugProcess.GetThread(threadUid);
|
||||
if (!DebugProcess.DebugStep(thread)) {
|
||||
hasError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If all threads are set to continue, continue the process.
|
||||
if (threadActionMap.Values.All(a => a.Action == VContAction.Continue))
|
||||
{
|
||||
DebugProcess.DebugContinue();
|
||||
}
|
||||
|
||||
if (hasError)
|
||||
{
|
||||
ReplyError();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyOK();
|
||||
}
|
||||
|
||||
foreach (var (threadUid, action) in threadActionMap)
|
||||
{
|
||||
if (action.Action == VContAction.Step)
|
||||
{
|
||||
gThread = cThread = threadUid;
|
||||
Reply($"T05thread:{threadUid:x};");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetThreadListXml()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
@ -772,6 +893,7 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
else
|
||||
{
|
||||
gThread = cThread = thread.ThreadUid;
|
||||
Reply($"T05thread:{thread.ThreadUid:x};");
|
||||
}
|
||||
}
|
||||
|
@ -966,7 +1088,6 @@ namespace Ryujinx.HLE.Debugger
|
|||
|
||||
public void BreakHandler(IExecutionContext ctx, ulong address, int imm)
|
||||
{
|
||||
gThread = cThread = ctx.ThreadUid;
|
||||
Logger.Notice.Print(LogClass.GdbStub, $"Break hit on thread {ctx.ThreadUid} at pc {address:x016}");
|
||||
|
||||
Messages.Add(new ThreadBreakMessage(ctx, address, imm));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue