diff options
Diffstat (limited to 'src/core/reporter.cpp')
| -rw-r--r-- | src/core/reporter.cpp | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 95dcfffb5..8fe621aa0 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/hle/kernel/hle_ipc.h" | 12 | #include "core/hle/kernel/hle_ipc.h" |
| 13 | #include "core/hle/kernel/process.h" | 13 | #include "core/hle/kernel/process.h" |
| 14 | #include "core/hle/result.h" | ||
| 14 | #include "core/reporter.h" | 15 | #include "core/reporter.h" |
| 15 | #include "core/settings.h" | 16 | #include "core/settings.h" |
| 16 | #include "fmt/time.h" | 17 | #include "fmt/time.h" |
| @@ -30,12 +31,12 @@ std::string GetTimestamp() { | |||
| 30 | using namespace nlohmann; | 31 | using namespace nlohmann; |
| 31 | 32 | ||
| 32 | void SaveToFile(const json& json, const std::string& filename) { | 33 | void SaveToFile(const json& json, const std::string& filename) { |
| 33 | FileUtil::CreateFullPath(filename); | 34 | if (!FileUtil::CreateFullPath(filename)) |
| 35 | LOG_ERROR(Core, "Failed to create path for '{}' to save report!", filename); | ||
| 36 | |||
| 34 | std::ofstream file( | 37 | std::ofstream file( |
| 35 | FileUtil::SanitizePath(filename, FileUtil::DirectorySeparator::PlatformDefault)); | 38 | FileUtil::SanitizePath(filename, FileUtil::DirectorySeparator::PlatformDefault)); |
| 36 | file << std::setw(4) << json << std::endl; | 39 | file << std::setw(4) << json << std::endl; |
| 37 | file.flush(); | ||
| 38 | file.close(); | ||
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | json GetYuzuVersionData() { | 42 | json GetYuzuVersionData() { |
| @@ -62,7 +63,7 @@ json GetReportCommonData(u64 title_id, ResultCode result, const std::string& tim | |||
| 62 | }; | 63 | }; |
| 63 | if (user_id.has_value()) | 64 | if (user_id.has_value()) |
| 64 | out["user_id"] = fmt::format("{:016X}{:016X}", (*user_id)[1], (*user_id)[0]); | 65 | out["user_id"] = fmt::format("{:016X}{:016X}", (*user_id)[1], (*user_id)[0]); |
| 65 | return std::move(out); | 66 | return out; |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 sp, u64 pc, | 69 | json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 sp, u64 pc, |
| @@ -91,13 +92,13 @@ json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 | |||
| 91 | out["backtrace"] = std::move(backtrace_out); | 92 | out["backtrace"] = std::move(backtrace_out); |
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | return std::move(out); | 95 | return out; |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | json GetProcessorStateDataAuto() { | 98 | json GetProcessorStateDataAuto(Core::System& system) { |
| 98 | const auto* process{Core::CurrentProcess()}; | 99 | const auto* process{system.CurrentProcess()}; |
| 99 | const auto& vm_manager{process->VMManager()}; | 100 | const auto& vm_manager{process->VMManager()}; |
| 100 | auto& arm{Core::CurrentArmInterface()}; | 101 | auto& arm{system.CurrentArmInterface()}; |
| 101 | 102 | ||
| 102 | Core::ARM_Interface::ThreadContext context{}; | 103 | Core::ARM_Interface::ThreadContext context{}; |
| 103 | arm.SaveContext(context); | 104 | arm.SaveContext(context); |
| @@ -107,9 +108,9 @@ json GetProcessorStateDataAuto() { | |||
| 107 | context.pstate, context.cpu_registers); | 108 | context.pstate, context.cpu_registers); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | json GetBacktraceData() { | 111 | json GetBacktraceData(Core::System& system) { |
| 111 | auto out = json::array(); | 112 | auto out = json::array(); |
| 112 | const auto& backtrace{Core::CurrentArmInterface().GetBacktrace()}; | 113 | const auto& backtrace{system.CurrentArmInterface().GetBacktrace()}; |
| 113 | for (const auto& entry : backtrace) { | 114 | for (const auto& entry : backtrace) { |
| 114 | out.push_back({ | 115 | out.push_back({ |
| 115 | {"module", entry.module}, | 116 | {"module", entry.module}, |
| @@ -120,18 +121,18 @@ json GetBacktraceData() { | |||
| 120 | }); | 121 | }); |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 123 | return std::move(out); | 124 | return out; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | json GetFullDataAuto(const std::string& timestamp, u64 title_id) { | 127 | json GetFullDataAuto(const std::string& timestamp, u64 title_id, Core::System& system) { |
| 127 | json out; | 128 | json out; |
| 128 | 129 | ||
| 129 | out["yuzu_version"] = GetYuzuVersionData(); | 130 | out["yuzu_version"] = GetYuzuVersionData(); |
| 130 | out["report_common"] = GetReportCommonData(title_id, RESULT_SUCCESS, timestamp); | 131 | out["report_common"] = GetReportCommonData(title_id, RESULT_SUCCESS, timestamp); |
| 131 | out["processor_state"] = GetProcessorStateDataAuto(); | 132 | out["processor_state"] = GetProcessorStateDataAuto(system); |
| 132 | out["backtrace"] = GetBacktraceData(); | 133 | out["backtrace"] = GetBacktraceData(system); |
| 133 | 134 | ||
| 134 | return std::move(out); | 135 | return out; |
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | template <bool read_value, typename DescriptorType> | 138 | template <bool read_value, typename DescriptorType> |
| @@ -152,7 +153,7 @@ json GetHLEBufferDescriptorData(const std::vector<DescriptorType>& buffer) { | |||
| 152 | buffer_out.push_back(std::move(entry)); | 153 | buffer_out.push_back(std::move(entry)); |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | return std::move(buffer_out); | 156 | return buffer_out; |
| 156 | } | 157 | } |
| 157 | 158 | ||
| 158 | json GetHLERequestContextData(Kernel::HLERequestContext& ctx) { | 159 | json GetHLERequestContextData(Kernel::HLERequestContext& ctx) { |
| @@ -177,7 +178,7 @@ json GetHLERequestContextData(Kernel::HLERequestContext& ctx) { | |||
| 177 | 178 | ||
| 178 | namespace Core { | 179 | namespace Core { |
| 179 | 180 | ||
| 180 | Reporter::Reporter() = default; | 181 | Reporter::Reporter(Core::System& system) : system(system) {} |
| 181 | 182 | ||
| 182 | Reporter::~Reporter() = default; | 183 | Reporter::~Reporter() = default; |
| 183 | 184 | ||
| @@ -189,7 +190,7 @@ void Reporter::SaveCrashReport(u64 title_id, ResultCode result, u64 set_flags, u | |||
| 189 | if (!IsReportingEnabled()) | 190 | if (!IsReportingEnabled()) |
| 190 | return; | 191 | return; |
| 191 | 192 | ||
| 192 | const auto timestamp{GetTimestamp()}; | 193 | const auto timestamp = GetTimestamp(); |
| 193 | json out; | 194 | json out; |
| 194 | 195 | ||
| 195 | out["yuzu_version"] = GetYuzuVersionData(); | 196 | out["yuzu_version"] = GetYuzuVersionData(); |
| @@ -214,9 +215,9 @@ void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 | |||
| 214 | if (!IsReportingEnabled()) | 215 | if (!IsReportingEnabled()) |
| 215 | return; | 216 | return; |
| 216 | 217 | ||
| 217 | const auto timestamp{GetTimestamp()}; | 218 | const auto timestamp = GetTimestamp(); |
| 218 | const auto title_id{Core::CurrentProcess()->GetTitleID()}; | 219 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 219 | auto out = GetFullDataAuto(timestamp, title_id); | 220 | auto out = GetFullDataAuto(timestamp, title_id, system); |
| 220 | 221 | ||
| 221 | auto break_out = json{ | 222 | auto break_out = json{ |
| 222 | {"type", fmt::format("{:08X}", type)}, | 223 | {"type", fmt::format("{:08X}", type)}, |
| @@ -240,9 +241,9 @@ void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u | |||
| 240 | if (!IsReportingEnabled()) | 241 | if (!IsReportingEnabled()) |
| 241 | return; | 242 | return; |
| 242 | 243 | ||
| 243 | const auto timestamp{GetTimestamp()}; | 244 | const auto timestamp = GetTimestamp(); |
| 244 | const auto title_id{Core::CurrentProcess()->GetTitleID()}; | 245 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 245 | auto out = GetFullDataAuto(timestamp, title_id); | 246 | auto out = GetFullDataAuto(timestamp, title_id, system); |
| 246 | 247 | ||
| 247 | auto function_out = GetHLERequestContextData(ctx); | 248 | auto function_out = GetHLERequestContextData(ctx); |
| 248 | function_out["command_id"] = command_id; | 249 | function_out["command_id"] = command_id; |
| @@ -261,9 +262,9 @@ void Reporter::SaveUnimplementedAppletReport( | |||
| 261 | if (!IsReportingEnabled()) | 262 | if (!IsReportingEnabled()) |
| 262 | return; | 263 | return; |
| 263 | 264 | ||
| 264 | const auto timestamp{GetTimestamp()}; | 265 | const auto timestamp = GetTimestamp(); |
| 265 | const auto title_id{Core::CurrentProcess()->GetTitleID()}; | 266 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 266 | auto out = GetFullDataAuto(timestamp, title_id); | 267 | auto out = GetFullDataAuto(timestamp, title_id, system); |
| 267 | 268 | ||
| 268 | out["applet_common_args"] = { | 269 | out["applet_common_args"] = { |
| 269 | {"applet_id", fmt::format("{:02X}", applet_id)}, | 270 | {"applet_id", fmt::format("{:02X}", applet_id)}, |
| @@ -290,12 +291,12 @@ void Reporter::SaveUnimplementedAppletReport( | |||
| 290 | SaveToFile(std::move(out), GetPath("unimpl_applet_report", title_id, timestamp)); | 291 | SaveToFile(std::move(out), GetPath("unimpl_applet_report", title_id, timestamp)); |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 293 | void Reporter::SavePlayReport(u64 title_id, u64 unk1, std::vector<std::vector<u8>> data, | 294 | void Reporter::SavePlayReport(u64 title_id, u64 process_id, std::vector<std::vector<u8>> data, |
| 294 | std::optional<u128> user_id) const { | 295 | std::optional<u128> user_id) const { |
| 295 | if (!IsReportingEnabled()) | 296 | if (!IsReportingEnabled()) |
| 296 | return; | 297 | return; |
| 297 | 298 | ||
| 298 | const auto timestamp{GetTimestamp()}; | 299 | const auto timestamp = GetTimestamp(); |
| 299 | json out; | 300 | json out; |
| 300 | 301 | ||
| 301 | out["yuzu_version"] = GetYuzuVersionData(); | 302 | out["yuzu_version"] = GetYuzuVersionData(); |
| @@ -306,7 +307,7 @@ void Reporter::SavePlayReport(u64 title_id, u64 unk1, std::vector<std::vector<u8 | |||
| 306 | data_out.push_back(Common::HexVectorToString(d)); | 307 | data_out.push_back(Common::HexVectorToString(d)); |
| 307 | } | 308 | } |
| 308 | 309 | ||
| 309 | out["play_report_unk1"] = fmt::format("{:016X}", unk1); | 310 | out["play_report_process_id"] = fmt::format("{:016X}", process_id); |
| 310 | out["play_report_data"] = std::move(data_out); | 311 | out["play_report_data"] = std::move(data_out); |
| 311 | 312 | ||
| 312 | SaveToFile(std::move(out), GetPath("play_report", title_id, timestamp)); | 313 | SaveToFile(std::move(out), GetPath("play_report", title_id, timestamp)); |
| @@ -318,13 +319,13 @@ void Reporter::SaveErrorReport(u64 title_id, ResultCode result, | |||
| 318 | if (!IsReportingEnabled()) | 319 | if (!IsReportingEnabled()) |
| 319 | return; | 320 | return; |
| 320 | 321 | ||
| 321 | const auto timestamp{GetTimestamp()}; | 322 | const auto timestamp = GetTimestamp(); |
| 322 | json out; | 323 | json out; |
| 323 | 324 | ||
| 324 | out["yuzu_version"] = GetYuzuVersionData(); | 325 | out["yuzu_version"] = GetYuzuVersionData(); |
| 325 | out["report_common"] = GetReportCommonData(title_id, result, timestamp); | 326 | out["report_common"] = GetReportCommonData(title_id, result, timestamp); |
| 326 | out["processor_state"] = GetProcessorStateDataAuto(); | 327 | out["processor_state"] = GetProcessorStateDataAuto(system); |
| 327 | out["backtrace"] = GetBacktraceData(); | 328 | out["backtrace"] = GetBacktraceData(system); |
| 328 | 329 | ||
| 329 | out["error_custom_text"] = { | 330 | out["error_custom_text"] = { |
| 330 | {"main", *custom_text_main}, | 331 | {"main", *custom_text_main}, |
| @@ -338,10 +339,11 @@ void Reporter::SaveUserReport() const { | |||
| 338 | if (!IsReportingEnabled()) | 339 | if (!IsReportingEnabled()) |
| 339 | return; | 340 | return; |
| 340 | 341 | ||
| 341 | const auto timestamp{GetTimestamp()}; | 342 | const auto timestamp = GetTimestamp(); |
| 342 | const auto title_id{Core::CurrentProcess()->GetTitleID()}; | 343 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 343 | 344 | ||
| 344 | SaveToFile(GetFullDataAuto(timestamp, title_id), GetPath("user_report", title_id, timestamp)); | 345 | SaveToFile(GetFullDataAuto(timestamp, title_id, system), |
| 346 | GetPath("user_report", title_id, timestamp)); | ||
| 345 | } | 347 | } |
| 346 | 348 | ||
| 347 | bool Reporter::IsReportingEnabled() const { | 349 | bool Reporter::IsReportingEnabled() const { |