Merge pull request #2307 from lioncash/regnames

service/fatal: Name FatalInfo structure members
This commit is contained in:
bunnei 2019-03-30 19:57:21 -04:00 committed by GitHub
commit f911d1f685
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -25,21 +25,34 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
Module::Interface::~Interface() = default; Module::Interface::~Interface() = default;
struct FatalInfo { struct FatalInfo {
std::array<u64_le, 31> registers{}; // TODO(ogniK): See if this actually is registers or enum class Architecture : s32 {
// not(find a game which has non zero valeus) AArch64,
u64_le unk0{}; AArch32,
u64_le unk1{}; };
u64_le unk2{};
u64_le unk3{}; const char* ArchAsString() const {
u64_le unk4{}; return arch == Architecture::AArch64 ? "AArch64" : "AArch32";
u64_le unk5{}; }
u64_le unk6{};
std::array<u64_le, 31> registers{};
u64_le sp{};
u64_le pc{};
u64_le pstate{};
u64_le afsr0{};
u64_le afsr1{};
u64_le esr{};
u64_le far{};
std::array<u64_le, 32> backtrace{}; std::array<u64_le, 32> backtrace{};
u64_le unk7{}; u64_le program_entry_point{};
u64_le unk8{};
// Bit flags that indicate which registers have been set with values
// for this context. The service itself uses these to determine which
// registers to specifically print out.
u64_le set_flags{};
u32_le backtrace_size{}; u32_le backtrace_size{};
u32_le unk9{}; Architecture arch{};
u32_le unk10{}; // TODO(ogniK): Is this even used or is it just padding? u32_le unk10{}; // TODO(ogniK): Is this even used or is it just padding?
}; };
static_assert(sizeof(FatalInfo) == 0x250, "FatalInfo is an invalid size"); static_assert(sizeof(FatalInfo) == 0x250, "FatalInfo is an invalid size");
@ -52,36 +65,36 @@ enum class FatalType : u32 {
static void GenerateErrorReport(ResultCode error_code, const FatalInfo& info) { static void GenerateErrorReport(ResultCode error_code, const FatalInfo& info) {
const auto title_id = Core::CurrentProcess()->GetTitleID(); const auto title_id = Core::CurrentProcess()->GetTitleID();
std::string crash_report = std::string crash_report = fmt::format(
fmt::format("Yuzu {}-{} crash report\n" "Yuzu {}-{} crash report\n"
"Title ID: {:016x}\n" "Title ID: {:016x}\n"
"Result: 0x{:X} ({:04}-{:04d})\n" "Result: 0x{:X} ({:04}-{:04d})\n"
"Set flags: 0x{:16X}\n"
"Program entry point: 0x{:16X}\n"
"\n", "\n",
Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw,
2000 + static_cast<u32>(error_code.module.Value()), 2000 + static_cast<u32>(error_code.module.Value()),
static_cast<u32>(error_code.description.Value()), info.unk8, info.unk7); static_cast<u32>(error_code.description.Value()), info.set_flags, info.program_entry_point);
if (info.backtrace_size != 0x0) { if (info.backtrace_size != 0x0) {
crash_report += "Registers:\n"; crash_report += "Registers:\n";
// TODO(ogniK): This is just a guess, find a game which actually has non zero values
for (size_t i = 0; i < info.registers.size(); i++) { for (size_t i = 0; i < info.registers.size(); i++) {
crash_report += crash_report +=
fmt::format(" X[{:02d}]: {:016x}\n", i, info.registers[i]); fmt::format(" X[{:02d}]: {:016x}\n", i, info.registers[i]);
} }
crash_report += fmt::format(" Unknown 0: {:016x}\n", info.unk0); crash_report += fmt::format(" SP: {:016x}\n", info.sp);
crash_report += fmt::format(" Unknown 1: {:016x}\n", info.unk1); crash_report += fmt::format(" PC: {:016x}\n", info.pc);
crash_report += fmt::format(" Unknown 2: {:016x}\n", info.unk2); crash_report += fmt::format(" PSTATE: {:016x}\n", info.pstate);
crash_report += fmt::format(" Unknown 3: {:016x}\n", info.unk3); crash_report += fmt::format(" AFSR0: {:016x}\n", info.afsr0);
crash_report += fmt::format(" Unknown 4: {:016x}\n", info.unk4); crash_report += fmt::format(" AFSR1: {:016x}\n", info.afsr1);
crash_report += fmt::format(" Unknown 5: {:016x}\n", info.unk5); crash_report += fmt::format(" ESR: {:016x}\n", info.esr);
crash_report += fmt::format(" Unknown 6: {:016x}\n", info.unk6); crash_report += fmt::format(" FAR: {:016x}\n", info.far);
crash_report += "\nBacktrace:\n"; crash_report += "\nBacktrace:\n";
for (size_t i = 0; i < info.backtrace_size; i++) { for (size_t i = 0; i < info.backtrace_size; i++) {
crash_report += crash_report +=
fmt::format(" Backtrace[{:02d}]: {:016x}\n", i, info.backtrace[i]); fmt::format(" Backtrace[{:02d}]: {:016x}\n", i, info.backtrace[i]);
} }
crash_report += fmt::format("\nUnknown 7: 0x{:016x}\n", info.unk7);
crash_report += fmt::format("Unknown 8: 0x{:016x}\n", info.unk8); crash_report += fmt::format("Architecture: {}\n", info.ArchAsString());
crash_report += fmt::format("Unknown 9: 0x{:016x}\n", info.unk9);
crash_report += fmt::format("Unknown 10: 0x{:016x}\n", info.unk10); crash_report += fmt::format("Unknown 10: 0x{:016x}\n", info.unk10);
} }
@ -125,13 +138,13 @@ static void ThrowFatalError(ResultCode error_code, FatalType fatal_type, const F
case FatalType::ErrorReport: case FatalType::ErrorReport:
GenerateErrorReport(error_code, info); GenerateErrorReport(error_code, info);
break; break;
}; }
} }
void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) { void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) {
LOG_ERROR(Service_Fatal, "called"); LOG_ERROR(Service_Fatal, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
auto error_code = rp.Pop<ResultCode>(); const auto error_code = rp.Pop<ResultCode>();
ThrowFatalError(error_code, FatalType::ErrorScreen, {}); ThrowFatalError(error_code, FatalType::ErrorScreen, {});
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -141,8 +154,8 @@ void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) {
void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) { void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {
LOG_ERROR(Service_Fatal, "called"); LOG_ERROR(Service_Fatal, "called");
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
auto error_code = rp.Pop<ResultCode>(); const auto error_code = rp.Pop<ResultCode>();
auto fatal_type = rp.PopEnum<FatalType>(); const auto fatal_type = rp.PopEnum<FatalType>();
ThrowFatalError(error_code, fatal_type, {}); // No info is passed with ThrowFatalWithPolicy ThrowFatalError(error_code, fatal_type, {}); // No info is passed with ThrowFatalWithPolicy
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -152,9 +165,9 @@ void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {
void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) { void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) {
LOG_ERROR(Service_Fatal, "called"); LOG_ERROR(Service_Fatal, "called");
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
auto error_code = rp.Pop<ResultCode>(); const auto error_code = rp.Pop<ResultCode>();
auto fatal_type = rp.PopEnum<FatalType>(); const auto fatal_type = rp.PopEnum<FatalType>();
auto fatal_info = ctx.ReadBuffer(); const auto fatal_info = ctx.ReadBuffer();
FatalInfo info{}; FatalInfo info{};
ASSERT_MSG(fatal_info.size() == sizeof(FatalInfo), "Invalid fatal info buffer size!"); ASSERT_MSG(fatal_info.size() == sizeof(FatalInfo), "Invalid fatal info buffer size!");