2022-10-02 10:30:46 +02:00
|
|
|
|
using Ryujinx.Common.Logging;
|
|
|
|
|
using Ryujinx.HLE.HOS.Services.Fatal.Types;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Fatal
|
2019-09-19 02:45:11 +02:00
|
|
|
|
{
|
|
|
|
|
[Service("fatal:u")]
|
|
|
|
|
class IService : IpcService
|
|
|
|
|
{
|
|
|
|
|
public IService(ServiceCtx context) { }
|
2022-10-02 10:30:46 +02:00
|
|
|
|
|
2023-04-15 01:00:34 +02:00
|
|
|
|
[CommandCmif(0)]
|
2022-10-02 10:30:46 +02:00
|
|
|
|
// ThrowFatal(u64 result_code, u64 pid)
|
|
|
|
|
public ResultCode ThrowFatal(ServiceCtx context)
|
|
|
|
|
{
|
|
|
|
|
ResultCode resultCode = (ResultCode)context.RequestData.ReadUInt64();
|
|
|
|
|
ulong pid = context.Request.HandleDesc.PId;
|
|
|
|
|
|
|
|
|
|
return ThrowFatalWithCpuContextImpl(context, resultCode, pid, FatalPolicy.ErrorReportAndErrorScreen, null);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-15 01:00:34 +02:00
|
|
|
|
[CommandCmif(1)]
|
2022-10-02 10:30:46 +02:00
|
|
|
|
// ThrowFatalWithPolicy(u64 result_code, u32 fatal_policy, u64 pid)
|
|
|
|
|
public ResultCode ThrowFatalWithPolicy(ServiceCtx context)
|
|
|
|
|
{
|
|
|
|
|
ResultCode resultCode = (ResultCode)context.RequestData.ReadUInt64();
|
|
|
|
|
FatalPolicy fatalPolicy = (FatalPolicy)context.RequestData.ReadUInt32();
|
|
|
|
|
ulong pid = context.Request.HandleDesc.PId;
|
|
|
|
|
|
|
|
|
|
return ThrowFatalWithCpuContextImpl(context, resultCode, pid, fatalPolicy, null);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-15 01:00:34 +02:00
|
|
|
|
[CommandCmif(2)]
|
2022-10-02 10:30:46 +02:00
|
|
|
|
// ThrowFatalWithCpuContext(u64 result_code, u32 fatal_policy, u64 pid, buffer<bytes, 0x15> cpu_context)
|
|
|
|
|
public ResultCode ThrowFatalWithCpuContext(ServiceCtx context)
|
|
|
|
|
{
|
|
|
|
|
ResultCode resultCode = (ResultCode)context.RequestData.ReadUInt64();
|
|
|
|
|
FatalPolicy fatalPolicy = (FatalPolicy)context.RequestData.ReadUInt32();
|
|
|
|
|
ulong pid = context.Request.HandleDesc.PId;
|
|
|
|
|
|
|
|
|
|
ulong cpuContextPosition = context.Request.SendBuff[0].Position;
|
|
|
|
|
ulong cpuContextSize = context.Request.SendBuff[0].Size;
|
|
|
|
|
|
|
|
|
|
ReadOnlySpan<byte> cpuContextData = context.Memory.GetSpan(cpuContextPosition, (int)cpuContextSize);
|
|
|
|
|
|
|
|
|
|
return ThrowFatalWithCpuContextImpl(context, resultCode, pid, fatalPolicy, cpuContextData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ResultCode ThrowFatalWithCpuContextImpl(ServiceCtx context, ResultCode resultCode, ulong pid, FatalPolicy fatalPolicy, ReadOnlySpan<byte> cpuContext)
|
|
|
|
|
{
|
|
|
|
|
StringBuilder errorReport = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine();
|
|
|
|
|
errorReport.AppendLine("ErrorReport log:");
|
|
|
|
|
|
2023-03-31 21:16:46 +02:00
|
|
|
|
errorReport.AppendLine($"\tTitleId: {context.Device.Processes.ActiveApplication.ProgramIdText}");
|
2022-10-02 10:30:46 +02:00
|
|
|
|
errorReport.AppendLine($"\tPid: {pid}");
|
|
|
|
|
errorReport.AppendLine($"\tResultCode: {((int)resultCode & 0x1FF) + 2000}-{((int)resultCode >> 9) & 0x3FFF:d4}");
|
|
|
|
|
errorReport.AppendLine($"\tFatalPolicy: {fatalPolicy}");
|
|
|
|
|
|
|
|
|
|
if (cpuContext != null)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine("CPU Context:");
|
|
|
|
|
|
2023-03-31 21:16:46 +02:00
|
|
|
|
if (context.Device.Processes.ActiveApplication.Is64Bit)
|
2022-10-02 10:30:46 +02:00
|
|
|
|
{
|
|
|
|
|
CpuContext64 cpuContext64 = MemoryMarshal.Cast<byte, CpuContext64>(cpuContext)[0];
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine($"\tStartAddress: 0x{cpuContext64.StartAddress:x16}");
|
|
|
|
|
errorReport.AppendLine($"\tRegisterSetFlags: {cpuContext64.RegisterSetFlags}");
|
|
|
|
|
|
|
|
|
|
if (cpuContext64.StackTraceSize > 0)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine("\tStackTrace:");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < cpuContext64.StackTraceSize; i++)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine($"\t\t0x{cpuContext64.StackTrace[i]:x16}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine("\tRegisters:");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < cpuContext64.X.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{cpuContext64.X[i]:x16}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine();
|
|
|
|
|
errorReport.AppendLine($"\t\tFP:\t0x{cpuContext64.FP:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tLR:\t0x{cpuContext64.LR:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tSP:\t0x{cpuContext64.SP:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tPC:\t0x{cpuContext64.PC:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tPState:\t0x{cpuContext64.PState:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tAfsr0:\t0x{cpuContext64.Afsr0:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tAfsr1:\t0x{cpuContext64.Afsr1:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tEsr:\t0x{cpuContext64.Esr:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tFar:\t0x{cpuContext64.Far:x16}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CpuContext32 cpuContext32 = MemoryMarshal.Cast<byte, CpuContext32>(cpuContext)[0];
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine($"\tStartAddress: 0x{cpuContext32.StartAddress:16}");
|
|
|
|
|
errorReport.AppendLine($"\tRegisterSetFlags: {cpuContext32.RegisterSetFlags}");
|
|
|
|
|
|
|
|
|
|
if (cpuContext32.StackTraceSize > 0)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine("\tStackTrace:");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < cpuContext32.StackTraceSize; i++)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine($"\t\t0x{cpuContext32.StackTrace[i]:x16}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine("\tRegisters:");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < cpuContext32.X.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{cpuContext32.X[i]:x16}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errorReport.AppendLine();
|
|
|
|
|
errorReport.AppendLine($"\t\tFP:\t0x{cpuContext32.FP:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tFP:\t0x{cpuContext32.IP:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tSP:\t0x{cpuContext32.SP:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tLR:\t0x{cpuContext32.LR:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tPC:\t0x{cpuContext32.PC:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tPState:\t0x{cpuContext32.PState:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tAfsr0:\t0x{cpuContext32.Afsr0:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tAfsr1:\t0x{cpuContext32.Afsr1:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tEsr:\t0x{cpuContext32.Esr:x16}");
|
|
|
|
|
errorReport.AppendLine($"\t\tFar:\t0x{cpuContext32.Far:x16}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger.Info?.Print(LogClass.ServiceFatal, errorReport.ToString());
|
|
|
|
|
|
|
|
|
|
context.Device.System.KernelContext.Syscall.Break((ulong)resultCode);
|
|
|
|
|
|
|
|
|
|
return ResultCode.Success;
|
|
|
|
|
}
|
2019-09-19 02:45:11 +02:00
|
|
|
|
}
|
|
|
|
|
}
|