1
0
Fork 0

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 598134fff6

Also cleanup on_exit() stuff
From fef701b57f
This commit is contained in:
grischka 2023-08-30 21:20:13 +02:00
parent ff2a372a9a
commit 3f3cbb51ed
7 changed files with 55 additions and 142 deletions

View File

@ -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)

View File

@ -8,7 +8,6 @@
REDIR(__bt_init) \
REDIR(__bt_exit) \
REDIR(tcc_backtrace) \
REDIR(tcc_location) \
\
REDIR(__bound_ptr_add) \
REDIR(__bound_ptr_indir1) \

View File

@ -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;

View File

@ -6,7 +6,6 @@
#include <string.h>
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

View File

@ -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('+');

168
tccrun.c
View File

@ -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

View File

@ -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) {