History

backtrace: test with DLLs

- 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 == '-') ...

grischka committed 6 years ago

Commit d79e1de1 parent a5f6e6113 files · +209 −218Browse files

Unified · Split

13 files
  1. i386-gen.c +44 −43
  2. lib/bcheck.c +2 −1
  3. libtcc.c +0 −10
  4. tcc.h +3 −0
  5. tccelf.c +4 −0
  6. tccgen.c +25 −27
  7. tccrun.c +5 −5
  8. tests/tests2/112_backtrace.expect +0 −22
  9. tests/tests2/113_btdll.c +43 −0
  10. tests/tests2/113_btdll.expect +6 −0
  11. tests/tests2/Makefile +20 −11
  12. win32/build-tcc.bat +1 −1
  13. x86_64-gen.c +56 −98
i386-gen.c+44−43
@@ -97,6 +97,8 @@ static int func_ret_sub; · 96 unmodified lines
9797 #ifdef CONFIG_TCC_BCHECK
9898 static addr_t func_bound_offset;
9999 static unsigned long func_bound_ind;
100+static void gen_bounds_prolog(void);
101+static void gen_bounds_epilog(void);
100102 #endif
101103
102104 /* XXX: make it faster ? */
@@ -480,6 +482,7 @@ ST_FUNC void gfunc_call(int nb_args) · 377 unmodified lines
480482 else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT)
481483 args_size -= 4;
482484 #endif
485+
483486 gcall_or_jmp(0);
484487
485488 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
499502 CType *func_type = &func_sym->type;
500503 int addr, align, size, func_call, fastcall_nb_regs;
501504 int param_index, param_addr;
502− int n_arg = 0;
503505 uint8_t *fastcall_regs_ptr;
504506 Sym *sym;
505507 CType *type;
@@ -542,7 +544,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 36 unmodified lines
542544 }
543545 /* define parameters */
544546 while ((sym = sym->next) != NULL) {
545− n_arg++;
546547 type = &sym->type;
547548 size = type_size(type, &align);
548549 size = (size + 3) & ~3;
@@ -576,19 +577,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 27 unmodified lines
576577 #endif
577578
578579 #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();
592582 #endif
593583 }
594584
@@ -598,34 +588,8 @@ ST_FUNC void gfunc_epilog(void) · 3 unmodified lines
598588 addr_t v, saved_ind;
599589
600590 #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();
629593 #endif
630594
631595 /* align local size to word & save local variables */
@@ -1096,6 +1060,43 @@ ST_FUNC void gen_bounded_ptr_deref(void) · 464 unmodified lines
10961060 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i);
10971061 rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
10981062 }
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+}
10991100 #endif
11001101
11011102 /* Save the stack pointer onto the stack */
lib/bcheck.c+2−1
@@ -353,7 +353,8 @@ void * __bound_ptr_add(void *p, size_t offset) · 352 unmodified lines
353353 if (addr <= tree->size) {
354354 if (tree->is_invalid || addr + offset > tree->size) {
355355 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);
357358 if (never_fatal <= 0)
358359 return INVALID_POINTER; /* return an invalid pointer */
359360 return p + offset;
libtcc.c+0−10
@@ -802,11 +802,6 @@ LIBTCCAPI TCCState *tcc_new(void) · 801 unmodified lines
802802 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
803803 tcc_define_symbol(s, "__STDC_HOSTED__", NULL);
804804
805−#if !defined(TCC_TARGET_PE)
806− /* glibc compatible macro (default for C99) */
807− tcc_define_symbol(s, "_ISOC99_SOURCE", "1");
808−#endif
809−
810805 /* target defines */
811806 #if defined(TCC_TARGET_I386)
812807 tcc_define_symbol(s, "__i386__", NULL);
@@ -1905,11 +1900,6 @@ reparse: · 1092 unmodified lines
19051900 * encoding used is implementationdefined.
19061901 */
19071902 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");
19131903 #endif /* !TCC_TARGET_PE */
19141904 s->cversion = 201112;
19151905 }
tcc.h+3−0
@@ -884,6 +884,9 @@ struct TCCState { · 883 unmodified lines
884884 const char *runtime_main;
885885 void **runtime_mem;
886886 int nb_runtime_mem;
887+#endif
888+
889+#ifdef CONFIG_TCC_BACKTRACE
887890 int rt_num_callers;
888891 #endif
889892
tccelf.c+4−0
@@ -1387,7 +1387,11 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 1386 unmodified lines
13871387 "__attribute__((constructor)) static void __bt_init_rt(){");
13881388 #ifdef TCC_TARGET_PE
13891389 if (s1->output_type == TCC_OUTPUT_DLL)
1390+#ifdef CONFIG_TCC_BCHECK
13901391 cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check);
1392+#else
1393+ cstr_printf(&cstr, "__bt_init_dll(0);");
1394+#endif
13911395 #endif
13921396 cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
13931397 s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);
tccgen.c+25−27
@@ -101,6 +101,8 @@ ST_DATA struct switch_t { · 100 unmodified lines
101101 int def_sym; /* default symbol */
102102 int *bsym;
103103 struct scope *scope;
104+ struct switch_t *prev;
105+ SValue sv;
104106 } *cur_switch; /* current switch */
105107
106108 #define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8
@@ -6447,6 +6449,7 @@ static void lblock(int *bsym, int *csym) · 6340 unmodified lines
64476449 static void block(int is_expr)
64486450 {
64496451 int a, b, c, d, e, t;
6452+ struct scope o;
64506453 Sym *s;
64516454
64526455 if (is_expr) {
@@ -6487,7 +6490,6 @@ again: · 34 unmodified lines
64876490 gsym(a);
64886491
64896492 } else if (t == '{') {
6490− struct scope o;
64916493 new_scope(&o);
64926494
64936495 /* handle local labels declarations */
@@ -6545,10 +6547,10 @@ again: · 51 unmodified lines
65456547 /* compute jump */
65466548 if (!cur_scope->bsym)
65476549 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)
65516551 leave_scope(cur_switch->scope);
6552+ else
6553+ leave_scope(loop_scope);
65526554 *cur_scope->bsym = gjmp(*cur_scope->bsym);
65536555 skip(';');
65546556
@@ -6561,7 +6563,6 @@ again: · 6 unmodified lines
65616563 skip(';');
65626564
65636565 } else if (t == TOK_FOR) {
6564− struct scope o;
65656566 new_scope(&o);
65666567
65676568 skip('(');
@@ -6611,22 +6612,18 @@ again: · 43 unmodified lines
66116612 gsym(a);
66126613
66136614 } 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;
66226616
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;
66256622
66266623 skip('(');
66276624 gexpr();
66286625 skip(')');
6629− switchval = *vtop--;
6626+ sw->sv = *vtop--; /* save switch value */
66306627
66316628 a = 0;
66326629 b = gjmp(0); /* jump to first case */
@@ -6635,28 +6632,29 @@ again: · 2 unmodified lines
66356632 /* case lookup */
66366633 gsym(b);
66376634
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)
66416638 tcc_error("duplicate case value");
66426639
66436640 /* Our switch table sorting is signed, so the compared
66446641 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;
66486645 gv(RC_INT);
6649− d = 0, gcase(sw.p, sw.n, &d);
6646+ d = 0, gcase(sw->p, sw->n, &d);
66506647 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);
66536650 else
66546651 gsym(d);
66556652 /* break label */
66566653 gsym(a);
66576654
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);
66606658
66616659 } else if (t == TOK_CASE) {
66626660 struct case_t *cr = tcc_malloc(sizeof(struct case_t));
tccrun.c+5−5
@@ -48,7 +48,7 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); · 47 unmodified lines
4848 static void rt_exit(int code);
4949 #endif /* CONFIG_TCC_BACKTRACE */
5050
51−/* defined when included from lib/bt.c */
51+/* defined when included from lib/bt-exe.c */
5252 #ifndef CONFIG_TCC_BACKTRACE_ONLY
5353
5454 #ifndef _WIN32
@@ -412,15 +412,15 @@ next: · 357 unmodified lines
412412 /* Stab_Sym.n_value is only 32bits */
413413 pc += rc->prog_base;
414414 #endif
415− break;
415+ goto check_pc;
416416 rel_pc:
417417 pc += func_addr;
418+ check_pc:
419+ if (pc >= wanted_pc && wanted_pc >= last_pc)
420+ goto found;
418421 break;
419422 }
420423
421− if (pc >= wanted_pc && wanted_pc >= last_pc)
422− goto found;
423−
424424 switch(sym->n_type) {
425425 /* function start or end */
426426 case N_FUN:
tests/tests2/112_backtrace.expect+0−22
@@ -12,8 +12,6 @@ · 11 unmodified lines
1212 [test_bcheck_1]
1313 * main
1414 * f1()
15−112_backtrace.c:38: at f1: BCHECK: ........ is outside of the region
16−112_backtrace.c:43: by main
1715 112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest
1816 112_backtrace.c:43: by main
1917 [returns 255]
@@ -32,12 +30,10 @@ · 12 unmodified lines
3230 [returns 1]
3331
3432 [test_bcheck_100]
35−112_backtrace.c:107: at main: BCHECK: ........ is outside of the region
3633 112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest
3734 [returns 255]
3835
3936 [test_bcheck_101]
40−112_backtrace.c:109: at main: BCHECK: ........ is outside of the region
4137 112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src
4238 [returns 255]
4339
@@ -50,42 +46,34 @@ · 6 unmodified lines
5046 [returns 255]
5147
5248 [test_bcheck_104]
53−112_backtrace.c:115: at main: BCHECK: ........ is outside of the region
5449 112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1
5550 [returns 255]
5651
5752 [test_bcheck_105]
58−112_backtrace.c:117: at main: BCHECK: ........ is outside of the region
5953 112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2
6054 [returns 255]
6155
6256 [test_bcheck_106]
63−112_backtrace.c:119: at main: BCHECK: ........ is outside of the region
6457 112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest
6558 [returns 255]
6659
6760 [test_bcheck_107]
68−112_backtrace.c:121: at main: BCHECK: ........ is outside of the region
6961 112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src
7062 [returns 255]
7163
7264 [test_bcheck_108]
73−112_backtrace.c:123: at main: BCHECK: ........ is outside of the region
7465 112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset
7566 [returns 255]
7667
7768 [test_bcheck_109]
78−112_backtrace.c:125: at main: BCHECK: ........ is outside of the region
7969 112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen
8070 [returns 255]
8171
8272 [test_bcheck_110]
83−112_backtrace.c:127: at main: BCHECK: ........ is outside of the region
8473 112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest
8574 [returns 255]
8675
8776 [test_bcheck_111]
88−112_backtrace.c:129: at main: BCHECK: ........ is outside of the region
8977 112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src
9078 [returns 255]
9179
@@ -98,12 +86,10 @@ · 6 unmodified lines
9886 [returns 255]
9987
10088 [test_bcheck_114]
101−112_backtrace.c:135: at main: BCHECK: ........ is outside of the region
10289 112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest
10390 [returns 255]
10491
10592 [test_bcheck_115]
106−112_backtrace.c:137: at main: BCHECK: ........ is outside of the region
10793 112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src
10894 [returns 255]
10995
@@ -116,32 +102,26 @@ · 6 unmodified lines
116102 [returns 255]
117103
118104 [test_bcheck_118]
119−112_backtrace.c:143: at main: BCHECK: ........ is outside of the region
120105 112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1
121106 [returns 255]
122107
123108 [test_bcheck_119]
124−112_backtrace.c:145: at main: BCHECK: ........ is outside of the region
125109 112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2
126110 [returns 255]
127111
128112 [test_bcheck_120]
129−112_backtrace.c:147: at main: BCHECK: ........ is outside of the region
130113 112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1
131114 [returns 255]
132115
133116 [test_bcheck_121]
134−112_backtrace.c:149: at main: BCHECK: ........ is outside of the region
135117 112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2
136118 [returns 255]
137119
138120 [test_bcheck_122]
139−112_backtrace.c:151: at main: BCHECK: ........ is outside of the region
140121 112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest
141122 [returns 255]
142123
143124 [test_bcheck_123]
144−112_backtrace.c:153: at main: BCHECK: ........ is outside of the region
145125 112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest
146126 [returns 255]
147127
@@ -154,11 +134,9 @@ · 6 unmodified lines
154134 [returns 255]
155135
156136 [test_bcheck_126]
157−112_backtrace.c:159: at main: BCHECK: ........ is outside of the region
158137 112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strchr
159138 [returns 255]
160139
161140 [test_bcheck_127]
162−112_backtrace.c:161: at main: BCHECK: ........ is outside of the region
163141 112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strdup
164142 [returns 255]
tests/tests2/113_btdll.c+43−0
@@ -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
tests/tests2/113_btdll.expect+6−0
@@ -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
tests/tests2/Makefile+20−11
@@ -24,7 +24,7 @@ ifeq (,$(filter i386,$(ARCH))) · 23 unmodified lines
2424 endif
2525 ifeq (,$(filter i386 x86_64,$(ARCH)))
2626 SKIP += 85_asm-outside-function.test
27− SKIP += 112_backtrace.test
27+ SKIP += 112_backtrace.test 113_btdll.test
2828 endif
2929 ifeq (-$(findstring gcc,$(CC))-,--)
3030 SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
@@ -61,7 +61,7 @@ GEN-ALWAYS = · 30 unmodified lines
6161 95_bitfields_ms.test : GEN = $(GEN-MSC)
6262
6363 # this test compiles/links two files:
64−104_inline.test : FLAGS += $(SRC)/104+_inline.c
64+104_inline.test : FLAGS += $(subst 104,104+,$1)
6565 104_inline.test : GEN = $(GEN-TCC)
6666
6767 # this test needs pthread
@@ -72,7 +72,16 @@ GEN-ALWAYS = · 4 unmodified lines
7272 108_constructor.test: NORUN = true
7373
7474 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=.
7685
7786 # Filter source directory in warnings/errors (out-of-tree builds)
7887 FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
@@ -81,10 +90,10 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; · 2 unmodified lines
8190
8291 %.test: %.c %.expect
8392 @echo Test: $*...
84− @$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3))
93+ @$(call T1,$<) $(T3)
8594
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)
8897 T3 = $(FILTER) >$*.output 2>&1 || true \
8998 && diff -Nbu $(filter %.expect,$^) $*.output \
9099 && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
@@ -95,7 +104,7 @@ tests2.%+: · 4 unmodified lines
95104
96105 # just run tcc to see the output, e.g. "make tests2.37-"
97106 tests2.%-:
98− @$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory
107+ @$(MAKE) $(call F1,$*) T3= --no-print-directory
99108
100109 # run single test, e.g. "make tests2.37"
101110 tests2.%:
@@ -111,9 +120,9 @@ F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" · 9 unmodified lines
111120 @rm -f *.exe *.obj *.pdb
112121
113122 # 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))
115124 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)
117126 GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe
118127 MS-CC = cl
119128
@@ -124,5 +133,5 @@ MS-CC = cl · 4 unmodified lines
124133 $(sort $(GEN-ALWAYS) $(UPDATE)) : force
125134 force:
126135
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)
win32/build-tcc.bat+1−1
@@ -163,7 +163,7 @@ copy>nul tcc-win32.txt doc · 162 unmodified lines
163163 .\tcc -m64 -c ../lib/alloca86_64-bt.S
164164 .\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o
165165 @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
167167 .\tcc -m%T% -c ../lib/bt-exe.c -o lib/bt-exe.o
168168 .\tcc -m%T% -c ../lib/bt-log.c -o lib/bt-log.o
169169 .\tcc -m%T% -c ../lib/bt-dll.c -o lib/bt-dll.o
x86_64-gen.c+56−98
@@ -701,10 +701,57 @@ ST_FUNC void gen_bounded_ptr_deref(void) · 700 unmodified lines
701701 rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i);
702702 rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
703703 }
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+}
704749 #endif
705750
706751 #ifdef TCC_TARGET_PE
707752
753+static int func_scratch, func_alloca;
754+
708755 #define REGN 4
709756 static const uint8_t arg_regs[REGN] = {
710757 TREG_RCX, TREG_RDX, TREG_R8, TREG_R9
@@ -720,8 +767,6 @@ static int arg_prepare_reg(int idx) { · 9 unmodified lines
720767 return arg_regs[idx];
721768 }
722769
723−static int func_scratch, func_alloca;
724−
725770 /* Generate function call. The function address is pushed first, then
726771 all the parameters in call order. This functions pops all the
727772 parameters and the function address. */
@@ -918,7 +963,6 @@ void gfunc_prolog(Sym *func_sym) · 190 unmodified lines
918963 int addr, reg_param_index, bt, size;
919964 Sym *sym;
920965 CType *type;
921− int n_arg = 0;
922966
923967 func_ret_sub = 0;
924968 func_scratch = 32;
@@ -946,7 +990,6 @@ void gfunc_prolog(Sym *func_sym) · 21 unmodified lines
946990
947991 /* define parameters */
948992 while ((sym = sym->next) != NULL) {
949− n_arg++;
950993 type = &sym->type;
951994 bt = type->t & VT_BTYPE;
952995 size = gfunc_arg_size(type);
@@ -983,23 +1026,8 @@ void gfunc_prolog(Sym *func_sym) · 30 unmodified lines
9831026 reg_param_index++;
9841027 }
9851028 #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();
10031031 #endif
10041032 }
10051033
@@ -1013,39 +1041,10 @@ void gfunc_epilog(void) · 7 unmodified lines
10131041 loc = (loc & -16) - func_scratch;
10141042
10151043 #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();
10481046 #endif
1047+
10491048 o(0xc9); /* leave */
10501049 if (func_ret_sub == 0) {
10511050 o(0xc3); /* ret */
@@ -1469,7 +1468,6 @@ void gfunc_prolog(Sym *func_sym) · 417 unmodified lines
14691468 X86_64_Mode mode;
14701469 int i, addr, align, size, reg_count;
14711470 int param_addr = 0, reg_param_index, sse_param_index;
1472− int n_arg = 0;
14731471 Sym *sym;
14741472 CType *type;
14751473
@@ -1553,7 +1551,6 @@ void gfunc_prolog(Sym *func_sym) · 77 unmodified lines
15531551 }
15541552 /* define parameters */
15551553 while ((sym = sym->next) != NULL) {
1556− n_arg++;
15571554 type = &sym->type;
15581555 mode = classify_x86_64_arg(type, NULL, &size, &align, &reg_count);
15591556 switch (mode) {
@@ -1606,19 +1603,8 @@ void gfunc_prolog(Sym *func_sym) · 46 unmodified lines
16061603 }
16071604
16081605 #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();
16221608 #endif
16231609 }
16241610
@@ -1628,36 +1614,8 @@ void gfunc_epilog(void) · 3 unmodified lines
16281614 int v, saved_ind;
16291615
16301616 #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();
16611619 #endif
16621620 o(0xc9); /* leave */
16631621 if (func_ret_sub == 0) {

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