diff options
| -rw-r--r-- | src/core/hle/service/fatal/fatal.cpp | 89 | 
1 files changed, 51 insertions, 38 deletions
| diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 770590d0b..2c229bcad 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -25,21 +25,34 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)  Module::Interface::~Interface() = default;  struct FatalInfo { -    std::array<u64_le, 31> registers{}; // TODO(ogniK): See if this actually is registers or -                                        // not(find a game which has non zero valeus) -    u64_le unk0{}; -    u64_le unk1{}; -    u64_le unk2{}; -    u64_le unk3{}; -    u64_le unk4{}; -    u64_le unk5{}; -    u64_le unk6{}; +    enum class Architecture : s32 { +        AArch64, +        AArch32, +    }; + +    const char* ArchAsString() const { +        return arch == Architecture::AArch64 ? "AArch64" : "AArch32"; +    } + +    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{}; -    u64_le unk7{}; -    u64_le unk8{}; +    u64_le program_entry_point{}; + +    // 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 unk9{}; +    Architecture arch{};      u32_le unk10{}; // TODO(ogniK): Is this even used or is it just padding?  };  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) {      const auto title_id = Core::CurrentProcess()->GetTitleID(); -    std::string crash_report = -        fmt::format("Yuzu {}-{} crash report\n" -                    "Title ID:                        {:016x}\n" -                    "Result:                          0x{:X} ({:04}-{:04d})\n" -                    "\n", -                    Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, -                    2000 + static_cast<u32>(error_code.module.Value()), -                    static_cast<u32>(error_code.description.Value()), info.unk8, info.unk7); +    std::string crash_report = fmt::format( +        "Yuzu {}-{} crash report\n" +        "Title ID:                        {:016x}\n" +        "Result:                          0x{:X} ({:04}-{:04d})\n" +        "Set flags:                       0x{:16X}\n" +        "Program entry point:             0x{:16X}\n" +        "\n", +        Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, +        2000 + static_cast<u32>(error_code.module.Value()), +        static_cast<u32>(error_code.description.Value()), info.set_flags, info.program_entry_point);      if (info.backtrace_size != 0x0) {          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++) {              crash_report +=                  fmt::format("    X[{:02d}]:                       {:016x}\n", i, info.registers[i]);          } -        crash_report += fmt::format("    Unknown 0:                   {:016x}\n", info.unk0); -        crash_report += fmt::format("    Unknown 1:                   {:016x}\n", info.unk1); -        crash_report += fmt::format("    Unknown 2:                   {:016x}\n", info.unk2); -        crash_report += fmt::format("    Unknown 3:                   {:016x}\n", info.unk3); -        crash_report += fmt::format("    Unknown 4:                   {:016x}\n", info.unk4); -        crash_report += fmt::format("    Unknown 5:                   {:016x}\n", info.unk5); -        crash_report += fmt::format("    Unknown 6:                   {:016x}\n", info.unk6); +        crash_report += fmt::format("    SP:                          {:016x}\n", info.sp); +        crash_report += fmt::format("    PC:                          {:016x}\n", info.pc); +        crash_report += fmt::format("    PSTATE:                      {:016x}\n", info.pstate); +        crash_report += fmt::format("    AFSR0:                       {:016x}\n", info.afsr0); +        crash_report += fmt::format("    AFSR1:                       {:016x}\n", info.afsr1); +        crash_report += fmt::format("    ESR:                         {:016x}\n", info.esr); +        crash_report += fmt::format("    FAR:                         {:016x}\n", info.far);          crash_report += "\nBacktrace:\n";          for (size_t i = 0; i < info.backtrace_size; i++) {              crash_report +=                  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("Unknown 9:                       0x{:016x}\n", info.unk9); + +        crash_report += fmt::format("Architecture:                    {}\n", info.ArchAsString());          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:          GenerateErrorReport(error_code, info);          break; -    }; +    }  }  void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) {      LOG_ERROR(Service_Fatal, "called");      IPC::RequestParser rp{ctx}; -    auto error_code = rp.Pop<ResultCode>(); +    const auto error_code = rp.Pop<ResultCode>();      ThrowFatalError(error_code, FatalType::ErrorScreen, {});      IPC::ResponseBuilder rb{ctx, 2}; @@ -141,8 +154,8 @@ void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) {  void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {      LOG_ERROR(Service_Fatal, "called");      IPC::RequestParser rp(ctx); -    auto error_code = rp.Pop<ResultCode>(); -    auto fatal_type = rp.PopEnum<FatalType>(); +    const auto error_code = rp.Pop<ResultCode>(); +    const auto fatal_type = rp.PopEnum<FatalType>();      ThrowFatalError(error_code, fatal_type, {}); // No info is passed with ThrowFatalWithPolicy      IPC::ResponseBuilder rb{ctx, 2}; @@ -152,9 +165,9 @@ void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {  void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) {      LOG_ERROR(Service_Fatal, "called");      IPC::RequestParser rp(ctx); -    auto error_code = rp.Pop<ResultCode>(); -    auto fatal_type = rp.PopEnum<FatalType>(); -    auto fatal_info = ctx.ReadBuffer(); +    const auto error_code = rp.Pop<ResultCode>(); +    const auto fatal_type = rp.PopEnum<FatalType>(); +    const auto fatal_info = ctx.ReadBuffer();      FatalInfo info{};      ASSERT_MSG(fatal_info.size() == sizeof(FatalInfo), "Invalid fatal info buffer size!"); | 
