- tests2/113_btdll.c: test handling multiple stabs infos Also: - libtcc.c: remove _ISOC99_SOURCE pre-defines. It is causing strange warnings such as 'strdup not declared' - i386/x86_64-gen.c cleanup bounds_pro/epilog. This discards the extra code for main's argv. If needed, __argv might be processed instead. - tccgen.c:block(): reduce stackspace usage. For example with code like "if (..) ... else if (..) ... else if (..)... " considerable numbers of nested block() calls may occur. Before that most stack space used when compiling itself was for libtcc.c:tcc_set_linker(). Now it's rather this construct at tccpp.c:2765: in next_nomacro1(): if (!((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM)) || c == '.' || ((c == '+' || c == '-') ...
Unified · Split
| @@ -97,6 +97,8 @@ static int func_ret_sub; · 96 unmodified lines | ||
| 97 | 97 | #ifdef CONFIG_TCC_BCHECK |
| 98 | 98 | static addr_t func_bound_offset; |
| 99 | 99 | static unsigned long func_bound_ind; |
| 100 | +static void gen_bounds_prolog(void); | |
| 101 | +static void gen_bounds_epilog(void); | |
| 100 | 102 | #endif |
| 101 | 103 | |
| 102 | 104 | /* XXX: make it faster ? */ |
| @@ -480,6 +482,7 @@ ST_FUNC void gfunc_call(int nb_args) · 377 unmodified lines | ||
| 480 | 482 | else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) |
| 481 | 483 | args_size -= 4; |
| 482 | 484 | #endif |
| 485 | + | |
| 483 | 486 | gcall_or_jmp(0); |
| 484 | 487 | |
| 485 | 488 | if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW) |
| @@ -499,7 +502,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 13 unmodified lines | ||
| 499 | 502 | CType *func_type = &func_sym->type; |
| 500 | 503 | int addr, align, size, func_call, fastcall_nb_regs; |
| 501 | 504 | int param_index, param_addr; |
| 502 | − int n_arg = 0; | |
| 503 | 505 | uint8_t *fastcall_regs_ptr; |
| 504 | 506 | Sym *sym; |
| 505 | 507 | CType *type; |
| @@ -542,7 +544,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 36 unmodified lines | ||
| 542 | 544 | } |
| 543 | 545 | /* define parameters */ |
| 544 | 546 | while ((sym = sym->next) != NULL) { |
| 545 | − n_arg++; | |
| 546 | 547 | type = &sym->type; |
| 547 | 548 | size = type_size(type, &align); |
| 548 | 549 | size = (size + 3) & ~3; |
| @@ -576,19 +577,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 27 unmodified lines | ||
| 576 | 577 | #endif |
| 577 | 578 | |
| 578 | 579 | #ifdef CONFIG_TCC_BCHECK |
| 579 | − /* leave some room for bound checking code */ | |
| 580 | − if (tcc_state->do_bounds_check) { | |
| 581 | − func_bound_offset = lbounds_section->data_offset; | |
| 582 | − func_bound_ind = ind; | |
| 583 | − oad(0xb8, 0); /* lbound section pointer */ | |
| 584 | − oad(0xb8, 0); /* call to function */ | |
| 585 | − if (n_arg >= 2 && strcmp (get_tok_str(func_sym->v, NULL), "main") == 0) { | |
| 586 | − o(0x0c458b); /* mov 0x12(%ebp),%eax */ | |
| 587 | − o(0x50); /* push %eax */ | |
| 588 | − gen_static_call(TOK___bound_main_arg); | |
| 589 | − o(0x04c483); /* add $0x4,%esp */ | |
| 590 | − } | |
| 591 | − } | |
| 580 | + if (tcc_state->do_bounds_check) | |
| 581 | + gen_bounds_prolog(); | |
| 592 | 582 | #endif |
| 593 | 583 | } |
| 594 | 584 | |
| @@ -598,34 +588,8 @@ ST_FUNC void gfunc_epilog(void) · 3 unmodified lines | ||
| 598 | 588 | addr_t v, saved_ind; |
| 599 | 589 | |
| 600 | 590 | #ifdef CONFIG_TCC_BCHECK |
| 601 | − if (tcc_state->do_bounds_check | |
| 602 | − && func_bound_offset != lbounds_section->data_offset) { | |
| 603 | − addr_t saved_ind; | |
| 604 | − addr_t *bounds_ptr; | |
| 605 | − Sym *sym_data; | |
| 606 | − | |
| 607 | − /* add end of table info */ | |
| 608 | − bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); | |
| 609 | − *bounds_ptr = 0; | |
| 610 | − | |
| 611 | − /* generate bound local allocation */ | |
| 612 | − saved_ind = ind; | |
| 613 | − ind = func_bound_ind; | |
| 614 | − sym_data = get_sym_ref(&char_pointer_type, lbounds_section, | |
| 615 | − func_bound_offset, lbounds_section->data_offset); | |
| 616 | − greloc(cur_text_section, sym_data, | |
| 617 | − ind + 1, R_386_32); | |
| 618 | − oad(0xb8, 0); /* mov %eax, xxx */ | |
| 619 | − gen_static_call(TOK___bound_local_new); | |
| 620 | − ind = saved_ind; | |
| 621 | − | |
| 622 | − /* generate bound check local freeing */ | |
| 623 | − o(0x5250); /* save returned value, if any */ | |
| 624 | − greloc(cur_text_section, sym_data, ind + 1, R_386_32); | |
| 625 | − oad(0xb8, 0); /* mov %eax, xxx */ | |
| 626 | − gen_static_call(TOK___bound_local_delete); | |
| 627 | − o(0x585a); /* restore returned value, if any */ | |
| 628 | − } | |
| 591 | + if (tcc_state->do_bounds_check) | |
| 592 | + gen_bounds_epilog(); | |
| 629 | 593 | #endif |
| 630 | 594 | |
| 631 | 595 | /* align local size to word & save local variables */ |
| @@ -1096,6 +1060,43 @@ ST_FUNC void gen_bounded_ptr_deref(void) · 464 unmodified lines | ||
| 1096 | 1060 | rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i); |
| 1097 | 1061 | rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info)); |
| 1098 | 1062 | } |
| 1063 | + | |
| 1064 | +static void gen_bounds_prolog(void) | |
| 1065 | +{ | |
| 1066 | + /* leave some room for bound checking code */ | |
| 1067 | + func_bound_offset = lbounds_section->data_offset; | |
| 1068 | + func_bound_ind = ind; | |
| 1069 | + oad(0xb8, 0); /* lbound section pointer */ | |
| 1070 | + oad(0xb8, 0); /* call to function */ | |
| 1071 | +} | |
| 1072 | + | |
| 1073 | +static void gen_bounds_epilog(void) | |
| 1074 | +{ | |
| 1075 | + addr_t saved_ind; | |
| 1076 | + addr_t *bounds_ptr; | |
| 1077 | + Sym *sym_data; | |
| 1078 | + | |
| 1079 | + /* add end of table info */ | |
| 1080 | + bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); | |
| 1081 | + *bounds_ptr = 0; | |
| 1082 | + | |
| 1083 | + /* generate bound local allocation */ | |
| 1084 | + saved_ind = ind; | |
| 1085 | + ind = func_bound_ind; | |
| 1086 | + sym_data = get_sym_ref(&char_pointer_type, lbounds_section, | |
| 1087 | + func_bound_offset, lbounds_section->data_offset); | |
| 1088 | + greloc(cur_text_section, sym_data, ind + 1, R_386_32); | |
| 1089 | + ind = ind + 5; | |
| 1090 | + gen_static_call(TOK___bound_local_new); | |
| 1091 | + ind = saved_ind; | |
| 1092 | + | |
| 1093 | + /* generate bound check local freeing */ | |
| 1094 | + o(0x5250); /* save returned value, if any */ | |
| 1095 | + greloc(cur_text_section, sym_data, ind + 1, R_386_32); | |
| 1096 | + oad(0xb8, 0); /* mov %eax, xxx */ | |
| 1097 | + gen_static_call(TOK___bound_local_delete); | |
| 1098 | + o(0x585a); /* restore returned value, if any */ | |
| 1099 | +} | |
| 1099 | 1100 | #endif |
| 1100 | 1101 | |
| 1101 | 1102 | /* Save the stack pointer onto the stack */ |
| @@ -353,7 +353,8 @@ void * __bound_ptr_add(void *p, size_t offset) · 352 unmodified lines | ||
| 353 | 353 | if (addr <= tree->size) { |
| 354 | 354 | if (tree->is_invalid || addr + offset > tree->size) { |
| 355 | 355 | POST_SEM (); |
| 356 | − bound_warning("%p is outside of the region", p + offset); | |
| 356 | + if (print_warn_ptr_add) | |
| 357 | + bound_warning("%p is outside of the region", p + offset); | |
| 357 | 358 | if (never_fatal <= 0) |
| 358 | 359 | return INVALID_POINTER; /* return an invalid pointer */ |
| 359 | 360 | return p + offset; |
| @@ -802,11 +802,6 @@ LIBTCCAPI TCCState *tcc_new(void) · 801 unmodified lines | ||
| 802 | 802 | tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); |
| 803 | 803 | tcc_define_symbol(s, "__STDC_HOSTED__", NULL); |
| 804 | 804 | |
| 805 | −#if !defined(TCC_TARGET_PE) | |
| 806 | − /* glibc compatible macro (default for C99) */ | |
| 807 | − tcc_define_symbol(s, "_ISOC99_SOURCE", "1"); | |
| 808 | −#endif | |
| 809 | − | |
| 810 | 805 | /* target defines */ |
| 811 | 806 | #if defined(TCC_TARGET_I386) |
| 812 | 807 | tcc_define_symbol(s, "__i386__", NULL); |
| @@ -1905,11 +1900,6 @@ reparse: · 1092 unmodified lines | ||
| 1905 | 1900 | * encoding used is implementationdefined. |
| 1906 | 1901 | */ |
| 1907 | 1902 | tcc_define_symbol(s, "__STDC_UTF_32__", "1"); |
| 1908 | − /* | |
| 1909 | − * glibc compatible macro used when -std=c11 is used. | |
| 1910 | − * _ISOC99_SOURCE remains defined as does gcc. | |
| 1911 | − */ | |
| 1912 | − tcc_define_symbol(s, "_ISOC11_SOURCE", "1"); | |
| 1913 | 1903 | #endif /* !TCC_TARGET_PE */ |
| 1914 | 1904 | s->cversion = 201112; |
| 1915 | 1905 | } |
| @@ -884,6 +884,9 @@ struct TCCState { · 883 unmodified lines | ||
| 884 | 884 | const char *runtime_main; |
| 885 | 885 | void **runtime_mem; |
| 886 | 886 | int nb_runtime_mem; |
| 887 | +#endif | |
| 888 | + | |
| 889 | +#ifdef CONFIG_TCC_BACKTRACE | |
| 887 | 890 | int rt_num_callers; |
| 888 | 891 | #endif |
| 889 | 892 | |
| @@ -1387,7 +1387,11 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 1386 unmodified lines | ||
| 1387 | 1387 | "__attribute__((constructor)) static void __bt_init_rt(){"); |
| 1388 | 1388 | #ifdef TCC_TARGET_PE |
| 1389 | 1389 | if (s1->output_type == TCC_OUTPUT_DLL) |
| 1390 | +#ifdef CONFIG_TCC_BCHECK | |
| 1390 | 1391 | cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check); |
| 1392 | +#else | |
| 1393 | + cstr_printf(&cstr, "__bt_init_dll(0);"); | |
| 1394 | +#endif | |
| 1391 | 1395 | #endif |
| 1392 | 1396 | cstr_printf(&cstr, "__bt_init(__rt_info,%d);}", |
| 1393 | 1397 | s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1); |
| @@ -101,6 +101,8 @@ ST_DATA struct switch_t { · 100 unmodified lines | ||
| 101 | 101 | int def_sym; /* default symbol */ |
| 102 | 102 | int *bsym; |
| 103 | 103 | struct scope *scope; |
| 104 | + struct switch_t *prev; | |
| 105 | + SValue sv; | |
| 104 | 106 | } *cur_switch; /* current switch */ |
| 105 | 107 | |
| 106 | 108 | #define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8 |
| @@ -6447,6 +6449,7 @@ static void lblock(int *bsym, int *csym) · 6340 unmodified lines | ||
| 6447 | 6449 | static void block(int is_expr) |
| 6448 | 6450 | { |
| 6449 | 6451 | int a, b, c, d, e, t; |
| 6452 | + struct scope o; | |
| 6450 | 6453 | Sym *s; |
| 6451 | 6454 | |
| 6452 | 6455 | if (is_expr) { |
| @@ -6487,7 +6490,6 @@ again: · 34 unmodified lines | ||
| 6487 | 6490 | gsym(a); |
| 6488 | 6491 | |
| 6489 | 6492 | } else if (t == '{') { |
| 6490 | − struct scope o; | |
| 6491 | 6493 | new_scope(&o); |
| 6492 | 6494 | |
| 6493 | 6495 | /* handle local labels declarations */ |
| @@ -6545,10 +6547,10 @@ again: · 51 unmodified lines | ||
| 6545 | 6547 | /* compute jump */ |
| 6546 | 6548 | if (!cur_scope->bsym) |
| 6547 | 6549 | tcc_error("cannot break"); |
| 6548 | − if (!cur_switch || cur_scope->bsym != cur_switch->bsym) | |
| 6549 | − leave_scope(loop_scope); | |
| 6550 | − else | |
| 6550 | + if (cur_switch && cur_scope->bsym == cur_switch->bsym) | |
| 6551 | 6551 | leave_scope(cur_switch->scope); |
| 6552 | + else | |
| 6553 | + leave_scope(loop_scope); | |
| 6552 | 6554 | *cur_scope->bsym = gjmp(*cur_scope->bsym); |
| 6553 | 6555 | skip(';'); |
| 6554 | 6556 | |
| @@ -6561,7 +6563,6 @@ again: · 6 unmodified lines | ||
| 6561 | 6563 | skip(';'); |
| 6562 | 6564 | |
| 6563 | 6565 | } else if (t == TOK_FOR) { |
| 6564 | − struct scope o; | |
| 6565 | 6566 | new_scope(&o); |
| 6566 | 6567 | |
| 6567 | 6568 | skip('('); |
| @@ -6611,22 +6612,18 @@ again: · 43 unmodified lines | ||
| 6611 | 6612 | gsym(a); |
| 6612 | 6613 | |
| 6613 | 6614 | } else if (t == TOK_SWITCH) { |
| 6614 | − struct switch_t *saved, sw; | |
| 6615 | − SValue switchval; | |
| 6616 | − | |
| 6617 | − sw.p = NULL; | |
| 6618 | − sw.n = 0; | |
| 6619 | − sw.def_sym = 0; | |
| 6620 | − sw.bsym = &a; | |
| 6621 | − sw.scope = cur_scope; | |
| 6615 | + struct switch_t *sw; | |
| 6622 | 6616 | |
| 6623 | − saved = cur_switch; | |
| 6624 | − cur_switch = &sw; | |
| 6617 | + sw = tcc_mallocz(sizeof *sw); | |
| 6618 | + sw->bsym = &a; | |
| 6619 | + sw->scope = cur_scope; | |
| 6620 | + sw->prev = cur_switch; | |
| 6621 | + cur_switch = sw; | |
| 6625 | 6622 | |
| 6626 | 6623 | skip('('); |
| 6627 | 6624 | gexpr(); |
| 6628 | 6625 | skip(')'); |
| 6629 | − switchval = *vtop--; | |
| 6626 | + sw->sv = *vtop--; /* save switch value */ | |
| 6630 | 6627 | |
| 6631 | 6628 | a = 0; |
| 6632 | 6629 | b = gjmp(0); /* jump to first case */ |
| @@ -6635,28 +6632,29 @@ again: · 2 unmodified lines | ||
| 6635 | 6632 | /* case lookup */ |
| 6636 | 6633 | gsym(b); |
| 6637 | 6634 | |
| 6638 | − qsort(sw.p, sw.n, sizeof(void*), case_cmp); | |
| 6639 | − for (b = 1; b < sw.n; b++) | |
| 6640 | − if (sw.p[b - 1]->v2 >= sw.p[b]->v1) | |
| 6635 | + qsort(sw->p, sw->n, sizeof(void*), case_cmp); | |
| 6636 | + for (b = 1; b < sw->n; b++) | |
| 6637 | + if (sw->p[b - 1]->v2 >= sw->p[b]->v1) | |
| 6641 | 6638 | tcc_error("duplicate case value"); |
| 6642 | 6639 | |
| 6643 | 6640 | /* Our switch table sorting is signed, so the compared |
| 6644 | 6641 | value needs to be as well when it's 64bit. */ |
| 6645 | − if ((switchval.type.t & VT_BTYPE) == VT_LLONG) | |
| 6646 | − switchval.type.t &= ~VT_UNSIGNED; | |
| 6647 | − vpushv(&switchval); | |
| 6642 | + vpushv(&sw->sv); | |
| 6643 | + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) | |
| 6644 | + vtop->type.t &= ~VT_UNSIGNED; | |
| 6648 | 6645 | gv(RC_INT); |
| 6649 | − d = 0, gcase(sw.p, sw.n, &d); | |
| 6646 | + d = 0, gcase(sw->p, sw->n, &d); | |
| 6650 | 6647 | vpop(); |
| 6651 | − if (sw.def_sym) | |
| 6652 | − gsym_addr(d, sw.def_sym); | |
| 6648 | + if (sw->def_sym) | |
| 6649 | + gsym_addr(d, sw->def_sym); | |
| 6653 | 6650 | else |
| 6654 | 6651 | gsym(d); |
| 6655 | 6652 | /* break label */ |
| 6656 | 6653 | gsym(a); |
| 6657 | 6654 | |
| 6658 | − dynarray_reset(&sw.p, &sw.n); | |
| 6659 | − cur_switch = saved; | |
| 6655 | + dynarray_reset(&sw->p, &sw->n); | |
| 6656 | + cur_switch = sw->prev; | |
| 6657 | + tcc_free(sw); | |
| 6660 | 6658 | |
| 6661 | 6659 | } else if (t == TOK_CASE) { |
| 6662 | 6660 | struct case_t *cr = tcc_malloc(sizeof(struct case_t)); |
| @@ -48,7 +48,7 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); · 47 unmodified lines | ||
| 48 | 48 | static void rt_exit(int code); |
| 49 | 49 | #endif /* CONFIG_TCC_BACKTRACE */ |
| 50 | 50 | |
| 51 | −/* defined when included from lib/bt.c */ | |
| 51 | +/* defined when included from lib/bt-exe.c */ | |
| 52 | 52 | #ifndef CONFIG_TCC_BACKTRACE_ONLY |
| 53 | 53 | |
| 54 | 54 | #ifndef _WIN32 |
| @@ -412,15 +412,15 @@ next: · 357 unmodified lines | ||
| 412 | 412 | /* Stab_Sym.n_value is only 32bits */ |
| 413 | 413 | pc += rc->prog_base; |
| 414 | 414 | #endif |
| 415 | − break; | |
| 415 | + goto check_pc; | |
| 416 | 416 | rel_pc: |
| 417 | 417 | pc += func_addr; |
| 418 | + check_pc: | |
| 419 | + if (pc >= wanted_pc && wanted_pc >= last_pc) | |
| 420 | + goto found; | |
| 418 | 421 | break; |
| 419 | 422 | } |
| 420 | 423 | |
| 421 | − if (pc >= wanted_pc && wanted_pc >= last_pc) | |
| 422 | − goto found; | |
| 423 | − | |
| 424 | 424 | switch(sym->n_type) { |
| 425 | 425 | /* function start or end */ |
| 426 | 426 | case N_FUN: |
| @@ -12,8 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | [test_bcheck_1] |
| 13 | 13 | * main |
| 14 | 14 | * f1() |
| 15 | −112_backtrace.c:38: at f1: BCHECK: ........ is outside of the region | |
| 16 | −112_backtrace.c:43: by main | |
| 17 | 15 | 112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest |
| 18 | 16 | 112_backtrace.c:43: by main |
| 19 | 17 | [returns 255] |
| @@ -32,12 +30,10 @@ · 12 unmodified lines | ||
| 32 | 30 | [returns 1] |
| 33 | 31 | |
| 34 | 32 | [test_bcheck_100] |
| 35 | −112_backtrace.c:107: at main: BCHECK: ........ is outside of the region | |
| 36 | 33 | 112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest |
| 37 | 34 | [returns 255] |
| 38 | 35 | |
| 39 | 36 | [test_bcheck_101] |
| 40 | −112_backtrace.c:109: at main: BCHECK: ........ is outside of the region | |
| 41 | 37 | 112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src |
| 42 | 38 | [returns 255] |
| 43 | 39 | |
| @@ -50,42 +46,34 @@ · 6 unmodified lines | ||
| 50 | 46 | [returns 255] |
| 51 | 47 | |
| 52 | 48 | [test_bcheck_104] |
| 53 | −112_backtrace.c:115: at main: BCHECK: ........ is outside of the region | |
| 54 | 49 | 112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1 |
| 55 | 50 | [returns 255] |
| 56 | 51 | |
| 57 | 52 | [test_bcheck_105] |
| 58 | −112_backtrace.c:117: at main: BCHECK: ........ is outside of the region | |
| 59 | 53 | 112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2 |
| 60 | 54 | [returns 255] |
| 61 | 55 | |
| 62 | 56 | [test_bcheck_106] |
| 63 | −112_backtrace.c:119: at main: BCHECK: ........ is outside of the region | |
| 64 | 57 | 112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest |
| 65 | 58 | [returns 255] |
| 66 | 59 | |
| 67 | 60 | [test_bcheck_107] |
| 68 | −112_backtrace.c:121: at main: BCHECK: ........ is outside of the region | |
| 69 | 61 | 112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src |
| 70 | 62 | [returns 255] |
| 71 | 63 | |
| 72 | 64 | [test_bcheck_108] |
| 73 | −112_backtrace.c:123: at main: BCHECK: ........ is outside of the region | |
| 74 | 65 | 112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset |
| 75 | 66 | [returns 255] |
| 76 | 67 | |
| 77 | 68 | [test_bcheck_109] |
| 78 | −112_backtrace.c:125: at main: BCHECK: ........ is outside of the region | |
| 79 | 69 | 112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen |
| 80 | 70 | [returns 255] |
| 81 | 71 | |
| 82 | 72 | [test_bcheck_110] |
| 83 | −112_backtrace.c:127: at main: BCHECK: ........ is outside of the region | |
| 84 | 73 | 112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest |
| 85 | 74 | [returns 255] |
| 86 | 75 | |
| 87 | 76 | [test_bcheck_111] |
| 88 | −112_backtrace.c:129: at main: BCHECK: ........ is outside of the region | |
| 89 | 77 | 112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src |
| 90 | 78 | [returns 255] |
| 91 | 79 | |
| @@ -98,12 +86,10 @@ · 6 unmodified lines | ||
| 98 | 86 | [returns 255] |
| 99 | 87 | |
| 100 | 88 | [test_bcheck_114] |
| 101 | −112_backtrace.c:135: at main: BCHECK: ........ is outside of the region | |
| 102 | 89 | 112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest |
| 103 | 90 | [returns 255] |
| 104 | 91 | |
| 105 | 92 | [test_bcheck_115] |
| 106 | −112_backtrace.c:137: at main: BCHECK: ........ is outside of the region | |
| 107 | 93 | 112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src |
| 108 | 94 | [returns 255] |
| 109 | 95 | |
| @@ -116,32 +102,26 @@ · 6 unmodified lines | ||
| 116 | 102 | [returns 255] |
| 117 | 103 | |
| 118 | 104 | [test_bcheck_118] |
| 119 | −112_backtrace.c:143: at main: BCHECK: ........ is outside of the region | |
| 120 | 105 | 112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1 |
| 121 | 106 | [returns 255] |
| 122 | 107 | |
| 123 | 108 | [test_bcheck_119] |
| 124 | −112_backtrace.c:145: at main: BCHECK: ........ is outside of the region | |
| 125 | 109 | 112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2 |
| 126 | 110 | [returns 255] |
| 127 | 111 | |
| 128 | 112 | [test_bcheck_120] |
| 129 | −112_backtrace.c:147: at main: BCHECK: ........ is outside of the region | |
| 130 | 113 | 112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1 |
| 131 | 114 | [returns 255] |
| 132 | 115 | |
| 133 | 116 | [test_bcheck_121] |
| 134 | −112_backtrace.c:149: at main: BCHECK: ........ is outside of the region | |
| 135 | 117 | 112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2 |
| 136 | 118 | [returns 255] |
| 137 | 119 | |
| 138 | 120 | [test_bcheck_122] |
| 139 | −112_backtrace.c:151: at main: BCHECK: ........ is outside of the region | |
| 140 | 121 | 112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest |
| 141 | 122 | [returns 255] |
| 142 | 123 | |
| 143 | 124 | [test_bcheck_123] |
| 144 | −112_backtrace.c:153: at main: BCHECK: ........ is outside of the region | |
| 145 | 125 | 112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest |
| 146 | 126 | [returns 255] |
| 147 | 127 | |
| @@ -154,11 +134,9 @@ · 6 unmodified lines | ||
| 154 | 134 | [returns 255] |
| 155 | 135 | |
| 156 | 136 | [test_bcheck_126] |
| 157 | −112_backtrace.c:159: at main: BCHECK: ........ is outside of the region | |
| 158 | 137 | 112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strchr |
| 159 | 138 | [returns 255] |
| 160 | 139 | |
| 161 | 140 | [test_bcheck_127] |
| 162 | −112_backtrace.c:161: at main: BCHECK: ........ is outside of the region | |
| 163 | 141 | 112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strdup |
| 164 | 142 | [returns 255] |
| @@ -0,0 +1,43 @@ | ||
| 1 | +int tcc_backtrace(const char*, ...); | |
| 2 | +#define hello() \ | |
| 3 | + tcc_backtrace("hello from %s() / %s:%d",__FUNCTION__,__FILE__,__LINE__) | |
| 4 | + | |
| 5 | +#ifndef _WIN32 | |
| 6 | +# define __declspec(n) | |
| 7 | +#endif | |
| 8 | + | |
| 9 | +#if DLL==1 | |
| 10 | +__declspec(dllexport) int f_1() | |
| 11 | +{ | |
| 12 | + hello(); | |
| 13 | + return 0; | |
| 14 | +} | |
| 15 | + | |
| 16 | + | |
| 17 | +#elif DLL==2 | |
| 18 | +__declspec(dllexport) int f_2() | |
| 19 | +{ | |
| 20 | + hello(); | |
| 21 | + return 0; | |
| 22 | +} | |
| 23 | + | |
| 24 | + | |
| 25 | +#else | |
| 26 | + | |
| 27 | +int f_1(); | |
| 28 | +int f_2(); | |
| 29 | +int f_main() | |
| 30 | +{ | |
| 31 | + hello(); | |
| 32 | + return 0; | |
| 33 | +} | |
| 34 | + | |
| 35 | +int main () | |
| 36 | +{ | |
| 37 | + f_1(); | |
| 38 | + f_2(); | |
| 39 | + f_main(); | |
| 40 | + return 0; | |
| 41 | +} | |
| 42 | + | |
| 43 | +#endif | |
| @@ -0,0 +1,6 @@ | ||
| 1 | +113_btdll.c:12: at f_1: hello from f_1() / 113_btdll.c:12 | |
| 2 | +113_btdll.c:37: by main | |
| 3 | +113_btdll.c:20: at f_2: hello from f_2() / 113_btdll.c:20 | |
| 4 | +113_btdll.c:38: by main | |
| 5 | +113_btdll.c:31: at f_main: hello from f_main() / 113_btdll.c:31 | |
| 6 | +113_btdll.c:39: by main | |
| @@ -24,7 +24,7 @@ ifeq (,$(filter i386,$(ARCH))) · 23 unmodified lines | ||
| 24 | 24 | endif |
| 25 | 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) |
| 26 | 26 | SKIP += 85_asm-outside-function.test |
| 27 | − SKIP += 112_backtrace.test | |
| 27 | + SKIP += 112_backtrace.test 113_btdll.test | |
| 28 | 28 | endif |
| 29 | 29 | ifeq (-$(findstring gcc,$(CC))-,--) |
| 30 | 30 | SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) |
| @@ -61,7 +61,7 @@ GEN-ALWAYS = · 30 unmodified lines | ||
| 61 | 61 | 95_bitfields_ms.test : GEN = $(GEN-MSC) |
| 62 | 62 | |
| 63 | 63 | # this test compiles/links two files: |
| 64 | −104_inline.test : FLAGS += $(SRC)/104+_inline.c | |
| 64 | +104_inline.test : FLAGS += $(subst 104,104+,$1) | |
| 65 | 65 | 104_inline.test : GEN = $(GEN-TCC) |
| 66 | 66 | |
| 67 | 67 | # this test needs pthread |
| @@ -72,7 +72,16 @@ GEN-ALWAYS = · 4 unmodified lines | ||
| 72 | 72 | 108_constructor.test: NORUN = true |
| 73 | 73 | |
| 74 | 74 | 112_backtrace.test: FLAGS += -dt -b |
| 75 | −112_backtrace.test: FILTER += -e 's;[0-9A-Fa-fx]\{8,\};........;g' -e 's;0x[0-9A-Fa-f]\+;0x?;g' | |
| 75 | +112_backtrace.test 113_btdll.test: FILTER += \ | |
| 76 | + -e 's;[0-9A-Fa-fx]\{8,\};........;g' \ | |
| 77 | + -e 's;0x[0-9A-Fa-f]\+;0x?;g' | |
| 78 | + | |
| 79 | +# this test creates two DLLs and an EXE | |
| 80 | +113_btdll.test: NORUN = true | |
| 81 | +113_btdll.test: FLAGS += \ | |
| 82 | + -bt $1 -shared -D DLL=1 -o a1$(DLLSUF) && $(TCC) \ | |
| 83 | + -bt $1 -shared -D DLL=2 -o a2$(DLLSUF) && $(TCC) \ | |
| 84 | + -bt a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=. | |
| 76 | 85 | |
| 77 | 86 | # Filter source directory in warnings/errors (out-of-tree builds) |
| 78 | 87 | FILTER = 2>&1 | sed -e 's,$(SRC)/,,g' |
| @@ -81,10 +90,10 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; · 2 unmodified lines | ||
| 81 | 90 | |
| 82 | 91 | %.test: %.c %.expect |
| 83 | 92 | @echo Test: $*... |
| 84 | − @$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3)) | |
| 93 | + @$(call T1,$<) $(T3) | |
| 85 | 94 | |
| 86 | −T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS) | |
| 87 | −T2 = $(TCC) $(FLAGS) -run $< $(ARGS) | |
| 95 | +T1 = $(TCC) $(FLAGS) $(T2) $(ARGS) | |
| 96 | +T2 = $(if $(NORUN),$1 -o a.exe && ./a.exe,-run $1) | |
| 88 | 97 | T3 = $(FILTER) >$*.output 2>&1 || true \ |
| 89 | 98 | && diff -Nbu $(filter %.expect,$^) $*.output \ |
| 90 | 99 | && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) |
| @@ -95,7 +104,7 @@ tests2.%+: · 4 unmodified lines | ||
| 95 | 104 | |
| 96 | 105 | # just run tcc to see the output, e.g. "make tests2.37-" |
| 97 | 106 | tests2.%-: |
| 98 | − @$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory | |
| 107 | + @$(MAKE) $(call F1,$*) T3= --no-print-directory | |
| 99 | 108 | |
| 100 | 109 | # run single test, e.g. "make tests2.37" |
| 101 | 110 | tests2.%: |
| @@ -111,9 +120,9 @@ F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" · 9 unmodified lines | ||
| 111 | 120 | @rm -f *.exe *.obj *.pdb |
| 112 | 121 | |
| 113 | 122 | # using TCC for .expect if -dt in FLAGS |
| 114 | −GEN = $(if $(filter -dt,$(FLAGS)),$(GEN-TCC),$(GEN-CC)) | |
| 123 | +GEN = $(if $(filter -dt -bt -b,$(FLAGS)),$(GEN-TCC),$(GEN-CC)) | |
| 115 | 124 | GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o a.exe && ./a.exe $(ARGS) |
| 116 | −GEN-TCC = $(TCC) $(FLAGS) -run $1 $(ARGS) | |
| 125 | +GEN-TCC = $(T1) | |
| 117 | 126 | GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe |
| 118 | 127 | MS-CC = cl |
| 119 | 128 | |
| @@ -124,5 +133,5 @@ MS-CC = cl · 4 unmodified lines | ||
| 124 | 133 | $(sort $(GEN-ALWAYS) $(UPDATE)) : force |
| 125 | 134 | force: |
| 126 | 135 | |
| 127 | −clean: | |
| 128 | − rm -f fred.txt *.output a.exe $(GEN-ALWAYS) | |
| 136 | +clean tests2.clean : | |
| 137 | + rm -f fred.txt *.output a.exe *.dll *.so *.def $(GEN-ALWAYS) | |
| @@ -163,7 +163,7 @@ copy>nul tcc-win32.txt doc · 162 unmodified lines | ||
| 163 | 163 | .\tcc -m64 -c ../lib/alloca86_64-bt.S |
| 164 | 164 | .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o |
| 165 | 165 | @if errorlevel 1 goto :the_end |
| 166 | −.\tcc -m%T% -c ../lib/bcheck.c -o lib/bcheck.o | |
| 166 | +.\tcc -m%T% -c ../lib/bcheck.c -o lib/bcheck.o -g | |
| 167 | 167 | .\tcc -m%T% -c ../lib/bt-exe.c -o lib/bt-exe.o |
| 168 | 168 | .\tcc -m%T% -c ../lib/bt-log.c -o lib/bt-log.o |
| 169 | 169 | .\tcc -m%T% -c ../lib/bt-dll.c -o lib/bt-dll.o |
| @@ -701,10 +701,57 @@ ST_FUNC void gen_bounded_ptr_deref(void) · 700 unmodified lines | ||
| 701 | 701 | rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i); |
| 702 | 702 | rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info)); |
| 703 | 703 | } |
| 704 | + | |
| 705 | +#ifdef TCC_TARGET_PE | |
| 706 | +# define TREG_FASTCALL_1 TREG_RCX | |
| 707 | +#else | |
| 708 | +# define TREG_FASTCALL_1 TREG_RDI | |
| 709 | +#endif | |
| 710 | + | |
| 711 | +static void gen_bounds_prolog(void) | |
| 712 | +{ | |
| 713 | + /* leave some room for bound checking code */ | |
| 714 | + func_bound_offset = lbounds_section->data_offset; | |
| 715 | + func_bound_ind = ind; | |
| 716 | + o(0xb848 + TREG_FASTCALL_1 * 0x100); /*lbound section pointer */ | |
| 717 | + gen_le64 (0); | |
| 718 | + oad(0xb8, 0); /* call to function */ | |
| 719 | +} | |
| 720 | + | |
| 721 | +static void gen_bounds_epilog(void) | |
| 722 | +{ | |
| 723 | + addr_t saved_ind; | |
| 724 | + addr_t *bounds_ptr; | |
| 725 | + Sym *sym_data; | |
| 726 | + | |
| 727 | + /* add end of table info */ | |
| 728 | + bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); | |
| 729 | + *bounds_ptr = 0; | |
| 730 | + | |
| 731 | + /* generate bound local allocation */ | |
| 732 | + sym_data = get_sym_ref(&char_pointer_type, lbounds_section, | |
| 733 | + func_bound_offset, lbounds_section->data_offset); | |
| 734 | + saved_ind = ind; | |
| 735 | + ind = func_bound_ind; | |
| 736 | + greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); | |
| 737 | + ind = ind + 10; | |
| 738 | + gen_bounds_call(TOK___bound_local_new); | |
| 739 | + ind = saved_ind; | |
| 740 | + | |
| 741 | + /* generate bound check local freeing */ | |
| 742 | + o(0x525051); /* save returned value, if any (+ scratch-space for windows) */ | |
| 743 | + greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); | |
| 744 | + o(0xb848 + TREG_FASTCALL_1 * 0x100); /* mov xxx, %rcx/di */ | |
| 745 | + gen_le64 (0); | |
| 746 | + gen_bounds_call(TOK___bound_local_delete); | |
| 747 | + o(0x59585a); /* restore returned value, if any */ | |
| 748 | +} | |
| 704 | 749 | #endif |
| 705 | 750 | |
| 706 | 751 | #ifdef TCC_TARGET_PE |
| 707 | 752 | |
| 753 | +static int func_scratch, func_alloca; | |
| 754 | + | |
| 708 | 755 | #define REGN 4 |
| 709 | 756 | static const uint8_t arg_regs[REGN] = { |
| 710 | 757 | TREG_RCX, TREG_RDX, TREG_R8, TREG_R9 |
| @@ -720,8 +767,6 @@ static int arg_prepare_reg(int idx) { · 9 unmodified lines | ||
| 720 | 767 | return arg_regs[idx]; |
| 721 | 768 | } |
| 722 | 769 | |
| 723 | −static int func_scratch, func_alloca; | |
| 724 | − | |
| 725 | 770 | /* Generate function call. The function address is pushed first, then |
| 726 | 771 | all the parameters in call order. This functions pops all the |
| 727 | 772 | parameters and the function address. */ |
| @@ -918,7 +963,6 @@ void gfunc_prolog(Sym *func_sym) · 190 unmodified lines | ||
| 918 | 963 | int addr, reg_param_index, bt, size; |
| 919 | 964 | Sym *sym; |
| 920 | 965 | CType *type; |
| 921 | − int n_arg = 0; | |
| 922 | 966 | |
| 923 | 967 | func_ret_sub = 0; |
| 924 | 968 | func_scratch = 32; |
| @@ -946,7 +990,6 @@ void gfunc_prolog(Sym *func_sym) · 21 unmodified lines | ||
| 946 | 990 | |
| 947 | 991 | /* define parameters */ |
| 948 | 992 | while ((sym = sym->next) != NULL) { |
| 949 | − n_arg++; | |
| 950 | 993 | type = &sym->type; |
| 951 | 994 | bt = type->t & VT_BTYPE; |
| 952 | 995 | size = gfunc_arg_size(type); |
| @@ -983,23 +1026,8 @@ void gfunc_prolog(Sym *func_sym) · 30 unmodified lines | ||
| 983 | 1026 | reg_param_index++; |
| 984 | 1027 | } |
| 985 | 1028 | #ifdef CONFIG_TCC_BCHECK |
| 986 | − /* leave some room for bound checking code */ | |
| 987 | − if (tcc_state->do_bounds_check) { | |
| 988 | − func_bound_offset = lbounds_section->data_offset; | |
| 989 | − func_bound_ind = ind; | |
| 990 | − o(0xb848); /* lbound section pointer */ | |
| 991 | − gen_le64 (0); | |
| 992 | − o(0xc18948); /* mov %rax,%rcx ## first arg in %rdi, this must be ptr */ | |
| 993 | − o(0x20ec8348); /* sub $20, %rsp */ | |
| 994 | − oad(0xb8, 0); /* call to function */ | |
| 995 | − o(0x20c48348); /* add $20, %rsp */ | |
| 996 | − if (n_arg >= 2 && strcmp (get_tok_str(func_sym->v, NULL), "main") == 0) { | |
| 997 | − o(0x184d8b48); /* mov 0x18(%rbp),%rcx */ | |
| 998 | − o(0x20ec8348); /* sub $20, %rsp */ | |
| 999 | − gen_bounds_call(TOK___bound_main_arg); | |
| 1000 | − o(0x20c48348); /* add $20, %rsp */ | |
| 1001 | − } | |
| 1002 | − } | |
| 1029 | + if (tcc_state->do_bounds_check) | |
| 1030 | + gen_bounds_prolog(); | |
| 1003 | 1031 | #endif |
| 1004 | 1032 | } |
| 1005 | 1033 | |
| @@ -1013,39 +1041,10 @@ void gfunc_epilog(void) · 7 unmodified lines | ||
| 1013 | 1041 | loc = (loc & -16) - func_scratch; |
| 1014 | 1042 | |
| 1015 | 1043 | #ifdef CONFIG_TCC_BCHECK |
| 1016 | − if (tcc_state->do_bounds_check | |
| 1017 | − && func_bound_offset != lbounds_section->data_offset) | |
| 1018 | − { | |
| 1019 | − addr_t saved_ind; | |
| 1020 | − addr_t *bounds_ptr; | |
| 1021 | − Sym *sym_data; | |
| 1022 | − | |
| 1023 | − /* add end of table info */ | |
| 1024 | − bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); | |
| 1025 | − *bounds_ptr = 0; | |
| 1026 | − | |
| 1027 | − /* generate bound local allocation */ | |
| 1028 | − sym_data = get_sym_ref(&char_pointer_type, lbounds_section, | |
| 1029 | − func_bound_offset, lbounds_section->data_offset); | |
| 1030 | − saved_ind = ind; | |
| 1031 | − ind = func_bound_ind; | |
| 1032 | − greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); | |
| 1033 | − ind = ind + 10 + 3 + 4; | |
| 1034 | − gen_bounds_call(TOK___bound_local_new); | |
| 1035 | − ind = saved_ind; | |
| 1036 | − | |
| 1037 | − /* generate bound check local freeing */ | |
| 1038 | − o(0x5250); /* save returned value, if any */ | |
| 1039 | − greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); | |
| 1040 | − o(0xb848); /* mov xxx, %rax */ | |
| 1041 | − gen_le64 (0); | |
| 1042 | − o(0xc18948); /* mov %rax,%rcx # first arg in %rdi, this must be ptr */ | |
| 1043 | − o(0x20ec8348); /* sub $20, %rsp */ | |
| 1044 | − gen_bounds_call(TOK___bound_local_delete); | |
| 1045 | − o(0x20c48348); /* add $20, %rsp */ | |
| 1046 | − o(0x585a); /* restore returned value, if any */ | |
| 1047 | − } | |
| 1044 | + if (tcc_state->do_bounds_check) | |
| 1045 | + gen_bounds_epilog(); | |
| 1048 | 1046 | #endif |
| 1047 | + | |
| 1049 | 1048 | o(0xc9); /* leave */ |
| 1050 | 1049 | if (func_ret_sub == 0) { |
| 1051 | 1050 | o(0xc3); /* ret */ |
| @@ -1469,7 +1468,6 @@ void gfunc_prolog(Sym *func_sym) · 417 unmodified lines | ||
| 1469 | 1468 | X86_64_Mode mode; |
| 1470 | 1469 | int i, addr, align, size, reg_count; |
| 1471 | 1470 | int param_addr = 0, reg_param_index, sse_param_index; |
| 1472 | − int n_arg = 0; | |
| 1473 | 1471 | Sym *sym; |
| 1474 | 1472 | CType *type; |
| 1475 | 1473 | |
| @@ -1553,7 +1551,6 @@ void gfunc_prolog(Sym *func_sym) · 77 unmodified lines | ||
| 1553 | 1551 | } |
| 1554 | 1552 | /* define parameters */ |
| 1555 | 1553 | while ((sym = sym->next) != NULL) { |
| 1556 | − n_arg++; | |
| 1557 | 1554 | type = &sym->type; |
| 1558 | 1555 | mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); |
| 1559 | 1556 | switch (mode) { |
| @@ -1606,19 +1603,8 @@ void gfunc_prolog(Sym *func_sym) · 46 unmodified lines | ||
| 1606 | 1603 | } |
| 1607 | 1604 | |
| 1608 | 1605 | #ifdef CONFIG_TCC_BCHECK |
| 1609 | − /* leave some room for bound checking code */ | |
| 1610 | − if (tcc_state->do_bounds_check) { | |
| 1611 | − func_bound_offset = lbounds_section->data_offset; | |
| 1612 | − func_bound_ind = ind; | |
| 1613 | − o(0xb848); /* lbound section pointer */ | |
| 1614 | − gen_le64 (0); | |
| 1615 | − o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ | |
| 1616 | − oad(0xb8, 0); /* call to function */ | |
| 1617 | − if (n_arg >= 2 && strcmp (get_tok_str(func_sym->v, NULL), "main") == 0) { | |
| 1618 | − o(0xf07d8b48); /* mov -0x10(%rbp),%rdi */ | |
| 1619 | − gen_bounds_call(TOK___bound_main_arg); | |
| 1620 | − } | |
| 1621 | − } | |
| 1606 | + if (tcc_state->do_bounds_check) | |
| 1607 | + gen_bounds_prolog(); | |
| 1622 | 1608 | #endif |
| 1623 | 1609 | } |
| 1624 | 1610 | |
| @@ -1628,36 +1614,8 @@ void gfunc_epilog(void) · 3 unmodified lines | ||
| 1628 | 1614 | int v, saved_ind; |
| 1629 | 1615 | |
| 1630 | 1616 | #ifdef CONFIG_TCC_BCHECK |
| 1631 | − if (tcc_state->do_bounds_check | |
| 1632 | − && func_bound_offset != lbounds_section->data_offset) | |
| 1633 | − { | |
| 1634 | − addr_t saved_ind; | |
| 1635 | − addr_t *bounds_ptr; | |
| 1636 | − Sym *sym_data; | |
| 1637 | − | |
| 1638 | − /* add end of table info */ | |
| 1639 | − bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); | |
| 1640 | − *bounds_ptr = 0; | |
| 1641 | − | |
| 1642 | − /* generate bound local allocation */ | |
| 1643 | − sym_data = get_sym_ref(&char_pointer_type, lbounds_section, | |
| 1644 | − func_bound_offset, lbounds_section->data_offset); | |
| 1645 | − saved_ind = ind; | |
| 1646 | − ind = func_bound_ind; | |
| 1647 | − greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); | |
| 1648 | − ind = ind + 10 + 3; | |
| 1649 | − gen_bounds_call(TOK___bound_local_new); | |
| 1650 | − ind = saved_ind; | |
| 1651 | − | |
| 1652 | − /* generate bound check local freeing */ | |
| 1653 | − o(0x5250); /* save returned value, if any */ | |
| 1654 | − greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); | |
| 1655 | − o(0xb848); /* mov xxx, %rax */ | |
| 1656 | − gen_le64 (0); | |
| 1657 | − o(0xc78948); /* mov %rax,%rdi # first arg in %rdi, this must be ptr */ | |
| 1658 | − gen_bounds_call(TOK___bound_local_delete); | |
| 1659 | − o(0x585a); /* restore returned value, if any */ | |
| 1660 | − } | |
| 1617 | + if (tcc_state->do_bounds_check) | |
| 1618 | + gen_bounds_epilog(); | |
| 1661 | 1619 | #endif |
| 1662 | 1620 | o(0xc9); /* leave */ |
| 1663 | 1621 | if (func_ret_sub == 0) { |