From 663a8ef24ba024d5e957ddbab687fb8c866f4535 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 25 Jul 2025 07:26:43 +1000 Subject: [PATCH] More specific crash messages for null pointer reads/writes on Windows and POSIX systems --- misc/n64/rsp_gpu.S | 8 ++++---- misc/n64/rsp_gpu_clipping.inc | 10 +++++----- src/Platform_Posix.c | 8 ++++++-- src/Platform_Windows.c | 28 ++++++++++++++++++++-------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/misc/n64/rsp_gpu.S b/misc/n64/rsp_gpu.S index aba4f34de..569918b80 100644 --- a/misc/n64/rsp_gpu.S +++ b/misc/n64/rsp_gpu.S @@ -123,8 +123,8 @@ GPUCmd_PushRDP: .func GPUCmd_MatrixLoad GPUCmd_MatrixLoad: - #define src s6 - #define dst s7 + #define src t4 + #define dst t5 #define vmat0_i $v02 #define vmat1_i $v03 @@ -348,8 +348,8 @@ GL_TnL: .func GPUCmd_DrawQuad GPUCmd_DrawQuad: #define vtx_ptr a0 - #define mtx_ptr s2 - #define src_ptr s3 + #define mtx_ptr v0 + #define src_ptr v1 #define v___ $v01 diff --git a/misc/n64/rsp_gpu_clipping.inc b/misc/n64/rsp_gpu_clipping.inc index 5ec5f7757..7dd882e5f 100644 --- a/misc/n64/rsp_gpu_clipping.inc +++ b/misc/n64/rsp_gpu_clipping.inc @@ -46,7 +46,7 @@ GL_ClipTriangle: #define plane_flag t6 #define in_count t7 #define in_end t8 - #define in_list s0 + #define in_list v0 #define out_list s1 #define plane s2 #define intersection s3 @@ -147,11 +147,11 @@ gl_clip_edge_loop: #define prev_flag t4 # Check which side of the plane the two vertices are on - lhu cur_vtx, 0(cur_ptr) - lhu prev_vtx, 0(prev_ptr) - lbu cur_flag, SCREEN_VTX_CLIP_CODE(cur_vtx) + lhu cur_vtx, 0(cur_ptr) + lhu prev_vtx, 0(prev_ptr) + lbu cur_flag, SCREEN_VTX_CLIP_CODE(cur_vtx) lbu prev_flag, SCREEN_VTX_CLIP_CODE(prev_vtx) - and cur_flag, plane_flag + and cur_flag, plane_flag and prev_flag, plane_flag # If they are on opposite sides, there is an intersection diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 452dce619..1f5c0dfa9 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -236,6 +236,8 @@ cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { /*########################################################################################################################* *-------------------------------------------------------Crash handling----------------------------------------------------* *#########################################################################################################################*/ +#define IsNullDerefException(info) (info->si_signo == SIGSEGV && info->si_addr == 0) + static const char* SignalDescribe(int type) { switch (type) { case SIGSEGV: return "SIGSEGV"; @@ -268,8 +270,10 @@ static void SignalHandler(int sig, siginfo_t* info, void* ctx) { desc = SignalDescribe(type); String_InitArray_NT(msg, msgBuffer); - if (desc) { - String_Format3(&msg, "Unhandled signal %c (code %i) at %x", desc, &code, &addr); + if (IsNullDerefException(info)) { + String_Format1(&msg, "Unhandled NULL_POINTER_DEREF (code %i)", &code); + } else if (desc) { + String_Format3(&msg, "Unhandled %c (code %i) at %x", desc, &code, &addr); } else { String_Format3(&msg, "Unhandled signal %i (code %i) at %x", &type, &code, &addr); } diff --git a/src/Platform_Windows.c b/src/Platform_Windows.c index a9dd02b00..2e26ebe4d 100644 --- a/src/Platform_Windows.c +++ b/src/Platform_Windows.c @@ -199,8 +199,16 @@ cc_uint64 Stopwatch_Measure(void) { /*########################################################################################################################* *-------------------------------------------------------Crash handling----------------------------------------------------* *#########################################################################################################################*/ -static const char* ExceptionDescribe(cc_uint32 code) { - switch (code) { +/* In EXCEPTION_ACCESS_VIOLATION case, arg 1 is access type and arg 2 is virtual address */ +/* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record */ +#define IsNullReadException(r) (r->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && r->ExceptionInformation[1] == 0 && r->ExceptionInformation[0] == 0) +#define IsNullWriteException(r) (r->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && r->ExceptionInformation[1] == 0 && r->ExceptionInformation[0] == 1) + +static const char* ExceptionDescribe(struct _EXCEPTION_RECORD* rec) { + if (IsNullReadException(rec)) return "NULL_POINTER_READ"; + if (IsNullWriteException(rec)) return "NULL_POINTER_WRITE"; + + switch (rec->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: return "ACCESS_VIOLATION"; case EXCEPTION_ILLEGAL_INSTRUCTION: return "ILLEGAL_INSTRUCTION"; case EXCEPTION_INT_DIVIDE_BY_ZERO: return "DIVIDE_BY_ZERO"; @@ -210,14 +218,16 @@ static const char* ExceptionDescribe(cc_uint32 code) { static LONG WINAPI UnhandledFilter(struct _EXCEPTION_POINTERS* info) { cc_string msg; char msgBuffer[128 + 1]; + struct _EXCEPTION_RECORD* rec; const char* desc; cc_uint32 code; cc_uintptr addr; DWORD i, numArgs; - code = (cc_uint32)info->ExceptionRecord->ExceptionCode; - addr = (cc_uintptr)info->ExceptionRecord->ExceptionAddress; - desc = ExceptionDescribe(code); + rec = info->ExceptionRecord; + code = (cc_uint32)rec->ExceptionCode; + addr = (cc_uintptr)rec->ExceptionAddress; + desc = ExceptionDescribe(rec); String_InitArray_NT(msg, msgBuffer); if (desc) { @@ -226,13 +236,15 @@ static LONG WINAPI UnhandledFilter(struct _EXCEPTION_POINTERS* info) { String_Format2(&msg, "Unhandled exception 0x%h at %x", &code, &addr); } - numArgs = info->ExceptionRecord->NumberParameters; - if (numArgs) { + numArgs = rec->NumberParameters; + if (IsNullReadException(rec) || IsNullWriteException(rec)) { + /* Pointless to log exception arguments in this case */ + } else if (numArgs) { numArgs = min(numArgs, EXCEPTION_MAXIMUM_PARAMETERS); String_AppendConst(&msg, " ["); for (i = 0; i < numArgs; i++) { - String_Format1(&msg, "0x%x,", &info->ExceptionRecord->ExceptionInformation[i]); + String_Format1(&msg, "0x%x,", &rec->ExceptionInformation[i]); } String_Append(&msg, ']'); }