service/fatal: Name FatalInfo structure members
Based off RE, most of these structure members are register values, which makes, sense given this service is used to convey fatal errors. One member indicates the program entry point address, one is a set of bit flags used to determine which registers to print, and one member indicates the architecture type. The only member that still isn't determined is the final member within the data structure.
This commit is contained in:
parent
f770c17d01
commit
cc737e5832
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue