From 3f3cbb51ed113df35593ec6b156e0fab82206666 Mon Sep 17 00:00:00 2001 From: grischka Date: Wed, 30 Aug 2023 21:20:13 +0200 Subject: [PATCH] bcheck: remove "tcc_location()" & x86_64 double fix using (modified) tcc_backtrace() instead. Also Also fix the original bug with doubles on x86_64. (which was not caused by incr_offset() actually). See 598134fff6a1c85bd048ab307ff91cd24dcfbafd Also cleanup on_exit() stuff From fef701b57fa75f1c387c3e6e8e7ba251a053698f --- lib/bcheck.c | 7 +-- lib/bt-dll.c | 1 - lib/bt-exe.c | 2 - lib/bt-log.c | 16 ++--- tccgen.c | 2 +- tccrun.c | 168 ++++++++++++++------------------------------------- x86_64-gen.c | 1 + 7 files changed, 55 insertions(+), 142 deletions(-) diff --git a/lib/bcheck.c b/lib/bcheck.c index e05209c6..1e374f16 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -41,7 +41,7 @@ #define BOUND_STATISTIC (1) #if BOUND_DEBUG - #define dprintf(a...) if (print_calls) { bounds_loc; fprintf(a); } + #define dprintf(a...) if (print_calls) { bounds_loc(a); } #else #define dprintf(a...) #endif @@ -446,7 +446,6 @@ static unsigned long long bound_splay_delete; #endif int tcc_backtrace(const char *fmt, ...); -void tcc_location(const char *fmt); /* print a bound error message */ #define bound_warning(...) \ @@ -463,10 +462,10 @@ void tcc_location(const char *fmt); exit(255); \ } while (0) -#define bounds_loc \ +#define bounds_loc(fp, ...) \ do { \ WAIT_SEM (); \ - tcc_location("^bcheck.c^"); \ + tcc_backtrace("^bcheck.c^\001" __VA_ARGS__); \ POST_SEM (); \ } while (0) diff --git a/lib/bt-dll.c b/lib/bt-dll.c index 00c67da7..7c62cefa 100644 --- a/lib/bt-dll.c +++ b/lib/bt-dll.c @@ -8,7 +8,6 @@ REDIR(__bt_init) \ REDIR(__bt_exit) \ REDIR(tcc_backtrace) \ - REDIR(tcc_location) \ \ REDIR(__bound_ptr_add) \ REDIR(__bound_ptr_indir1) \ diff --git a/lib/bt-exe.c b/lib/bt-exe.c index 7cd56e70..3a2d02e4 100644 --- a/lib/bt-exe.c +++ b/lib/bt-exe.c @@ -8,7 +8,6 @@ #include "../tccrun.c" int (*__rt_error)(void*, void*, const char *, va_list); -void (*__rt_location)(void*, void*, const char *); __attribute__((weak)) void __bound_checking_lock(void); __attribute__((weak)) void __bound_checking_unlock(void); @@ -34,7 +33,6 @@ void __bt_init(rt_context *p, int num_callers) rc->num_callers = num_callers - 1; rc->top_func = main; __rt_error = _rt_error; - __rt_location = _rt_location; set_exception_handler(); } else { p->next = rc->next, rc->next = p; diff --git a/lib/bt-log.c b/lib/bt-log.c index c6a11146..bff9a794 100644 --- a/lib/bt-log.c +++ b/lib/bt-log.c @@ -6,7 +6,6 @@ #include int (*__rt_error)(void*, void*, const char *, va_list); -void (*__rt_location)(void*, void*, const char *); #ifdef _WIN32 # define DLL_EXPORT __declspec(dllexport) @@ -32,26 +31,19 @@ DLL_EXPORT int tcc_backtrace(const char *fmt, ...) ret = __rt_error(fp, ip, fmt, ap); va_end(ap); } else { - const char *p; + const char *p, *nl = "\n"; if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0]))) fmt = p + 1; + if (fmt[0] == '\001') + ++fmt, nl = ""; va_start(ap, fmt); ret = vfprintf(stderr, fmt, ap); va_end(ap); - fprintf(stderr, "\n"), fflush(stderr); + fprintf(stderr, nl), fflush(stderr); } return ret; } -DLL_EXPORT void tcc_location(const char *fmt) -{ - if (__rt_location) { - void *fp = __builtin_frame_address(1); - void *ip = __builtin_return_address(0); - __rt_location(fp, ip, fmt); - } -} - #if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__) #pragma GCC diagnostic pop #endif diff --git a/tccgen.c b/tccgen.c index 88436a83..529abe9c 100644 --- a/tccgen.c +++ b/tccgen.c @@ -6010,7 +6010,6 @@ special_math_val: indir(); qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); test_lvalue(); - gaddrof(); /* expect pointer on structure */ if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) expect("struct or union"); @@ -6021,6 +6020,7 @@ special_math_val: expect("field name"); s = find_field(&vtop->type, tok, &cumofs); /* add field offset to pointer */ + gaddrof(); vtop->type = char_pointer_type; /* change type to 'char *' */ vpushi(cumofs); gen_op('+'); diff --git a/tccrun.c b/tccrun.c index 40545ad0..b102d829 100644 --- a/tccrun.c +++ b/tccrun.c @@ -23,9 +23,9 @@ /* only native compiler supports -run */ #ifdef TCC_IS_NATIVE -#ifdef CONFIG_TCC_BACKTRACE typedef struct rt_context { +#ifdef CONFIG_TCC_BACKTRACE /* --> tccelf.c:tcc_add_btstub wants those below in that order: */ union { struct { @@ -46,15 +46,27 @@ typedef struct rt_context int num_callers; addr_t ip, fp, sp; void *top_func; - jmp_buf jmp_buf; - char do_jmp; +#endif + jmp_buf jb; + int do_jmp; +# define NR_AT_EXIT 32 + int nr_exit; + void *exitfunc[NR_AT_EXIT]; + void *exitarg[NR_AT_EXIT]; } rt_context; static rt_context g_rtctxt; +static void rt_exit(int code) +{ + rt_context *rc = &g_rtctxt; + if (rc->do_jmp) + longjmp(rc->jb, code ? code : 256); + exit(code); +} + +#ifdef CONFIG_TCC_BACKTRACE static void set_exception_handler(void); static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); -static void _rt_location(void *fp, void *ip, const char *fmt); -static void rt_exit(int code); #endif /* CONFIG_TCC_BACKTRACE */ /* defined when included from lib/bt-exe.c */ @@ -147,79 +159,35 @@ static void run_cdtors(TCCState *s1, const char *start, const char *end, ((void(*)(int, char **, char **))*a++)(argc, argv, envp); } -#define NR_AT_EXIT 32 - -static struct exit_context { - int exit_called; - int nr_exit; - void (*exitfunc[NR_AT_EXIT])(int, void *); - void *exitarg[NR_AT_EXIT]; -#ifndef CONFIG_TCC_BACKTRACE - jmp_buf run_jmp_buf; -#endif -} g_exit_context; - -static void init_exit(void) +static void run_on_exit(int ret) { - struct exit_context *e = &g_exit_context; - - e->exit_called = 0; - e->nr_exit = 0; + rt_context *rc = &g_rtctxt; + int n = rc->nr_exit; + while (n) + --n, ((void(*)(int,void*))rc->exitfunc[n])(ret, rc->exitarg[n]); } -static void call_exit(int ret) +static int rt_on_exit(void *function, void *arg) { - struct exit_context *e = &g_exit_context; - - while (e->nr_exit) { - e->nr_exit--; - e->exitfunc[e->nr_exit](ret, e->exitarg[e->nr_exit]); - } -} - -static int rt_atexit(void (*function)(void)) -{ - struct exit_context *e = &g_exit_context; - - if (e->nr_exit < NR_AT_EXIT) { - e->exitfunc[e->nr_exit] = (void (*)(int, void *))function; - e->exitarg[e->nr_exit++] = NULL; + rt_context *rc = &g_rtctxt; + if (rc->nr_exit < NR_AT_EXIT) { + rc->exitfunc[rc->nr_exit] = function; + rc->exitarg[rc->nr_exit++] = arg; return 0; } return 1; } -static int rt_on_exit(void (*function)(int, void *), void *arg) +static int rt_atexit(void *function) { - struct exit_context *e = &g_exit_context; - - if (e->nr_exit < NR_AT_EXIT) { - e->exitfunc[e->nr_exit] = function; - e->exitarg[e->nr_exit++] = arg; - return 0; - } - return 1; -} - -static void run_exit(int code) -{ - struct exit_context *e = &g_exit_context; - - e->exit_called = 1; -#ifdef CONFIG_TCC_BACKTRACE - longjmp((&g_rtctxt)->jmp_buf, code ? code : 256); -#else - longjmp(e->run_jmp_buf, code ? code : 256); -#endif + return rt_on_exit(function, NULL); } /* launch the compiled program with the given arguments */ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) { int (*prog_main)(int, char **, char **), ret; -#ifdef CONFIG_TCC_BACKTRACE rt_context *rc = &g_rtctxt; -#endif #if defined(__APPLE__) || defined(__FreeBSD__) char **envp = NULL; @@ -233,17 +201,21 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) s1->runtime_main = s1->nostdlib ? "_start" : "main"; if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1)) return 0; - tcc_add_symbol(s1, "exit", run_exit); + + tcc_add_symbol(s1, "exit", rt_exit); tcc_add_symbol(s1, "atexit", rt_atexit); tcc_add_symbol(s1, "on_exit", rt_on_exit); if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) return -1; + prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1); if ((addr_t)-1 == (addr_t)prog_main) return -1; -#ifdef CONFIG_TCC_BACKTRACE memset(rc, 0, sizeof *rc); + rc->do_jmp = 1; + +#ifdef CONFIG_TCC_BACKTRACE if (s1->do_debug) { void *p; if (s1->dwarf) { @@ -272,11 +244,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) #endif rc->top_func = tcc_get_symbol(s1, "main"); rc->num_callers = s1->rt_num_callers; - rc->do_jmp = 1; if ((p = tcc_get_symbol(s1, "__rt_error"))) *(void**)p = _rt_error; - if ((p = tcc_get_symbol(s1, "__rt_location"))) - *(void**)p = _rt_location; #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check) { rc->bounds_start = (void*)bounds_section->sh_addr; @@ -291,23 +260,15 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) errno = 0; /* clean errno value */ fflush(stdout); fflush(stderr); - init_exit(); + /* These aren't C symbols, so don't need leading underscore handling. */ run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp); -#ifdef CONFIG_TCC_BACKTRACE - if (!(ret = setjmp(rc->jmp_buf))) -#else - if (!(ret = setjmp((&g_exit_context)->run_jmp_buf))) -#endif - { + if (!(ret = setjmp(rc->jb))) ret = prog_main(argc, argv, envp); - } run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL); - call_exit(ret); - if ((s1->dflag & 16) && ret) + run_on_exit(ret); + if (s1->dflag & 16 && ret) /* tcc -dt -run ... */ fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); - if ((s1->dflag & 16) == 0 && (&g_exit_context)->exit_called) - exit(ret); return ret; } @@ -1044,7 +1005,7 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap) rt_context *rc = &g_rtctxt; addr_t pc = 0; char skip[100]; - int i, level, ret, n; + int i, level, ret, n, one; const char *a, *b, *msg; if (fp) { @@ -1063,6 +1024,10 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap) memcpy(skip, a, b - a), skip[b - a] = 0; fmt = b + 1; } + one = 0; + /* hack for bcheck.c:dprintf(): one level, no newline */ + if (fmt[0] == '\001') + ++fmt, one = 1; n = rc->num_callers ? rc->num_callers : 6; for (i = level = 0; level < n; i++) { @@ -1082,6 +1047,8 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap) rt_vprintf(fmt, ap); } else if (ret == -1) break; + if (one) + break; rt_printf("\n"); if (ret == -1 || (pc == (addr_t)rc->top_func && pc)) break; @@ -1092,41 +1059,6 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap) return 0; } -static void _rt_location(void *fp, void *ip, const char *fmt) -{ - rt_context *rc = &g_rtctxt; - addr_t pc = 0; - char skip[100]; - int i, ret; - const char *a, *b; - - rc->fp = (addr_t)fp; - rc->ip = (addr_t)ip; - - skip[0] = 0; - /* If fmt is like "^file.c^..." then skip calls from 'file.c' */ - if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0]))) - memcpy(skip, a, b - a), skip[b - a] = 0; - - for (i = 0; ; i++) { - ret = rt_get_caller_pc(&pc, rc, i); - a = ""; - if (ret != -1) { - if (rc->dwarf) - pc = rt_printline_dwarf(rc, pc, "at", skip); - else - pc = rt_printline(rc, pc, "at", skip); - if (pc == (addr_t)-1) - continue; - a = ": "; - } - rt_printf(a); - break; - } - - rc->ip = rc->fp = 0; -} - /* emit a run time error at position 'pc' */ static int rt_error(const char *fmt, ...) { @@ -1138,14 +1070,6 @@ static int rt_error(const char *fmt, ...) return ret; } -static void rt_exit(int code) -{ - rt_context *rc = &g_rtctxt; - if (rc->do_jmp) - longjmp(rc->jmp_buf, code ? code : 256); - exit(code); -} - /* ------------------------------------------------------------- */ #ifndef _WIN32 diff --git a/x86_64-gen.c b/x86_64-gen.c index a41cbc10..e04df10a 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -2047,6 +2047,7 @@ void gen_opf(int op) assert(vtop->r & VT_LVAL); gv(RC_FLOAT); vswap(); + fc = vtop->c.i; /* bcheck may have saved previous vtop[-1] */ } if ((ft & VT_BTYPE) == VT_DOUBLE) {