mirror of
https://github.com/Atmosphere-NX/Atmosphere-libs.git
synced 2025-06-21 19:12:42 +02:00
libstrat: Custom exception handlers/std::abort
This commit is contained in:
parent
1f9e2d042c
commit
b9724cdcad
@ -37,4 +37,6 @@
|
||||
|
||||
#include "stratosphere/results.hpp"
|
||||
|
||||
#include "stratosphere/title_ids.hpp"
|
||||
#include "stratosphere/title_ids.hpp"
|
||||
|
||||
#include "stratosphere/on_crash.hpp"
|
27
include/stratosphere/on_crash.hpp
Normal file
27
include/stratosphere/on_crash.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <cstdlib>
|
||||
#include "services/bpc_ams.h"
|
||||
|
||||
static constexpr size_t AtmosphereFatalErrorNumGprs = 29;
|
||||
|
||||
static constexpr u32 AtmosphereFatalErrorMagic = 0x30454641; /* "AFE0" */
|
||||
|
||||
/* Will be called by libstratosphere on crash. */
|
||||
void StratosphereCrashHandler(ThreadExceptionDump *ctx);
|
54
include/stratosphere/services/bpc_ams.h
Normal file
54
include/stratosphere/services/bpc_ams.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
u32 magic;
|
||||
u32 error_desc;
|
||||
u64 title_id;
|
||||
union {
|
||||
u64 gprs[32];
|
||||
struct {
|
||||
u64 _gprs[29];
|
||||
u64 fp;
|
||||
u64 lr;
|
||||
u64 sp;
|
||||
};
|
||||
};
|
||||
u64 pc;
|
||||
u64 padding;
|
||||
u32 pstate;
|
||||
u32 afsr0;
|
||||
u32 afsr1;
|
||||
u32 esr;
|
||||
u64 far;
|
||||
u64 report_identifier; /* Normally just system tick. */
|
||||
} AtmosphereFatalErrorContext;
|
||||
|
||||
Result bpcAmsInitialize(void);
|
||||
void bpcAmsExit(void);
|
||||
|
||||
Result bpcAmsRebootToFatalError(AtmosphereFatalErrorContext *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
76
source/bpc_ams.c
Normal file
76
source/bpc_ams.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <switch/arm/atomics.h>
|
||||
#include <stratosphere/services/bpc_ams.h>
|
||||
|
||||
static Service g_bpcAmsSrv;
|
||||
static u64 g_bpcAmsAmsRefcnt;
|
||||
|
||||
Result bpcAmsInitialize(void) {
|
||||
atomicIncrement64(&g_bpcAmsAmsRefcnt);
|
||||
|
||||
if (serviceIsActive(&g_bpcAmsSrv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Handle h;
|
||||
Result rc = svcConnectToNamedPort(&h, "bpc:ams");
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
serviceCreate(&g_bpcAmsSrv, h);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void bpcAmsExit(void) {
|
||||
if (atomicDecrement64(&g_bpcAmsAmsRefcnt) == 0)
|
||||
serviceClose(&g_bpcAmsSrv);
|
||||
}
|
||||
|
||||
Result bpcAmsRebootToFatalError(AtmosphereFatalErrorContext *ctx) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddSendBuffer(&c, ctx, sizeof(*ctx), BufferType_Normal);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_bpcAmsSrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 65000;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_bpcAmsSrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_bpcAmsSrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
73
source/on_crash.cpp
Normal file
73
source/on_crash.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
__attribute__((weak)) u64 __stratosphere_title_id = 0;
|
||||
void __attribute__((weak)) __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
|
||||
|
||||
/* Redefine abort, so that it triggers these handlers. */
|
||||
void abort();
|
||||
};
|
||||
|
||||
void StratosphereCrashHandler(ThreadExceptionDump *ctx) {
|
||||
AtmosphereFatalErrorContext ams_ctx;
|
||||
/* Convert thread dump to atmosphere dump. */
|
||||
{
|
||||
ams_ctx.magic = AtmosphereFatalErrorMagic;
|
||||
ams_ctx.error_desc = ctx->error_desc;
|
||||
ams_ctx.title_id = __stratosphere_title_id;
|
||||
for (size_t i = 0; i < AtmosphereFatalErrorNumGprs; i++) {
|
||||
ams_ctx.gprs[i] = ctx->cpu_gprs[i].x;
|
||||
}
|
||||
ams_ctx.fp = ctx->fp.x;
|
||||
ams_ctx.lr = ctx->lr.x;
|
||||
ams_ctx.sp = ctx->sp.x;
|
||||
ams_ctx.pc = ctx->pc.x;
|
||||
ams_ctx.pstate = ctx->pstate;
|
||||
ams_ctx.afsr0 = ctx->afsr0;
|
||||
ams_ctx.afsr1 = ctx->afsr1;
|
||||
ams_ctx.far = ctx->far.x;
|
||||
ams_ctx.report_identifier = armGetSystemTick();
|
||||
}
|
||||
|
||||
/* Just call the user exception handler. */
|
||||
__libstratosphere_exception_handler(&ams_ctx);
|
||||
}
|
||||
|
||||
/* Default exception handler behavior. */
|
||||
void __attribute__((weak)) __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) {
|
||||
Result rc = bpcAmsInitialize();
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
rc = bpcAmsRebootToFatalError(ctx);
|
||||
bpcAmsExit();
|
||||
}
|
||||
if (R_FAILED(rc)) {
|
||||
std::abort();
|
||||
}
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
/* Custom abort handler, so that std::abort will trigger these. */
|
||||
void abort() {
|
||||
/* Just perform a data abort. */
|
||||
while (true) {
|
||||
*((volatile u64 *)0x8) = 0xCAFEBABE;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user