mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-01 11:02:55 +00:00
gdb: More cleanup changes
- Move the message handler into its debugger class part, - Move all message types into one file and collapse 3 of the ones with no data into a generic, stateless message with a single property being its type, - Add an Fpscr helper property on IExecutionContext along with a comment about what Fpscr is (similar to the other registers in there) - Moved the Rcmd helpers (such as GetRegisters, GetMinidump, etc) into a dedicated Debugger class part, - Fixed the double-collection (ToArray being called twice) in GetThreadUids & GetThread in KProcess
This commit is contained in:
@@ -57,172 +57,24 @@ namespace Ryujinx.HLE.Debugger
|
||||
internal KProcess Process => Device.System?.DebugGetApplicationProcess();
|
||||
internal IDebuggableProcess DebugProcess => Device.System?.DebugGetApplicationProcessDebugInterface();
|
||||
|
||||
internal KThread[] GetThreads() =>
|
||||
DebugProcess.GetThreadUids().Select(x => DebugProcess.GetThread(x)).ToArray();
|
||||
internal KThread[] GetThreads() => DebugProcess.ThreadUids.Select(DebugProcess.GetThread).ToArray();
|
||||
|
||||
internal bool IsProcess32Bit => DebugProcess.GetThread(GThread.Value).Context.IsAarch32;
|
||||
|
||||
private void MessageHandlerMain()
|
||||
{
|
||||
while (!_shuttingDown)
|
||||
{
|
||||
IMessage msg = _messages.Take();
|
||||
try
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case BreakInMessage:
|
||||
Logger.Notice.Print(LogClass.GdbStub, "Break-in requested");
|
||||
_commandProcessor.Commands.Interrupt();
|
||||
break;
|
||||
|
||||
case SendNackMessage:
|
||||
_writeStream.WriteByte((byte)'-');
|
||||
break;
|
||||
|
||||
case CommandMessage { Command: var cmd }:
|
||||
Logger.Debug?.Print(LogClass.GdbStub, $"Received Command: {cmd}");
|
||||
_writeStream.WriteByte((byte)'+');
|
||||
_commandProcessor.Process(cmd);
|
||||
break;
|
||||
|
||||
case ThreadBreakMessage { Context: var ctx }:
|
||||
DebugProcess.DebugStop();
|
||||
GThread = CThread = ctx.ThreadUid;
|
||||
_breakHandlerEvent.Set();
|
||||
_commandProcessor.Reply($"T05thread:{ctx.ThreadUid:x};");
|
||||
break;
|
||||
|
||||
case KillMessage:
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.GdbStub, "Error while processing GDB messages", e);
|
||||
}
|
||||
catch (NullReferenceException e)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.GdbStub, "Error while processing GDB messages", e);
|
||||
}
|
||||
catch (ObjectDisposedException e)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.GdbStub, "Error while processing GDB messages", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal bool WriteRegister(IExecutionContext ctx, int gdbRegId, StringStream ss) =>
|
||||
|
||||
internal bool WriteRegister(IExecutionContext ctx, int registerId, StringStream ss) =>
|
||||
IsProcess32Bit
|
||||
? ctx.WriteRegister32(gdbRegId, ss)
|
||||
: ctx.WriteRegister64(gdbRegId, ss);
|
||||
? ctx.WriteRegister32(registerId, ss)
|
||||
: ctx.WriteRegister64(registerId, ss);
|
||||
|
||||
internal string ReadRegister(IExecutionContext ctx, int gdbRegId) =>
|
||||
internal string ReadRegister(IExecutionContext ctx, int registerId) =>
|
||||
IsProcess32Bit
|
||||
? ctx.ReadRegister32(gdbRegId)
|
||||
: ctx.ReadRegister64(gdbRegId);
|
||||
|
||||
public string GetStackTrace()
|
||||
{
|
||||
if (GThread == null)
|
||||
return "No thread selected\n";
|
||||
|
||||
return Process?.Debugger?.GetGuestStackTrace(DebugProcess.GetThread(GThread.Value)) ?? "No application process found\n";
|
||||
}
|
||||
|
||||
public string GetRegisters()
|
||||
{
|
||||
if (GThread == null)
|
||||
return "No thread selected\n";
|
||||
|
||||
return Process?.Debugger?.GetCpuRegisterPrintout(DebugProcess.GetThread(GThread.Value)) ?? "No application process found\n";
|
||||
}
|
||||
|
||||
public string GetMinidump()
|
||||
{
|
||||
var response = new StringBuilder();
|
||||
response.AppendLine("=== Begin Minidump ===\n");
|
||||
response.AppendLine(GetProcessInfo());
|
||||
|
||||
foreach (var thread in GetThreads())
|
||||
{
|
||||
response.AppendLine($"=== Thread {thread.ThreadUid} ===");
|
||||
try
|
||||
{
|
||||
string stackTrace = Process.Debugger.GetGuestStackTrace(thread);
|
||||
response.AppendLine(stackTrace);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
response.AppendLine($"[Error getting stack trace: {e.Message}]");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string registers = Process.Debugger.GetCpuRegisterPrintout(thread);
|
||||
response.AppendLine(registers);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
response.AppendLine($"[Error getting registers: {e.Message}]");
|
||||
}
|
||||
}
|
||||
|
||||
response.AppendLine("=== End Minidump ===");
|
||||
|
||||
Logger.Info?.Print(LogClass.GdbStub, response.ToString());
|
||||
return response.ToString();
|
||||
}
|
||||
|
||||
public string GetProcessInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Process == null)
|
||||
return "No application process found\n";
|
||||
|
||||
KProcess kProcess = Process;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine($"Program Id: 0x{kProcess.TitleId:x16}");
|
||||
sb.AppendLine($"Application: {(kProcess.IsApplication ? 1 : 0)}");
|
||||
sb.AppendLine("Layout:");
|
||||
sb.AppendLine(
|
||||
$" Alias: 0x{kProcess.MemoryManager.AliasRegionStart:x10} - 0x{kProcess.MemoryManager.AliasRegionEnd - 1:x10}");
|
||||
sb.AppendLine(
|
||||
$" Heap: 0x{kProcess.MemoryManager.HeapRegionStart:x10} - 0x{kProcess.MemoryManager.HeapRegionEnd - 1:x10}");
|
||||
sb.AppendLine(
|
||||
$" Aslr: 0x{kProcess.MemoryManager.AslrRegionStart:x10} - 0x{kProcess.MemoryManager.AslrRegionEnd - 1:x10}");
|
||||
sb.AppendLine(
|
||||
$" Stack: 0x{kProcess.MemoryManager.StackRegionStart:x10} - 0x{kProcess.MemoryManager.StackRegionEnd - 1:x10}");
|
||||
|
||||
sb.AppendLine("Modules:");
|
||||
var debugger = kProcess.Debugger;
|
||||
if (debugger != null)
|
||||
{
|
||||
var images = debugger.GetLoadedImages();
|
||||
for (int i = 0; i < images.Count; i++)
|
||||
{
|
||||
var image = images[i];
|
||||
ulong endAddress = image.BaseAddress + image.Size - 1;
|
||||
string name = image.Name;
|
||||
sb.AppendLine($" 0x{image.BaseAddress:x10} - 0x{endAddress:x10} {name}");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.GdbStub, $"Error getting process info: {e.Message}");
|
||||
return $"Error getting process info: {e.Message}\n";
|
||||
}
|
||||
}
|
||||
? ctx.ReadRegister32(registerId)
|
||||
: ctx.ReadRegister64(registerId);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
@@ -237,7 +89,7 @@ namespace Ryujinx.HLE.Debugger
|
||||
_readStream?.Close();
|
||||
_writeStream?.Close();
|
||||
_debuggerThread.Join();
|
||||
_messages.Add(new KillMessage());
|
||||
_messages.Add(StatelessMessage.Kill);
|
||||
_messageHandlerThread.Join();
|
||||
_messages.Dispose();
|
||||
_breakHandlerEvent.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user