mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-05 11:58:00 +00:00
fatal/creport: Add cpu context.
This commit is contained in:
parent
50c65ea7e1
commit
9714db14d2
15 changed files with 60 additions and 20 deletions
|
@ -28,7 +28,7 @@ struct CodeInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
class CodeList {
|
class CodeList {
|
||||||
private:
|
public:
|
||||||
static const size_t max_code_count = 0x10;
|
static const size_t max_code_count = 0x10;
|
||||||
u32 code_count = 0;
|
u32 code_count = 0;
|
||||||
CodeInfo code_infos[max_code_count];
|
CodeInfo code_infos[max_code_count];
|
||||||
|
|
|
@ -42,6 +42,35 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FatalContext *CrashReport::GetFatalContext() {
|
||||||
|
FatalContext *ctx = new FatalContext;
|
||||||
|
*ctx = (FatalContext){0};
|
||||||
|
|
||||||
|
ctx->is_aarch32 = false;
|
||||||
|
ctx->type = static_cast<u32>(this->exception_info.type);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 29; i++) {
|
||||||
|
ctx->aarch64_ctx.x[i] = this->crashed_thread_info.context.cpu_gprs[i].x;
|
||||||
|
}
|
||||||
|
ctx->aarch64_ctx.fp = this->crashed_thread_info.context.fp;
|
||||||
|
ctx->aarch64_ctx.lr = this->crashed_thread_info.context.lr;
|
||||||
|
ctx->aarch64_ctx.pc = this->crashed_thread_info.context.pc.x;
|
||||||
|
|
||||||
|
ctx->aarch64_ctx.stack_trace_size = this->crashed_thread_info.stack_trace_size;
|
||||||
|
for (size_t i = 0; i < ctx->aarch64_ctx.stack_trace_size; i++) {
|
||||||
|
ctx->aarch64_ctx.stack_trace[i] = this->crashed_thread_info.stack_trace[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->code_list.code_count) {
|
||||||
|
ctx->aarch64_ctx.start_address = this->code_list.code_infos[0].start_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For ams fatal... */
|
||||||
|
ctx->aarch64_ctx.afsr0 = this->process_info.title_id;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
void CrashReport::ProcessExceptions() {
|
void CrashReport::ProcessExceptions() {
|
||||||
if (!IsOpen()) {
|
if (!IsOpen()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -61,6 +61,7 @@ class CrashReport {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void BuildReport(u64 pid, bool has_extra_info);
|
void BuildReport(u64 pid, bool has_extra_info);
|
||||||
|
FatalContext *GetFatalContext();
|
||||||
void SaveReport();
|
void SaveReport();
|
||||||
|
|
||||||
bool IsAddressReadable(u64 address, u64 size, MemoryInfo *mi = NULL);
|
bool IsAddressReadable(u64 address, u64 size, MemoryInfo *mi = NULL);
|
||||||
|
|
|
@ -132,7 +132,9 @@ int main(int argc, char **argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fatalWithType(g_Creport.GetResult(), FatalType_ErrorScreen);
|
FatalContext *ctx = g_Creport.GetFatalContext();
|
||||||
|
|
||||||
|
fatalWithContext(g_Creport.GetResult(), FatalType_ErrorScreen, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@
|
||||||
#include "creport_code_info.hpp"
|
#include "creport_code_info.hpp"
|
||||||
|
|
||||||
class ThreadInfo {
|
class ThreadInfo {
|
||||||
private:
|
public:
|
||||||
ThreadContext context{};
|
ThreadContext context{};
|
||||||
u64 thread_id = 0;
|
u64 thread_id = 0;
|
||||||
u64 stack_top = 0;
|
u64 stack_top = 0;
|
||||||
|
|
|
@ -53,7 +53,7 @@ static void RunTask(IFatalTask *task, u32 stack_size = 0x4000) {
|
||||||
cur_thread->Start();
|
cur_thread->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) {
|
void RunFatalTasks(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) {
|
||||||
RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event));
|
RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event));
|
||||||
RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event));
|
RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event));
|
||||||
RunTask(new ShowFatalTask(ctx, title_id, battery_event), 0x10000);
|
RunTask(new ShowFatalTask(ctx, title_id, battery_event), 0x10000);
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
|
|
||||||
class IFatalTask {
|
class IFatalTask {
|
||||||
protected:
|
protected:
|
||||||
FatalContext *ctx;
|
FatalThrowContext *ctx;
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
public:
|
public:
|
||||||
IFatalTask(FatalContext *ctx, u64 tid) : ctx(ctx), title_id(tid) { }
|
IFatalTask(FatalThrowContext *ctx, u64 tid) : ctx(ctx), title_id(tid) { }
|
||||||
virtual Result Run() = 0;
|
virtual Result Run() = 0;
|
||||||
virtual const char *GetName() const = 0;
|
virtual const char *GetName() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event);
|
void RunFatalTasks(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event);
|
||||||
|
|
|
@ -23,7 +23,7 @@ class AdjustClockTask : public IFatalTask {
|
||||||
private:
|
private:
|
||||||
Result AdjustClock();
|
Result AdjustClock();
|
||||||
public:
|
public:
|
||||||
AdjustClockTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
AdjustClockTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "AdjustClockTask";
|
return "AdjustClockTask";
|
||||||
|
|
|
@ -24,7 +24,7 @@ class ErrorReportTask : public IFatalTask {
|
||||||
bool create_report;
|
bool create_report;
|
||||||
Event *erpt_event;
|
Event *erpt_event;
|
||||||
public:
|
public:
|
||||||
ErrorReportTask(FatalContext *ctx, u64 title_id, bool error_report, Event *evt) : IFatalTask(ctx, title_id), create_report(error_report), erpt_event(evt) { }
|
ErrorReportTask(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *evt) : IFatalTask(ctx, title_id), create_report(error_report), erpt_event(evt) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "WriteErrorReport";
|
return "WriteErrorReport";
|
||||||
|
|
|
@ -27,7 +27,7 @@ class PowerControlTask : public IFatalTask {
|
||||||
bool TryShutdown();
|
bool TryShutdown();
|
||||||
void MonitorBatteryState();
|
void MonitorBatteryState();
|
||||||
public:
|
public:
|
||||||
PowerControlTask(FatalContext *ctx, u64 title_id, Event *er_evt, Event *bt_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt), battery_event(bt_evt) { }
|
PowerControlTask(FatalThrowContext *ctx, u64 title_id, Event *er_evt, Event *bt_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt), battery_event(bt_evt) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "PowerControlTask";
|
return "PowerControlTask";
|
||||||
|
@ -40,7 +40,7 @@ class PowerButtonObserveTask : public IFatalTask {
|
||||||
private:
|
private:
|
||||||
void WaitForPowerButton();
|
void WaitForPowerButton();
|
||||||
public:
|
public:
|
||||||
PowerButtonObserveTask(FatalContext *ctx, u64 title_id, Event *er_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt) { }
|
PowerButtonObserveTask(FatalThrowContext *ctx, u64 title_id, Event *er_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "PowerButtonObserveTask";
|
return "PowerButtonObserveTask";
|
||||||
|
@ -49,7 +49,7 @@ class PowerButtonObserveTask : public IFatalTask {
|
||||||
|
|
||||||
class StateTransitionStopTask : public IFatalTask {
|
class StateTransitionStopTask : public IFatalTask {
|
||||||
public:
|
public:
|
||||||
StateTransitionStopTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
StateTransitionStopTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "StateTransitionStopTask";
|
return "StateTransitionStopTask";
|
||||||
|
|
|
@ -293,7 +293,7 @@ Result ShowFatalTask::ShowFatal() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this->ctx->cpu_ctx.is_aarch32) {
|
if (this->ctx->cpu_ctx.is_aarch32) {
|
||||||
FontManager::PrintFormatLine("Backtrace - Start Address: ");
|
FontManager::Print("Backtrace - Start Address: ");
|
||||||
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address);
|
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address);
|
||||||
FontManager::PrintLine("");
|
FontManager::PrintLine("");
|
||||||
FontManager::AddSpacingLines(0.5f);
|
FontManager::AddSpacingLines(0.5f);
|
||||||
|
@ -325,9 +325,10 @@ Result ShowFatalTask::ShowFatal() {
|
||||||
FontManager::SetPosition(backtrace_x, FontManager::GetY());
|
FontManager::SetPosition(backtrace_x, FontManager::GetY());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FontManager::PrintFormatLine("Backtrace - Start Address: ");
|
FontManager::Print("Backtrace - Start Address: ");
|
||||||
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address);
|
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address);
|
||||||
FontManager::PrintLine("");
|
FontManager::PrintLine("");
|
||||||
|
FontManager::AddSpacingLines(0.5f);
|
||||||
for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) {
|
for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) {
|
||||||
u64 bt_cur = 0, bt_next = 0;
|
u64 bt_cur = 0, bt_next = 0;
|
||||||
if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) {
|
if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ class ShowFatalTask : public IFatalTask {
|
||||||
Result PrepareScreenForDrawing();
|
Result PrepareScreenForDrawing();
|
||||||
Result ShowFatal();
|
Result ShowFatal();
|
||||||
public:
|
public:
|
||||||
ShowFatalTask(FatalContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { }
|
ShowFatalTask(FatalThrowContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "ShowFatal";
|
return "ShowFatal";
|
||||||
|
@ -43,7 +43,7 @@ class BacklightControlTask : public IFatalTask {
|
||||||
private:
|
private:
|
||||||
void TurnOnBacklight();
|
void TurnOnBacklight();
|
||||||
public:
|
public:
|
||||||
BacklightControlTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
BacklightControlTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "BacklightControlTask";
|
return "BacklightControlTask";
|
||||||
|
|
|
@ -23,7 +23,7 @@ class StopSoundTask : public IFatalTask {
|
||||||
private:
|
private:
|
||||||
void StopSound();
|
void StopSound();
|
||||||
public:
|
public:
|
||||||
StopSoundTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
StopSoundTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { }
|
||||||
virtual Result Run() override;
|
virtual Result Run() override;
|
||||||
virtual const char *GetName() const override {
|
virtual const char *GetName() const override {
|
||||||
return "SoundTask";
|
return "SoundTask";
|
||||||
|
|
|
@ -42,7 +42,7 @@ Result ThrowFatalForSelf(u32 error) {
|
||||||
|
|
||||||
Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) {
|
Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) {
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
FatalContext ctx;
|
FatalThrowContext ctx;
|
||||||
ctx.error_code = error;
|
ctx.error_code = error;
|
||||||
ctx.cpu_ctx = *cpu_ctx;
|
ctx.cpu_ctx = *cpu_ctx;
|
||||||
|
|
||||||
|
@ -52,6 +52,12 @@ Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu
|
||||||
/* Get title id. On failure, it'll be zero. */
|
/* Get title id. On failure, it'll be zero. */
|
||||||
u64 title_id = 0;
|
u64 title_id = 0;
|
||||||
pminfoGetTitleId(&title_id, pid);
|
pminfoGetTitleId(&title_id, pid);
|
||||||
|
ctx.is_creport = title_id == 0x0100000000000036;
|
||||||
|
|
||||||
|
/* Support for ams creport. TODO: Make this its own command? */
|
||||||
|
if (ctx.is_creport && !cpu_ctx->is_aarch32 && cpu_ctx->aarch64_ctx.afsr0 != 0) {
|
||||||
|
title_id = cpu_ctx->aarch64_ctx.afsr0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (policy) {
|
switch (policy) {
|
||||||
case FatalType_ErrorReport:
|
case FatalType_ErrorReport:
|
||||||
|
|
|
@ -96,8 +96,9 @@ struct FatalCpuContext {
|
||||||
u32 type;
|
u32 type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FatalContext {
|
struct FatalThrowContext {
|
||||||
u32 error_code;
|
u32 error_code;
|
||||||
|
bool is_creport;
|
||||||
FatalCpuContext cpu_ctx;
|
FatalCpuContext cpu_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue