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
95static unsigned long func_sub_sp_offset;95static unsigned long func_sub_sp_offset;
96static int func_ret_sub;96static int func_ret_sub;
97#ifdef CONFIG_TCC_BCHECK97#ifdef CONFIG_TCC_BCHECK
98static addr_t func_bound_offset;
98static unsigned long func_bound_ind;99static unsigned long func_bound_ind;
99#endif100#endif
100 101
@@ -401,10 +402,8 @@ ST_FUNC void gfunc_call(int nb_args) · 300 unmodified lines
401 Sym *func_sym;402 Sym *func_sym;
402 403
403#ifdef CONFIG_TCC_BCHECK404#ifdef CONFIG_TCC_BCHECK
404 if (tcc_state->do_bounds_check) {405 if (tcc_state->do_bounds_check)
405 save_temp_local (nb_args);
406 gbound_args(nb_args);406 gbound_args(nb_args);
407 }
408#endif407#endif
409 408
410 args_size = 0;409 args_size = 0;
@@ -486,10 +485,6 @@ ST_FUNC void gfunc_call(int nb_args) · 75 unmodified lines
486 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)485 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
487 gadd_sp(args_size);486 gadd_sp(args_size);
488 vtop--;487 vtop--;
489#ifdef CONFIG_TCC_BCHECK
490 if (tcc_state->do_bounds_check)
491 restore_temp_local ();
492#endif
493}488}
494 489
495#ifdef TCC_TARGET_PE490#ifdef TCC_TARGET_PE
tcc.h+4−8
@@ -474,9 +474,8 @@ struct SymAttr { · 473 unmodified lines
474 dllexport : 1,474 dllexport : 1,
475 nodecorate : 1,475 nodecorate : 1,
476 dllimport : 1,476 dllimport : 1,
477 constructor : 1,477 addrtaken : 1,
478 destructor : 1,478 unused : 3;
479 unused : 2;
480};479};
481 480
482/* function attributes or temporary attributes for parsing */481/* function attributes or temporary attributes for parsing */
@@ -620,6 +619,8 @@ typedef struct TokenString { · 137 unmodified lines
620typedef struct AttributeDef {619typedef struct AttributeDef {
621 struct SymAttr a;620 struct SymAttr a;
622 struct FuncAttr f;621 struct FuncAttr f;
622 unsigned short constructor:1;
623 unsigned short destructor:1;
623 struct Section *section;624 struct Section *section;
624 Sym *cleanup_func;625 Sym *cleanup_func;
625 int alias_target; /* token */626 int alias_target; /* token */
@@ -1378,9 +1379,6 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi · 752 unmodified lines
1378ST_DATA int func_var; /* true if current function is variadic */1379ST_DATA int func_var; /* true if current function is variadic */
1379ST_DATA int func_vc;1380ST_DATA int func_vc;
1380ST_DATA const char *funcname;1381ST_DATA const char *funcname;
1381#ifdef CONFIG_TCC_BCHECK
1382ST_DATA addr_t func_bound_offset;
1383#endif
1384 1382
1385ST_FUNC void tcc_debug_start(TCCState *s1);1383ST_FUNC void tcc_debug_start(TCCState *s1);
1386ST_FUNC void tcc_debug_end(TCCState *s1);1384ST_FUNC void tcc_debug_end(TCCState *s1);
@@ -1446,8 +1444,6 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty); · 59 unmodified lines
1446#endif1444#endif
1447#ifdef CONFIG_TCC_BCHECK1445#ifdef CONFIG_TCC_BCHECK
1448ST_FUNC void gbound_args(int nb_args);1446ST_FUNC void gbound_args(int nb_args);
1449ST_FUNC void save_temp_local(int nb_args);
1450ST_FUNC void restore_temp_local(void);
1451#endif1447#endif
1452 1448
1453/* ------------ tccelf.c ------------ */1449/* ------------ tccelf.c ------------ */
tccgen.c+38−127
@@ -111,16 +111,6 @@ ST_DATA struct temp_local_variable { · 110 unmodified lines
111 short align;111 short align;
112} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];112} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
113short nb_temp_local_vars;113short nb_temp_local_vars;
114#ifdef CONFIG_TCC_BCHECK
115static short call_nesting;
116static char used_location[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
117static int nb_bound_local_param;
118struct {
119 unsigned long data_offset;
120 int v;
121} *bound_local_param;
122ST_DATA addr_t func_bound_offset;
123#endif
124 114
125static struct scope {115static struct scope {
126 struct scope *prev;116 struct scope *prev;
@@ -1502,11 +1492,7 @@ static int get_temp_local_var(int size,int align){ · 1375 unmodified lines
1502 found=0;1492 found=0;
1503 for(i=0;i<nb_temp_local_vars;i++){1493 for(i=0;i<nb_temp_local_vars;i++){
1504 temp_var=&arr_temp_local_vars[i];1494 temp_var=&arr_temp_local_vars[i];
1505 if(temp_var->size<size||align!=temp_var->align1495 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 ){
1510 continue;1496 continue;
1511 }1497 }
1512 /*check if temp_var is free*/1498 /*check if temp_var is free*/
@@ -1607,50 +1593,36 @@ ST_FUNC void gbound_args(int nb_args) · 94 unmodified lines
1607 }1593 }
1608}1594}
1609 1595
1610ST_FUNC void save_temp_local(int nb_args)1596/* Add bounds for local symbols from S to E (via ->prev) */
1611{1597static void add_local_bounds(Sym *s, Sym *e)
1612 int i, j;1598{
1613 1599 for (; s != e; s = s->prev) {
1614 if (call_nesting++ == 0)1600 if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
1615 for (i = 1; i <= nb_args; ++i)1601 continue;
1616 for (j = 0; j < nb_temp_local_vars; j++)1602 /* Add arrays/structs/unions because we always take address */
1617 if (vtop[1 - i].c.i == arr_temp_local_vars[j].location) {1603 if ((s->type.t & VT_ARRAY)
1618 used_location[j] = 1;1604 || (s->type.t & VT_BTYPE) == VT_STRUCT
1619 break;1605 || s->a.addrtaken) {
1620 }1606 /* add local bound info */
1621}1607 int align, size = type_size(&s->type, &align);
1622 1608 addr_t *bounds_ptr = section_ptr_add(lbounds_section,
1623ST_FUNC void restore_temp_local()1609 2 * sizeof(addr_t));
1624{1610 bounds_ptr[0] = s->c;
1625 if (--call_nesting == 0)1611 bounds_ptr[1] = size;
1626 memset (used_location, 0, sizeof (used_location));1612 }
1613 }
1627}1614}
1615#endif
1628 1616
1629static void add_bound_param(CType *type, int size, int v, int c)1617/* Wrapper around sym_pop, that potentially also registers local bounds. */
1618static void pop_local_syms(Sym **ptop, Sym *b, int keep)
1630{1619{
1631 addr_t *bounds_ptr;1620#ifdef CONFIG_TCC_BCHECK
1632 /* Add arrays/structs/unions because we always take address */1621 if (!keep && tcc_state->do_bounds_check)
1633 int taken = (type->t & VT_ARRAY)1622 add_local_bounds(*ptop, b);
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}
1653#endif1623#endif
1624 sym_pop(ptop, b, keep);
1625}
1654 1626
1655static void incr_bf_adr(int o)1627static void incr_bf_adr(int o)
1656{1628{
@@ -3690,11 +3662,11 @@ redo: · 2033 unmodified lines
3690 }3662 }
3691 case TOK_CONSTRUCTOR1:3663 case TOK_CONSTRUCTOR1:
3692 case TOK_CONSTRUCTOR2:3664 case TOK_CONSTRUCTOR2:
3693 ad->a.constructor = 1;3665 ad->constructor = 1;
3694 break;3666 break;
3695 case TOK_DESTRUCTOR1:3667 case TOK_DESTRUCTOR1:
3696 case TOK_DESTRUCTOR2:3668 case TOK_DESTRUCTOR2:
3697 ad->a.destructor = 1;3669 ad->destructor = 1;
3698 break;3670 break;
3699 case TOK_SECTION1:3671 case TOK_SECTION1:
3700 case TOK_SECTION2:3672 case TOK_SECTION2:
@@ -5138,23 +5110,8 @@ ST_FUNC void unary(void) · 1437 unmodified lines
5138 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&5110 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
5139 !(vtop->type.t & VT_ARRAY))5111 !(vtop->type.t & VT_ARRAY))
5140 test_lvalue();5112 test_lvalue();
5141#ifdef CONFIG_TCC_BCHECK5113 if (vtop->sym)
5142 if (tcc_state->do_bounds_check && vtop->sym) {5114 vtop->sym->a.addrtaken = 1;
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
5158 mk_pointer(&vtop->type);5115 mk_pointer(&vtop->type);
5159 gaddrof();5116 gaddrof();
5160 break;5117 break;
@@ -6454,7 +6411,7 @@ void prev_scope(struct scope *o, int is_expr) · 1293 unmodified lines
6454 tables, though. sym_pop will do that. */6411 tables, though. sym_pop will do that. */
6455 6412
6456 /* pop locally defined symbols */6413 /* pop locally defined symbols */
6457 sym_pop(&local_stack, o->lstk, is_expr);6414 pop_local_syms(&local_stack, o->lstk, is_expr);
6458 6415
6459 cur_scope = o->prev;6416 cur_scope = o->prev;
6460 --local_scope;6417 --local_scope;
@@ -7426,17 +7383,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 965 unmodified lines
7426 Sym *sym = NULL;7383 Sym *sym = NULL;
7427 int saved_nocode_wanted = nocode_wanted;7384 int saved_nocode_wanted = nocode_wanted;
7428#ifdef CONFIG_TCC_BCHECK7385#ifdef CONFIG_TCC_BCHECK
7429 int bcheck;7386 int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
7430#endif7387#endif
7431 7388
7432 /* Always allocate static or global variables */7389 /* Always allocate static or global variables */
7433 if (v && (r & VT_VALMASK) == VT_CONST)7390 if (v && (r & VT_VALMASK) == VT_CONST)
7434 nocode_wanted |= 0x80000000;7391 nocode_wanted |= 0x80000000;
7435 7392
7436#ifdef CONFIG_TCC_BCHECK
7437 bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
7438#endif
7439
7440 flexible_array = NULL;7393 flexible_array = NULL;
7441 if ((type->t & VT_BTYPE) == VT_STRUCT) {7394 if ((type->t & VT_BTYPE) == VT_STRUCT) {
7442 Sym *field = type->ref->next;7395 Sym *field = type->ref->next;
@@ -7508,17 +7461,15 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 65 unmodified lines
7508 sec = NULL;7461 sec = NULL;
7509#ifdef CONFIG_TCC_BCHECK7462#ifdef CONFIG_TCC_BCHECK
7510 if (bcheck && v) {7463 if (bcheck && v) {
7511 /* add padding between stack variables */7464 /* add padding between stack variables for bound checking */
7512 loc--;7465 loc--;
7513 }7466 }
7514#endif7467#endif
7515 loc = (loc - size) & -align;7468 loc = (loc - size) & -align;
7516 addr = loc;7469 addr = loc;
7517#ifdef CONFIG_TCC_BCHECK7470#ifdef CONFIG_TCC_BCHECK
7518 /* handles bounds */
7519 if (bcheck && v) {7471 if (bcheck && v) {
7520 add_bound_param (type, size, v, addr);7472 /* add padding between stack variables for bound checking */
7521 /* add padding between stack variables */
7522 loc--;7473 loc--;
7523 }7474 }
7524#endif7475#endif
@@ -7682,10 +7633,10 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 157 unmodified lines
7682 /* NOTE: we patch the symbol size later */7633 /* NOTE: we patch the symbol size later */
7683 put_extern_sym(sym, cur_text_section, ind, 0);7634 put_extern_sym(sym, cur_text_section, ind, 0);
7684 7635
7685 if (ad && ad->a.constructor) {7636 if (ad && ad->constructor) {
7686 add_init_array (tcc_state, sym);7637 add_init_array (tcc_state, sym);
7687 }7638 }
7688 if (ad && ad->a.destructor) {7639 if (ad && ad->destructor) {
7689 add_fini_array (tcc_state, sym);7640 add_fini_array (tcc_state, sym);
7690 }7641 }
7691 7642
@@ -7698,56 +7649,16 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 6 unmodified lines
7698 sym_push2(&local_stack, SYM_FIELD, 0, 0);7649 sym_push2(&local_stack, SYM_FIELD, 0, 0);
7699 local_scope = 1; /* for function parameters */7650 local_scope = 1; /* for function parameters */
7700 gfunc_prolog(sym);7651 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
7720 local_scope = 0;7652 local_scope = 0;
7721 rsym = 0;7653 rsym = 0;
7722 clear_temp_local_var_list();7654 clear_temp_local_var_list();
7723 block(0);7655 block(0);
7724 gsym(rsym);7656 gsym(rsym);
7725 nocode_wanted = 0;7657 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
7747 gfunc_epilog();7658 gfunc_epilog();
7748 cur_text_section->data_offset = ind;7659 cur_text_section->data_offset = ind;
7749 /* reset local stack */7660 /* reset local stack */
7750 sym_pop(&local_stack, NULL, 0);7661 pop_local_syms(&local_stack, NULL, 0);
7751 local_scope = 0;7662 local_scope = 0;
7752 label_pop(&global_label_stack, NULL, 0);7663 label_pop(&global_label_stack, NULL, 0);
7753 sym_pop(&all_cleanups, NULL, 0);7664 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
637}637}
638 638
639#if defined(CONFIG_TCC_BCHECK)639#if defined(CONFIG_TCC_BCHECK)
640static addr_t func_bound_offset;
640static unsigned long func_bound_ind;641static unsigned long func_bound_ind;
641 642
642static void gen_bounds_call(int v)643static void gen_bounds_call(int v)
@@ -783,10 +784,8 @@ void gfunc_call(int nb_args) · 140 unmodified lines
783 int arg;784 int arg;
784 785
785#ifdef CONFIG_TCC_BCHECK786#ifdef CONFIG_TCC_BCHECK
786 if (tcc_state->do_bounds_check) {787 if (tcc_state->do_bounds_check)
787 save_temp_local (nb_args);
788 gbound_args(nb_args);788 gbound_args(nb_args);
789 }
790#endif789#endif
791 790
792 args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;791 args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
@@ -907,10 +906,6 @@ void gfunc_call(int nb_args) · 114 unmodified lines
907 906
908 }907 }
909 vtop--;908 vtop--;
910#ifdef CONFIG_TCC_BCHECK
911 if (tcc_state->do_bounds_check)
912 restore_temp_local ();
913#endif
914}909}
915 910
916 911
@@ -1276,10 +1271,8 @@ void gfunc_call(int nb_args) · 359 unmodified lines
1276 char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;1271 char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
1277 1272
1278#ifdef CONFIG_TCC_BCHECK1273#ifdef CONFIG_TCC_BCHECK
1279 if (tcc_state->do_bounds_check) {1274 if (tcc_state->do_bounds_check)
1280 save_temp_local (nb_args);
1281 gbound_args(nb_args);1275 gbound_args(nb_args);
1282 }
1283#endif1276#endif
1284 1277
1285 /* calculate the number of integer/float register arguments, remember1278 /* calculate the number of integer/float register arguments, remember
@@ -1460,10 +1453,6 @@ void gfunc_call(int nb_args) · 174 unmodified lines
1460 if (args_size)1453 if (args_size)
1461 gadd_sp(args_size);1454 gadd_sp(args_size);
1462 vtop--;1455 vtop--;
1463#ifdef CONFIG_TCC_BCHECK
1464 if (tcc_state->do_bounds_check)
1465 restore_temp_local ();
1466#endif
1467}1456}
1468 1457
1469#define FUNC_PROLOG_SIZE 111458#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