From 598134fff6a1c85bd048ab307ff91cd24dcfbafd Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Wed, 30 Aug 2023 16:10:39 +0200 Subject: [PATCH] Undo part of incr_offset patch. The incr_offset offset code was not working with bounds checking. So I reverted part of tccgen.c. See new test code 132. Also added some debugging code that prints location of bounds checking calls. Needed this to find the problem. See lib/bcheck.c, lib/bt-dll.c, lib/bt-exe.c, lib/bt-log.c, tccrun.c --- lib/bcheck.c | 10 +++++++- lib/bt-dll.c | 1 + lib/bt-exe.c | 2 ++ lib/bt-log.c | 10 ++++++++ tccgen.c | 10 ++++---- tccrun.c | 38 ++++++++++++++++++++++++++++++ tests/tests2/132_bound_test.c | 29 +++++++++++++++++++++++ tests/tests2/132_bound_test.expect | 1 + 8 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 tests/tests2/132_bound_test.c create mode 100644 tests/tests2/132_bound_test.expect diff --git a/lib/bcheck.c b/lib/bcheck.c index b8dd1c53..e05209c6 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) fprintf(a) + #define dprintf(a...) if (print_calls) { bounds_loc; fprintf(a); } #else #define dprintf(a...) #endif @@ -446,6 +446,7 @@ 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(...) \ @@ -462,6 +463,13 @@ int tcc_backtrace(const char *fmt, ...); exit(255); \ } while (0) +#define bounds_loc \ + do { \ + WAIT_SEM (); \ + tcc_location("^bcheck.c^"); \ + POST_SEM (); \ + } while (0) + static void bound_alloc_error(const char *s) { fprintf(stderr,"FATAL: %s\n",s); diff --git a/lib/bt-dll.c b/lib/bt-dll.c index 7c62cefa..00c67da7 100644 --- a/lib/bt-dll.c +++ b/lib/bt-dll.c @@ -8,6 +8,7 @@ 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 3a2d02e4..7cd56e70 100644 --- a/lib/bt-exe.c +++ b/lib/bt-exe.c @@ -8,6 +8,7 @@ #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); @@ -33,6 +34,7 @@ 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 8f7a4dbb..c6a11146 100644 --- a/lib/bt-log.c +++ b/lib/bt-log.c @@ -6,6 +6,7 @@ #include int (*__rt_error)(void*, void*, const char *, va_list); +void (*__rt_location)(void*, void*, const char *); #ifdef _WIN32 # define DLL_EXPORT __declspec(dllexport) @@ -42,6 +43,15 @@ DLL_EXPORT int tcc_backtrace(const char *fmt, ...) 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 205c27f7..88436a83 100644 --- a/tccgen.c +++ b/tccgen.c @@ -6010,6 +6010,7 @@ 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"); @@ -6020,15 +6021,16 @@ special_math_val: expect("field name"); s = find_field(&vtop->type, tok, &cumofs); /* add field offset to pointer */ - incr_offset(cumofs); + vtop->type = char_pointer_type; /* change type to 'char *' */ + vpushi(cumofs); + gen_op('+'); /* change type to field type, and set to lvalue */ vtop->type = s->type; vtop->type.t |= qualifiers; /* an array is never an lvalue */ - if (vtop->type.t & VT_ARRAY) { - vtop->r &= ~VT_LVAL; + if (!(vtop->type.t & VT_ARRAY)) { + vtop->r |= VT_LVAL; #ifdef CONFIG_TCC_BCHECK - } else { /* if bound checking, the referenced pointer must be checked */ if (tcc_state->do_bounds_check) vtop->r |= VT_MUSTBOUND; diff --git a/tccrun.c b/tccrun.c index d373abca..40545ad0 100644 --- a/tccrun.c +++ b/tccrun.c @@ -53,6 +53,7 @@ typedef struct rt_context static rt_context g_rtctxt; 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 */ @@ -274,6 +275,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) 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; @@ -1089,6 +1092,41 @@ 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, ...) { diff --git a/tests/tests2/132_bound_test.c b/tests/tests2/132_bound_test.c new file mode 100644 index 00000000..4898e8d7 --- /dev/null +++ b/tests/tests2/132_bound_test.c @@ -0,0 +1,29 @@ +#include +#include + +union ieee_double_extract +{ + struct { + unsigned int manl:32; + unsigned int manh:20; + unsigned int exp:11; + unsigned int sig:1; + } s; + double d; +}; + +double scale(double d) +{ + union ieee_double_extract x; + + x.d = d; + x.d *= 1000; + return x.d; +} + +int +main(void) +{ + printf("%g\n", scale(42)); + return 0; +} diff --git a/tests/tests2/132_bound_test.expect b/tests/tests2/132_bound_test.expect new file mode 100644 index 00000000..6096bd1b --- /dev/null +++ b/tests/tests2/132_bound_test.expect @@ -0,0 +1 @@ +42000