Print Guest Stack Trace in ServiceNotImplemented Exception (#650)
* Print Guest Stack Trace in ServiceNotImplemented Exception * Remove PrintGuestStackTrace * Print Process Name and PID at the start of guest stack trace
This commit is contained in:
parent
1bef70c068
commit
efebd8f94d
6 changed files with 76 additions and 47 deletions
|
@ -76,60 +76,70 @@ namespace Ryujinx.HLE.Exceptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sb.AppendLine("Guest Stack Trace:");
|
||||||
|
sb.AppendLine(Context.Thread.GetGuestStackTrace());
|
||||||
|
|
||||||
// Print buffer information
|
// Print buffer information
|
||||||
sb.AppendLine("Buffer Information");
|
if (Request.PtrBuff.Count > 0 ||
|
||||||
|
Request.SendBuff.Count > 0 ||
|
||||||
if (Request.PtrBuff.Count > 0)
|
Request.ReceiveBuff.Count > 0 ||
|
||||||
|
Request.ExchangeBuff.Count > 0 ||
|
||||||
|
Request.RecvListBuff.Count > 0)
|
||||||
{
|
{
|
||||||
sb.AppendLine("\tPtrBuff:");
|
sb.AppendLine("Buffer Information:");
|
||||||
|
|
||||||
foreach (var buff in Request.PtrBuff)
|
if (Request.PtrBuff.Count > 0)
|
||||||
{
|
{
|
||||||
sb.AppendLine($"\t[{buff.Index}] Position: 0x{buff.Position:x16} Size: 0x{buff.Size:x16}");
|
sb.AppendLine("\tPtrBuff:");
|
||||||
|
|
||||||
|
foreach (var buff in Request.PtrBuff)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"\t[{buff.Index}] Position: 0x{buff.Position:x16} Size: 0x{buff.Size:x16}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Request.SendBuff.Count > 0)
|
if (Request.SendBuff.Count > 0)
|
||||||
{
|
|
||||||
sb.AppendLine("\tSendBuff:");
|
|
||||||
|
|
||||||
foreach (var buff in Request.SendBuff)
|
|
||||||
{
|
{
|
||||||
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16} Flags: {buff.Flags}");
|
sb.AppendLine("\tSendBuff:");
|
||||||
|
|
||||||
|
foreach (var buff in Request.SendBuff)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16} Flags: {buff.Flags}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Request.ReceiveBuff.Count > 0)
|
if (Request.ReceiveBuff.Count > 0)
|
||||||
{
|
|
||||||
sb.AppendLine("\tReceiveBuff:");
|
|
||||||
|
|
||||||
foreach (var buff in Request.ReceiveBuff)
|
|
||||||
{
|
{
|
||||||
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16} Flags: {buff.Flags}");
|
sb.AppendLine("\tReceiveBuff:");
|
||||||
|
|
||||||
|
foreach (var buff in Request.ReceiveBuff)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16} Flags: {buff.Flags}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Request.ExchangeBuff.Count > 0)
|
if (Request.ExchangeBuff.Count > 0)
|
||||||
{
|
|
||||||
sb.AppendLine("\tExchangeBuff:");
|
|
||||||
|
|
||||||
foreach (var buff in Request.ExchangeBuff)
|
|
||||||
{
|
{
|
||||||
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16} Flags: {buff.Flags}");
|
sb.AppendLine("\tExchangeBuff:");
|
||||||
|
|
||||||
|
foreach (var buff in Request.ExchangeBuff)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16} Flags: {buff.Flags}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Request.RecvListBuff.Count > 0)
|
if (Request.RecvListBuff.Count > 0)
|
||||||
{
|
|
||||||
sb.AppendLine("\tRecvListBuff:");
|
|
||||||
|
|
||||||
foreach (var buff in Request.RecvListBuff)
|
|
||||||
{
|
{
|
||||||
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16}");
|
sb.AppendLine("\tRecvListBuff:");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.AppendLine();
|
foreach (var buff in Request.RecvListBuff)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"\tPosition: 0x{buff.Position:x16} Size: 0x{buff.Size:x16}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
sb.AppendLine("Raw Request Data:");
|
sb.AppendLine("Raw Request Data:");
|
||||||
sb.Append(HexUtils.HexTable(Request.RawData));
|
sb.Append(HexUtils.HexTable(Request.RawData));
|
||||||
|
|
|
@ -2,6 +2,7 @@ using ChocolArm64.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ namespace Ryujinx.HLE.HOS.Ipc
|
||||||
Switch device,
|
Switch device,
|
||||||
KProcess process,
|
KProcess process,
|
||||||
MemoryManager memory,
|
MemoryManager memory,
|
||||||
|
KThread thread,
|
||||||
KClientSession session,
|
KClientSession session,
|
||||||
IpcMessage request,
|
IpcMessage request,
|
||||||
long cmdPtr)
|
long cmdPtr)
|
||||||
|
@ -36,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Ipc
|
||||||
device,
|
device,
|
||||||
process,
|
process,
|
||||||
memory,
|
memory,
|
||||||
|
thread,
|
||||||
session,
|
session,
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
|
|
|
@ -4,6 +4,7 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Diagnostics.Demangler;
|
using Ryujinx.HLE.HOS.Diagnostics.Demangler;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.Loaders.Elf;
|
using Ryujinx.HLE.Loaders.Elf;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -41,14 +42,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
_images = new List<Image>();
|
_images = new List<Image>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintGuestStackTrace(CpuThreadState threadState)
|
public string GetGuestStackTrace(CpuThreadState threadState)
|
||||||
{
|
{
|
||||||
EnsureLoaded();
|
EnsureLoaded();
|
||||||
|
|
||||||
StringBuilder trace = new StringBuilder();
|
StringBuilder trace = new StringBuilder();
|
||||||
|
|
||||||
trace.AppendLine("Guest stack trace:");
|
|
||||||
|
|
||||||
void AppendTrace(long address)
|
void AppendTrace(long address)
|
||||||
{
|
{
|
||||||
Image image = GetImage(address, out int imageIndex);
|
Image image = GetImage(address, out int imageIndex);
|
||||||
|
@ -68,22 +67,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
string imageName = GetGuessedNsoNameFromIndex(imageIndex);
|
string imageName = GetGuessedNsoNameFromIndex(imageIndex);
|
||||||
|
|
||||||
string imageNameAndOffset = $"[{_owner.Name}] {imageName}:0x{offset:x8}";
|
trace.AppendLine($" {imageName}:0x{offset:x8} {subName}");
|
||||||
|
|
||||||
trace.AppendLine($" {imageNameAndOffset} {subName}");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trace.AppendLine($" [{_owner.Name}] ??? {subName}");
|
trace.AppendLine($" ??? {subName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: ARM32.
|
//TODO: ARM32.
|
||||||
long framePointer = (long)threadState.X29;
|
long framePointer = (long)threadState.X29;
|
||||||
|
|
||||||
|
trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}");
|
||||||
|
|
||||||
while (framePointer != 0)
|
while (framePointer != 0)
|
||||||
{
|
{
|
||||||
if ((framePointer & 7) != 0 ||
|
if ((framePointer & 7) != 0 ||
|
||||||
!_owner.CpuMemory.IsMapped(framePointer) ||
|
!_owner.CpuMemory.IsMapped(framePointer) ||
|
||||||
!_owner.CpuMemory.IsMapped(framePointer + 8))
|
!_owner.CpuMemory.IsMapped(framePointer + 8))
|
||||||
{
|
{
|
||||||
|
@ -97,7 +96,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
framePointer = _owner.CpuMemory.ReadInt64(framePointer);
|
framePointer = _owner.CpuMemory.ReadInt64(framePointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.PrintInfo(LogClass.Cpu, trace.ToString());
|
return trace.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetSubName(Image image, long address, out string name)
|
private bool TryGetSubName(Image image, long address, out string name)
|
||||||
|
|
|
@ -143,6 +143,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
_device,
|
_device,
|
||||||
_process,
|
_process,
|
||||||
_process.CpuMemory,
|
_process.CpuMemory,
|
||||||
|
ipcMessage.Thread,
|
||||||
ipcMessage.Session,
|
ipcMessage.Session,
|
||||||
ipcMessage.Message,
|
ipcMessage.Message,
|
||||||
ipcMessage.MessagePtr);
|
ipcMessage.MessagePtr);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
using ChocolArm64;
|
using ChocolArm64;
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
|
@ -1009,9 +1011,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
ReleaseAndResume();
|
ReleaseAndResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetGuestStackTrace()
|
||||||
|
{
|
||||||
|
return Owner.Debugger.GetGuestStackTrace(Context.ThreadState);
|
||||||
|
}
|
||||||
|
|
||||||
public void PrintGuestStackTrace()
|
public void PrintGuestStackTrace()
|
||||||
{
|
{
|
||||||
Owner.Debugger.PrintGuestStackTrace(Context.ThreadState);
|
StringBuilder trace = new StringBuilder();
|
||||||
|
|
||||||
|
trace.AppendLine("Guest stack trace:");
|
||||||
|
trace.AppendLine(GetGuestStackTrace());
|
||||||
|
|
||||||
|
Logger.PrintInfo(LogClass.Cpu, trace.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThreadFinishedHandler(object sender, EventArgs e)
|
private void ThreadFinishedHandler(object sender, EventArgs e)
|
||||||
|
|
|
@ -2,6 +2,7 @@ using ChocolArm64.Memory;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS
|
namespace Ryujinx.HLE.HOS
|
||||||
|
@ -11,6 +12,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
public Switch Device { get; }
|
public Switch Device { get; }
|
||||||
public KProcess Process { get; }
|
public KProcess Process { get; }
|
||||||
public MemoryManager Memory { get; }
|
public MemoryManager Memory { get; }
|
||||||
|
public KThread Thread { get; }
|
||||||
public KClientSession Session { get; }
|
public KClientSession Session { get; }
|
||||||
public IpcMessage Request { get; }
|
public IpcMessage Request { get; }
|
||||||
public IpcMessage Response { get; }
|
public IpcMessage Response { get; }
|
||||||
|
@ -21,6 +23,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
Switch device,
|
Switch device,
|
||||||
KProcess process,
|
KProcess process,
|
||||||
MemoryManager memory,
|
MemoryManager memory,
|
||||||
|
KThread thread,
|
||||||
KClientSession session,
|
KClientSession session,
|
||||||
IpcMessage request,
|
IpcMessage request,
|
||||||
IpcMessage response,
|
IpcMessage response,
|
||||||
|
@ -30,6 +33,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
Device = device;
|
Device = device;
|
||||||
Process = process;
|
Process = process;
|
||||||
Memory = memory;
|
Memory = memory;
|
||||||
|
Thread = thread;
|
||||||
Session = session;
|
Session = session;
|
||||||
Request = request;
|
Request = request;
|
||||||
Response = response;
|
Response = response;
|
||||||
|
|
Loading…
Reference in a new issue