diff --git a/i386-gen.c b/i386-gen.c index 51a514ae..7e1e0f49 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -95,6 +95,7 @@ ST_DATA const int reg_classes[NB_REGS] = { static unsigned long func_sub_sp_offset; static int func_ret_sub; #ifdef CONFIG_TCC_BCHECK +static addr_t func_bound_offset; static unsigned long func_bound_ind; #endif @@ -401,10 +402,8 @@ ST_FUNC void gfunc_call(int nb_args) Sym *func_sym; #ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) { - save_temp_local (nb_args); + if (tcc_state->do_bounds_check) gbound_args(nb_args); - } #endif args_size = 0; @@ -486,10 +485,6 @@ ST_FUNC void gfunc_call(int nb_args) if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW) gadd_sp(args_size); vtop--; -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - restore_temp_local (); -#endif } #ifdef TCC_TARGET_PE diff --git a/tcc.h b/tcc.h index eb46bbda..9013e87d 100644 --- a/tcc.h +++ b/tcc.h @@ -474,9 +474,8 @@ struct SymAttr { dllexport : 1, nodecorate : 1, dllimport : 1, - constructor : 1, - destructor : 1, - unused : 2; + addrtaken : 1, + unused : 3; }; /* function attributes or temporary attributes for parsing */ @@ -620,6 +619,8 @@ typedef struct TokenString { typedef struct AttributeDef { struct SymAttr a; struct FuncAttr f; + unsigned short constructor:1; + unsigned short destructor:1; struct Section *section; Sym *cleanup_func; int alias_target; /* token */ @@ -1378,9 +1379,6 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi ST_DATA int func_var; /* true if current function is variadic */ ST_DATA int func_vc; ST_DATA const char *funcname; -#ifdef CONFIG_TCC_BCHECK -ST_DATA addr_t func_bound_offset; -#endif ST_FUNC void tcc_debug_start(TCCState *s1); ST_FUNC void tcc_debug_end(TCCState *s1); @@ -1446,8 +1444,6 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty); #endif #ifdef CONFIG_TCC_BCHECK ST_FUNC void gbound_args(int nb_args); -ST_FUNC void save_temp_local(int nb_args); -ST_FUNC void restore_temp_local(void); #endif /* ------------ tccelf.c ------------ */ diff --git a/tccgen.c b/tccgen.c index 946a9e21..21aaac63 100644 --- a/tccgen.c +++ b/tccgen.c @@ -111,16 +111,6 @@ ST_DATA struct temp_local_variable { short align; } arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER]; short nb_temp_local_vars; -#ifdef CONFIG_TCC_BCHECK -static short call_nesting; -static char used_location[MAX_TEMP_LOCAL_VARIABLE_NUMBER]; -static int nb_bound_local_param; -struct { - unsigned long data_offset; - int v; -} *bound_local_param; -ST_DATA addr_t func_bound_offset; -#endif static struct scope { struct scope *prev; @@ -1502,11 +1492,7 @@ static int get_temp_local_var(int size,int align){ found=0; for(i=0;isizealign -#ifdef CONFIG_TCC_BCHECK - || (tcc_state->do_bounds_check && used_location[i]) -#endif - ){ + if(temp_var->sizealign){ continue; } /*check if temp_var is free*/ @@ -1607,51 +1593,37 @@ ST_FUNC void gbound_args(int nb_args) } } -ST_FUNC void save_temp_local(int nb_args) +/* Add bounds for local symbols from S to E (via ->prev) */ +static void add_local_bounds(Sym *s, Sym *e) { - int i, j; - - if (call_nesting++ == 0) - for (i = 1; i <= nb_args; ++i) - for (j = 0; j < nb_temp_local_vars; j++) - if (vtop[1 - i].c.i == arr_temp_local_vars[j].location) { - used_location[j] = 1; - break; - } -} - -ST_FUNC void restore_temp_local() -{ - if (--call_nesting == 0) - memset (used_location, 0, sizeof (used_location)); -} - -static void add_bound_param(CType *type, int size, int v, int c) -{ - addr_t *bounds_ptr; - /* Add arrays/structs/unions because we always take address */ - int taken = (type->t & VT_ARRAY) - || (type->t & VT_BTYPE) == VT_STRUCT; - - if (taken == 0) { - /* Add parameter to check */ - nb_bound_local_param++; - bound_local_param = - tcc_realloc (bound_local_param, - nb_bound_local_param * - sizeof (*bound_local_param)); - bound_local_param[nb_bound_local_param-1].data_offset = - lbounds_section->data_offset; - bound_local_param[nb_bound_local_param-1].v = v; + for (; s != e; s = s->prev) { + if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL) + continue; + /* Add arrays/structs/unions because we always take address */ + if ((s->type.t & VT_ARRAY) + || (s->type.t & VT_BTYPE) == VT_STRUCT + || s->a.addrtaken) { + /* add local bound info */ + int align, size = type_size(&s->type, &align); + addr_t *bounds_ptr = section_ptr_add(lbounds_section, + 2 * sizeof(addr_t)); + bounds_ptr[0] = s->c; + bounds_ptr[1] = size; + } } - /* add local bound info */ - bounds_ptr = section_ptr_add(lbounds_section, - 2 * sizeof(addr_t)); - bounds_ptr[0] = c; - bounds_ptr[1] = taken ? size : ~size; } #endif +/* Wrapper around sym_pop, that potentially also registers local bounds. */ +static void pop_local_syms(Sym **ptop, Sym *b, int keep) +{ +#ifdef CONFIG_TCC_BCHECK + if (!keep && tcc_state->do_bounds_check) + add_local_bounds(*ptop, b); +#endif + sym_pop(ptop, b, keep); +} + static void incr_bf_adr(int o) { vtop->type = char_pointer_type; @@ -3690,11 +3662,11 @@ redo: } case TOK_CONSTRUCTOR1: case TOK_CONSTRUCTOR2: - ad->a.constructor = 1; + ad->constructor = 1; break; case TOK_DESTRUCTOR1: case TOK_DESTRUCTOR2: - ad->a.destructor = 1; + ad->destructor = 1; break; case TOK_SECTION1: case TOK_SECTION2: @@ -5138,23 +5110,8 @@ ST_FUNC void unary(void) if ((vtop->type.t & VT_BTYPE) != VT_FUNC && !(vtop->type.t & VT_ARRAY)) test_lvalue(); -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check && vtop->sym) { - int i; - - /* Mark parameter as being used for address off */ - for (i = 0; i < nb_bound_local_param; i++) { - if (bound_local_param[i].v == vtop->sym->v) { - addr_t *bounds_ptr = - (addr_t *) (lbounds_section->data + - bound_local_param[i].data_offset); - bounds_ptr[1] = ~bounds_ptr[1]; - bound_local_param[i].v = 0; - break; - } - } - } -#endif + if (vtop->sym) + vtop->sym->a.addrtaken = 1; mk_pointer(&vtop->type); gaddrof(); break; @@ -6454,7 +6411,7 @@ void prev_scope(struct scope *o, int is_expr) tables, though. sym_pop will do that. */ /* pop locally defined symbols */ - sym_pop(&local_stack, o->lstk, is_expr); + pop_local_syms(&local_stack, o->lstk, is_expr); cur_scope = o->prev; --local_scope; @@ -7426,17 +7383,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, Sym *sym = NULL; int saved_nocode_wanted = nocode_wanted; #ifdef CONFIG_TCC_BCHECK - int bcheck; + int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; #endif /* Always allocate static or global variables */ if (v && (r & VT_VALMASK) == VT_CONST) nocode_wanted |= 0x80000000; -#ifdef CONFIG_TCC_BCHECK - bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; -#endif - flexible_array = NULL; if ((type->t & VT_BTYPE) == VT_STRUCT) { Sym *field = type->ref->next; @@ -7508,17 +7461,15 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, sec = NULL; #ifdef CONFIG_TCC_BCHECK if (bcheck && v) { - /* add padding between stack variables */ + /* add padding between stack variables for bound checking */ loc--; } #endif loc = (loc - size) & -align; addr = loc; #ifdef CONFIG_TCC_BCHECK - /* handles bounds */ if (bcheck && v) { - add_bound_param (type, size, v, addr); - /* add padding between stack variables */ + /* add padding between stack variables for bound checking */ loc--; } #endif @@ -7682,10 +7633,10 @@ static void gen_function(Sym *sym, AttributeDef *ad) /* NOTE: we patch the symbol size later */ put_extern_sym(sym, cur_text_section, ind, 0); - if (ad && ad->a.constructor) { + if (ad && ad->constructor) { add_init_array (tcc_state, sym); } - if (ad && ad->a.destructor) { + if (ad && ad->destructor) { add_fini_array (tcc_state, sym); } @@ -7698,56 +7649,16 @@ static void gen_function(Sym *sym, AttributeDef *ad) sym_push2(&local_stack, SYM_FIELD, 0, 0); local_scope = 1; /* for function parameters */ gfunc_prolog(sym); -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check - && sym->type.ref->f.func_type != FUNC_ELLIPSIS) { - Sym *fpar; - - /* Add function arguments in case & is used */ - for (fpar = sym->type.ref->next; fpar; fpar = fpar->next) { - Sym *fsym = sym_find (fpar->v & ~SYM_FIELD); - - if (fsym && (fsym->r & VT_VALMASK) == VT_LOCAL) { - int align; - int size = type_size(&fsym->type, &align); - - if (size > 0) - add_bound_param (&fsym->type, size, fsym->v, fsym->c); - } - } - } -#endif local_scope = 0; rsym = 0; clear_temp_local_var_list(); block(0); gsym(rsym); nocode_wanted = 0; -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) { - addr_t o = func_bound_offset; - - /* Remove parameters where address off is not used */ - while (o != lbounds_section->data_offset) { - addr_t *bounds_ptr = (addr_t *) (lbounds_section->data + o); - if ((ssize_t) bounds_ptr[1] < 0) { - lbounds_section->data_offset -= 2 * sizeof (addr_t); - memmove(bounds_ptr, bounds_ptr + 2, - lbounds_section->data_offset - o); - } - else { - o += 2 * sizeof (addr_t); - } - } - tcc_free (bound_local_param); - nb_bound_local_param = 0; - bound_local_param = NULL; - } -#endif gfunc_epilog(); cur_text_section->data_offset = ind; /* reset local stack */ - sym_pop(&local_stack, NULL, 0); + pop_local_syms(&local_stack, NULL, 0); local_scope = 0; label_pop(&global_label_stack, NULL, 0); sym_pop(&all_cleanups, NULL, 0); diff --git a/x86_64-gen.c b/x86_64-gen.c index b4a546c2..439fd988 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -637,6 +637,7 @@ static void gcall_or_jmp(int is_jmp) } #if defined(CONFIG_TCC_BCHECK) +static addr_t func_bound_offset; static unsigned long func_bound_ind; static void gen_bounds_call(int v) @@ -783,10 +784,8 @@ void gfunc_call(int nb_args) int arg; #ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) { - save_temp_local (nb_args); + if (tcc_state->do_bounds_check) gbound_args(nb_args); - } #endif args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE; @@ -907,10 +906,6 @@ void gfunc_call(int nb_args) } vtop--; -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - restore_temp_local (); -#endif } @@ -1276,10 +1271,8 @@ void gfunc_call(int nb_args) char _onstack[nb_args ? nb_args : 1], *onstack = _onstack; #ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) { - save_temp_local (nb_args); + if (tcc_state->do_bounds_check) gbound_args(nb_args); - } #endif /* calculate the number of integer/float register arguments, remember @@ -1460,10 +1453,6 @@ void gfunc_call(int nb_args) if (args_size) gadd_sp(args_size); vtop--; -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - restore_temp_local (); -#endif } #define FUNC_PROLOG_SIZE 11