mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Add stack overflow detection to fatal error code
This commit is contained in:
parent
f71ad5ac2c
commit
9382ff0939
3 changed files with 27 additions and 9 deletions
|
@ -42,6 +42,8 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
||||||
return "SError";
|
return "SError";
|
||||||
case 0x301:
|
case 0x301:
|
||||||
return "Bad SVC";
|
return "Bad SVC";
|
||||||
|
case 0xFFD:
|
||||||
|
return "Stack overflow";
|
||||||
case 0xFFE:
|
case 0xFFE:
|
||||||
return "std::abort() called";
|
return "std::abort() called";
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -73,6 +73,7 @@ namespace ams {
|
||||||
static constexpr uintptr_t StdAbortMagicAddress = 0x8;
|
static constexpr uintptr_t StdAbortMagicAddress = 0x8;
|
||||||
static constexpr u64 StdAbortMagicValue = 0xA55AF00DDEADCAFEul;
|
static constexpr u64 StdAbortMagicValue = 0xA55AF00DDEADCAFEul;
|
||||||
static constexpr u32 StdAbortErrorDesc = 0xFFE;
|
static constexpr u32 StdAbortErrorDesc = 0xFFE;
|
||||||
|
static constexpr u32 StackOverflowErrorDesc = 0xFFD;
|
||||||
static constexpr u32 DataAbortErrorDesc = 0x101;
|
static constexpr u32 DataAbortErrorDesc = 0x101;
|
||||||
static constexpr u32 Magic = util::FourCC<'A', 'F', 'E', '2'>::Code;
|
static constexpr u32 Magic = util::FourCC<'A', 'F', 'E', '2'>::Code;
|
||||||
|
|
||||||
|
|
|
@ -77,11 +77,26 @@ namespace ams {
|
||||||
ams_ctx.afsr1 = ctx->afsr1;
|
ams_ctx.afsr1 = ctx->afsr1;
|
||||||
ams_ctx.far = ctx->far.x;
|
ams_ctx.far = ctx->far.x;
|
||||||
ams_ctx.report_identifier = armGetSystemTick();
|
ams_ctx.report_identifier = armGetSystemTick();
|
||||||
|
|
||||||
|
/* Detect stack overflow. */
|
||||||
|
if (ams_ctx.error_desc == FatalErrorContext::DataAbortErrorDesc) {
|
||||||
|
svc::lp64::MemoryInfo mem_info;
|
||||||
|
svc::PageInfo page_info;
|
||||||
|
|
||||||
|
if (/* Check if stack pointer is in guard page. */
|
||||||
|
R_SUCCEEDED(svc::QueryMemory(std::addressof(mem_info), std::addressof(page_info), ams_ctx.sp)) &&
|
||||||
|
mem_info.state == svc::MemoryState_Free &&
|
||||||
|
/* Check if stack pointer fell off stack. */
|
||||||
|
R_SUCCEEDED(svc::QueryMemory(std::addressof(mem_info), std::addressof(page_info), ams_ctx.sp + 0x1000)) &&
|
||||||
|
mem_info.state == svc::MemoryState_Stack) {
|
||||||
|
ams_ctx.error_desc = FatalErrorContext::StackOverflowErrorDesc;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Grab module base. */
|
/* Grab module base. */
|
||||||
{
|
{
|
||||||
MemoryInfo mem_info;
|
svc::lp64::MemoryInfo mem_info;
|
||||||
u32 page_info;
|
svc::PageInfo page_info;
|
||||||
if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, GetPc()))) {
|
if (R_SUCCEEDED(svc::QueryMemory(std::addressof(mem_info), std::addressof(page_info), GetPc()))) {
|
||||||
ams_ctx.module_base = mem_info.addr;
|
ams_ctx.module_base = mem_info.addr;
|
||||||
} else {
|
} else {
|
||||||
ams_ctx.module_base = 0;
|
ams_ctx.module_base = 0;
|
||||||
|
@ -97,9 +112,9 @@ namespace ams {
|
||||||
|
|
||||||
/* Read a new frame. */
|
/* Read a new frame. */
|
||||||
StackFrame cur_frame;
|
StackFrame cur_frame;
|
||||||
MemoryInfo mem_info;
|
svc::lp64::MemoryInfo mem_info;
|
||||||
u32 page_info;
|
svc::PageInfo page_info;
|
||||||
if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, cur_fp)) && (mem_info.perm & Perm_R) == Perm_R) {
|
if (R_SUCCEEDED(svc::QueryMemory(std::addressof(mem_info), std::addressof(page_info), cur_fp)) && (mem_info.perm & Perm_R) == Perm_R) {
|
||||||
std::memcpy(&cur_frame, reinterpret_cast<void *>(cur_fp), sizeof(cur_frame));
|
std::memcpy(&cur_frame, reinterpret_cast<void *>(cur_fp), sizeof(cur_frame));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -116,9 +131,9 @@ namespace ams {
|
||||||
|
|
||||||
/* Grab up to 0x100 of stack. */
|
/* Grab up to 0x100 of stack. */
|
||||||
{
|
{
|
||||||
MemoryInfo mem_info;
|
svc::lp64::MemoryInfo mem_info;
|
||||||
u32 page_info;
|
svc::PageInfo page_info;
|
||||||
if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, ams_ctx.sp)) && (mem_info.perm & Perm_R) == Perm_R) {
|
if (R_SUCCEEDED(svc::QueryMemory(std::addressof(mem_info), std::addressof(page_info), ams_ctx.sp)) && (mem_info.perm & Perm_R) == Perm_R) {
|
||||||
size_t copy_size = std::min(FatalErrorContext::MaxStackDumpSize, static_cast<size_t>(mem_info.addr + mem_info.size - ams_ctx.sp));
|
size_t copy_size = std::min(FatalErrorContext::MaxStackDumpSize, static_cast<size_t>(mem_info.addr + mem_info.size - ams_ctx.sp));
|
||||||
ams_ctx.stack_dump_size = copy_size;
|
ams_ctx.stack_dump_size = copy_size;
|
||||||
std::memcpy(ams_ctx.stack_dump, reinterpret_cast<void *>(ams_ctx.sp), copy_size);
|
std::memcpy(ams_ctx.stack_dump, reinterpret_cast<void *>(ams_ctx.sp), copy_size);
|
||||||
|
|
Loading…
Reference in a new issue