History

a bounds checking code for the ARCH=x86_64

seyko committed 11 years ago

Commit 559675b1 parent e92dc598 files · +319 −64Browse files

Unified · Split

8 files
  1. lib/Makefile +1 −1
  2. lib/alloca86_64-bt.S +60 −0
  3. lib/bcheck.c +58 −53
  4. tcc.h +1 −1
  5. tccelf.c +0 −2
  6. tccgen.c +17 −2
  7. tests/boundtest.c +56 −5
  8. x86_64-gen.c +126 −0
lib/Makefile+1−1
@@ -44,7 +44,7 @@ native : TCC = $(TOP)/tcc$(EXESUF) · 43 unmodified lines
4444 cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
4545
4646 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)
4848 ARM_O = libtcc1.o armeabi.o alloca-arm.o
4949 WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
5050 WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
lib/alloca86_64-bt.S+60−0
@@ -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+/* ---------------------------------------------- */
lib/bcheck.c+58−53
@@ -31,6 +31,12 @@ · 30 unmodified lines
3131
3232 /* #define BOUND_DEBUG */
3333
34+#ifdef BOUND_DEBUG
35+ #define dprintf(a...) fprintf(a)
36+#else
37+ #define dprintf(a...)
38+#endif
39+
3440 /* define so that bound array is static (faster, but use memory if
3541 bound checking not used) */
3642 /* #define BOUND_STATIC */
@@ -50,12 +56,12 @@ · 13 unmodified lines
5056
5157 #define BOUND_T1_BITS 13
5258 #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))
5461
5562 #define BOUND_T1_SIZE (1 << BOUND_T1_BITS)
5663 #define BOUND_T2_SIZE (1 << BOUND_T2_BITS)
5764 #define BOUND_T3_SIZE (1 << BOUND_T3_BITS)
58−#define BOUND_E_BITS 4
5965
6066 #define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS)
6167 #define BOUND_T23_SIZE (1 << BOUND_T23_BITS)
@@ -64,7 +70,7 @@ · 2 unmodified lines
6470 /* this pointer is generated when bound check is incorrect */
6571 #define INVALID_POINTER ((void *)(-2))
6672 /* size of an empty region */
67−#define EMPTY_SIZE 0xffffffff
73+#define EMPTY_SIZE ((size_t)(-1))
6874 /* size of an invalid region */
6975 #define INVALID_SIZE 0
7076
@@ -168,9 +174,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) · 97 unmodified lines
168174
169175 __bound_init();
170176
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);
174178
175179 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
176180 e = (BoundEntry *)((char *)e +
@@ -197,6 +201,8 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 20 unmodified lines
197201 size_t addr = (size_t)p; \
198202 BoundEntry *e; \
199203 \
204+ dprintf(stderr, "%s %s: %p %p start\n", __FILE__, __FUNCTION__, p, offset); \
205+ \
200206 __bound_init(); \
201207 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \
202208 e = (BoundEntry *)((char *)e + \
@@ -212,6 +218,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 9 unmodified lines
212218 fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); \
213219 return INVALID_POINTER; /* return an invalid pointer */ \
214220 } \
221+ dprintf(stderr, "%s %s: return p+offset = %p\n", __FILE__, __FUNCTION__, p + offset); \
215222 return p + offset; \
216223 }
217224
@@ -232,9 +239,8 @@ BOUND_PTR_INDIR(16) · 14 unmodified lines
232239 void FASTCALL __bound_local_new(void *p1)
233240 {
234241 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);
238244 GET_CALLER_FP(fp);
239245 for(;;) {
240246 addr = p[0];
@@ -245,9 +251,7 @@ void FASTCALL __bound_local_new(void *p1) · 4 unmodified lines
245251 p += 2;
246252 __bound_new_region((void *)addr, size);
247253 }
248−#ifdef BOUND_DEBUG
249− fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
250−#endif
254+ dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
251255 }
252256
253257 /* 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
268272 static BoundEntry *__bound_new_page(void)
269273 {
270274 BoundEntry *page;
271− int i;
275+ size_t i;
272276
273277 page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE);
274278 if (!page)
@@ -296,11 +300,11 @@ static void bound_free_entry(BoundEntry *e) · 21 unmodified lines
296300 libc_free(e);
297301 }
298302
299−static inline BoundEntry *get_page(int index)
303+static BoundEntry *get_page(size_t index)
300304 {
301305 BoundEntry *page;
302306 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) {
304308 /* create a new page if necessary */
305309 page = __bound_new_page();
306310 __bound_t1[index] = page;
@@ -325,7 +329,7 @@ static void mark_invalid(size_t addr, size_t size) · 18 unmodified lines
325329 t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS);
326330
327331 #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);
329333 #endif
330334
331335 /* first we handle full pages */
@@ -364,7 +368,7 @@ static void mark_invalid(size_t addr, size_t size) · 32 unmodified lines
364368
365369 void __bound_init(void)
366370 {
367− int i;
371+ size_t i;
368372 BoundEntry *page;
369373 size_t start, size;
370374 size_t *p;
@@ -375,9 +379,7 @@ void __bound_init(void) · 4 unmodified lines
375379
376380 inited = 1;
377381
378−#ifdef BOUND_DEBUG
379− fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
380−#endif
382+ dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
381383
382384 /* save malloc hooks and install bound check hooks */
383385 install_malloc_hooks();
@@ -445,19 +447,18 @@ void __bound_init(void) · 61 unmodified lines
445447 __bound_new_region((void *)p[0], p[1]);
446448 p += 2;
447449 }
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__);
451452 }
452453
453454 void __bound_main_arg(void **p)
454455 {
455456 void *start = p;
456457 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",
459460 __FILE__, __FUNCTION__, (void *) p - start);
460−#endif
461+
461462 __bound_new_region(start, (void *) p - start);
462463 }
463464
@@ -495,10 +496,8 @@ void __bound_new_region(void *p, size_t size) · 31 unmodified lines
495496
496497 __bound_init();
497498
498−#ifdef BOUND_DEBUG
499− fprintf(stderr, "%s, %s(%p, %p) start\n",
499+ dprintf(stderr, "%s, %s(%p, %p) start\n",
500500 __FILE__, __FUNCTION__, p, size);
501−#endif
502501
503502 start = (size_t)p;
504503 end = start + size;
@@ -553,9 +552,8 @@ void __bound_new_region(void *p, size_t size) · 48 unmodified lines
553552 }
554553 add_region(e, start, size);
555554 }
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__);
559557 }
560558
561559 /* delete a region */
@@ -610,9 +608,7 @@ int __bound_delete_region(void *p) · 48 unmodified lines
610608
611609 __bound_init();
612610
613−#ifdef BOUND_DEBUG
614− fprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__);
615−#endif
611+ dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__);
616612
617613 start = (size_t)p;
618614 t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
@@ -681,9 +677,7 @@ int __bound_delete_region(void *p) · 62 unmodified lines
681677 delete_region(e, p, empty_size);
682678 }
683679
684−#ifdef BOUND_DEBUG
685− fprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__);
686−#endif
680+ dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__);
687681
688682 return 0;
689683 }
@@ -771,10 +765,9 @@ void *__bound_malloc(size_t size, const void *caller) · 81 unmodified lines
771765 if (!ptr)
772766 return NULL;
773767
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",
776769 __FILE__, __FUNCTION__, ptr, size);
777−#endif
770+
778771 __bound_new_region(ptr, size);
779772 return ptr;
780773 }
@@ -805,10 +798,9 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 24 unmodified lines
805798 if (!ptr)
806799 return NULL;
807800
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",
810802 __FILE__, __FUNCTION__, ptr, size);
811−#endif
803+
812804 __bound_new_region(ptr, size);
813805 return ptr;
814806 }
@@ -861,23 +853,23 @@ void *__bound_calloc(size_t nmemb, size_t size) · 46 unmodified lines
861853 static void bound_dump(void)
862854 {
863855 BoundEntry *page, *e;
864− int i, j;
856+ size_t i, j;
865857
866− printf("region dump:\n");
858+ fprintf(stderr, "region dump:\n");
867859 for(i=0;i<BOUND_T1_SIZE;i++) {
868860 page = __bound_t1[i];
869861 for(j=0;j<BOUND_T2_SIZE;j++) {
870862 e = page + j;
871863 /* do not print invalid or empty entries */
872864 if (e->size != EMPTY_SIZE && e->start != 0) {
873− printf("%08x:",
865+ fprintf(stderr, "%08x:",
874866 (i << (BOUND_T2_BITS + BOUND_T3_BITS)) +
875867 (j << BOUND_T3_BITS));
876868 do {
877− printf(" %08lx:%08lx", e->start, e->start + e->size);
869+ fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size);
878870 e = e->next;
879871 } while (e != NULL);
880− printf("\n");
872+ fprintf(stderr, "\n");
881873 }
882874 }
883875 }
@@ -891,19 +883,27 @@ static void __bound_check(const void *p, size_t size) · 7 unmodified lines
891883 {
892884 if (size == 0)
893885 return;
894− p = __bound_ptr_add((void *)p, size);
886+ p = __bound_ptr_add((void *)p, size - 1);
895887 if (p == INVALID_POINTER)
896888 bound_error("invalid pointer");
897889 }
898890
899891 void *__bound_memcpy(void *dst, const void *src, size_t size)
900892 {
893+ void* p;
894+
895+ dprintf(stderr, "%s %s: start, dst=%p src=%p size=%p\n", __FILE__, __FUNCTION__, dst, src, size);
896+
901897 __bound_check(dst, size);
902898 __bound_check(src, size);
903899 /* check also region overlap */
904900 if (src >= dst && src < dst + size)
905901 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;
907907 }
908908
909909 void *__bound_memmove(void *dst, const void *src, size_t size)
@@ -939,7 +939,12 @@ int __bound_strlen(const char *s) · 29 unmodified lines
939939
940940 char *__bound_strcpy(char *dst, const char *src)
941941 {
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);
943946 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;
945950 }
tcc.h+1−1
@@ -164,7 +164,7 @@ · 163 unmodified lines
164164
165165 #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
166166 !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \
167− !defined(TCC_TARGET_X86_64) && !defined(CONFIG_USE_LIBGCC)
167+ !defined(CONFIG_USE_LIBGCC)
168168 #define CONFIG_TCC_BCHECK /* enable bound checking code */
169169 #endif
170170
tccelf.c+0−2
@@ -1579,7 +1579,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 1578 unmodified lines
15791579 add_elf_sym(symtab_section, 0, 0,
15801580 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
15811581 bounds_section->sh_num, "__bounds_start");
1582−#ifdef TCC_TARGET_I386
15831582 if (s1->output_type != TCC_OUTPUT_MEMORY) {
15841583 /* add 'call __bound_init()' in .init section */
15851584
@@ -1601,7 +1600,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 15 unmodified lines
16011600 tcc_warning("__bound_init not defined");
16021601 }
16031602 #endif
1604−#endif
16051603 }
16061604
16071605 /* add tcc runtime libraries */
tccgen.c+17−2
@@ -708,7 +708,7 @@ static void gbound(void) · 707 unmodified lines
708708 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
709709 /* must save type because we must set it to int to get pointer */
710710 type1 = vtop->type;
711− vtop->type.t = VT_INT;
711+ vtop->type.t = VT_PTR;
712712 gaddrof();
713713 vpushi(0);
714714 gen_bounded_ptr_add();
@@ -1752,7 +1752,22 @@ ST_FUNC void gen_op(int op) · 1037 unmodified lines
17521752 #endif
17531753 }
17541754 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+ */
17561771 /* if evaluating constant expression, no code should be
17571772 generated, so no bound check */
17581773 if (tcc_state->do_bounds_check && !const_wanted) {
tests/boundtest.c+56−5
@@ -50,12 +50,15 @@ int test4(void) · 49 unmodified lines
5050 int i, sum = 0;
5151 int *tab4;
5252
53+ fprintf(stderr, "%s start\n", __FUNCTION__);
54+
5355 tab4 = malloc(20 * sizeof(int));
5456 for(i=0;i<20;i++) {
5557 sum += tab4[i];
5658 }
5759 free(tab4);
5860
61+ fprintf(stderr, "%s end\n", __FUNCTION__);
5962 return sum;
6063 }
6164
@@ -65,12 +68,15 @@ int test5(void) · 3 unmodified lines
6568 int i, sum = 0;
6669 int *tab4;
6770
71+ fprintf(stderr, "%s start\n", __FUNCTION__);
72+
6873 tab4 = malloc(20 * sizeof(int));
6974 for(i=0;i<21;i++) {
7075 sum += tab4[i];
7176 }
7277 free(tab4);
7378
79+ fprintf(stderr, "%s end\n", __FUNCTION__);
7480 return sum;
7581 }
7682
@@ -187,8 +193,43 @@ int test15(void) · 110 unmodified lines
187193 return strlen(p);
188194 }
189195
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+
190232 int (*table_test[])(void) = {
191− test1,
192233 test1,
193234 test2,
194235 test3,
@@ -204,23 +245,33 @@ int (*table_test[])(void) = { · 9 unmodified lines
204245 test13,
205246 test14,
206247 test15,
248+ test16,
249+ test17,
207250 };
208251
209252 int main(int argc, char **argv)
210253 {
211254 int index;
212255 int (*ftest)(void);
256+ int index_max = sizeof(table_test)/sizeof(table_test[0]);
213257
214258 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);
218263 exit(1);
219264 }
220265
221266 index = 0;
222267 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+
224275 /* well, we also use bounds on this ! */
225276 ftest = table_test[index];
226277 ftest();
x86_64-gen.c+126−0
@@ -625,6 +625,90 @@ static void gcall_or_jmp(int is_jmp) · 624 unmodified lines
625625 }
626626 }
627627
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+
628712 #ifdef TCC_TARGET_PE
629713
630714 #define REGN 4
@@ -1520,6 +1604,17 @@ void gfunc_prolog(CType *func_type) · 889 unmodified lines
15201604 sym_push(sym->v & ~SYM_FIELD, type,
15211605 VT_LOCAL | VT_LVAL, param_addr);
15221606 }
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
15231618 }
15241619
15251620 /* generate function epilog */
@@ -1527,6 +1622,37 @@ void gfunc_epilog(void) · 1 unmodified line
15271622 {
15281623 int v, saved_ind;
15291624
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
15301656 o(0xc9); /* leave */
15311657 if (func_ret_sub == 0) {
15321658 o(0xc3); /* ret */

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