Unified · Split
| @@ -44,7 +44,7 @@ native : TCC = $(TOP)/tcc$(EXESUF) · 43 unmodified lines | ||
| 44 | 44 | cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) |
| 45 | 45 | |
| 46 | 46 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) |
| 47 | −X86_64_O = libtcc1.o alloca86_64.o | |
| 47 | +X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O) | |
| 48 | 48 | ARM_O = libtcc1.o armeabi.o alloca-arm.o |
| 49 | 49 | WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o |
| 50 | 50 | WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o |
| @@ -0,0 +1,60 @@ | ||
| 1 | +/* ---------------------------------------------- */ | |
| 2 | +/* alloca86_64.S */ | |
| 3 | + | |
| 4 | +.globl __bound_alloca | |
| 5 | +__bound_alloca: | |
| 6 | + | |
| 7 | +#ifdef TCC_TARGET_PE | |
| 8 | + # bound checking is not implemented | |
| 9 | + pop %rdx | |
| 10 | + mov %rcx,%rax | |
| 11 | + add $15,%rax | |
| 12 | + and $-16,%rax | |
| 13 | + jz p3 | |
| 14 | + | |
| 15 | +p1: | |
| 16 | + cmp $4096,%rax | |
| 17 | + jbe p2 | |
| 18 | + test %rax,-4096(%rsp) | |
| 19 | + sub $4096,%rsp | |
| 20 | + sub $4096,%rax | |
| 21 | + jmp p1 | |
| 22 | +p2: | |
| 23 | + | |
| 24 | + sub %rax,%rsp | |
| 25 | + mov %rsp,%rax | |
| 26 | + add $32,%rax | |
| 27 | + | |
| 28 | +p3: | |
| 29 | + push %rdx | |
| 30 | + ret | |
| 31 | +#else | |
| 32 | + pop %rdx | |
| 33 | + mov %rdi,%rax | |
| 34 | + movl %rax,%rsi # size, a second parm to the __bound_new_region | |
| 35 | + | |
| 36 | + add $15,%rax | |
| 37 | + and $-16,%rax | |
| 38 | + jz p3 | |
| 39 | + | |
| 40 | + | |
| 41 | + sub %rax,%rsp | |
| 42 | + mov %rsp,%rdi # pointer, a first parm to the __bound_new_region | |
| 43 | + mov %rsp,%rax | |
| 44 | + | |
| 45 | + push %rdx | |
| 46 | + push %rax | |
| 47 | + call __bound_new_region | |
| 48 | + pop %rax | |
| 49 | + pop %rdx | |
| 50 | + | |
| 51 | +p3: | |
| 52 | + push %rdx | |
| 53 | + ret | |
| 54 | +#endif | |
| 55 | + | |
| 56 | +/* mark stack as nonexecutable */ | |
| 57 | +#if defined __ELF__ && defined __linux__ | |
| 58 | + .section .note.GNU-stack,"",@progbits | |
| 59 | +#endif | |
| 60 | +/* ---------------------------------------------- */ | |
| @@ -31,6 +31,12 @@ · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | /* #define BOUND_DEBUG */ |
| 33 | 33 | |
| 34 | +#ifdef BOUND_DEBUG | |
| 35 | + #define dprintf(a...) fprintf(a) | |
| 36 | +#else | |
| 37 | + #define dprintf(a...) | |
| 38 | +#endif | |
| 39 | + | |
| 34 | 40 | /* define so that bound array is static (faster, but use memory if |
| 35 | 41 | bound checking not used) */ |
| 36 | 42 | /* #define BOUND_STATIC */ |
| @@ -50,12 +56,12 @@ · 13 unmodified lines | ||
| 50 | 56 | |
| 51 | 57 | #define BOUND_T1_BITS 13 |
| 52 | 58 | #define BOUND_T2_BITS 11 |
| 53 | −#define BOUND_T3_BITS (32 - BOUND_T1_BITS - BOUND_T2_BITS) | |
| 59 | +#define BOUND_T3_BITS (sizeof(size_t)*8 - BOUND_T1_BITS - BOUND_T2_BITS) | |
| 60 | +#define BOUND_E_BITS (sizeof(size_t)) | |
| 54 | 61 | |
| 55 | 62 | #define BOUND_T1_SIZE (1 << BOUND_T1_BITS) |
| 56 | 63 | #define BOUND_T2_SIZE (1 << BOUND_T2_BITS) |
| 57 | 64 | #define BOUND_T3_SIZE (1 << BOUND_T3_BITS) |
| 58 | −#define BOUND_E_BITS 4 | |
| 59 | 65 | |
| 60 | 66 | #define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS) |
| 61 | 67 | #define BOUND_T23_SIZE (1 << BOUND_T23_BITS) |
| @@ -64,7 +70,7 @@ · 2 unmodified lines | ||
| 64 | 70 | /* this pointer is generated when bound check is incorrect */ |
| 65 | 71 | #define INVALID_POINTER ((void *)(-2)) |
| 66 | 72 | /* size of an empty region */ |
| 67 | −#define EMPTY_SIZE 0xffffffff | |
| 73 | +#define EMPTY_SIZE ((size_t)(-1)) | |
| 68 | 74 | /* size of an invalid region */ |
| 69 | 75 | #define INVALID_SIZE 0 |
| 70 | 76 | |
| @@ -168,9 +174,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) · 97 unmodified lines | ||
| 168 | 174 | |
| 169 | 175 | __bound_init(); |
| 170 | 176 | |
| 171 | −#if defined(BOUND_DEBUG) | |
| 172 | − printf("%s %s: 0x%x %d\n", __FILE__, __FUNCTION__, (int)p, offset); | |
| 173 | −#endif | |
| 177 | + dprintf(stderr, "%s %s: %p %p\n", __FILE__, __FUNCTION__, p, offset); | |
| 174 | 178 | |
| 175 | 179 | e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; |
| 176 | 180 | e = (BoundEntry *)((char *)e + |
| @@ -197,6 +201,8 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 20 unmodified lines | ||
| 197 | 201 | size_t addr = (size_t)p; \ |
| 198 | 202 | BoundEntry *e; \ |
| 199 | 203 | \ |
| 204 | + dprintf(stderr, "%s %s: %p %p start\n", __FILE__, __FUNCTION__, p, offset); \ | |
| 205 | + \ | |
| 200 | 206 | __bound_init(); \ |
| 201 | 207 | e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \ |
| 202 | 208 | e = (BoundEntry *)((char *)e + \ |
| @@ -212,6 +218,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 9 unmodified lines | ||
| 212 | 218 | fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); \ |
| 213 | 219 | return INVALID_POINTER; /* return an invalid pointer */ \ |
| 214 | 220 | } \ |
| 221 | + dprintf(stderr, "%s %s: return p+offset = %p\n", __FILE__, __FUNCTION__, p + offset); \ | |
| 215 | 222 | return p + offset; \ |
| 216 | 223 | } |
| 217 | 224 | |
| @@ -232,9 +239,8 @@ BOUND_PTR_INDIR(16) · 14 unmodified lines | ||
| 232 | 239 | void FASTCALL __bound_local_new(void *p1) |
| 233 | 240 | { |
| 234 | 241 | size_t addr, size, fp, *p = p1; |
| 235 | −#ifdef BOUND_DEBUG | |
| 236 | − fprintf(stderr, "%s, %s start p1=%p *p1=%p\n", __FILE__, __FUNCTION__, p, *p); | |
| 237 | −#endif | |
| 242 | + | |
| 243 | + dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p); | |
| 238 | 244 | GET_CALLER_FP(fp); |
| 239 | 245 | for(;;) { |
| 240 | 246 | addr = p[0]; |
| @@ -245,9 +251,7 @@ void FASTCALL __bound_local_new(void *p1) · 4 unmodified lines | ||
| 245 | 251 | p += 2; |
| 246 | 252 | __bound_new_region((void *)addr, size); |
| 247 | 253 | } |
| 248 | −#ifdef BOUND_DEBUG | |
| 249 | − fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); | |
| 250 | −#endif | |
| 254 | + dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); | |
| 251 | 255 | } |
| 252 | 256 | |
| 253 | 257 | /* called when leaving a function to delete all the local regions */ |
| @@ -268,7 +272,7 @@ void FASTCALL __bound_local_delete(void *p1) · 14 unmodified lines | ||
| 268 | 272 | static BoundEntry *__bound_new_page(void) |
| 269 | 273 | { |
| 270 | 274 | BoundEntry *page; |
| 271 | − int i; | |
| 275 | + size_t i; | |
| 272 | 276 | |
| 273 | 277 | page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE); |
| 274 | 278 | if (!page) |
| @@ -296,11 +300,11 @@ static void bound_free_entry(BoundEntry *e) · 21 unmodified lines | ||
| 296 | 300 | libc_free(e); |
| 297 | 301 | } |
| 298 | 302 | |
| 299 | −static inline BoundEntry *get_page(int index) | |
| 303 | +static BoundEntry *get_page(size_t index) | |
| 300 | 304 | { |
| 301 | 305 | BoundEntry *page; |
| 302 | 306 | page = __bound_t1[index]; |
| 303 | − if (page == __bound_empty_t2 || page == __bound_invalid_t2) { | |
| 307 | + if (!page || page == __bound_empty_t2 || page == __bound_invalid_t2) { | |
| 304 | 308 | /* create a new page if necessary */ |
| 305 | 309 | page = __bound_new_page(); |
| 306 | 310 | __bound_t1[index] = page; |
| @@ -325,7 +329,7 @@ static void mark_invalid(size_t addr, size_t size) · 18 unmodified lines | ||
| 325 | 329 | t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS); |
| 326 | 330 | |
| 327 | 331 | #if 0 |
| 328 | − printf("mark_invalid: start = %x %x\n", t2_start, t2_end); | |
| 332 | + dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end); | |
| 329 | 333 | #endif |
| 330 | 334 | |
| 331 | 335 | /* first we handle full pages */ |
| @@ -364,7 +368,7 @@ static void mark_invalid(size_t addr, size_t size) · 32 unmodified lines | ||
| 364 | 368 | |
| 365 | 369 | void __bound_init(void) |
| 366 | 370 | { |
| 367 | − int i; | |
| 371 | + size_t i; | |
| 368 | 372 | BoundEntry *page; |
| 369 | 373 | size_t start, size; |
| 370 | 374 | size_t *p; |
| @@ -375,9 +379,7 @@ void __bound_init(void) · 4 unmodified lines | ||
| 375 | 379 | |
| 376 | 380 | inited = 1; |
| 377 | 381 | |
| 378 | −#ifdef BOUND_DEBUG | |
| 379 | − fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); | |
| 380 | −#endif | |
| 382 | + dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); | |
| 381 | 383 | |
| 382 | 384 | /* save malloc hooks and install bound check hooks */ |
| 383 | 385 | install_malloc_hooks(); |
| @@ -445,19 +447,18 @@ void __bound_init(void) · 61 unmodified lines | ||
| 445 | 447 | __bound_new_region((void *)p[0], p[1]); |
| 446 | 448 | p += 2; |
| 447 | 449 | } |
| 448 | −#ifdef BOUND_DEBUG | |
| 449 | − fprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); | |
| 450 | −#endif | |
| 450 | + | |
| 451 | + dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); | |
| 451 | 452 | } |
| 452 | 453 | |
| 453 | 454 | void __bound_main_arg(void **p) |
| 454 | 455 | { |
| 455 | 456 | void *start = p; |
| 456 | 457 | while (*p++); |
| 457 | −#ifdef BOUND_DEBUG | |
| 458 | − fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", | |
| 458 | + | |
| 459 | + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", | |
| 459 | 460 | __FILE__, __FUNCTION__, (void *) p - start); |
| 460 | −#endif | |
| 461 | + | |
| 461 | 462 | __bound_new_region(start, (void *) p - start); |
| 462 | 463 | } |
| 463 | 464 | |
| @@ -495,10 +496,8 @@ void __bound_new_region(void *p, size_t size) · 31 unmodified lines | ||
| 495 | 496 | |
| 496 | 497 | __bound_init(); |
| 497 | 498 | |
| 498 | −#ifdef BOUND_DEBUG | |
| 499 | − fprintf(stderr, "%s, %s(%p, %p) start\n", | |
| 499 | + dprintf(stderr, "%s, %s(%p, %p) start\n", | |
| 500 | 500 | __FILE__, __FUNCTION__, p, size); |
| 501 | −#endif | |
| 502 | 501 | |
| 503 | 502 | start = (size_t)p; |
| 504 | 503 | end = start + size; |
| @@ -553,9 +552,8 @@ void __bound_new_region(void *p, size_t size) · 48 unmodified lines | ||
| 553 | 552 | } |
| 554 | 553 | add_region(e, start, size); |
| 555 | 554 | } |
| 556 | −#ifdef BOUND_DEBUG | |
| 557 | − fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); | |
| 558 | −#endif | |
| 555 | + | |
| 556 | + dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); | |
| 559 | 557 | } |
| 560 | 558 | |
| 561 | 559 | /* delete a region */ |
| @@ -610,9 +608,7 @@ int __bound_delete_region(void *p) · 48 unmodified lines | ||
| 610 | 608 | |
| 611 | 609 | __bound_init(); |
| 612 | 610 | |
| 613 | −#ifdef BOUND_DEBUG | |
| 614 | − fprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); | |
| 615 | −#endif | |
| 611 | + dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); | |
| 616 | 612 | |
| 617 | 613 | start = (size_t)p; |
| 618 | 614 | t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); |
| @@ -681,9 +677,7 @@ int __bound_delete_region(void *p) · 62 unmodified lines | ||
| 681 | 677 | delete_region(e, p, empty_size); |
| 682 | 678 | } |
| 683 | 679 | |
| 684 | −#ifdef BOUND_DEBUG | |
| 685 | − fprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); | |
| 686 | −#endif | |
| 680 | + dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); | |
| 687 | 681 | |
| 688 | 682 | return 0; |
| 689 | 683 | } |
| @@ -771,10 +765,9 @@ void *__bound_malloc(size_t size, const void *caller) · 81 unmodified lines | ||
| 771 | 765 | if (!ptr) |
| 772 | 766 | return NULL; |
| 773 | 767 | |
| 774 | −#ifdef BOUND_DEBUG | |
| 775 | − fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", | |
| 768 | + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", | |
| 776 | 769 | __FILE__, __FUNCTION__, ptr, size); |
| 777 | −#endif | |
| 770 | + | |
| 778 | 771 | __bound_new_region(ptr, size); |
| 779 | 772 | return ptr; |
| 780 | 773 | } |
| @@ -805,10 +798,9 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 24 unmodified lines | ||
| 805 | 798 | if (!ptr) |
| 806 | 799 | return NULL; |
| 807 | 800 | |
| 808 | −#ifdef BOUND_DEBUG | |
| 809 | − fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", | |
| 801 | + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", | |
| 810 | 802 | __FILE__, __FUNCTION__, ptr, size); |
| 811 | −#endif | |
| 803 | + | |
| 812 | 804 | __bound_new_region(ptr, size); |
| 813 | 805 | return ptr; |
| 814 | 806 | } |
| @@ -861,23 +853,23 @@ void *__bound_calloc(size_t nmemb, size_t size) · 46 unmodified lines | ||
| 861 | 853 | static void bound_dump(void) |
| 862 | 854 | { |
| 863 | 855 | BoundEntry *page, *e; |
| 864 | − int i, j; | |
| 856 | + size_t i, j; | |
| 865 | 857 | |
| 866 | − printf("region dump:\n"); | |
| 858 | + fprintf(stderr, "region dump:\n"); | |
| 867 | 859 | for(i=0;i<BOUND_T1_SIZE;i++) { |
| 868 | 860 | page = __bound_t1[i]; |
| 869 | 861 | for(j=0;j<BOUND_T2_SIZE;j++) { |
| 870 | 862 | e = page + j; |
| 871 | 863 | /* do not print invalid or empty entries */ |
| 872 | 864 | if (e->size != EMPTY_SIZE && e->start != 0) { |
| 873 | − printf("%08x:", | |
| 865 | + fprintf(stderr, "%08x:", | |
| 874 | 866 | (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + |
| 875 | 867 | (j << BOUND_T3_BITS)); |
| 876 | 868 | do { |
| 877 | − printf(" %08lx:%08lx", e->start, e->start + e->size); | |
| 869 | + fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size); | |
| 878 | 870 | e = e->next; |
| 879 | 871 | } while (e != NULL); |
| 880 | − printf("\n"); | |
| 872 | + fprintf(stderr, "\n"); | |
| 881 | 873 | } |
| 882 | 874 | } |
| 883 | 875 | } |
| @@ -891,19 +883,27 @@ static void __bound_check(const void *p, size_t size) · 7 unmodified lines | ||
| 891 | 883 | { |
| 892 | 884 | if (size == 0) |
| 893 | 885 | return; |
| 894 | − p = __bound_ptr_add((void *)p, size); | |
| 886 | + p = __bound_ptr_add((void *)p, size - 1); | |
| 895 | 887 | if (p == INVALID_POINTER) |
| 896 | 888 | bound_error("invalid pointer"); |
| 897 | 889 | } |
| 898 | 890 | |
| 899 | 891 | void *__bound_memcpy(void *dst, const void *src, size_t size) |
| 900 | 892 | { |
| 893 | + void* p; | |
| 894 | + | |
| 895 | + dprintf(stderr, "%s %s: start, dst=%p src=%p size=%p\n", __FILE__, __FUNCTION__, dst, src, size); | |
| 896 | + | |
| 901 | 897 | __bound_check(dst, size); |
| 902 | 898 | __bound_check(src, size); |
| 903 | 899 | /* check also region overlap */ |
| 904 | 900 | if (src >= dst && src < dst + size) |
| 905 | 901 | bound_error("overlapping regions in memcpy()"); |
| 906 | − return memcpy(dst, src, size); | |
| 902 | + | |
| 903 | + p = memcpy(dst, src, size); | |
| 904 | + | |
| 905 | + dprintf(stderr, "%s %s: end, p=%p\n", __FILE__, __FUNCTION__, p); | |
| 906 | + return p; | |
| 907 | 907 | } |
| 908 | 908 | |
| 909 | 909 | void *__bound_memmove(void *dst, const void *src, size_t size) |
| @@ -939,7 +939,12 @@ int __bound_strlen(const char *s) · 29 unmodified lines | ||
| 939 | 939 | |
| 940 | 940 | char *__bound_strcpy(char *dst, const char *src) |
| 941 | 941 | { |
| 942 | − int len; | |
| 942 | + size_t len; | |
| 943 | + void *p; | |
| 944 | + | |
| 945 | + dprintf(stderr, "%s %s: strcpy start, dst=%p src=%p\n", __FILE__, __FUNCTION__, dst, src); | |
| 943 | 946 | len = __bound_strlen(src); |
| 944 | − return __bound_memcpy(dst, src, len + 1); | |
| 947 | + p = __bound_memcpy(dst, src, len + 1); | |
| 948 | + dprintf(stderr, "%s %s: strcpy end, p=%p\n", __FILE__, __FUNCTION__, dst, src, p); | |
| 949 | + return p; | |
| 945 | 950 | } |
| @@ -164,7 +164,7 @@ · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ |
| 166 | 166 | !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \ |
| 167 | − !defined(TCC_TARGET_X86_64) && !defined(CONFIG_USE_LIBGCC) | |
| 167 | + !defined(CONFIG_USE_LIBGCC) | |
| 168 | 168 | #define CONFIG_TCC_BCHECK /* enable bound checking code */ |
| 169 | 169 | #endif |
| 170 | 170 | |
| @@ -1579,7 +1579,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 1578 unmodified lines | ||
| 1579 | 1579 | add_elf_sym(symtab_section, 0, 0, |
| 1580 | 1580 | ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, |
| 1581 | 1581 | bounds_section->sh_num, "__bounds_start"); |
| 1582 | −#ifdef TCC_TARGET_I386 | |
| 1583 | 1582 | if (s1->output_type != TCC_OUTPUT_MEMORY) { |
| 1584 | 1583 | /* add 'call __bound_init()' in .init section */ |
| 1585 | 1584 | |
| @@ -1601,7 +1600,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 15 unmodified lines | ||
| 1601 | 1600 | tcc_warning("__bound_init not defined"); |
| 1602 | 1601 | } |
| 1603 | 1602 | #endif |
| 1604 | −#endif | |
| 1605 | 1603 | } |
| 1606 | 1604 | |
| 1607 | 1605 | /* add tcc runtime libraries */ |
| @@ -708,7 +708,7 @@ static void gbound(void) · 707 unmodified lines | ||
| 708 | 708 | lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL); |
| 709 | 709 | /* must save type because we must set it to int to get pointer */ |
| 710 | 710 | type1 = vtop->type; |
| 711 | − vtop->type.t = VT_INT; | |
| 711 | + vtop->type.t = VT_PTR; | |
| 712 | 712 | gaddrof(); |
| 713 | 713 | vpushi(0); |
| 714 | 714 | gen_bounded_ptr_add(); |
| @@ -1752,7 +1752,22 @@ ST_FUNC void gen_op(int op) · 1037 unmodified lines | ||
| 1752 | 1752 | #endif |
| 1753 | 1753 | } |
| 1754 | 1754 | gen_op('*'); |
| 1755 | −#ifdef CONFIG_TCC_BCHECK | |
| 1755 | +#if 0 | |
| 1756 | +/* #ifdef CONFIG_TCC_BCHECK | |
| 1757 | + The main reason to removing this code: | |
| 1758 | + #include <stdio.h> | |
| 1759 | + int main () | |
| 1760 | + { | |
| 1761 | + int v[10]; | |
| 1762 | + int i = 10; | |
| 1763 | + int j = 9; | |
| 1764 | + fprintf(stderr, "v+i-j = %p\n", v+i-j); | |
| 1765 | + fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); | |
| 1766 | + } | |
| 1767 | + When this code is on. then the output looks like | |
| 1768 | + v+i-j = 0xfffffffe | |
| 1769 | + v+(i-j) = 0xbff84000 | |
| 1770 | + */ | |
| 1756 | 1771 | /* if evaluating constant expression, no code should be |
| 1757 | 1772 | generated, so no bound check */ |
| 1758 | 1773 | if (tcc_state->do_bounds_check && !const_wanted) { |
| @@ -50,12 +50,15 @@ int test4(void) · 49 unmodified lines | ||
| 50 | 50 | int i, sum = 0; |
| 51 | 51 | int *tab4; |
| 52 | 52 | |
| 53 | + fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 54 | + | |
| 53 | 55 | tab4 = malloc(20 * sizeof(int)); |
| 54 | 56 | for(i=0;i<20;i++) { |
| 55 | 57 | sum += tab4[i]; |
| 56 | 58 | } |
| 57 | 59 | free(tab4); |
| 58 | 60 | |
| 61 | + fprintf(stderr, "%s end\n", __FUNCTION__); | |
| 59 | 62 | return sum; |
| 60 | 63 | } |
| 61 | 64 | |
| @@ -65,12 +68,15 @@ int test5(void) · 3 unmodified lines | ||
| 65 | 68 | int i, sum = 0; |
| 66 | 69 | int *tab4; |
| 67 | 70 | |
| 71 | + fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 72 | + | |
| 68 | 73 | tab4 = malloc(20 * sizeof(int)); |
| 69 | 74 | for(i=0;i<21;i++) { |
| 70 | 75 | sum += tab4[i]; |
| 71 | 76 | } |
| 72 | 77 | free(tab4); |
| 73 | 78 | |
| 79 | + fprintf(stderr, "%s end\n", __FUNCTION__); | |
| 74 | 80 | return sum; |
| 75 | 81 | } |
| 76 | 82 | |
| @@ -187,8 +193,43 @@ int test15(void) · 110 unmodified lines | ||
| 187 | 193 | return strlen(p); |
| 188 | 194 | } |
| 189 | 195 | |
| 196 | +/* ok */ | |
| 197 | +int test16() | |
| 198 | +{ | |
| 199 | + char *demo = "This is only a test."; | |
| 200 | + char *p; | |
| 201 | + | |
| 202 | + fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 203 | + | |
| 204 | + p = alloca(16); | |
| 205 | + strcpy(p,"12345678901234"); | |
| 206 | + printf("alloca: p is %s\n", p); | |
| 207 | + | |
| 208 | + /* Test alloca embedded in a larger expression */ | |
| 209 | + printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) ); | |
| 210 | + | |
| 211 | + fprintf(stderr, "%s end\n", __FUNCTION__); | |
| 212 | +} | |
| 213 | + | |
| 214 | +/* error */ | |
| 215 | +int test17() | |
| 216 | +{ | |
| 217 | + char *demo = "This is only a test."; | |
| 218 | + char *p; | |
| 219 | + | |
| 220 | + fprintf(stderr, "%s start\n", __FUNCTION__); | |
| 221 | + | |
| 222 | + p = alloca(16); | |
| 223 | + strcpy(p,"12345678901234"); | |
| 224 | + printf("alloca: p is %s\n", p); | |
| 225 | + | |
| 226 | + /* Test alloca embedded in a larger expression */ | |
| 227 | + printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) ); | |
| 228 | + | |
| 229 | + fprintf(stderr, "%s end\n", __FUNCTION__); | |
| 230 | +} | |
| 231 | + | |
| 190 | 232 | int (*table_test[])(void) = { |
| 191 | − test1, | |
| 192 | 233 | test1, |
| 193 | 234 | test2, |
| 194 | 235 | test3, |
| @@ -204,23 +245,33 @@ int (*table_test[])(void) = { · 9 unmodified lines | ||
| 204 | 245 | test13, |
| 205 | 246 | test14, |
| 206 | 247 | test15, |
| 248 | + test16, | |
| 249 | + test17, | |
| 207 | 250 | }; |
| 208 | 251 | |
| 209 | 252 | int main(int argc, char **argv) |
| 210 | 253 | { |
| 211 | 254 | int index; |
| 212 | 255 | int (*ftest)(void); |
| 256 | + int index_max = sizeof(table_test)/sizeof(table_test[0]); | |
| 213 | 257 | |
| 214 | 258 | if (argc < 2) { |
| 215 | − printf("usage: boundtest n\n" | |
| 216 | − "test TCC bound checking system\n" | |
| 217 | − ); | |
| 259 | + printf( | |
| 260 | + "test TCC bound checking system\n" | |
| 261 | + "usage: boundtest N\n" | |
| 262 | + " 1 <= N <= %d\n", index_max); | |
| 218 | 263 | exit(1); |
| 219 | 264 | } |
| 220 | 265 | |
| 221 | 266 | index = 0; |
| 222 | 267 | if (argc >= 2) |
| 223 | − index = atoi(argv[1]); | |
| 268 | + index = atoi(argv[1]) - 1; | |
| 269 | + | |
| 270 | + if ((index < 0) || (index >= index_max)) { | |
| 271 | + printf("N is outside of the valid range (%d)\n", index); | |
| 272 | + exit(2); | |
| 273 | + } | |
| 274 | + | |
| 224 | 275 | /* well, we also use bounds on this ! */ |
| 225 | 276 | ftest = table_test[index]; |
| 226 | 277 | ftest(); |
| @@ -625,6 +625,90 @@ static void gcall_or_jmp(int is_jmp) · 624 unmodified lines | ||
| 625 | 625 | } |
| 626 | 626 | } |
| 627 | 627 | |
| 628 | +#if defined(CONFIG_TCC_BCHECK) | |
| 629 | +#ifndef TCC_TARGET_PE | |
| 630 | +static addr_t func_bound_offset; | |
| 631 | +static unsigned long func_bound_ind; | |
| 632 | +#endif | |
| 633 | + | |
| 634 | +static void gen_static_call(int v) | |
| 635 | +{ | |
| 636 | + Sym *sym = external_global_sym(v, &func_old_type, 0); | |
| 637 | + oad(0xe8, -4); | |
| 638 | + greloc(cur_text_section, sym, ind-4, R_X86_64_PC32); | |
| 639 | +} | |
| 640 | + | |
| 641 | +/* generate a bounded pointer addition */ | |
| 642 | +ST_FUNC void gen_bounded_ptr_add(void) | |
| 643 | +{ | |
| 644 | + /* save all temporary registers */ | |
| 645 | + save_regs(0); | |
| 646 | + | |
| 647 | + /* prepare fast x86_64 function call */ | |
| 648 | + gv(RC_RAX); | |
| 649 | + o(0xc68948); // mov %rax,%rsi ## second arg in %rsi, this must be size | |
| 650 | + vtop--; | |
| 651 | + | |
| 652 | + gv(RC_RAX); | |
| 653 | + o(0xc78948); // mov %rax,%rdi ## first arg in %rdi, this must be ptr | |
| 654 | + vtop--; | |
| 655 | + | |
| 656 | + /* do a fast function call */ | |
| 657 | + gen_static_call(TOK___bound_ptr_add); | |
| 658 | + | |
| 659 | + /* returned pointer is in rax */ | |
| 660 | + vtop++; | |
| 661 | + vtop->r = TREG_RAX | VT_BOUNDED; | |
| 662 | + | |
| 663 | + | |
| 664 | + /* relocation offset of the bounding function call point */ | |
| 665 | + vtop->c.ull = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela))); | |
| 666 | +} | |
| 667 | + | |
| 668 | +/* patch pointer addition in vtop so that pointer dereferencing is | |
| 669 | + also tested */ | |
| 670 | +ST_FUNC void gen_bounded_ptr_deref(void) | |
| 671 | +{ | |
| 672 | + addr_t func; | |
| 673 | + int size, align; | |
| 674 | + ElfW(Rela) *rel; | |
| 675 | + Sym *sym; | |
| 676 | + | |
| 677 | + size = 0; | |
| 678 | + /* XXX: put that code in generic part of tcc */ | |
| 679 | + if (!is_float(vtop->type.t)) { | |
| 680 | + if (vtop->r & VT_LVAL_BYTE) | |
| 681 | + size = 1; | |
| 682 | + else if (vtop->r & VT_LVAL_SHORT) | |
| 683 | + size = 2; | |
| 684 | + } | |
| 685 | + if (!size) | |
| 686 | + size = type_size(&vtop->type, &align); | |
| 687 | + switch(size) { | |
| 688 | + case 1: func = TOK___bound_ptr_indir1; break; | |
| 689 | + case 2: func = TOK___bound_ptr_indir2; break; | |
| 690 | + case 4: func = TOK___bound_ptr_indir4; break; | |
| 691 | + case 8: func = TOK___bound_ptr_indir8; break; | |
| 692 | + case 12: func = TOK___bound_ptr_indir12; break; | |
| 693 | + case 16: func = TOK___bound_ptr_indir16; break; | |
| 694 | + default: | |
| 695 | + tcc_error("unhandled size when dereferencing bounded pointer"); | |
| 696 | + func = 0; | |
| 697 | + break; | |
| 698 | + } | |
| 699 | + | |
| 700 | + sym = external_global_sym(func, &func_old_type, 0); | |
| 701 | + if (!sym->c) | |
| 702 | + put_extern_sym(sym, NULL, 0, 0); | |
| 703 | + | |
| 704 | + /* patch relocation */ | |
| 705 | + /* XXX: find a better solution ? */ | |
| 706 | + | |
| 707 | + rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.ull); | |
| 708 | + rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info)); | |
| 709 | +} | |
| 710 | +#endif | |
| 711 | + | |
| 628 | 712 | #ifdef TCC_TARGET_PE |
| 629 | 713 | |
| 630 | 714 | #define REGN 4 |
| @@ -1520,6 +1604,17 @@ void gfunc_prolog(CType *func_type) · 889 unmodified lines | ||
| 1520 | 1604 | sym_push(sym->v & ~SYM_FIELD, type, |
| 1521 | 1605 | VT_LOCAL | VT_LVAL, param_addr); |
| 1522 | 1606 | } |
| 1607 | + | |
| 1608 | +#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 | + oad(0xb8, 0); /* lbound section pointer */ | |
| 1614 | + o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ | |
| 1615 | + oad(0xb8, 0); /* call to function */ | |
| 1616 | + } | |
| 1617 | +#endif | |
| 1523 | 1618 | } |
| 1524 | 1619 | |
| 1525 | 1620 | /* generate function epilog */ |
| @@ -1527,6 +1622,37 @@ void gfunc_epilog(void) · 1 unmodified line | ||
| 1527 | 1622 | { |
| 1528 | 1623 | int v, saved_ind; |
| 1529 | 1624 | |
| 1625 | +#ifdef CONFIG_TCC_BCHECK | |
| 1626 | + if (tcc_state->do_bounds_check | |
| 1627 | + && func_bound_offset != lbounds_section->data_offset) | |
| 1628 | + { | |
| 1629 | + addr_t saved_ind; | |
| 1630 | + addr_t *bounds_ptr; | |
| 1631 | + Sym *sym_data; | |
| 1632 | + | |
| 1633 | + /* add end of table info */ | |
| 1634 | + bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); | |
| 1635 | + *bounds_ptr = 0; | |
| 1636 | + | |
| 1637 | + /* generate bound local allocation */ | |
| 1638 | + sym_data = get_sym_ref(&char_pointer_type, lbounds_section, | |
| 1639 | + func_bound_offset, lbounds_section->data_offset); | |
| 1640 | + saved_ind = ind; | |
| 1641 | + ind = func_bound_ind; | |
| 1642 | + greloc(cur_text_section, sym_data, ind + 1, R_386_32); | |
| 1643 | + ind = ind + 5 + 3; | |
| 1644 | + gen_static_call(TOK___bound_local_new); | |
| 1645 | + ind = saved_ind; | |
| 1646 | + | |
| 1647 | + /* generate bound check local freeing */ | |
| 1648 | + o(0x5250); /* save returned value, if any */ | |
| 1649 | + greloc(cur_text_section, sym_data, ind + 1, R_386_32); | |
| 1650 | + oad(0xb8, 0); /* mov xxx, %rax */ | |
| 1651 | + o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ | |
| 1652 | + gen_static_call(TOK___bound_local_delete); | |
| 1653 | + o(0x585a); /* restore returned value, if any */ | |
| 1654 | + } | |
| 1655 | +#endif | |
| 1530 | 1656 | o(0xc9); /* leave */ |
| 1531 | 1657 | if (func_ret_sub == 0) { |
| 1532 | 1658 | o(0xc3); /* ret */ |