mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-12-22 08:08:53 -05:00
Linux crash handler (#1209)
* crash handler linux * cleanups * missing underscore * more cleanups * cleanups * 32 bit
This commit is contained in:
parent
bf505dba5c
commit
584a4ad818
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,6 +9,7 @@ __pycache__/
|
|||||||
.idea/
|
.idea/
|
||||||
cmake-build-debug
|
cmake-build-debug
|
||||||
venv/
|
venv/
|
||||||
|
.cache/
|
||||||
|
|
||||||
# Project-specific ignores
|
# Project-specific ignores
|
||||||
build/
|
build/
|
||||||
@ -410,6 +411,7 @@ oot.otr
|
|||||||
*.sav
|
*.sav
|
||||||
shipofharkinian.ini
|
shipofharkinian.ini
|
||||||
shipofharkinian.json
|
shipofharkinian.json
|
||||||
|
imgui.ini
|
||||||
|
|
||||||
# Switch Stuff
|
# Switch Stuff
|
||||||
|
|
||||||
|
@ -334,6 +334,12 @@ set(Source_Files__Resources__mpq
|
|||||||
)
|
)
|
||||||
source_group("Source Files\\Resources\\mpq" FILES ${Source_Files__Resources__mpq})
|
source_group("Source Files\\Resources\\mpq" FILES ${Source_Files__Resources__mpq})
|
||||||
|
|
||||||
|
set(Source_Files__Crash_Handler
|
||||||
|
"CrashHandler.cpp"
|
||||||
|
"CrashHandler.h"
|
||||||
|
)
|
||||||
|
source_group("Source Files\\Crash Handler" FILES ${Source_Files__Crash_Handler})
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
set(Source_Files__Darwin
|
set(Source_Files__Darwin
|
||||||
"OSXFolderManager.mm"
|
"OSXFolderManager.mm"
|
||||||
@ -388,6 +394,7 @@ set(ALL_FILES
|
|||||||
${Source_Files__Resources__Factories}
|
${Source_Files__Resources__Factories}
|
||||||
${Source_Files__Resources__Files}
|
${Source_Files__Resources__Files}
|
||||||
${Source_Files__Resources__mpq}
|
${Source_Files__Resources__mpq}
|
||||||
|
${Source_Files__Crash_Handler}
|
||||||
${Source_Files__Darwin}
|
${Source_Files__Darwin}
|
||||||
${Source_Files__NintendoSwitch}
|
${Source_Files__NintendoSwitch}
|
||||||
${Source_Files__CafeOS}
|
${Source_Files__CafeOS}
|
||||||
|
172
libultraship/libultraship/CrashHandler.cpp
Normal file
172
libultraship/libultraship/CrashHandler.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "Utils/StringHelper.h"
|
||||||
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cxxabi.h> // for __cxa_demangle
|
||||||
|
#include <dlfcn.h> // for dladdr
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern "C" void DeinitOTR(void);
|
||||||
|
|
||||||
|
|
||||||
|
static void PrintRegisters(ucontext_t* ctx) {
|
||||||
|
char regbuffer[1024];
|
||||||
|
SPDLOG_CRITICAL("Registers:");
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]);
|
||||||
|
SPDLOG_CRITICAL("RAX: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]);
|
||||||
|
SPDLOG_CRITICAL("RDI: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]);
|
||||||
|
SPDLOG_CRITICAL("RSI: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]);
|
||||||
|
SPDLOG_CRITICAL("RDX: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]);
|
||||||
|
SPDLOG_CRITICAL("RCX: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]);
|
||||||
|
SPDLOG_CRITICAL("R8 : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]);
|
||||||
|
SPDLOG_CRITICAL("R9 : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]);
|
||||||
|
SPDLOG_CRITICAL("R10: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]);
|
||||||
|
SPDLOG_CRITICAL("R11: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]);
|
||||||
|
SPDLOG_CRITICAL("RSP: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]);
|
||||||
|
SPDLOG_CRITICAL("RBX: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]);
|
||||||
|
SPDLOG_CRITICAL("RBP: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]);
|
||||||
|
SPDLOG_CRITICAL("R12: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]);
|
||||||
|
SPDLOG_CRITICAL("R13: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]);
|
||||||
|
SPDLOG_CRITICAL("R14: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]);
|
||||||
|
SPDLOG_CRITICAL("R15: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]);
|
||||||
|
SPDLOG_CRITICAL("RIP: {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]);
|
||||||
|
SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer);
|
||||||
|
#else
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]);
|
||||||
|
SPDLOG_CRITICAL("EDI : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]);
|
||||||
|
SPDLOG_CRITICAL("ESI : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]);
|
||||||
|
SPDLOG_CRITICAL("EBP : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]);
|
||||||
|
SPDLOG_CRITICAL("ESP : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]);
|
||||||
|
SPDLOG_CRITICAL("EBX : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]);
|
||||||
|
SPDLOG_CRITICAL("EDX : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]);
|
||||||
|
SPDLOG_CRITICAL("ECX : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]);
|
||||||
|
SPDLOG_CRITICAL("EAX : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]);
|
||||||
|
SPDLOG_CRITICAL("EIP : {} ", regbuffer);
|
||||||
|
snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]);
|
||||||
|
SPDLOG_CRITICAL("EFL : {} ", regbuffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data)
|
||||||
|
{
|
||||||
|
std::array<void*, 4096> arr;
|
||||||
|
ucontext_t* ctx = static_cast<ucontext_t*>(data);
|
||||||
|
constexpr size_t nMaxFrames = arr.size();
|
||||||
|
size_t size = backtrace(arr.data(), nMaxFrames);
|
||||||
|
char** symbols = backtrace_symbols(arr.data(), nMaxFrames);
|
||||||
|
|
||||||
|
SPDLOG_CRITICAL("(Signal: {})\n", sig);
|
||||||
|
|
||||||
|
switch (sig) {
|
||||||
|
case SIGILL:
|
||||||
|
SPDLOG_CRITICAL("ILLEGAL INSTRUCTION");
|
||||||
|
break;
|
||||||
|
case SIGABRT:
|
||||||
|
SPDLOG_CRITICAL("ABORT");
|
||||||
|
break;
|
||||||
|
case SIGFPE:
|
||||||
|
SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION");
|
||||||
|
break;
|
||||||
|
case SIGSEGV:
|
||||||
|
SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintRegisters(ctx);
|
||||||
|
|
||||||
|
SPDLOG_CRITICAL("Traceback:\n");
|
||||||
|
for (size_t i = 1; i < size; i++)
|
||||||
|
{
|
||||||
|
Dl_info info;
|
||||||
|
int gotAddress = dladdr(arr[i], &info);
|
||||||
|
std::string functionName(symbols[i]);
|
||||||
|
|
||||||
|
if (gotAddress != 0 && info.dli_sname != nullptr)
|
||||||
|
{
|
||||||
|
FILE* pipe;
|
||||||
|
int32_t status;
|
||||||
|
char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
|
||||||
|
const char* nameFound = info.dli_sname;
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
{
|
||||||
|
nameFound = demangled;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
char command[256];
|
||||||
|
char addrLine[128];
|
||||||
|
snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr);
|
||||||
|
pipe = popen(command, "r");
|
||||||
|
fgets(addrLine, 128, pipe);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound,
|
||||||
|
(char*)arr[i] - (char*)info.dli_saddr);
|
||||||
|
free(demangled);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDLOG_CRITICAL("{} {}", i, functionName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
free(symbols);
|
||||||
|
DeinitOTR();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) {
|
||||||
|
DeinitOTR();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void SetupHandlerLinux() {
|
||||||
|
struct sigaction action;
|
||||||
|
struct sigaction shutdownAction;
|
||||||
|
|
||||||
|
action.sa_flags = SA_SIGINFO;
|
||||||
|
action.sa_sigaction = ErrorHandler;
|
||||||
|
|
||||||
|
sigaction(SIGILL, &action, nullptr);
|
||||||
|
sigaction(SIGABRT, &action, nullptr);
|
||||||
|
sigaction(SIGFPE, &action, nullptr);
|
||||||
|
sigaction(SIGSEGV, &action, nullptr);
|
||||||
|
|
||||||
|
shutdownAction.sa_flags = SA_SIGINFO;
|
||||||
|
shutdownAction.sa_sigaction = ShutdownHandler;
|
||||||
|
sigaction(SIGINT, &shutdownAction, nullptr);
|
||||||
|
sigaction(SIGTERM, &shutdownAction, nullptr);
|
||||||
|
sigaction(SIGQUIT, &shutdownAction, nullptr);
|
||||||
|
sigaction(SIGKILL, &shutdownAction, nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
18
libultraship/libultraship/CrashHandler.h
Normal file
18
libultraship/libultraship/CrashHandler.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef CRASH_HANDLER_H
|
||||||
|
#define CRASH_HANDLER_H
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SetupHandlerLinux(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __linux__
|
||||||
|
|
||||||
|
#endif // CRASH_HANDLER_H
|
@ -1656,7 +1656,7 @@ void PadMgr_HandleRetraceMsg(PadMgr* padmgr);
|
|||||||
void PadMgr_HandlePreNMI(PadMgr* padmgr);
|
void PadMgr_HandlePreNMI(PadMgr* padmgr);
|
||||||
// This function must remain commented out, because it is called incorrectly in
|
// This function must remain commented out, because it is called incorrectly in
|
||||||
// fault.c (actual bug in game), and the compiler notices and won't compile it
|
// fault.c (actual bug in game), and the compiler notices and won't compile it
|
||||||
// void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode);
|
void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode);
|
||||||
void PadMgr_Init(PadMgr* padmgr, OSMesgQueue* siIntMsgQ, IrqMgr* irqMgr, OSId id, OSPri priority, void* stack);
|
void PadMgr_Init(PadMgr* padmgr, OSMesgQueue* siIntMsgQ, IrqMgr* irqMgr, OSId id, OSPri priority, void* stack);
|
||||||
void Sched_SwapFrameBuffer(CfbInfo* cfbInfo);
|
void Sched_SwapFrameBuffer(CfbInfo* cfbInfo);
|
||||||
void func_800C84E4(SchedContext* sc, CfbInfo* cfbInfo);
|
void func_800C84E4(SchedContext* sc, CfbInfo* cfbInfo);
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
|
|
||||||
#include "z64.h"
|
#include "z64.h"
|
||||||
|
|
||||||
#define DECLARE_SEGMENT(name) \
|
#define DECLARE_SEGMENT(name)
|
||||||
//extern u8 _##name##SegmentStart[]; \
|
//extern u8 _##name##SegmentStart[];
|
||||||
//extern u8 _##name##SegmentEnd[];
|
//extern u8 _##name##SegmentEnd[];
|
||||||
|
|
||||||
#define DECLARE_ROM_SEGMENT(name) \
|
#define DECLARE_ROM_SEGMENT(name)
|
||||||
//extern u8 _##name##SegmentRomStart[]; \
|
//extern u8 _##name##SegmentRomStart[];
|
||||||
//extern u8 _##name##SegmentRomEnd[];
|
//extern u8 _##name##SegmentRomEnd[];
|
||||||
|
|
||||||
#define DECLARE_BSS_SEGMENT(name) \
|
#define DECLARE_BSS_SEGMENT(name) \
|
||||||
extern u8 _##name##SegmentBssStart[]; \
|
extern u8 _##name##SegmentBssStart[]; \
|
||||||
extern u8 _##name##SegmentBssEnd[];
|
extern u8 _##name##SegmentBssEnd[];
|
||||||
|
|
||||||
#define DECLARE_OVERLAY_SEGMENT(name) \
|
#define DECLARE_OVERLAY_SEGMENT(name)
|
||||||
//DECLARE_SEGMENT(ovl_##name) \
|
//DECLARE_SEGMENT(ovl_##name)
|
||||||
//DECLARE_ROM_SEGMENT(ovl_##name)
|
//DECLARE_ROM_SEGMENT(ovl_##name)
|
||||||
|
|
||||||
DECLARE_SEGMENT(boot)
|
DECLARE_SEGMENT(boot)
|
||||||
|
@ -32,6 +32,8 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
void InitOTR(void);
|
||||||
|
void DeinitOTR(void);
|
||||||
void VanillaItemTable_Init();
|
void VanillaItemTable_Init();
|
||||||
void OTRAudio_Init();
|
void OTRAudio_Init();
|
||||||
void InitAudio();
|
void InitAudio();
|
||||||
|
@ -293,7 +293,7 @@ void Fault_Sleep(u32 duration) {
|
|||||||
|
|
||||||
void Fault_PadCallback(Input* input) {
|
void Fault_PadCallback(Input* input) {
|
||||||
//! @bug This function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C
|
//! @bug This function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C
|
||||||
PadMgr_RequestPadData(input, 0);
|
PadMgr_RequestPadData(&gPadMgr, input, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fault_UpdatePadImpl()
|
void Fault_UpdatePadImpl()
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <soh/Enhancements/bootcommands.h>
|
#include <soh/Enhancements/bootcommands.h>
|
||||||
#include "soh/OTRGlobals.h"
|
#include "soh/OTRGlobals.h"
|
||||||
|
|
||||||
|
#include "../libultraship/CrashHandler.h"
|
||||||
|
|
||||||
|
|
||||||
s32 gScreenWidth = SCREEN_WIDTH;
|
s32 gScreenWidth = SCREEN_WIDTH;
|
||||||
s32 gScreenHeight = SCREEN_HEIGHT;
|
s32 gScreenHeight = SCREEN_HEIGHT;
|
||||||
@ -38,6 +40,10 @@ void Main_LogSystemHeap(void) {
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
SetupHandlerLinux();
|
||||||
|
#endif
|
||||||
|
|
||||||
GameConsole_Init();
|
GameConsole_Init();
|
||||||
InitOTR();
|
InitOTR();
|
||||||
BootCommands_Init();
|
BootCommands_Init();
|
||||||
@ -64,14 +70,14 @@ void Main(void* arg) {
|
|||||||
Fault_Init();
|
Fault_Init();
|
||||||
SysCfb_Init(0);
|
SysCfb_Init(0);
|
||||||
Heaps_Alloc();
|
Heaps_Alloc();
|
||||||
sysHeap = gSystemHeap;
|
sysHeap = (uintptr_t)gSystemHeap;
|
||||||
fb = SysCfb_GetFbPtr(0);
|
fb = SysCfb_GetFbPtr(0);
|
||||||
gSystemHeapSize = 1024 * 1024 * 4;
|
gSystemHeapSize = 1024 * 1024 * 4;
|
||||||
// "System heap initalization"
|
// "System heap initalization"
|
||||||
osSyncPrintf("システムヒープ初期化 %08x-%08x %08x\n", sysHeap, fb, gSystemHeapSize);
|
osSyncPrintf("システムヒープ初期化 %08x-%08x %08x\n", sysHeap, fb, gSystemHeapSize);
|
||||||
SystemHeap_Init(sysHeap, gSystemHeapSize); // initializes the system heap
|
SystemHeap_Init((void*)sysHeap, gSystemHeapSize); // initializes the system heap
|
||||||
if (osMemSize >= 0x800000) {
|
if (osMemSize >= 0x800000) {
|
||||||
debugHeap = SysCfb_GetFbEnd();
|
debugHeap = (void*)SysCfb_GetFbEnd();
|
||||||
debugHeapSize = (0x80600000 - (uintptr_t)debugHeap);
|
debugHeapSize = (0x80600000 - (uintptr_t)debugHeap);
|
||||||
} else {
|
} else {
|
||||||
debugHeapSize = 0x400;
|
debugHeapSize = 0x400;
|
||||||
|
Loading…
Reference in New Issue
Block a user