From efebd8f94de03ef5cab63803f0cf37fc39258682 Mon Sep 17 00:00:00 2001 From: jduncanator <1518948+jduncanator@users.noreply.github.com> Date: Fri, 15 Mar 2019 14:37:54 +1100 Subject: [PATCH] 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 --- .../ServiceNotImplementedException.cs | 84 +++++++++++-------- Ryujinx.HLE/HOS/Ipc/IpcHandler.cs | 3 + .../HOS/Kernel/Process/HleProcessDebugger.cs | 17 ++-- .../HOS/Kernel/SupervisorCall/SvcIpc.cs | 1 + Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 14 +++- Ryujinx.HLE/HOS/ServiceCtx.cs | 4 + 6 files changed, 76 insertions(+), 47 deletions(-) diff --git a/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs b/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs index d5ea3bbf..893ce26e 100644 --- a/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs +++ b/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs @@ -76,60 +76,70 @@ namespace Ryujinx.HLE.Exceptions } } + sb.AppendLine("Guest Stack Trace:"); + sb.AppendLine(Context.Thread.GetGuestStackTrace()); + // Print buffer information - sb.AppendLine("Buffer Information"); - - if (Request.PtrBuff.Count > 0) + if (Request.PtrBuff.Count > 0 || + Request.SendBuff.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) - { - sb.AppendLine("\tSendBuff:"); - - foreach (var buff in Request.SendBuff) + if (Request.SendBuff.Count > 0) { - 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) - { - sb.AppendLine("\tReceiveBuff:"); - - foreach (var buff in Request.ReceiveBuff) + if (Request.ReceiveBuff.Count > 0) { - 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) - { - sb.AppendLine("\tExchangeBuff:"); - - foreach (var buff in Request.ExchangeBuff) + if (Request.ExchangeBuff.Count > 0) { - 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) - { - sb.AppendLine("\tRecvListBuff:"); - - foreach (var buff in Request.RecvListBuff) + if (Request.RecvListBuff.Count > 0) { - 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.Append(HexUtils.HexTable(Request.RawData)); diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs index 1eba4b41..9f087a1a 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs @@ -2,6 +2,7 @@ using ChocolArm64.Memory; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Ipc; using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.IO; @@ -13,6 +14,7 @@ namespace Ryujinx.HLE.HOS.Ipc Switch device, KProcess process, MemoryManager memory, + KThread thread, KClientSession session, IpcMessage request, long cmdPtr) @@ -36,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Ipc device, process, memory, + thread, session, request, response, diff --git a/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index 0268de7d..d31f95b4 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -4,6 +4,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Diagnostics.Demangler; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.Loaders.Elf; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -41,14 +42,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process _images = new List(); } - public void PrintGuestStackTrace(CpuThreadState threadState) + public string GetGuestStackTrace(CpuThreadState threadState) { EnsureLoaded(); StringBuilder trace = new StringBuilder(); - trace.AppendLine("Guest stack trace:"); - void AppendTrace(long address) { Image image = GetImage(address, out int imageIndex); @@ -68,22 +67,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Process string imageName = GetGuessedNsoNameFromIndex(imageIndex); - string imageNameAndOffset = $"[{_owner.Name}] {imageName}:0x{offset:x8}"; - - trace.AppendLine($" {imageNameAndOffset} {subName}"); + trace.AppendLine($" {imageName}:0x{offset:x8} {subName}"); } else { - trace.AppendLine($" [{_owner.Name}] ??? {subName}"); + trace.AppendLine($" ??? {subName}"); } } //TODO: ARM32. long framePointer = (long)threadState.X29; + trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}"); + while (framePointer != 0) { - if ((framePointer & 7) != 0 || + if ((framePointer & 7) != 0 || !_owner.CpuMemory.IsMapped(framePointer) || !_owner.CpuMemory.IsMapped(framePointer + 8)) { @@ -97,7 +96,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process framePointer = _owner.CpuMemory.ReadInt64(framePointer); } - Logger.PrintInfo(LogClass.Cpu, trace.ToString()); + return trace.ToString(); } private bool TryGetSubName(Image image, long address, out string name) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs index e19d9d26..eb7595c0 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs @@ -143,6 +143,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall _device, _process, _process.CpuMemory, + ipcMessage.Thread, ipcMessage.Session, ipcMessage.Message, ipcMessage.MessagePtr); diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 17e0f3c3..ebde34ba 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -1,10 +1,12 @@ using ChocolArm64; using ChocolArm64.Memory; +using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Collections.Generic; using System.Linq; +using System.Text; namespace Ryujinx.HLE.HOS.Kernel.Threading { @@ -1009,9 +1011,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ReleaseAndResume(); } + public string GetGuestStackTrace() + { + return Owner.Debugger.GetGuestStackTrace(Context.ThreadState); + } + 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) diff --git a/Ryujinx.HLE/HOS/ServiceCtx.cs b/Ryujinx.HLE/HOS/ServiceCtx.cs index af42d417..99b2d5af 100644 --- a/Ryujinx.HLE/HOS/ServiceCtx.cs +++ b/Ryujinx.HLE/HOS/ServiceCtx.cs @@ -2,6 +2,7 @@ using ChocolArm64.Memory; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel.Ipc; using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; using System.IO; namespace Ryujinx.HLE.HOS @@ -11,6 +12,7 @@ namespace Ryujinx.HLE.HOS public Switch Device { get; } public KProcess Process { get; } public MemoryManager Memory { get; } + public KThread Thread { get; } public KClientSession Session { get; } public IpcMessage Request { get; } public IpcMessage Response { get; } @@ -21,6 +23,7 @@ namespace Ryujinx.HLE.HOS Switch device, KProcess process, MemoryManager memory, + KThread thread, KClientSession session, IpcMessage request, IpcMessage response, @@ -30,6 +33,7 @@ namespace Ryujinx.HLE.HOS Device = device; Process = process; Memory = memory; + Thread = thread; Session = session; Request = request; Response = response;