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
This commit is contained in:
herman ten brugge 2023-08-30 16:10:39 +02:00
parent d1c107738b
commit 598134fff6
8 changed files with 96 additions and 5 deletions

View file

@ -41,7 +41,7 @@
#define BOUND_STATISTIC (1) #define BOUND_STATISTIC (1)
#if BOUND_DEBUG #if BOUND_DEBUG
#define dprintf(a...) if (print_calls) fprintf(a) #define dprintf(a...) if (print_calls) { bounds_loc; fprintf(a); }
#else #else
#define dprintf(a...) #define dprintf(a...)
#endif #endif
@ -446,6 +446,7 @@ static unsigned long long bound_splay_delete;
#endif #endif
int tcc_backtrace(const char *fmt, ...); int tcc_backtrace(const char *fmt, ...);
void tcc_location(const char *fmt);
/* print a bound error message */ /* print a bound error message */
#define bound_warning(...) \ #define bound_warning(...) \
@ -462,6 +463,13 @@ int tcc_backtrace(const char *fmt, ...);
exit(255); \ exit(255); \
} while (0) } while (0)
#define bounds_loc \
do { \
WAIT_SEM (); \
tcc_location("^bcheck.c^"); \
POST_SEM (); \
} while (0)
static void bound_alloc_error(const char *s) static void bound_alloc_error(const char *s)
{ {
fprintf(stderr,"FATAL: %s\n",s); fprintf(stderr,"FATAL: %s\n",s);

View file

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

View file

@ -8,6 +8,7 @@
#include "../tccrun.c" #include "../tccrun.c"
int (*__rt_error)(void*, void*, const char *, va_list); 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_lock(void);
__attribute__((weak)) void __bound_checking_unlock(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->num_callers = num_callers - 1;
rc->top_func = main; rc->top_func = main;
__rt_error = _rt_error; __rt_error = _rt_error;
__rt_location = _rt_location;
set_exception_handler(); set_exception_handler();
} else { } else {
p->next = rc->next, rc->next = p; p->next = rc->next, rc->next = p;

View file

@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
int (*__rt_error)(void*, void*, const char *, va_list); int (*__rt_error)(void*, void*, const char *, va_list);
void (*__rt_location)(void*, void*, const char *);
#ifdef _WIN32 #ifdef _WIN32
# define DLL_EXPORT __declspec(dllexport) # define DLL_EXPORT __declspec(dllexport)
@ -42,6 +43,15 @@ DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
return ret; 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__) #if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

View file

@ -6010,6 +6010,7 @@ special_math_val:
indir(); indir();
qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE);
test_lvalue(); test_lvalue();
gaddrof();
/* expect pointer on structure */ /* expect pointer on structure */
if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
expect("struct or union"); expect("struct or union");
@ -6020,15 +6021,16 @@ special_math_val:
expect("field name"); expect("field name");
s = find_field(&vtop->type, tok, &cumofs); s = find_field(&vtop->type, tok, &cumofs);
/* add field offset to pointer */ /* 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 */ /* change type to field type, and set to lvalue */
vtop->type = s->type; vtop->type = s->type;
vtop->type.t |= qualifiers; vtop->type.t |= qualifiers;
/* an array is never an lvalue */ /* an array is never an lvalue */
if (vtop->type.t & VT_ARRAY) { if (!(vtop->type.t & VT_ARRAY)) {
vtop->r &= ~VT_LVAL; vtop->r |= VT_LVAL;
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
} else {
/* if bound checking, the referenced pointer must be checked */ /* if bound checking, the referenced pointer must be checked */
if (tcc_state->do_bounds_check) if (tcc_state->do_bounds_check)
vtop->r |= VT_MUSTBOUND; vtop->r |= VT_MUSTBOUND;

View file

@ -53,6 +53,7 @@ typedef struct rt_context
static rt_context g_rtctxt; static rt_context g_rtctxt;
static void set_exception_handler(void); static void set_exception_handler(void);
static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); 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); static void rt_exit(int code);
#endif /* CONFIG_TCC_BACKTRACE */ #endif /* CONFIG_TCC_BACKTRACE */
@ -274,6 +275,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
rc->do_jmp = 1; rc->do_jmp = 1;
if ((p = tcc_get_symbol(s1, "__rt_error"))) if ((p = tcc_get_symbol(s1, "__rt_error")))
*(void**)p = _rt_error; *(void**)p = _rt_error;
if ((p = tcc_get_symbol(s1, "__rt_location")))
*(void**)p = _rt_location;
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check) { if (s1->do_bounds_check) {
rc->bounds_start = (void*)bounds_section->sh_addr; 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; 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' */ /* emit a run time error at position 'pc' */
static int rt_error(const char *fmt, ...) static int rt_error(const char *fmt, ...)
{ {

View file

@ -0,0 +1,29 @@
#include <stdio.h>
#include <float.h>
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;
}

View file

@ -0,0 +1 @@
42000