From 3252f1f10a725452cd7e6e3c319c91e0cd00c7be Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 7 Jun 2022 17:02:23 +1100 Subject: [PATCH] signal --- bake.cmd | 2 +- code/assert.c | 2 +- code/os/win/entry.c | 3 ++ code/os/win/env.c | 8 +++++ code/os/win/except.c | 57 +++++++++++++++++++++++++++++++++ code/os/win/io.c | 2 +- code/os/win/{memory.c => mem.c} | 0 code/signal.c | 46 ++++++++++++++++++++++++++ code/stdio.c | 8 ++--- inc/_macros.h | 1 + inc/_os.h | 4 ++- inc/assert.h | 1 + inc/signal.h | 29 ++++++++++------- test/test.c | 15 +++++++-- 14 files changed, 156 insertions(+), 22 deletions(-) create mode 100644 code/os/win/except.c rename code/os/win/{memory.c => mem.c} (100%) create mode 100644 code/signal.c diff --git a/bake.cmd b/bake.cmd index 15e4ac2..fa0fdfd 100644 --- a/bake.cmd +++ b/bake.cmd @@ -16,7 +16,7 @@ shift /1 set CIABATTA_OPTIONS=-Iinc -Wall -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS set PLATFORM=win -if "%1"=="fast" ( +if "%1"=="test" ( goto :skip_crt_compilation ) :: For each C file in code/ we check whether it's OS-dependent. diff --git a/code/assert.c b/code/assert.c index 00ddc71..47d3636 100644 --- a/code/assert.c +++ b/code/assert.c @@ -20,5 +20,5 @@ extern void _assert_error( } printf("\tFile: %s\n", file); printf("\tLine: %s\n", line); - _compiler_brk(); + abort(); } diff --git a/code/os/win/entry.c b/code/os/win/entry.c index 500d69e..eb538b3 100644 --- a/code/os/win/entry.c +++ b/code/os/win/entry.c @@ -1,4 +1,6 @@ +#include <_os.h> + #include #include #include @@ -71,6 +73,7 @@ void mainCRTStartup() { srand(0); setlocale(LC_ALL, "C"); + _os_init_eh(); int exit_code = main(arg_count, args); ExitProcess(exit_code); diff --git a/code/os/win/env.c b/code/os/win/env.c index c97a4f3..8688081 100644 --- a/code/os/win/env.c +++ b/code/os/win/env.c @@ -1,2 +1,10 @@ #include + +#define WIN32_LEAN_AND_MEAN +#include + +void _os_exit(int code) +{ + ExitProcess(code); +} diff --git a/code/os/win/except.c b/code/os/win/except.c new file mode 100644 index 0000000..9a1d38d --- /dev/null +++ b/code/os/win/except.c @@ -0,0 +1,57 @@ + +#include <_os.h> + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include <_macros.h> + +typedef struct SignalMapping { + DWORD code; + int signal; +} SignalMapping; + +static SignalMapping map[] = { + {EXCEPTION_ACCESS_VIOLATION, SIGSEGV}, + {EXCEPTION_IN_PAGE_ERROR, SIGSEGV}, + {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, SIGSEGV}, + {EXCEPTION_DATATYPE_MISALIGNMENT, SIGALIGN}, + {EXCEPTION_BREAKPOINT, SIGBREAK}, + {EXCEPTION_FLT_DENORMAL_OPERAND, SIGFPE}, + {EXCEPTION_FLT_DIVIDE_BY_ZERO, SIGFPE}, + {EXCEPTION_FLT_INEXACT_RESULT, SIGFPE}, + {EXCEPTION_FLT_INVALID_OPERATION, SIGFPE}, + {EXCEPTION_FLT_OVERFLOW, SIGFPE}, + {EXCEPTION_FLT_STACK_CHECK, SIGFPE}, + {EXCEPTION_FLT_UNDERFLOW, SIGFPE}, + {EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL}, + {EXCEPTION_INT_DIVIDE_BY_ZERO, SIGFPE}, + {EXCEPTION_INT_OVERFLOW, SIGFPE}, + {EXCEPTION_PRIV_INSTRUCTION, SIGILL}, + {EXCEPTION_SINGLE_STEP, SIGSTEP}, +}; + +static LONG _win32_handler(EXCEPTION_POINTERS *ExceptionInfo) +{ + EXCEPTION_RECORD *exception = ExceptionInfo->ExceptionRecord; + DWORD code = exception->ExceptionCode; + int signal = -1; + for(int mapping = 0; mapping != _countof(map); ++mapping) { + if(code == map[mapping].code) { + signal = map[mapping].signal; + } + } + if(signal != -1) { + raise(signal); + } + return EXCEPTION_CONTINUE_SEARCH; +} + +void _os_init_eh() { + void *res = AddVectoredExceptionHandler(1, &_win32_handler); + if(res == NULL) { + ExitProcess(-69420); + } +} diff --git a/code/os/win/io.c b/code/os/win/io.c index 795659a..edea935 100644 --- a/code/os/win/io.c +++ b/code/os/win/io.c @@ -7,7 +7,7 @@ struct FILE { int unused; }; -void _file_write(void* ctx, size_t n, const char str[]) { +void _os_file_write(void* ctx, size_t n, const char str[]) { DWORD written = 0; WriteFile((HANDLE) ctx, str, n, &written, NULL); } diff --git a/code/os/win/memory.c b/code/os/win/mem.c similarity index 100% rename from code/os/win/memory.c rename to code/os/win/mem.c diff --git a/code/signal.c b/code/signal.c new file mode 100644 index 0000000..7b9c196 --- /dev/null +++ b/code/signal.c @@ -0,0 +1,46 @@ + +#include <_os.h> +#include + +void _signal_default_handler(int sig) +{ + +} + +void _signal_ignore_handler(int sig) +{ + // ignore :kekw: +} + +static void (*(handlers[]))(int) = { + [SIGINT] = _signal_ignore_handler, + [SIGILL] = _signal_ignore_handler, + [SIGFPE] = _signal_ignore_handler, + [SIGSEGV] = _signal_ignore_handler, + [SIGTERM] = _signal_ignore_handler, + [SIGABRT] = _signal_ignore_handler, + [SIGBREAK] = _signal_ignore_handler, + [SIGALIGN] = _signal_ignore_handler, + [SIGSTEP] = _signal_ignore_handler, +}; + +void (*signal(int sig, void (*func)(int)))(int) +{ + if(_SIG_MIN <= sig && sig <= _SIG_MAX) { + handlers[sig] = func; + return func; + } + return SIG_ERR; +} + +int raise(int sig) +{ + if(_SIG_MIN <= sig && sig <= _SIG_MAX) { + handlers[sig](sig); + if(sig == SIGFPE || sig == SIGILL || sig == SIGSEGV) { + _os_exit(-69420); + } + return 1; + } + return 0; +} diff --git a/code/stdio.c b/code/stdio.c index 4ffde74..21f69a4 100644 --- a/code/stdio.c +++ b/code/stdio.c @@ -40,12 +40,12 @@ static void string_write(void *ctx, size_t n, const char *restrict str) { } int fprintf(FILE *file, const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, file, _file_write, fmt); + CALL_PRINTF(fmt_print_char, file, _os_file_write, fmt); return result; } int printf(const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, stdout, _file_write, fmt); + CALL_PRINTF(fmt_print_char, stdout, _os_file_write, fmt); return result; } @@ -62,11 +62,11 @@ int sprintf(char *restrict s, const char *restrict fmt, ...) { } int vfprintf(FILE *file, const char *restrict fmt, va_list args) { - return fmt_print_char(file, _file_write, fmt, args); + return fmt_print_char(file, _os_file_write, fmt, args); } int vprintf(const char *restrict fmt, va_list args) { - return fmt_print_char(stdout, _file_write, fmt, args); + return fmt_print_char(stdout, _os_file_write, fmt, args); } int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) { diff --git a/inc/_macros.h b/inc/_macros.h index 0f4e977..fa90589 100644 --- a/inc/_macros.h +++ b/inc/_macros.h @@ -6,3 +6,4 @@ #define _con(a,b) a ## b +#define _countof(arr) (sizeof (arr) / sizeof ((arr)[0])) diff --git a/inc/_os.h b/inc/_os.h index 253bdc6..37c46d0 100644 --- a/inc/_os.h +++ b/inc/_os.h @@ -15,5 +15,7 @@ #endif // OS-dependent IO Functions -void _file_write(void* ctx, size_t n, const char str[]); +void _os_file_write(void* ctx, size_t n, const char str[]); +void _os_exit(int code); +void _os_init_eh(); typedef struct FILE FILE; diff --git a/inc/assert.h b/inc/assert.h index 478f8ba..dd950b8 100644 --- a/inc/assert.h +++ b/inc/assert.h @@ -1,5 +1,6 @@ #pragma once #include "_compiler.h" +#include "_macros.h" extern void _assert_error( char *cond, diff --git a/inc/signal.h b/inc/signal.h index c3016c8..e8a00c6 100644 --- a/inc/signal.h +++ b/inc/signal.h @@ -3,19 +3,24 @@ typedef int sig_atomic_t; -// TODO: implement this -#define SIG_DFL 0 -#define SIG_ERR 1 -#define SIG_IGN 2 +// TODO: idk about SIG_ERR, for now this +#define SIG_ERR ((void(*)(int))0) +#define SIG_DFL _signal_default_handler +#define SIG_IGN _signal_ignore_handler -// not sure why but windows picked these, we can change it later -#define SIGINT 2 -#define SIGILL 4 -#define SIGFPE 8 -#define SIGSEGV 11 -#define SIGTERM 15 -#define SIGBREAK 21 -#define SIGABRT 22 +// Note(bumbread): from the impl standpoint the numbers are arbitrary +#define _SIG_MIN 0 +#define SIGINT 1 +#define SIGILL 2 +#define SIGFPE 3 +#define SIGSEGV 4 +#define SIGTERM 5 +#define SIGABRT 6 +// These guys are impl defined +#define SIGBREAK 7 +#define SIGALIGN 8 +#define SIGSTEP 9 +#define _SIG_MAX 9 void (*signal(int sig, void (*func)(int)))(int); int raise(int sig); diff --git a/test/test.c b/test/test.c index afde00a..4ee6606 100644 --- a/test/test.c +++ b/test/test.c @@ -4,10 +4,21 @@ #include #include +#include #include +#include + +void my_va_handler(int a) { + printf("NULLPTR deref or something idk not an expert in signals\n"); +} + int main(int argc, char** argv) { - uint64_t mynumber = 4; - printf("Hello, guys %"PRIu64"\n", mynumber); + signal(SIGSEGV, my_va_handler); + signal(SIGFPE, my_va_handler); + + int a = INT_MAX; + a /= 0; + return 0; } \ No newline at end of file