From 3566408199abb977b69fdb1ade07fe3a8a1ce3ff Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sat, 7 Mar 2026 15:12:19 +0100 Subject: [PATCH] tcc doesn't handle string literals like u"" --- src/core/core_platform.c | 242 +++++++++++++++++++++++++++++++-------- src/core/core_string16.c | 33 +++--- 2 files changed, 210 insertions(+), 65 deletions(-) diff --git a/src/core/core_platform.c b/src/core/core_platform.c index 6b3c7ed..44537c0 100644 --- a/src/core/core_platform.c +++ b/src/core/core_platform.c @@ -349,21 +349,29 @@ fn void os_core_init(void) { tcx->perm = perm; } #elif PLATFORM_POSIX - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include +#if defined(__linux__) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif + #if !PLATFORM_EMSCRIPTEN - #include - #include +#include +#include #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + fn void *os_vmem_reserve(usize size) { void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); return result == MAP_FAILED ? NULL : result; @@ -399,56 +407,190 @@ fn f64 os_parse_float(char *str) { return strtod(str, NULL); } -gb struct backtrace_state *backtrace_state = NULL; - -fn void os_core_backtrace_error_callback(void *data, const char *msg, int errnum) { - unused(data); - errorf("libbacktrace error: %s (errnum: %d)\n", msg, errnum); -} - -fn int os_core_backtrace_print_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) { - unused(data); - unused(pc); - b32 printed = false; - if (filename != NULL) { - char buffer[512]; - char *f = realpath(filename, buffer); - printf("%s:%d:1: ", f, lineno); - printed = true; - } - if (function != NULL) { - printf("%s", function); - printed = true; - } - if (printed) { - printf("\n"); - } - return 0; -} - #if !PLATFORM_EMSCRIPTEN -fn void os_unix_crash_handler(int signal, siginfo_t* info, void* context) { - unused(context); - unused(signal); - unused(info); - backtrace_full(backtrace_state, 2, os_core_backtrace_print_callback, os_core_backtrace_error_callback, NULL); + +typedef struct b_stacktrace_tag* b_stacktrace_handle; +b_stacktrace_handle b_stacktrace_get(); +int b_stacktrace_depth(b_stacktrace_handle stacktrace); +char* b_stacktrace_to_string(b_stacktrace_handle stacktrace); +char* malloc_backtrace(void); + +typedef struct print_buf { + char* buf; + int pos; + int size; +} print_buf; + +static print_buf buf_init(void) { + print_buf ret = { + (char*) malloc(1024), + 0, + 1024 + }; + return ret; +} + +static void buf_printf(print_buf* b, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + const int len = vsnprintf(NULL, 0, fmt, args) + 1; + va_end(args); + + const int new_end = b->pos + len; + + if (new_end > b->size) { + while (new_end > b->size) b->size *= 2; + b->buf = (char*)realloc(b->buf, b->size); + } + + va_start(args, fmt); + b->pos += vsnprintf(b->buf + b->pos, len, fmt, args); + va_end(args); +} + +char* malloc_backtrace(void) { + b_stacktrace_handle h = b_stacktrace_get(); + char* ret = b_stacktrace_to_string(h); + free(h); + return ret; +} + +#define B_STACKTRACE_MAX_DEPTH 1024 + +typedef struct b_stacktrace { + void* trace[B_STACKTRACE_MAX_DEPTH]; + int trace_size; +} b_stacktrace; + +b_stacktrace_handle b_stacktrace_get(void) { + b_stacktrace* ret = (b_stacktrace*)malloc(sizeof(b_stacktrace)); + ret->trace_size = backtrace(ret->trace, B_STACKTRACE_MAX_DEPTH); + return (b_stacktrace_handle)(ret); +} + +int b_stacktrace_depth(b_stacktrace_handle h) { + const b_stacktrace* stacktrace = (b_stacktrace*)h; + return stacktrace->trace_size; +} + +char* b_stacktrace_to_string(b_stacktrace_handle h) { + const b_stacktrace* stacktrace = (b_stacktrace*)h; + char** messages = backtrace_symbols(stacktrace->trace, stacktrace->trace_size); + print_buf out = buf_init(); + int i; + + int skip_count = 5; + for (i = 0; i < stacktrace->trace_size; ++i) { + void* tracei = stacktrace->trace[i]; + char* msg = messages[i]; + + if (i < skip_count) { + continue; + } + + /* calculate load offset */ + Dl_info info; + dladdr(tracei, &info); + if (info.dli_fbase == (void*)0x400000) { + /* address from executable, so don't offset */ + info.dli_fbase = NULL; + } + + while (*msg && *msg != '(') ++msg; + *msg = 0; + + { + char cmd[1024]; + char line[2048]; + + FILE* fp; + snprintf(cmd, 1024, "addr2line -e %s -f -C -p %p 2>/dev/null", messages[i], (void*)((char*)tracei - (char*)info.dli_fbase)); + + fp = popen(cmd, "r"); + if (!fp) { + buf_printf(&out, "Failed to generate trace further...\n"); + break; + } + + while (fgets(line, sizeof(line), fp)) { + buf_printf(&out, " "); + if (strstr(line, "?? ")) { + /* just output address if nothing can be found */ + buf_printf(&out, "%p\n", tracei); + } + else { + int len = strlen(line); + char *at = strstr(line, " at "); + if (at) { + char *function = line; + int function_len = at - line; + char *file = at + 4; + int file_len = strlen(file) - 1; + buf_printf(&out, " %.*s %.*s (%s)\n", file_len, file, function_len, function, messages[i]); + } else { + buf_printf(&out, " %.*s (%s)\n", len - 1, line, messages[i]); + } + } + } + + pclose(fp); + } + } + + free(messages); + return out.buf; +} + +void print_backtrace(void) { + char *backtrace = malloc_backtrace(); + puts(backtrace); + free(backtrace); +} + +const char *signal_to_string(int signal) { + switch (signal) { + case SIGINT: return "SIGINT"; + case SIGILL: return "SIGILL"; + case SIGABRT: return "SIGABRT"; + case SIGFPE: return "SIGFPE"; + case SIGSEGV: return "SIGSEGV"; + case SIGTERM: return "SIGTERM"; + case SIGHUP: return "SIGALRM"; + case SIGQUIT: return "SIGQUIT"; + case SIGTRAP: return "SIGTRAP"; + case SIGKILL: return "SIGKILL"; + case SIGPIPE: return "SIGPIPE"; + case SIGALRM: return "SIGHUP"; + case SIGPOLL: return "SIGPOLL"; + default: return ""; + } +} + +void backtrace_handle_signal(int signal, siginfo_t* info, void* context) { + (void)context; // unused + printf("Stack trace (%s/%d):", signal_to_string(signal), signal); + if (signal == SIGSEGV) { + printf(" at addr: %p", info->si_addr); + } + puts(""); + print_backtrace(); exit(1); } -fn void os_unix_register_crash_handler() { - backtrace_state = backtrace_create_state(NULL, 1, os_core_backtrace_error_callback, NULL); - +void setup_backtrace() { struct sigaction sa; - sa.sa_sigaction = os_unix_crash_handler; + sa.sa_sigaction = backtrace_handle_signal; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGABRT, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); sigaction(SIGBUS, &sa, NULL); sigaction(SIGILL, &sa, NULL); - sigaction(SIGFPE, &sa, NULL); + sigaction(SIGTRAP, &sa, NULL); } + #endif fn void os_core_small_init(ma_arena_t *arena) { @@ -459,7 +601,7 @@ fn void os_core_small_init(ma_arena_t *arena) { tcx->log.print_file_and_line = true; tcx->log.log_proc = default_log_proc; #if !PLATFORM_EMSCRIPTEN - os_unix_register_crash_handler(); + setup_backtrace(); #endif } diff --git a/src/core/core_string16.c b/src/core/core_string16.c index ad652f6..2e624b6 100644 --- a/src/core/core_string16.c +++ b/src/core/core_string16.c @@ -303,13 +303,13 @@ fn s16_t s16_chop_last_char(s16_t s, s16_t ch) { return result; } -fn s16_t s16_chop_last_slash(s16_t s) { - return s16_chop_last_char(s, s16("/")); -} +// fn s16_t s16_chop_last_slash(s16_t s) { +// return s16_chop_last_char(s, s16("/")); +// } -fn s16_t s16_chop_last_period(s16_t s) { - return s16_chop_last_char(s, s16(".")); -} +// fn s16_t s16_chop_last_period(s16_t s) { +// return s16_chop_last_char(s, s16(".")); +// } fn s16_t s16_skip_to_last_char(s16_t s, s16_t ch) { int64_t pos; @@ -320,17 +320,17 @@ fn s16_t s16_skip_to_last_char(s16_t s, s16_t ch) { return result; } -fn s16_t s16_skip_to_last_slash(s16_t s) { - return s16_skip_to_last_char(s, s16("/")); -} +// fn s16_t s16_skip_to_last_slash(s16_t s) { +// return s16_skip_to_last_char(s, s16("/")); +// } -fn s16_t s16_skip_to_last_period(s16_t s) { - return s16_skip_to_last_char(s, s16(".")); -} +// fn s16_t s16_skip_to_last_period(s16_t s) { +// return s16_skip_to_last_char(s, s16(".")); +// } -fn s16_t s16_get_name_no_ext(s16_t s) { - return s16_skip_to_last_slash(s16_chop_last_period(s)); -} +// fn s16_t s16_get_name_no_ext(s16_t s) { +// return s16_skip_to_last_slash(s16_chop_last_period(s)); +// } fn s16_t s16_to_lower_case(ma_arena_t *ma, s16_t s) { s16_t copy = s16_copy(ma, s); @@ -504,6 +504,7 @@ fn s16_t s16_copy_ex(alo_t ma, s16_t string) { return result; } +#if 0 fn_test void test_string16(void) { ma_temp_t scratch = ma_begin_scratch(); @@ -617,3 +618,5 @@ fn_test void test_string16(void) { ma_end_scratch(scratch); } + +#endif \ No newline at end of file