- 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 | #ifdef CONFIG_TCC_BCHECK | 97 | #ifdef CONFIG_TCC_BCHECK |
| 98 | static addr_t func_bound_offset; | 98 | static addr_t func_bound_offset; |
| 99 | static unsigned long func_bound_ind; | 99 | static unsigned long func_bound_ind; |
| 100 | static void gen_bounds_prolog(void); | ||
| 101 | static void gen_bounds_epilog(void); | ||
| 100 | #endif | 102 | #endif |
| 101 | 103 | ||
| 102 | /* XXX: make it faster ? */ | 104 | /* XXX: make it faster ? */ |
| @@ -480,6 +482,7 @@ ST_FUNC void gfunc_call(int nb_args) · 377 unmodified lines | |||
| 480 | else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) | 482 | else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) |
| 481 | args_size -= 4; | 483 | args_size -= 4; |
| 482 | #endif | 484 | #endif |
| 485 | |||
| 483 | gcall_or_jmp(0); | 486 | gcall_or_jmp(0); |
| 484 | 487 | ||
| 485 | if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW) | 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 | CType *func_type = &func_sym->type; | 502 | CType *func_type = &func_sym->type; |
| 500 | int addr, align, size, func_call, fastcall_nb_regs; | 503 | int addr, align, size, func_call, fastcall_nb_regs; |
| 501 | int param_index, param_addr; | 504 | int param_index, param_addr; |
| 502 | int n_arg = 0; | ||
| 503 | uint8_t *fastcall_regs_ptr; | 505 | uint8_t *fastcall_regs_ptr; |
| 504 | Sym *sym; | 506 | Sym *sym; |
| 505 | CType *type; | 507 | CType *type; |
| @@ -542,7 +544,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 36 unmodified lines | |||
| 542 | } | 544 | } |
| 543 | /* define parameters */ | 545 | /* define parameters */ |
| 544 | while ((sym = sym->next) != NULL) { | 546 | while ((sym = sym->next) != NULL) { |
| 545 | n_arg++; | ||
| 546 | type = &sym->type; | 547 | type = &sym->type; |
| 547 | size = type_size(type, &align); | 548 | size = type_size(type, &align); |
| 548 | size = (size + 3) & ~3; | 549 | size = (size + 3) & ~3; |
| @@ -576,19 +577,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 27 unmodified lines | |||
| 576 | #endif | 577 | #endif |
| 577 | 578 | ||
| 578 | #ifdef CONFIG_TCC_BCHECK | 579 | #ifdef CONFIG_TCC_BCHECK |
| 579 | /* leave some room for bound checking code */ | 580 | if (tcc_state->do_bounds_check) |
| 580 | if (tcc_state->do_bounds_check) { | 581 | gen_bounds_prolog(); |
| 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 | } | ||
| 592 | #endif | 582 | #endif |
| 593 | } | 583 | } |
| 594 | 584 | ||
| @@ -598,34 +588,8 @@ ST_FUNC void gfunc_epilog(void) · 3 unmodified lines | |||
| 598 | addr_t v, saved_ind; | 588 | addr_t v, saved_ind; |
| 599 | 589 | ||
| 600 | #ifdef CONFIG_TCC_BCHECK | 590 | #ifdef CONFIG_TCC_BCHECK |
| 601 | if (tcc_state->do_bounds_check | 591 | if (tcc_state->do_bounds_check) |
| 602 | && func_bound_offset != lbounds_section->data_offset) { | 592 | gen_bounds_epilog(); |
| 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 | } | ||
| 629 | #endif | 593 | #endif |
| 630 | 594 | ||
| 631 | /* align local size to word & save local variables */ | 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 | rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i); | 1060 | rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i); |
| 1097 | rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info)); | 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 | #endif | 1100 | #endif |
| 1100 | 1101 | ||
| 1101 | /* Save the stack pointer onto the stack */ | 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 | if (addr <= tree->size) { | 353 | if (addr <= tree->size) { |
| 354 | if (tree->is_invalid || addr + offset > tree->size) { | 354 | if (tree->is_invalid || addr + offset > tree->size) { |
| 355 | POST_SEM (); | 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 | if (never_fatal <= 0) | 358 | if (never_fatal <= 0) |
| 358 | return INVALID_POINTER; /* return an invalid pointer */ | 359 | return INVALID_POINTER; /* return an invalid pointer */ |
| 359 | return p + offset; | 360 | return p + offset; |
| @@ -802,11 +802,6 @@ LIBTCCAPI TCCState *tcc_new(void) · 801 unmodified lines | |||
| 802 | tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); | 802 | tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); |
| 803 | tcc_define_symbol(s, "__STDC_HOSTED__", NULL); | 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 | /* target defines */ | 805 | /* target defines */ |
| 811 | #if defined(TCC_TARGET_I386) | 806 | #if defined(TCC_TARGET_I386) |
| 812 | tcc_define_symbol(s, "__i386__", NULL); | 807 | tcc_define_symbol(s, "__i386__", NULL); |
| @@ -1905,11 +1900,6 @@ reparse: · 1092 unmodified lines | |||
| 1905 | * encoding used is implementationdefined. | 1900 | * encoding used is implementationdefined. |
| 1906 | */ | 1901 | */ |
| 1907 | tcc_define_symbol(s, "__STDC_UTF_32__", "1"); | 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 | #endif /* !TCC_TARGET_PE */ | 1903 | #endif /* !TCC_TARGET_PE */ |
| 1914 | s->cversion = 201112; | 1904 | s->cversion = 201112; |
| 1915 | } | 1905 | } |
| @@ -884,6 +884,9 @@ struct TCCState { · 883 unmodified lines | |||
| 884 | const char *runtime_main; | 884 | const char *runtime_main; |
| 885 | void **runtime_mem; | 885 | void **runtime_mem; |
| 886 | int nb_runtime_mem; | 886 | int nb_runtime_mem; |
| 887 | #endif | ||
| 888 | |||
| 889 | #ifdef CONFIG_TCC_BACKTRACE | ||
| 887 | int rt_num_callers; | 890 | int rt_num_callers; |
| 888 | #endif | 891 | #endif |
| 889 | 892 | ||
| @@ -1387,7 +1387,11 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 1386 unmodified lines | |||
| 1387 | "__attribute__((constructor)) static void __bt_init_rt(){"); | 1387 | "__attribute__((constructor)) static void __bt_init_rt(){"); |
| 1388 | #ifdef TCC_TARGET_PE | 1388 | #ifdef TCC_TARGET_PE |
| 1389 | if (s1->output_type == TCC_OUTPUT_DLL) | 1389 | if (s1->output_type == TCC_OUTPUT_DLL) |
| 1390 | #ifdef CONFIG_TCC_BCHECK | ||
| 1390 | cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check); | 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 | #endif | 1395 | #endif |
| 1392 | cstr_printf(&cstr, "__bt_init(__rt_info,%d);}", | 1396 | cstr_printf(&cstr, "__bt_init(__rt_info,%d);}", |
| 1393 | s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1); | 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 | int def_sym; /* default symbol */ | 101 | int def_sym; /* default symbol */ |
| 102 | int *bsym; | 102 | int *bsym; |
| 103 | struct scope *scope; | 103 | struct scope *scope; |
| 104 | struct switch_t *prev; | ||
| 105 | SValue sv; | ||
| 104 | } *cur_switch; /* current switch */ | 106 | } *cur_switch; /* current switch */ |
| 105 | 107 | ||
| 106 | #define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8 | 108 | #define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8 |
| @@ -6447,6 +6449,7 @@ static void lblock(int *bsym, int *csym) · 6340 unmodified lines | |||
| 6447 | static void block(int is_expr) | 6449 | static void block(int is_expr) |
| 6448 | { | 6450 | { |
| 6449 | int a, b, c, d, e, t; | 6451 | int a, b, c, d, e, t; |
| 6452 | struct scope o; | ||
| 6450 | Sym *s; | 6453 | Sym *s; |
| 6451 | 6454 | ||
| 6452 | if (is_expr) { | 6455 | if (is_expr) { |
| @@ -6487,7 +6490,6 @@ again: · 34 unmodified lines | |||
| 6487 | gsym(a); | 6490 | gsym(a); |
| 6488 | 6491 | ||
| 6489 | } else if (t == '{') { | 6492 | } else if (t == '{') { |
| 6490 | struct scope o; | ||
| 6491 | new_scope(&o); | 6493 | new_scope(&o); |
| 6492 | 6494 | ||
| 6493 | /* handle local labels declarations */ | 6495 | /* handle local labels declarations */ |
| @@ -6545,10 +6547,10 @@ again: · 51 unmodified lines | |||
| 6545 | /* compute jump */ | 6547 | /* compute jump */ |
| 6546 | if (!cur_scope->bsym) | 6548 | if (!cur_scope->bsym) |
| 6547 | tcc_error("cannot break"); | 6549 | tcc_error("cannot break"); |
| 6548 | if (!cur_switch || cur_scope->bsym != cur_switch->bsym) | 6550 | if (cur_switch && cur_scope->bsym == cur_switch->bsym) |
| 6549 | leave_scope(loop_scope); | ||
| 6550 | else | ||
| 6551 | leave_scope(cur_switch->scope); | 6551 | leave_scope(cur_switch->scope); |
| 6552 | else | ||
| 6553 | leave_scope(loop_scope); | ||
| 6552 | *cur_scope->bsym = gjmp(*cur_scope->bsym); | 6554 | *cur_scope->bsym = gjmp(*cur_scope->bsym); |
| 6553 | skip(';'); | 6555 | skip(';'); |
| 6554 | 6556 | ||
| @@ -6561,7 +6563,6 @@ again: · 6 unmodified lines | |||
| 6561 | skip(';'); | 6563 | skip(';'); |
| 6562 | 6564 | ||
| 6563 | } else if (t == TOK_FOR) { | 6565 | } else if (t == TOK_FOR) { |
| 6564 | struct scope o; | ||
| 6565 | new_scope(&o); | 6566 | new_scope(&o); |
| 6566 | 6567 | ||
| 6567 | skip('('); | 6568 | skip('('); |
| @@ -6611,22 +6612,18 @@ again: · 43 unmodified lines | |||
| 6611 | gsym(a); | 6612 | gsym(a); |
| 6612 | 6613 | ||
| 6613 | } else if (t == TOK_SWITCH) { | 6614 | } else if (t == TOK_SWITCH) { |
| 6614 | struct switch_t *saved, sw; | 6615 | struct switch_t *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; | ||
| 6622 | 6616 | ||
| 6623 | saved = cur_switch; | 6617 | sw = tcc_mallocz(sizeof *sw); |
| 6624 | cur_switch = &sw; | 6618 | sw->bsym = &a; |
| 6619 | sw->scope = cur_scope; | ||
| 6620 | sw->prev = cur_switch; | ||
| 6621 | cur_switch = sw; | ||
| 6625 | 6622 | ||
| 6626 | skip('('); | 6623 | skip('('); |
| 6627 | gexpr(); | 6624 | gexpr(); |
| 6628 | skip(')'); | 6625 | skip(')'); |
| 6629 | switchval = *vtop--; | 6626 | sw->sv = *vtop--; /* save switch value */ |
| 6630 | 6627 | ||
| 6631 | a = 0; | 6628 | a = 0; |
| 6632 | b = gjmp(0); /* jump to first case */ | 6629 | b = gjmp(0); /* jump to first case */ |
| @@ -6635,28 +6632,29 @@ again: · 2 unmodified lines | |||
| 6635 | /* case lookup */ | 6632 | /* case lookup */ |
| 6636 | gsym(b); | 6633 | gsym(b); |
| 6637 | 6634 | ||
| 6638 | qsort(sw.p, sw.n, sizeof(void*), case_cmp); | 6635 | qsort(sw->p, sw->n, sizeof(void*), case_cmp); |
| 6639 | for (b = 1; b < sw.n; b++) | 6636 | for (b = 1; b < sw->n; b++) |
| 6640 | if (sw.p[b - 1]->v2 >= sw.p[b]->v1) | 6637 | if (sw->p[b - 1]->v2 >= sw->p[b]->v1) |
| 6641 | tcc_error("duplicate case value"); | 6638 | tcc_error("duplicate case value"); |
| 6642 | 6639 | ||
| 6643 | /* Our switch table sorting is signed, so the compared | 6640 | /* Our switch table sorting is signed, so the compared |
| 6644 | value needs to be as well when it's 64bit. */ | 6641 | value needs to be as well when it's 64bit. */ |
| 6645 | if ((switchval.type.t & VT_BTYPE) == VT_LLONG) | 6642 | vpushv(&sw->sv); |
| 6646 | switchval.type.t &= ~VT_UNSIGNED; | 6643 | if ((vtop->type.t & VT_BTYPE) == VT_LLONG) |
| 6647 | vpushv(&switchval); | 6644 | vtop->type.t &= ~VT_UNSIGNED; |
| 6648 | gv(RC_INT); | 6645 | gv(RC_INT); |
| 6649 | d = 0, gcase(sw.p, sw.n, &d); | 6646 | d = 0, gcase(sw->p, sw->n, &d); |
| 6650 | vpop(); | 6647 | vpop(); |
| 6651 | if (sw.def_sym) | 6648 | if (sw->def_sym) |
| 6652 | gsym_addr(d, sw.def_sym); | 6649 | gsym_addr(d, sw->def_sym); |
| 6653 | else | 6650 | else |
| 6654 | gsym(d); | 6651 | gsym(d); |
| 6655 | /* break label */ | 6652 | /* break label */ |
| 6656 | gsym(a); | 6653 | gsym(a); |
| 6657 | 6654 | ||
| 6658 | dynarray_reset(&sw.p, &sw.n); | 6655 | dynarray_reset(&sw->p, &sw->n); |
| 6659 | cur_switch = saved; | 6656 | cur_switch = sw->prev; |
| 6657 | tcc_free(sw); | ||
| 6660 | 6658 | ||
| 6661 | } else if (t == TOK_CASE) { | 6659 | } else if (t == TOK_CASE) { |
| 6662 | struct case_t *cr = tcc_malloc(sizeof(struct case_t)); | 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 | static void rt_exit(int code); | 48 | static void rt_exit(int code); |
| 49 | #endif /* CONFIG_TCC_BACKTRACE */ | 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 | #ifndef CONFIG_TCC_BACKTRACE_ONLY | 52 | #ifndef CONFIG_TCC_BACKTRACE_ONLY |
| 53 | 53 | ||
| 54 | #ifndef _WIN32 | 54 | #ifndef _WIN32 |
| @@ -412,15 +412,15 @@ next: · 357 unmodified lines | |||
| 412 | /* Stab_Sym.n_value is only 32bits */ | 412 | /* Stab_Sym.n_value is only 32bits */ |
| 413 | pc += rc->prog_base; | 413 | pc += rc->prog_base; |
| 414 | #endif | 414 | #endif |
| 415 | break; | 415 | goto check_pc; |
| 416 | rel_pc: | 416 | rel_pc: |
| 417 | pc += func_addr; | 417 | pc += func_addr; |
| 418 | check_pc: | ||
| 419 | if (pc >= wanted_pc && wanted_pc >= last_pc) | ||
| 420 | goto found; | ||
| 418 | break; | 421 | break; |
| 419 | } | 422 | } |
| 420 | 423 | ||
| 421 | if (pc >= wanted_pc && wanted_pc >= last_pc) | ||
| 422 | goto found; | ||
| 423 | |||
| 424 | switch(sym->n_type) { | 424 | switch(sym->n_type) { |
| 425 | /* function start or end */ | 425 | /* function start or end */ |
| 426 | case N_FUN: | 426 | case N_FUN: |
| @@ -12,8 +12,6 @@ · 11 unmodified lines | |||
| 12 | [test_bcheck_1] | 12 | [test_bcheck_1] |
| 13 | * main | 13 | * main |
| 14 | * f1() | 14 | * f1() |
| 15 | 112_backtrace.c:38: at f1: BCHECK: ........ is outside of the region | ||
| 16 | 112_backtrace.c:43: by main | ||
| 17 | 112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest | 15 | 112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest |
| 18 | 112_backtrace.c:43: by main | 16 | 112_backtrace.c:43: by main |
| 19 | [returns 255] | 17 | [returns 255] |
| @@ -32,12 +30,10 @@ · 12 unmodified lines | |||
| 32 | [returns 1] | 30 | [returns 1] |
| 33 | 31 | ||
| 34 | [test_bcheck_100] | 32 | [test_bcheck_100] |
| 35 | 112_backtrace.c:107: at main: BCHECK: ........ is outside of the region | ||
| 36 | 112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest | 33 | 112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest |
| 37 | [returns 255] | 34 | [returns 255] |
| 38 | 35 | ||
| 39 | [test_bcheck_101] | 36 | [test_bcheck_101] |
| 40 | 112_backtrace.c:109: at main: BCHECK: ........ is outside of the region | ||
| 41 | 112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src | 37 | 112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src |
| 42 | [returns 255] | 38 | [returns 255] |
| 43 | 39 | ||
| @@ -50,42 +46,34 @@ · 6 unmodified lines | |||
| 50 | [returns 255] | 46 | [returns 255] |
| 51 | 47 | ||
| 52 | [test_bcheck_104] | 48 | [test_bcheck_104] |
| 53 | 112_backtrace.c:115: at main: BCHECK: ........ is outside of the region | ||
| 54 | 112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1 | 49 | 112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1 |
| 55 | [returns 255] | 50 | [returns 255] |
| 56 | 51 | ||
| 57 | [test_bcheck_105] | 52 | [test_bcheck_105] |
| 58 | 112_backtrace.c:117: at main: BCHECK: ........ is outside of the region | ||
| 59 | 112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2 | 53 | 112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2 |
| 60 | [returns 255] | 54 | [returns 255] |
| 61 | 55 | ||
| 62 | [test_bcheck_106] | 56 | [test_bcheck_106] |
| 63 | 112_backtrace.c:119: at main: BCHECK: ........ is outside of the region | ||
| 64 | 112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest | 57 | 112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest |
| 65 | [returns 255] | 58 | [returns 255] |
| 66 | 59 | ||
| 67 | [test_bcheck_107] | 60 | [test_bcheck_107] |
| 68 | 112_backtrace.c:121: at main: BCHECK: ........ is outside of the region | ||
| 69 | 112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src | 61 | 112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src |
| 70 | [returns 255] | 62 | [returns 255] |
| 71 | 63 | ||
| 72 | [test_bcheck_108] | 64 | [test_bcheck_108] |
| 73 | 112_backtrace.c:123: at main: BCHECK: ........ is outside of the region | ||
| 74 | 112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset | 65 | 112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset |
| 75 | [returns 255] | 66 | [returns 255] |
| 76 | 67 | ||
| 77 | [test_bcheck_109] | 68 | [test_bcheck_109] |
| 78 | 112_backtrace.c:125: at main: BCHECK: ........ is outside of the region | ||
| 79 | 112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen | 69 | 112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen |
| 80 | [returns 255] | 70 | [returns 255] |
| 81 | 71 | ||
| 82 | [test_bcheck_110] | 72 | [test_bcheck_110] |
| 83 | 112_backtrace.c:127: at main: BCHECK: ........ is outside of the region | ||
| 84 | 112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest | 73 | 112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest |
| 85 | [returns 255] | 74 | [returns 255] |
| 86 | 75 | ||
| 87 | [test_bcheck_111] | 76 | [test_bcheck_111] |
| 88 | 112_backtrace.c:129: at main: BCHECK: ........ is outside of the region | ||
| 89 | 112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src | 77 | 112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src |
| 90 | [returns 255] | 78 | [returns 255] |
| 91 | 79 | ||
| @@ -98,12 +86,10 @@ · 6 unmodified lines | |||
| 98 | [returns 255] | 86 | [returns 255] |
| 99 | 87 | ||
| 100 | [test_bcheck_114] | 88 | [test_bcheck_114] |
| 101 | 112_backtrace.c:135: at main: BCHECK: ........ is outside of the region | ||
| 102 | 112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest | 89 | 112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest |
| 103 | [returns 255] | 90 | [returns 255] |
| 104 | 91 | ||
| 105 | [test_bcheck_115] | 92 | [test_bcheck_115] |
| 106 | 112_backtrace.c:137: at main: BCHECK: ........ is outside of the region | ||
| 107 | 112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src | 93 | 112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src |
| 108 | [returns 255] | 94 | [returns 255] |
| 109 | 95 | ||
| @@ -116,32 +102,26 @@ · 6 unmodified lines | |||
| 116 | [returns 255] | 102 | [returns 255] |
| 117 | 103 | ||
| 118 | [test_bcheck_118] | 104 | [test_bcheck_118] |
| 119 | 112_backtrace.c:143: at main: BCHECK: ........ is outside of the region | ||
| 120 | 112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1 | 105 | 112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1 |
| 121 | [returns 255] | 106 | [returns 255] |
| 122 | 107 | ||
| 123 | [test_bcheck_119] | 108 | [test_bcheck_119] |
| 124 | 112_backtrace.c:145: at main: BCHECK: ........ is outside of the region | ||
| 125 | 112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2 | 109 | 112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2 |
| 126 | [returns 255] | 110 | [returns 255] |
| 127 | 111 | ||
| 128 | [test_bcheck_120] | 112 | [test_bcheck_120] |
| 129 | 112_backtrace.c:147: at main: BCHECK: ........ is outside of the region | ||
| 130 | 112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1 | 113 | 112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1 |
| 131 | [returns 255] | 114 | [returns 255] |
| 132 | 115 | ||
| 133 | [test_bcheck_121] | 116 | [test_bcheck_121] |
| 134 | 112_backtrace.c:149: at main: BCHECK: ........ is outside of the region | ||
| 135 | 112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2 | 117 | 112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2 |
| 136 | [returns 255] | 118 | [returns 255] |
| 137 | 119 | ||
| 138 | [test_bcheck_122] | 120 | [test_bcheck_122] |
| 139 | 112_backtrace.c:151: at main: BCHECK: ........ is outside of the region | ||
| 140 | 112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest | 121 | 112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest |
| 141 | [returns 255] | 122 | [returns 255] |
| 142 | 123 | ||
| 143 | [test_bcheck_123] | 124 | [test_bcheck_123] |
| 144 | 112_backtrace.c:153: at main: BCHECK: ........ is outside of the region | ||
| 145 | 112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest | 125 | 112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest |
| 146 | [returns 255] | 126 | [returns 255] |
| 147 | 127 | ||
| @@ -154,11 +134,9 @@ · 6 unmodified lines | |||
| 154 | [returns 255] | 134 | [returns 255] |
| 155 | 135 | ||
| 156 | [test_bcheck_126] | 136 | [test_bcheck_126] |
| 157 | 112_backtrace.c:159: at main: BCHECK: ........ is outside of the region | ||
| 158 | 112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strchr | 137 | 112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strchr |
| 159 | [returns 255] | 138 | [returns 255] |
| 160 | 139 | ||
| 161 | [test_bcheck_127] | 140 | [test_bcheck_127] |
| 162 | 112_backtrace.c:161: at main: BCHECK: ........ is outside of the region | ||
| 163 | 112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strdup | 141 | 112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strdup |
| 164 | [returns 255] | 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 | endif | 24 | endif |
| 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) | 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) |
| 26 | SKIP += 85_asm-outside-function.test | 26 | SKIP += 85_asm-outside-function.test |
| 27 | SKIP += 112_backtrace.test | 27 | SKIP += 112_backtrace.test 113_btdll.test |
| 28 | endif | 28 | endif |
| 29 | ifeq (-$(findstring gcc,$(CC))-,--) | 29 | ifeq (-$(findstring gcc,$(CC))-,--) |
| 30 | SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) | 30 | SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) |
| @@ -61,7 +61,7 @@ GEN-ALWAYS = · 30 unmodified lines | |||
| 61 | 95_bitfields_ms.test : GEN = $(GEN-MSC) | 61 | 95_bitfields_ms.test : GEN = $(GEN-MSC) |
| 62 | 62 | ||
| 63 | # this test compiles/links two files: | 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 | 104_inline.test : GEN = $(GEN-TCC) | 65 | 104_inline.test : GEN = $(GEN-TCC) |
| 66 | 66 | ||
| 67 | # this test needs pthread | 67 | # this test needs pthread |
| @@ -72,7 +72,16 @@ GEN-ALWAYS = · 4 unmodified lines | |||
| 72 | 108_constructor.test: NORUN = true | 72 | 108_constructor.test: NORUN = true |
| 73 | 73 | ||
| 74 | 112_backtrace.test: FLAGS += -dt -b | 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 | # Filter source directory in warnings/errors (out-of-tree builds) | 86 | # Filter source directory in warnings/errors (out-of-tree builds) |
| 78 | FILTER = 2>&1 | sed -e 's,$(SRC)/,,g' | 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 | %.test: %.c %.expect | 91 | %.test: %.c %.expect |
| 83 | @echo Test: $*... | 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) | 95 | T1 = $(TCC) $(FLAGS) $(T2) $(ARGS) |
| 87 | T2 = $(TCC) $(FLAGS) -run $< $(ARGS) | 96 | T2 = $(if $(NORUN),$1 -o a.exe && ./a.exe,-run $1) |
| 88 | T3 = $(FILTER) >$*.output 2>&1 || true \ | 97 | T3 = $(FILTER) >$*.output 2>&1 || true \ |
| 89 | && diff -Nbu $(filter %.expect,$^) $*.output \ | 98 | && diff -Nbu $(filter %.expect,$^) $*.output \ |
| 90 | && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) | 99 | && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) |
| @@ -95,7 +104,7 @@ tests2.%+: · 4 unmodified lines | |||
| 95 | 104 | ||
| 96 | # just run tcc to see the output, e.g. "make tests2.37-" | 105 | # just run tcc to see the output, e.g. "make tests2.37-" |
| 97 | tests2.%-: | 106 | tests2.%-: |
| 98 | @$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory | 107 | @$(MAKE) $(call F1,$*) T3= --no-print-directory |
| 99 | 108 | ||
| 100 | # run single test, e.g. "make tests2.37" | 109 | # run single test, e.g. "make tests2.37" |
| 101 | tests2.%: | 110 | tests2.%: |
| @@ -111,9 +120,9 @@ F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" · 9 unmodified lines | |||
| 111 | @rm -f *.exe *.obj *.pdb | 120 | @rm -f *.exe *.obj *.pdb |
| 112 | 121 | ||
| 113 | # using TCC for .expect if -dt in FLAGS | 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 | GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o a.exe && ./a.exe $(ARGS) | 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 | GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe | 126 | GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe |
| 118 | MS-CC = cl | 127 | MS-CC = cl |
| 119 | 128 | ||
| @@ -124,5 +133,5 @@ MS-CC = cl · 4 unmodified lines | |||
| 124 | $(sort $(GEN-ALWAYS) $(UPDATE)) : force | 133 | $(sort $(GEN-ALWAYS) $(UPDATE)) : force |
| 125 | force: | 134 | force: |
| 126 | 135 | ||
| 127 | clean: | 136 | clean tests2.clean : |
| 128 | rm -f fred.txt *.output a.exe $(GEN-ALWAYS) | 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 | .\tcc -m64 -c ../lib/alloca86_64-bt.S | 163 | .\tcc -m64 -c ../lib/alloca86_64-bt.S |
| 164 | .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o | 164 | .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o |
| 165 | @if errorlevel 1 goto :the_end | 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 | .\tcc -m%T% -c ../lib/bt-exe.c -o lib/bt-exe.o | 167 | .\tcc -m%T% -c ../lib/bt-exe.c -o lib/bt-exe.o |
| 168 | .\tcc -m%T% -c ../lib/bt-log.c -o lib/bt-log.o | 168 | .\tcc -m%T% -c ../lib/bt-log.c -o lib/bt-log.o |
| 169 | .\tcc -m%T% -c ../lib/bt-dll.c -o lib/bt-dll.o | 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 | rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i); | 701 | rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i); |
| 702 | rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info)); | 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 | #endif | 749 | #endif |
| 705 | 750 | ||
| 706 | #ifdef TCC_TARGET_PE | 751 | #ifdef TCC_TARGET_PE |
| 707 | 752 | ||
| 753 | static int func_scratch, func_alloca; | ||
| 754 | |||
| 708 | #define REGN 4 | 755 | #define REGN 4 |
| 709 | static const uint8_t arg_regs[REGN] = { | 756 | static const uint8_t arg_regs[REGN] = { |
| 710 | TREG_RCX, TREG_RDX, TREG_R8, TREG_R9 | 757 | TREG_RCX, TREG_RDX, TREG_R8, TREG_R9 |
| @@ -720,8 +767,6 @@ static int arg_prepare_reg(int idx) { · 9 unmodified lines | |||
| 720 | return arg_regs[idx]; | 767 | return arg_regs[idx]; |
| 721 | } | 768 | } |
| 722 | 769 | ||
| 723 | static int func_scratch, func_alloca; | ||
| 724 | |||
| 725 | /* Generate function call. The function address is pushed first, then | 770 | /* Generate function call. The function address is pushed first, then |
| 726 | all the parameters in call order. This functions pops all the | 771 | all the parameters in call order. This functions pops all the |
| 727 | parameters and the function address. */ | 772 | parameters and the function address. */ |
| @@ -918,7 +963,6 @@ void gfunc_prolog(Sym *func_sym) · 190 unmodified lines | |||
| 918 | int addr, reg_param_index, bt, size; | 963 | int addr, reg_param_index, bt, size; |
| 919 | Sym *sym; | 964 | Sym *sym; |
| 920 | CType *type; | 965 | CType *type; |
| 921 | int n_arg = 0; | ||
| 922 | 966 | ||
| 923 | func_ret_sub = 0; | 967 | func_ret_sub = 0; |
| 924 | func_scratch = 32; | 968 | func_scratch = 32; |
| @@ -946,7 +990,6 @@ void gfunc_prolog(Sym *func_sym) · 21 unmodified lines | |||
| 946 | 990 | ||
| 947 | /* define parameters */ | 991 | /* define parameters */ |
| 948 | while ((sym = sym->next) != NULL) { | 992 | while ((sym = sym->next) != NULL) { |
| 949 | n_arg++; | ||
| 950 | type = &sym->type; | 993 | type = &sym->type; |
| 951 | bt = type->t & VT_BTYPE; | 994 | bt = type->t & VT_BTYPE; |
| 952 | size = gfunc_arg_size(type); | 995 | size = gfunc_arg_size(type); |
| @@ -983,23 +1026,8 @@ void gfunc_prolog(Sym *func_sym) · 30 unmodified lines | |||
| 983 | reg_param_index++; | 1026 | reg_param_index++; |
| 984 | } | 1027 | } |
| 985 | #ifdef CONFIG_TCC_BCHECK | 1028 | #ifdef CONFIG_TCC_BCHECK |
| 986 | /* leave some room for bound checking code */ | 1029 | if (tcc_state->do_bounds_check) |
| 987 | if (tcc_state->do_bounds_check) { | 1030 | gen_bounds_prolog(); |
| 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 | } | ||
| 1003 | #endif | 1031 | #endif |
| 1004 | } | 1032 | } |
| 1005 | 1033 | ||
| @@ -1013,39 +1041,10 @@ void gfunc_epilog(void) · 7 unmodified lines | |||
| 1013 | loc = (loc & -16) - func_scratch; | 1041 | loc = (loc & -16) - func_scratch; |
| 1014 | 1042 | ||
| 1015 | #ifdef CONFIG_TCC_BCHECK | 1043 | #ifdef CONFIG_TCC_BCHECK |
| 1016 | if (tcc_state->do_bounds_check | 1044 | if (tcc_state->do_bounds_check) |
| 1017 | && func_bound_offset != lbounds_section->data_offset) | 1045 | gen_bounds_epilog(); |
| 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 | } | ||
| 1048 | #endif | 1046 | #endif |
| 1047 | |||
| 1049 | o(0xc9); /* leave */ | 1048 | o(0xc9); /* leave */ |
| 1050 | if (func_ret_sub == 0) { | 1049 | if (func_ret_sub == 0) { |
| 1051 | o(0xc3); /* ret */ | 1050 | o(0xc3); /* ret */ |
| @@ -1469,7 +1468,6 @@ void gfunc_prolog(Sym *func_sym) · 417 unmodified lines | |||
| 1469 | X86_64_Mode mode; | 1468 | X86_64_Mode mode; |
| 1470 | int i, addr, align, size, reg_count; | 1469 | int i, addr, align, size, reg_count; |
| 1471 | int param_addr = 0, reg_param_index, sse_param_index; | 1470 | int param_addr = 0, reg_param_index, sse_param_index; |
| 1472 | int n_arg = 0; | ||
| 1473 | Sym *sym; | 1471 | Sym *sym; |
| 1474 | CType *type; | 1472 | CType *type; |
| 1475 | 1473 | ||
| @@ -1553,7 +1551,6 @@ void gfunc_prolog(Sym *func_sym) · 77 unmodified lines | |||
| 1553 | } | 1551 | } |
| 1554 | /* define parameters */ | 1552 | /* define parameters */ |
| 1555 | while ((sym = sym->next) != NULL) { | 1553 | while ((sym = sym->next) != NULL) { |
| 1556 | n_arg++; | ||
| 1557 | type = &sym->type; | 1554 | type = &sym->type; |
| 1558 | mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); | 1555 | mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); |
| 1559 | switch (mode) { | 1556 | switch (mode) { |
| @@ -1606,19 +1603,8 @@ void gfunc_prolog(Sym *func_sym) · 46 unmodified lines | |||
| 1606 | } | 1603 | } |
| 1607 | 1604 | ||
| 1608 | #ifdef CONFIG_TCC_BCHECK | 1605 | #ifdef CONFIG_TCC_BCHECK |
| 1609 | /* leave some room for bound checking code */ | 1606 | if (tcc_state->do_bounds_check) |
| 1610 | if (tcc_state->do_bounds_check) { | 1607 | gen_bounds_prolog(); |
| 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 | } | ||
| 1622 | #endif | 1608 | #endif |
| 1623 | } | 1609 | } |
| 1624 | 1610 | ||
| @@ -1628,36 +1614,8 @@ void gfunc_epilog(void) · 3 unmodified lines | |||
| 1628 | int v, saved_ind; | 1614 | int v, saved_ind; |
| 1629 | 1615 | ||
| 1630 | #ifdef CONFIG_TCC_BCHECK | 1616 | #ifdef CONFIG_TCC_BCHECK |
| 1631 | if (tcc_state->do_bounds_check | 1617 | if (tcc_state->do_bounds_check) |
| 1632 | && func_bound_offset != lbounds_section->data_offset) | 1618 | gen_bounds_epilog(); |
| 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 | } | ||
| 1661 | #endif | 1619 | #endif |
| 1662 | o(0xc9); /* leave */ | 1620 | o(0xc9); /* leave */ |
| 1663 | if (func_ret_sub == 0) { | 1621 | if (func_ret_sub == 0) { |