tcc doesn't handle string literals like u""
This commit is contained in:
@@ -349,6 +349,19 @@ fn void os_core_init(void) {
|
||||
tcx->perm = perm;
|
||||
}
|
||||
#elif PLATFORM_POSIX
|
||||
#if defined(__linux__) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
|
||||
#if !PLATFORM_EMSCRIPTEN
|
||||
#include <execinfo.h>
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -356,14 +369,9 @@ fn void os_core_init(void) {
|
||||
#include <time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if !PLATFORM_EMSCRIPTEN
|
||||
#include <execinfo.h>
|
||||
#include <backtrace.h>
|
||||
#endif
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user