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:
parent
d1c107738b
commit
598134fff6
8 changed files with 96 additions and 5 deletions
10
lib/bcheck.c
10
lib/bcheck.c
|
@ -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);
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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;
|
||||||
|
|
10
lib/bt-log.c
10
lib/bt-log.c
|
@ -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
|
||||||
|
|
10
tccgen.c
10
tccgen.c
|
@ -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;
|
||||||
|
|
38
tccrun.c
38
tccrun.c
|
@ -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, ...)
|
||||||
{
|
{
|
||||||
|
|
29
tests/tests2/132_bound_test.c
Normal file
29
tests/tests2/132_bound_test.c
Normal 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;
|
||||||
|
}
|
1
tests/tests2/132_bound_test.expect
Normal file
1
tests/tests2/132_bound_test.expect
Normal file
|
@ -0,0 +1 @@
|
||||||
|
42000
|
Loading…
Reference in a new issue