History

Cleanup new bound checking code

remove quadratic loops by not using side tables; address-taken can simply be a flag per local sym, and the lbounds section can be filled after symbols go out of scope at which point we know if the address was taken, so that there's no need to compress it again after the funcion is done.

Michael Matz committed 6 years ago

Commit 65f2fe31 parent 4a70b2b4 files · +47 −156Browse files

Unified · Split

4 files
  1. i386-gen.c +2 −7
  2. tcc.h +4 −8
  3. tccgen.c +38 −127
  4. x86_64-gen.c +3 −14
i386-gen.c+2−7
@@ -95,6 +95,7 @@ ST_DATA const int reg_classes[NB_REGS] = { · 94 unmodified lines
9595 static unsigned long func_sub_sp_offset;
9696 static int func_ret_sub;
9797 #ifdef CONFIG_TCC_BCHECK
98+static addr_t func_bound_offset;
9899 static unsigned long func_bound_ind;
99100 #endif
100101
@@ -401,10 +402,8 @@ ST_FUNC void gfunc_call(int nb_args) · 300 unmodified lines
401402 Sym *func_sym;
402403
403404 #ifdef CONFIG_TCC_BCHECK
404− if (tcc_state->do_bounds_check) {
405− save_temp_local (nb_args);
405+ if (tcc_state->do_bounds_check)
406406 gbound_args(nb_args);
407− }
408407 #endif
409408
410409 args_size = 0;
@@ -486,10 +485,6 @@ ST_FUNC void gfunc_call(int nb_args) · 75 unmodified lines
486485 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
487486 gadd_sp(args_size);
488487 vtop--;
489−#ifdef CONFIG_TCC_BCHECK
490− if (tcc_state->do_bounds_check)
491− restore_temp_local ();
492−#endif
493488 }
494489
495490 #ifdef TCC_TARGET_PE
tcc.h+4−8
@@ -474,9 +474,8 @@ struct SymAttr { · 473 unmodified lines
474474 dllexport : 1,
475475 nodecorate : 1,
476476 dllimport : 1,
477− constructor : 1,
478− destructor : 1,
479− unused : 2;
477+ addrtaken : 1,
478+ unused : 3;
480479 };
481480
482481 /* function attributes or temporary attributes for parsing */
@@ -620,6 +619,8 @@ typedef struct TokenString { · 137 unmodified lines
620619 typedef struct AttributeDef {
621620 struct SymAttr a;
622621 struct FuncAttr f;
622+ unsigned short constructor:1;
623+ unsigned short destructor:1;
623624 struct Section *section;
624625 Sym *cleanup_func;
625626 int alias_target; /* token */
@@ -1378,9 +1379,6 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi · 752 unmodified lines
13781379 ST_DATA int func_var; /* true if current function is variadic */
13791380 ST_DATA int func_vc;
13801381 ST_DATA const char *funcname;
1381−#ifdef CONFIG_TCC_BCHECK
1382−ST_DATA addr_t func_bound_offset;
1383−#endif
13841382
13851383 ST_FUNC void tcc_debug_start(TCCState *s1);
13861384 ST_FUNC void tcc_debug_end(TCCState *s1);
@@ -1446,8 +1444,6 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty); · 59 unmodified lines
14461444 #endif
14471445 #ifdef CONFIG_TCC_BCHECK
14481446 ST_FUNC void gbound_args(int nb_args);
1449−ST_FUNC void save_temp_local(int nb_args);
1450−ST_FUNC void restore_temp_local(void);
14511447 #endif
14521448
14531449 /* ------------ tccelf.c ------------ */
tccgen.c+38−127
@@ -111,16 +111,6 @@ ST_DATA struct temp_local_variable { · 110 unmodified lines
111111 short align;
112112 } arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
113113 short nb_temp_local_vars;
114−#ifdef CONFIG_TCC_BCHECK
115−static short call_nesting;
116−static char used_location[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
117−static int nb_bound_local_param;
118−struct {
119− unsigned long data_offset;
120− int v;
121−} *bound_local_param;
122−ST_DATA addr_t func_bound_offset;
123−#endif
124114
125115 static struct scope {
126116 struct scope *prev;
@@ -1502,11 +1492,7 @@ static int get_temp_local_var(int size,int align){ · 1375 unmodified lines
15021492 found=0;
15031493 for(i=0;i<nb_temp_local_vars;i++){
15041494 temp_var=&arr_temp_local_vars[i];
1505− if(temp_var->size<size||align!=temp_var->align
1506−#ifdef CONFIG_TCC_BCHECK
1507− || (tcc_state->do_bounds_check && used_location[i])
1508−#endif
1509− ){
1495+ if(temp_var->size<size||align!=temp_var->align){
15101496 continue;
15111497 }
15121498 /*check if temp_var is free*/
@@ -1607,50 +1593,36 @@ ST_FUNC void gbound_args(int nb_args) · 94 unmodified lines
16071593 }
16081594 }
16091595
1610−ST_FUNC void save_temp_local(int nb_args)
1611−{
1612− int i, j;
1613−
1614− if (call_nesting++ == 0)
1615− for (i = 1; i <= nb_args; ++i)
1616− for (j = 0; j < nb_temp_local_vars; j++)
1617− if (vtop[1 - i].c.i == arr_temp_local_vars[j].location) {
1618− used_location[j] = 1;
1619− break;
1620− }
1621−}
1622−
1623−ST_FUNC void restore_temp_local()
1624−{
1625− if (--call_nesting == 0)
1626− memset (used_location, 0, sizeof (used_location));
1596+/* Add bounds for local symbols from S to E (via ->prev) */
1597+static void add_local_bounds(Sym *s, Sym *e)
1598+{
1599+ for (; s != e; s = s->prev) {
1600+ if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
1601+ continue;
1602+ /* Add arrays/structs/unions because we always take address */
1603+ if ((s->type.t & VT_ARRAY)
1604+ || (s->type.t & VT_BTYPE) == VT_STRUCT
1605+ || s->a.addrtaken) {
1606+ /* add local bound info */
1607+ int align, size = type_size(&s->type, &align);
1608+ addr_t *bounds_ptr = section_ptr_add(lbounds_section,
1609+ 2 * sizeof(addr_t));
1610+ bounds_ptr[0] = s->c;
1611+ bounds_ptr[1] = size;
1612+ }
1613+ }
16271614 }
1615+#endif
16281616
1629−static void add_bound_param(CType *type, int size, int v, int c)
1617+/* Wrapper around sym_pop, that potentially also registers local bounds. */
1618+static void pop_local_syms(Sym **ptop, Sym *b, int keep)
16301619 {
1631− addr_t *bounds_ptr;
1632− /* Add arrays/structs/unions because we always take address */
1633− int taken = (type->t & VT_ARRAY)
1634− || (type->t & VT_BTYPE) == VT_STRUCT;
1635−
1636− if (taken == 0) {
1637− /* Add parameter to check */
1638− nb_bound_local_param++;
1639− bound_local_param =
1640− tcc_realloc (bound_local_param,
1641− nb_bound_local_param *
1642− sizeof (*bound_local_param));
1643− bound_local_param[nb_bound_local_param-1].data_offset =
1644− lbounds_section->data_offset;
1645− bound_local_param[nb_bound_local_param-1].v = v;
1646− }
1647− /* add local bound info */
1648− bounds_ptr = section_ptr_add(lbounds_section,
1649− 2 * sizeof(addr_t));
1650− bounds_ptr[0] = c;
1651− bounds_ptr[1] = taken ? size : ~size;
1652−}
1620+#ifdef CONFIG_TCC_BCHECK
1621+ if (!keep && tcc_state->do_bounds_check)
1622+ add_local_bounds(*ptop, b);
16531623 #endif
1624+ sym_pop(ptop, b, keep);
1625+}
16541626
16551627 static void incr_bf_adr(int o)
16561628 {
@@ -3690,11 +3662,11 @@ redo: · 2033 unmodified lines
36903662 }
36913663 case TOK_CONSTRUCTOR1:
36923664 case TOK_CONSTRUCTOR2:
3693− ad->a.constructor = 1;
3665+ ad->constructor = 1;
36943666 break;
36953667 case TOK_DESTRUCTOR1:
36963668 case TOK_DESTRUCTOR2:
3697− ad->a.destructor = 1;
3669+ ad->destructor = 1;
36983670 break;
36993671 case TOK_SECTION1:
37003672 case TOK_SECTION2:
@@ -5138,23 +5110,8 @@ ST_FUNC void unary(void) · 1437 unmodified lines
51385110 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
51395111 !(vtop->type.t & VT_ARRAY))
51405112 test_lvalue();
5141−#ifdef CONFIG_TCC_BCHECK
5142− if (tcc_state->do_bounds_check && vtop->sym) {
5143− int i;
5144−
5145− /* Mark parameter as being used for address off */
5146− for (i = 0; i < nb_bound_local_param; i++) {
5147− if (bound_local_param[i].v == vtop->sym->v) {
5148− addr_t *bounds_ptr =
5149− (addr_t *) (lbounds_section->data +
5150− bound_local_param[i].data_offset);
5151− bounds_ptr[1] = ~bounds_ptr[1];
5152− bound_local_param[i].v = 0;
5153− break;
5154− }
5155− }
5156− }
5157−#endif
5113+ if (vtop->sym)
5114+ vtop->sym->a.addrtaken = 1;
51585115 mk_pointer(&vtop->type);
51595116 gaddrof();
51605117 break;
@@ -6454,7 +6411,7 @@ void prev_scope(struct scope *o, int is_expr) · 1293 unmodified lines
64546411 tables, though. sym_pop will do that. */
64556412
64566413 /* pop locally defined symbols */
6457− sym_pop(&local_stack, o->lstk, is_expr);
6414+ pop_local_syms(&local_stack, o->lstk, is_expr);
64586415
64596416 cur_scope = o->prev;
64606417 --local_scope;
@@ -7426,17 +7383,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 965 unmodified lines
74267383 Sym *sym = NULL;
74277384 int saved_nocode_wanted = nocode_wanted;
74287385 #ifdef CONFIG_TCC_BCHECK
7429− int bcheck;
7386+ int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
74307387 #endif
74317388
74327389 /* Always allocate static or global variables */
74337390 if (v && (r & VT_VALMASK) == VT_CONST)
74347391 nocode_wanted |= 0x80000000;
74357392
7436−#ifdef CONFIG_TCC_BCHECK
7437− bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
7438−#endif
7439−
74407393 flexible_array = NULL;
74417394 if ((type->t & VT_BTYPE) == VT_STRUCT) {
74427395 Sym *field = type->ref->next;
@@ -7508,17 +7461,15 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 65 unmodified lines
75087461 sec = NULL;
75097462 #ifdef CONFIG_TCC_BCHECK
75107463 if (bcheck && v) {
7511− /* add padding between stack variables */
7464+ /* add padding between stack variables for bound checking */
75127465 loc--;
75137466 }
75147467 #endif
75157468 loc = (loc - size) & -align;
75167469 addr = loc;
75177470 #ifdef CONFIG_TCC_BCHECK
7518− /* handles bounds */
75197471 if (bcheck && v) {
7520− add_bound_param (type, size, v, addr);
7521− /* add padding between stack variables */
7472+ /* add padding between stack variables for bound checking */
75227473 loc--;
75237474 }
75247475 #endif
@@ -7682,10 +7633,10 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 157 unmodified lines
76827633 /* NOTE: we patch the symbol size later */
76837634 put_extern_sym(sym, cur_text_section, ind, 0);
76847635
7685− if (ad && ad->a.constructor) {
7636+ if (ad && ad->constructor) {
76867637 add_init_array (tcc_state, sym);
76877638 }
7688− if (ad && ad->a.destructor) {
7639+ if (ad && ad->destructor) {
76897640 add_fini_array (tcc_state, sym);
76907641 }
76917642
@@ -7698,56 +7649,16 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 6 unmodified lines
76987649 sym_push2(&local_stack, SYM_FIELD, 0, 0);
76997650 local_scope = 1; /* for function parameters */
77007651 gfunc_prolog(sym);
7701−#ifdef CONFIG_TCC_BCHECK
7702− if (tcc_state->do_bounds_check
7703− && sym->type.ref->f.func_type != FUNC_ELLIPSIS) {
7704− Sym *fpar;
7705−
7706− /* Add function arguments in case & is used */
7707− for (fpar = sym->type.ref->next; fpar; fpar = fpar->next) {
7708− Sym *fsym = sym_find (fpar->v & ~SYM_FIELD);
7709−
7710− if (fsym && (fsym->r & VT_VALMASK) == VT_LOCAL) {
7711− int align;
7712− int size = type_size(&fsym->type, &align);
7713−
7714− if (size > 0)
7715− add_bound_param (&fsym->type, size, fsym->v, fsym->c);
7716− }
7717− }
7718− }
7719−#endif
77207652 local_scope = 0;
77217653 rsym = 0;
77227654 clear_temp_local_var_list();
77237655 block(0);
77247656 gsym(rsym);
77257657 nocode_wanted = 0;
7726−#ifdef CONFIG_TCC_BCHECK
7727− if (tcc_state->do_bounds_check) {
7728− addr_t o = func_bound_offset;
7729−
7730− /* Remove parameters where address off is not used */
7731− while (o != lbounds_section->data_offset) {
7732− addr_t *bounds_ptr = (addr_t *) (lbounds_section->data + o);
7733− if ((ssize_t) bounds_ptr[1] < 0) {
7734− lbounds_section->data_offset -= 2 * sizeof (addr_t);
7735− memmove(bounds_ptr, bounds_ptr + 2,
7736− lbounds_section->data_offset - o);
7737− }
7738− else {
7739− o += 2 * sizeof (addr_t);
7740− }
7741− }
7742− tcc_free (bound_local_param);
7743− nb_bound_local_param = 0;
7744− bound_local_param = NULL;
7745− }
7746−#endif
77477658 gfunc_epilog();
77487659 cur_text_section->data_offset = ind;
77497660 /* reset local stack */
7750− sym_pop(&local_stack, NULL, 0);
7661+ pop_local_syms(&local_stack, NULL, 0);
77517662 local_scope = 0;
77527663 label_pop(&global_label_stack, NULL, 0);
77537664 sym_pop(&all_cleanups, NULL, 0);
x86_64-gen.c+3−14
@@ -637,6 +637,7 @@ static void gcall_or_jmp(int is_jmp) · 636 unmodified lines
637637 }
638638
639639 #if defined(CONFIG_TCC_BCHECK)
640+static addr_t func_bound_offset;
640641 static unsigned long func_bound_ind;
641642
642643 static void gen_bounds_call(int v)
@@ -783,10 +784,8 @@ void gfunc_call(int nb_args) · 140 unmodified lines
783784 int arg;
784785
785786 #ifdef CONFIG_TCC_BCHECK
786− if (tcc_state->do_bounds_check) {
787− save_temp_local (nb_args);
787+ if (tcc_state->do_bounds_check)
788788 gbound_args(nb_args);
789− }
790789 #endif
791790
792791 args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
@@ -907,10 +906,6 @@ void gfunc_call(int nb_args) · 114 unmodified lines
907906
908907 }
909908 vtop--;
910−#ifdef CONFIG_TCC_BCHECK
911− if (tcc_state->do_bounds_check)
912− restore_temp_local ();
913−#endif
914909 }
915910
916911
@@ -1276,10 +1271,8 @@ void gfunc_call(int nb_args) · 359 unmodified lines
12761271 char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
12771272
12781273 #ifdef CONFIG_TCC_BCHECK
1279− if (tcc_state->do_bounds_check) {
1280− save_temp_local (nb_args);
1274+ if (tcc_state->do_bounds_check)
12811275 gbound_args(nb_args);
1282− }
12831276 #endif
12841277
12851278 /* calculate the number of integer/float register arguments, remember
@@ -1460,10 +1453,6 @@ void gfunc_call(int nb_args) · 174 unmodified lines
14601453 if (args_size)
14611454 gadd_sp(args_size);
14621455 vtop--;
1463−#ifdef CONFIG_TCC_BCHECK
1464− if (tcc_state->do_bounds_check)
1465− restore_temp_local ();
1466−#endif
14671456 }
14681457
14691458 #define FUNC_PROLOG_SIZE 11

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t