Hello up there. On the list Grischka made a point that we can't recommend using -b as long as tcc -b tcc.c doesn't produce anything useful. Now it does, so please don't treat -b mode as second class citizen anymore. Thanks, Kirill * bcheck2: tests: Add tests for compile/run tcc.c with `tcc -b` then compile tcc.c again, then run tcctest.c lib/bcheck: Fix code typo in __bound_delete_region() lib/bcheck: Don't assume heap goes right after bss Make tcc work after self-compiling with bounds-check enabled
Unified · Split
| @@ -11,8 +11,11 @@ tc1.c · 10 unmodified lines | |||
| 11 | error.c | 11 | error.c |
| 12 | i386-gen1.c | 12 | i386-gen1.c |
| 13 | test.out1 | 13 | test.out1 |
| 14 | test.out1b | ||
| 14 | test.out2 | 15 | test.out2 |
| 16 | test.out2b | ||
| 15 | test.out3 | 17 | test.out3 |
| 18 | test.out3b | ||
| 16 | web.sh | 19 | web.sh |
| 17 | memdebug.c | 20 | memdebug.c |
| 18 | bench | 21 | bench |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | && !defined(__DragonFly__) && !defined(__OpenBSD__) | 25 | && !defined(__DragonFly__) && !defined(__OpenBSD__) |
| 26 | #include <malloc.h> | 26 | #include <malloc.h> |
| 27 | #endif | 27 | #endif |
| 28 | #include <unistd.h> | ||
| 28 | 29 | ||
| 29 | //#define BOUND_DEBUG | 30 | //#define BOUND_DEBUG |
| 30 | 31 | ||
| @@ -94,9 +95,6 @@ static void *saved_realloc_hook; · 63 unmodified lines | |||
| 94 | static void *saved_memalign_hook; | 95 | static void *saved_memalign_hook; |
| 95 | #endif | 96 | #endif |
| 96 | 97 | ||
| 97 | /* linker definitions */ | ||
| 98 | extern char _end; | ||
| 99 | |||
| 100 | /* TCC definitions */ | 98 | /* TCC definitions */ |
| 101 | extern char __bounds_start; /* start of static bounds table */ | 99 | extern char __bounds_start; /* start of static bounds table */ |
| 102 | /* error message, just for TCC */ | 100 | /* error message, just for TCC */ |
| @@ -379,9 +377,32 @@ void __bound_init(void) · 276 unmodified lines | |||
| 379 | 377 | ||
| 380 | #if !defined(__TINYC__) && defined(CONFIG_TCC_MALLOC_HOOKS) | 378 | #if !defined(__TINYC__) && defined(CONFIG_TCC_MALLOC_HOOKS) |
| 381 | /* malloc zone is also marked invalid. can only use that with | 379 | /* malloc zone is also marked invalid. can only use that with |
| 382 | hooks because all libs should use the same malloc. The solution | 380 | * hooks because all libs should use the same malloc. The solution |
| 383 | would be to build a new malloc for tcc. */ | 381 | * would be to build a new malloc for tcc. |
| 384 | start = (unsigned long)&_end; | 382 | * |
| 383 | * usually heap (= malloc zone) comes right after bss, i.e. after _end, but | ||
| 384 | * not always - either if we are running from under `tcc -b -run`, or if | ||
| 385 | * address space randomization is turned on(a), heap start will be separated | ||
| 386 | * from bss end. | ||
| 387 | * | ||
| 388 | * So sbrk(0) will be a good approximation for start_brk: | ||
| 389 | * | ||
| 390 | * - if we are a separately compiled program, __bound_init() runs early, | ||
| 391 | * and sbrk(0) should be equal or very near to start_brk(b) (in case other | ||
| 392 | * constructors malloc something), or | ||
| 393 | * | ||
| 394 | * - if we are running from under `tcc -b -run`, sbrk(0) will return | ||
| 395 | * start of heap portion which is under this program control, and not | ||
| 396 | * mark as invalid earlier allocated memory. | ||
| 397 | * | ||
| 398 | * | ||
| 399 | * (a) /proc/sys/kernel/randomize_va_space = 2, on Linux; | ||
| 400 | * usually turned on by default. | ||
| 401 | * | ||
| 402 | * (b) on Linux >= v3.3, the alternative is to read | ||
| 403 | * start_brk from /proc/self/stat | ||
| 404 | */ | ||
| 405 | start = (unsigned long)sbrk(0); | ||
| 385 | size = 128 * 0x100000; | 406 | size = 128 * 0x100000; |
| 386 | mark_invalid(start, size); | 407 | mark_invalid(start, size); |
| 387 | #endif | 408 | #endif |
| @@ -592,7 +613,7 @@ int __bound_delete_region(void *p) · 204 unmodified lines | |||
| 592 | } | 613 | } |
| 593 | } | 614 | } |
| 594 | /* last page */ | 615 | /* last page */ |
| 595 | page = get_page(t2_end); | 616 | page = get_page(t1_end); |
| 596 | e2 = (BoundEntry *)((char *)page + t2_end); | 617 | e2 = (BoundEntry *)((char *)page + t2_end); |
| 597 | for(e=page;e<e2;e++) { | 618 | for(e=page;e<e2;e++) { |
| 598 | e->start = 0; | 619 | e->start = 0; |
| @@ -1127,7 +1127,8 @@ ST_DATA Sym *local_label_stack; · 1126 unmodified lines | |||
| 1127 | ST_DATA Sym *global_label_stack; | 1127 | ST_DATA Sym *global_label_stack; |
| 1128 | ST_DATA Sym *define_stack; | 1128 | ST_DATA Sym *define_stack; |
| 1129 | ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; | 1129 | ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; |
| 1130 | ST_DATA SValue vstack[VSTACK_SIZE], *vtop; | 1130 | ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop; |
| 1131 | #define vstack (__vstack + 1) | ||
| 1131 | ST_DATA int rsym, anon_sym, ind, loc; | 1132 | ST_DATA int rsym, anon_sym, ind, loc; |
| 1132 | 1133 | ||
| 1133 | ST_DATA int const_wanted; /* true if constant wanted */ | 1134 | ST_DATA int const_wanted; /* true if constant wanted */ |
| @@ -55,7 +55,7 @@ ST_DATA Sym *define_stack; · 54 unmodified lines | |||
| 55 | ST_DATA Sym *global_label_stack; | 55 | ST_DATA Sym *global_label_stack; |
| 56 | ST_DATA Sym *local_label_stack; | 56 | ST_DATA Sym *local_label_stack; |
| 57 | 57 | ||
| 58 | ST_DATA SValue vstack[VSTACK_SIZE], *vtop; | 58 | ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop; |
| 59 | 59 | ||
| 60 | ST_DATA int const_wanted; /* true if constant wanted */ | 60 | ST_DATA int const_wanted; /* true if constant wanted */ |
| 61 | ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ | 61 | ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ |
| @@ -3041,7 +3041,6 @@ ST_FUNC void preprocess_init(TCCState *s1) · 3040 unmodified lines | |||
| 3041 | s1->ifdef_stack_ptr = s1->ifdef_stack; | 3041 | s1->ifdef_stack_ptr = s1->ifdef_stack; |
| 3042 | file->ifdef_stack_ptr = s1->ifdef_stack_ptr; | 3042 | file->ifdef_stack_ptr = s1->ifdef_stack_ptr; |
| 3043 | 3043 | ||
| 3044 | /* XXX: not ANSI compliant: bound checking says error */ | ||
| 3045 | vtop = vstack - 1; | 3044 | vtop = vstack - 1; |
| 3046 | s1->pack_stack[0] = 0; | 3045 | s1->pack_stack[0] = 0; |
| 3047 | s1->pack_stack_ptr = s1->pack_stack; | 3046 | s1->pack_stack_ptr = s1->pack_stack; |
| @@ -12,6 +12,9 @@ TESTS = libtest \ · 11 unmodified lines | |||
| 12 | test3 \ | 12 | test3 \ |
| 13 | speedtest \ | 13 | speedtest \ |
| 14 | btest \ | 14 | btest \ |
| 15 | test1b\ | ||
| 16 | test2b\ | ||
| 17 | test3b\ | ||
| 15 | weaktest | 18 | weaktest |
| 16 | 19 | ||
| 17 | # test4 # this test does not seem to work on any platform | 20 | # test4 # this test does not seem to work on any platform |
| @@ -20,6 +23,9 @@ TESTS = libtest \ · 2 unmodified lines | |||
| 20 | # bounds-checking is supported only on i386 | 23 | # bounds-checking is supported only on i386 |
| 21 | ifneq ($(ARCH),i386) | 24 | ifneq ($(ARCH),i386) |
| 22 | TESTS := $(filter-out btest,$(TESTS)) | 25 | TESTS := $(filter-out btest,$(TESTS)) |
| 26 | TESTS := $(filter-out test1b,$(TESTS)) | ||
| 27 | TESTS := $(filter-out test2b,$(TESTS)) | ||
| 28 | TESTS := $(filter-out test3b,$(TESTS)) | ||
| 23 | endif | 29 | endif |
| 24 | 30 | ||
| 25 | # these should work too | 31 | # these should work too |
| @@ -87,18 +93,33 @@ test1: test.ref · 61 unmodified lines | |||
| 87 | $(TCC) -run tcctest.c > test.out1 | 93 | $(TCC) -run tcctest.c > test.out1 |
| 88 | @if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi | 94 | @if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi |
| 89 | 95 | ||
| 96 | test1b: test.ref | ||
| 97 | @echo ------------ $@ ------------ | ||
| 98 | $(TCC) -b -run tcctest.c > test.out1b | ||
| 99 | @if diff -u test.ref test.out1b ; then echo "Auto Test OK"; fi | ||
| 100 | |||
| 90 | # iterated test2 (compile tcc then compile tcctest.c !) | 101 | # iterated test2 (compile tcc then compile tcctest.c !) |
| 91 | test2: test.ref | 102 | test2: test.ref |
| 92 | @echo ------------ $@ ------------ | 103 | @echo ------------ $@ ------------ |
| 93 | $(TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out2 | 104 | $(TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out2 |
| 94 | @if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi | 105 | @if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi |
| 95 | 106 | ||
| 107 | test2b: test.ref ../bcheck.o | ||
| 108 | @echo ------------ $@ ------------ | ||
| 109 | $(TCC) -b $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out2b | ||
| 110 | @if diff -u test.ref test.out2b ; then echo "Auto Test2b OK"; fi | ||
| 111 | |||
| 96 | # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) | 112 | # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) |
| 97 | test3: test.ref | 113 | test3: test.ref |
| 98 | @echo ------------ $@ ------------ | 114 | @echo ------------ $@ ------------ |
| 99 | $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out3 | 115 | $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out3 |
| 100 | @if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi | 116 | @if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi |
| 101 | 117 | ||
| 118 | test3b: test.ref | ||
| 119 | @echo ------------ $@ ------------ | ||
| 120 | $(TCC) -b $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out3b | ||
| 121 | @if diff -u test.ref test.out3b ; then echo "Auto Test3 OK"; fi | ||
| 122 | |||
| 102 | # binary output test | 123 | # binary output test |
| 103 | test4: test.ref | 124 | test4: test.ref |
| 104 | @echo ------------ $@ ------------ | 125 | @echo ------------ $@ ------------ |
| @@ -190,5 +211,5 @@ cache: tcc_g · 85 unmodified lines | |||
| 190 | 211 | ||
| 191 | # clean | 212 | # clean |
| 192 | clean: | 213 | clean: |
| 193 | rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.gcc \ | 214 | rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc \ |
| 194 | tcctest[1234] ex? libtcc_test$(EXESUF) tcc_g tcclib.h | 215 | tcctest[1234] ex? libtcc_test$(EXESUF) tcc_g tcclib.h |