History

Add bound checking to arm, arm64 and riscv64

Checked on: - i386/x86_64 (linux/windows) - arm/arm64 (rapberry pi) - riscv64 (simulator) Not tested for arm softfloat because raspberry pi does not support it. Modifications: Makefile: add arm-asm.c to arm64_FILES add riscv64-asm.c (new file) to riscv64_FILES lib/Makefile: add fetch_and_add_arm.o(new file) to ARM_O add fetch_and_add_arm64.o(new file) to ARM64_O add fetch_and_add_riscv64.o(new file) to RISCV64_O add $(BCHECK_O) to OBJ-arm/OBJ-arm64/OBJ-riscv64 tcc.h: Enable CONFIG_TCC_BCHECK for arm32/arm64/riscv64 Add arm-asm.c, riscv64-asm.c tcctok.h: for arm use memmove4 instead of memcpy4 for arm use memmove8 instead of memcpy8 tccgen.c: put_extern_sym2: for arm check memcpy/memmove/memset/memmove4/memmove8 only use alloca for i386/x86_64 for arm use memmove4 instead of memcpy4 for arm use memmove8 instead of memcpy8 fix builtin_frame_address/builtin_return_address for arm/riscv64 tccrun.c: Add riscv64 support fix rt_getcontext/rt_get_caller_pc for arm tccelf.c: tcc_load_dll: Print filename for bad architecture libtcc.c: add arm-asm.c/riscv64-asm.c tcc-doc.texi: Add arm, arm64, riscv64 support for bound checking lib/bcheck.c: add __bound___aeabi_memcpy/__bound___aeabi_memmove __bound___aeabi_memmove4/__bound___aeabi_memmove8 __bound___aeabi_memset for arm call fetch_and_add_arm/fetch_and_add_arm64/fetch_and_add_riscv64 __bound_init: Fix type for start/end/ad __bound_malloc/__bound_memalign/__bound_realloc/__bound_calloc: Use size + 1 arm-gen.c: add bound checking code like i386/x86_64 assign_regs: only malloc if nb_args != 0 gen_opi/gen_opf: Fix reload problems arm-link.c: relocate_plt: Fix address calculating arm64-gen.c: add bound checking code like i386/x86_64 load/store: remove VT_BOUNDED from sv->r arm64_hfa_aux/arm64_hfa_aux: Fix array code gfunc_prolog: only malloc if n != 0 arm64-link.c: code_reloc/gotplt_entry_type/relocate: add R_AARCH64_LDST64_ABS_LO12_NC relocate: Use addXXle instead of writeXXle riscv64-gen.c: add bound checking code like i386/x86_64 add NB_ASM_REGS/CONFIG_TCC_ASM riscv64-link.c: relocate: Use addXXle instead of writeXXle i386-gen.c/x86_64-gen.c gen_bounds_epilog: Fix code (unrelated) tests/Makefile: add $(BTESTS) for arm/arm64/riscv64 tests/tests2/Makefile: Use 85 only on i386/x86_64 because of asm code Use 113 only on i386/x86_64 because of DLL code Add 112/114/115/116 for arm/arm64/riscv64 Fix FILTER (failed on riscv64) tests/boundtest.c: Only use alloca for i386/x86_64

herman ten brugge committed 6 years ago

Commit 0b8ee731 parent 9eef33925 files · +865 −77Browse files

Unified · Split

25 files
  1. Makefile +2 −2
  2. arm-gen.c +206 −12
  3. arm-link.c +1 −1
  4. arm64-gen.c +164 −7
  5. arm64-link.c +8 −2
  6. i386-gen.c +3 −2
  7. lib/Makefile +6 −6
  8. lib/bcheck.c +86 −11
  9. lib/fetch_and_add_arm.S +16 −0
  10. lib/fetch_and_add_arm64.S +14 −0
  11. lib/fetch_and_add_riscv64.S +12 −0
  12. libtcc.c +2 −0
  13. riscv64-asm.c +94 −0
  14. riscv64-gen.c +155 −0
  15. riscv64-link.c +2 −2
  16. tcc-doc.texi +1 −1
  17. tcc.h +5 −1
  18. tccelf.c +1 −1
  19. tccgen.c +29 −2
  20. tccrun.c +21 −18
  21. tcctok.h +2 −2
  22. tests/Makefile +9 −0
  23. tests/boundtest.c +17 −2
  24. tests/tests2/Makefile +6 −3
  25. x86_64-gen.c +3 −2
Makefile+2−2
@@ -176,9 +176,9 @@ arm-fpa-ld_FILES = $(arm_FILES) · 175 unmodified lines
176arm-vfp_FILES = $(arm_FILES)176arm-vfp_FILES = $(arm_FILES)
177arm-eabi_FILES = $(arm_FILES)177arm-eabi_FILES = $(arm_FILES)
178arm-eabihf_FILES = $(arm_FILES)178arm-eabihf_FILES = $(arm_FILES)
179arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c179arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c arm-asm.c
180c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c180c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
181riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c181riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c riscv64-asm.c
182 182
183# libtcc sources183# libtcc sources
184LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))184LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
arm-gen.c+206−12
@@ -158,6 +158,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 157 unmodified lines
158static int func_sub_sp_offset, last_itod_magic;158static int func_sub_sp_offset, last_itod_magic;
159static int leaffunc;159static int leaffunc;
160 160
161#if defined(CONFIG_TCC_BCHECK)
162static addr_t func_bound_offset;
163static unsigned long func_bound_ind;
164static int func_bound_add_epilog;
165#endif
166
161#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)167#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
162static CType float_type, double_type, func_float_type, func_double_type;168static CType float_type, double_type, func_float_type, func_double_type;
163ST_FUNC void arm_init(struct TCCState *s)169ST_FUNC void arm_init(struct TCCState *s)
@@ -193,11 +199,17 @@ ST_FUNC void arm_init(struct TCCState *s) · 29 unmodified lines
193}199}
194#endif200#endif
195 201
202#define CHECK_R(r) ((r) >= TREG_R0 && (r) <= TREG_LR)
203
196static int two2mask(int a,int b) {204static int two2mask(int a,int b) {
205 if (!CHECK_R(a) || !CHECK_R(b))
206 tcc_error("compiler error! registers %i,%i is not valid",a,b);
197 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);207 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
198}208}
199 209
200static int regmask(int r) {210static int regmask(int r) {
211 if (!CHECK_R(r))
212 tcc_error("compiler error! register %i is not valid",r);
201 return reg_classes[r]&~(RC_INT|RC_FLOAT);213 return reg_classes[r]&~(RC_INT|RC_FLOAT);
202}214}
203 215
@@ -751,6 +763,14 @@ static void gcall_or_jmp(int is_jmp) · 547 unmodified lines
751 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);763 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
752 o(vtop->c.i);764 o(vtop->c.i);
753 }765 }
766#ifdef CONFIG_TCC_BCHECK
767 if (tcc_state->do_bounds_check &&
768 (vtop->sym->v == TOK_setjmp ||
769 vtop->sym->v == TOK__setjmp ||
770 vtop->sym->v == TOK_sigsetjmp ||
771 vtop->sym->v == TOK___sigsetjmp))
772 func_bound_add_epilog = 1;
773#endif
754 }else{774 }else{
755 if(!is_jmp)775 if(!is_jmp)
756 o(0xE28FE004); // add lr,pc,#4776 o(0xE28FE004); // add lr,pc,#4
@@ -759,6 +779,9 @@ static void gcall_or_jmp(int is_jmp) · 2 unmodified lines
759 }779 }
760 } else {780 } else {
761 /* otherwise, indirect call */781 /* otherwise, indirect call */
782#ifdef CONFIG_TCC_BCHECK
783 vtop->r &= ~VT_MUSTBOUND;
784#endif
762 r = gv(RC_INT);785 r = gv(RC_INT);
763 if(!is_jmp)786 if(!is_jmp)
764 o(0xE1A0E00F); // mov lr,pc787 o(0xE1A0E00F); // mov lr,pc
@@ -766,6 +789,121 @@ static void gcall_or_jmp(int is_jmp) · 1 unmodified line
766 }789 }
767}790}
768 791
792#if defined(CONFIG_TCC_BCHECK)
793
794static void gen_bounds_call(int v)
795{
796 Sym *sym = external_global_sym(v, &func_old_type);
797
798 greloc(cur_text_section, sym, ind, R_ARM_PC24);
799 o(0xebfffffe);
800}
801
802/* generate a bounded pointer addition */
803ST_FUNC void gen_bounded_ptr_add(void)
804{
805 vpush_global_sym(&func_old_type, TOK___bound_ptr_add);
806 vrott(3);
807 gfunc_call(2);
808 vpushi(0);
809 /* returned pointer is in REG_IRET */
810 vtop->r = REG_IRET | VT_BOUNDED;
811 if (nocode_wanted)
812 return;
813 /* relocation offset of the bounding function call point */
814 vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
815}
816
817/* patch pointer addition in vtop so that pointer dereferencing is
818 also tested */
819ST_FUNC void gen_bounded_ptr_deref(void)
820{
821 addr_t func;
822 int size, align;
823 Elf32_Rel *rel;
824 Sym *sym;
825
826 if (nocode_wanted)
827 return;
828
829 size = type_size(&vtop->type, &align);
830 switch(size) {
831 case 1: func = TOK___bound_ptr_indir1; break;
832 case 2: func = TOK___bound_ptr_indir2; break;
833 case 4: func = TOK___bound_ptr_indir4; break;
834 case 8: func = TOK___bound_ptr_indir8; break;
835 case 12: func = TOK___bound_ptr_indir12; break;
836 case 16: func = TOK___bound_ptr_indir16; break;
837 default:
838 /* may happen with struct member access */
839 return;
840 //tcc_error("unhandled size when dereferencing bounded pointer");
841 //func = 0;
842 //break;
843 }
844 sym = external_global_sym(func, &func_old_type);
845 if (!sym->c)
846 put_extern_sym(sym, NULL, 0, 0);
847 /* patch relocation */
848 /* XXX: find a better solution ? */
849 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i);
850 rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
851}
852
853static void gen_bounds_prolog(void)
854{
855 /* leave some room for bound checking code */
856 func_bound_offset = lbounds_section->data_offset;
857 func_bound_ind = ind;
858 func_bound_add_epilog = 0;
859 o(0xe1a00000); /* ld r0,lbounds_section->data_offset */
860 o(0xe1a00000);
861 o(0xe1a00000);
862 o(0xe1a00000); /* call __bound_local_new */
863}
864
865static void gen_bounds_epilog(void)
866{
867 addr_t saved_ind;
868 addr_t *bounds_ptr;
869 Sym *sym_data;
870 int offset_modified = func_bound_offset != lbounds_section->data_offset;
871
872 if (!offset_modified && !func_bound_add_epilog)
873 return;
874
875 /* add end of table info */
876 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
877 *bounds_ptr = 0;
878
879 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
880 func_bound_offset, lbounds_section->data_offset);
881
882 /* generate bound local allocation */
883 if (offset_modified) {
884 saved_ind = ind;
885 ind = func_bound_ind;
886 o(0xe59f0000); /* ldr r0, [pc] */
887 o(0xea000000); /* b $+4 */
888 greloc(cur_text_section, sym_data, ind, R_ARM_ABS32);
889 o(0x00000000); /* lbounds_section->data_offset */
890 gen_bounds_call(TOK___bound_local_new);
891 ind = saved_ind;
892 }
893
894 /* generate bound check local freeing */
895 o(0xe92d0003); /* push {r0,r1} */
896 o(0xed2d0b02); /* vpush {d0} */
897 o(0xe59f0000); /* ldr r0, [pc] */
898 o(0xea000000); /* b $+4 */
899 greloc(cur_text_section, sym_data, ind, R_ARM_ABS32);
900 o(0x00000000); /* lbounds_section->data_offset */
901 gen_bounds_call(TOK___bound_local_delete);
902 o(0xecbd0b02); /* vpop {d0} */
903 o(0xe8bd0003); /* pop {r0,r1} */
904}
905#endif
906
769static int unalias_ldbl(int btype)907static int unalias_ldbl(int btype)
770{908{
771#if LDOUBLE_SIZE == 8909#if LDOUBLE_SIZE == 8
@@ -956,7 +1094,7 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) · 184 unmodified lines
956 1094
957 ncrn = nsaa = 0;1095 ncrn = nsaa = 0;
958 *todo = 0;1096 *todo = 0;
959 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));1097 plan->pplans = nb_args ? tcc_malloc(nb_args * sizeof(*plan->pplans)) : NULL;
960 memset(plan->clsplans, 0, sizeof(plan->clsplans));1098 memset(plan->clsplans, 0, sizeof(plan->clsplans));
961 for(i = nb_args; i-- ;) {1099 for(i = nb_args; i-- ;) {
962 int j, start_vfpreg = 0;1100 int j, start_vfpreg = 0;
@@ -1215,10 +1353,16 @@ void gfunc_call(int nb_args) · 252 unmodified lines
1215 int def_float_abi = float_abi;1353 int def_float_abi = float_abi;
1216 int todo;1354 int todo;
1217 struct plan plan;1355 struct plan plan;
1218
1219#ifdef TCC_ARM_EABI1356#ifdef TCC_ARM_EABI
1220 int variadic;1357 int variadic;
1358#endif
1221 1359
1360#ifdef CONFIG_TCC_BCHECK
1361 if (tcc_state->do_bounds_check)
1362 gbound_args(nb_args);
1363#endif
1364
1365#ifdef TCC_ARM_EABI
1222 if (float_abi == ARM_HARD_FLOAT) {1366 if (float_abi == ARM_HARD_FLOAT) {
1223 variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);1367 variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);
1224 if (variadic || floats_in_core_regs(&vtop[-nb_args]))1368 if (variadic || floats_in_core_regs(&vtop[-nb_args]))
@@ -1367,6 +1511,10 @@ from_stack: · 142 unmodified lines
1367 last_itod_magic=0;1511 last_itod_magic=0;
1368 leaffunc = 1;1512 leaffunc = 1;
1369 loc = 0;1513 loc = 0;
1514#ifdef CONFIG_TCC_BCHECK
1515 if (tcc_state->do_bounds_check)
1516 gen_bounds_prolog();
1517#endif
1370}1518}
1371 1519
1372/* generate function epilog */1520/* generate function epilog */
@@ -1374,6 +1522,11 @@ void gfunc_epilog(void) · 1 unmodified line
1374{1522{
1375 uint32_t x;1523 uint32_t x;
1376 int diff;1524 int diff;
1525
1526#ifdef CONFIG_TCC_BCHECK
1527 if (tcc_state->do_bounds_check)
1528 gen_bounds_epilog();
1529#endif
1377 /* Copy float return value to core register if base standard is used and1530 /* Copy float return value to core register if base standard is used and
1378 float computation is made with VFP */1531 float computation is made with VFP */
1379#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)1532#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
@@ -1582,10 +1735,10 @@ void gen_opi(int op) · 202 unmodified lines
1582 vswap();1735 vswap();
1583 c=intr(gv(RC_INT));1736 c=intr(gv(RC_INT));
1584 vswap();1737 vswap();
1585 opc=0xE0000000|(opc<<20)|(c<<16);1738 opc=0xE0000000|(opc<<20);
1586 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1739 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1587 uint32_t x;1740 uint32_t x;
1588 x=stuff_const(opc|0x2000000,vtop->c.i);1741 x=stuff_const(opc|0x2000000|(c<<16),vtop->c.i);
1589 if(x) {1742 if(x) {
1590 r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));1743 r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1591 o(x|(r<<12));1744 o(x|(r<<12));
@@ -1593,8 +1746,13 @@ void gen_opi(int op) · 1 unmodified line
1593 }1746 }
1594 }1747 }
1595 fr=intr(gv(RC_INT));1748 fr=intr(gv(RC_INT));
1749 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
1750 vswap();
1751 c=intr(gv(RC_INT));
1752 vswap();
1753 }
1596 r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));1754 r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
1597 o(opc|(r<<12)|fr);1755 o(opc|(c<<16)|(r<<12)|fr);
1598done:1756done:
1599 vtop--;1757 vtop--;
1600 if (op >= TOK_ULT && op <= TOK_GT)1758 if (op >= TOK_ULT && op <= TOK_GT)
@@ -1608,15 +1766,19 @@ done: · 7 unmodified lines
1608 vswap();1766 vswap();
1609 r=intr(gv(RC_INT));1767 r=intr(gv(RC_INT));
1610 vswap();1768 vswap();
1611 opc|=r;
1612 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1769 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1613 fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));1770 fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
1614 c = vtop->c.i & 0x1f;1771 c = vtop->c.i & 0x1f;
1615 o(opc|(c<<7)|(fr<<12));1772 o(opc|r|(c<<7)|(fr<<12));
1616 } else {1773 } else {
1617 fr=intr(gv(RC_INT));1774 fr=intr(gv(RC_INT));
1775 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
1776 vswap();
1777 r=intr(gv(RC_INT));
1778 vswap();
1779 }
1618 c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));1780 c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
1619 o(opc|(c<<12)|(fr<<8)|0x10);1781 o(opc|r|(c<<12)|(fr<<8)|0x10);
1620 }1782 }
1621 vtop--;1783 vtop--;
1622 break;1784 break;
@@ -1701,9 +1863,9 @@ void gen_opf(int op) · 78 unmodified lines
1701 vtop--;1863 vtop--;
1702 o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */1864 o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
1703 } else {1865 } else {
1704 x|=vfpr(gv(RC_FLOAT));1866 gv2(RC_FLOAT,RC_FLOAT);
1705 vswap();1867 x|=vfpr(vtop[0].r);
1706 o(x|(vfpr(gv(RC_FLOAT))<<12));1868 o(x|(vfpr(vtop[-1].r) << 12));
1707 vtop--;1869 vtop--;
1708 }1870 }
1709 o(0xEEF1FA10); /* fmstat */1871 o(0xEEF1FA10); /* fmstat */
@@ -1726,6 +1888,12 @@ void gen_opf(int op) · 16 unmodified lines
1726 r2=gv(RC_FLOAT);1888 r2=gv(RC_FLOAT);
1727 x|=vfpr(r2)<<16;1889 x|=vfpr(r2)<<16;
1728 r|=regmask(r2);1890 r|=regmask(r2);
1891 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
1892 vswap();
1893 r=gv(RC_FLOAT);
1894 vswap();
1895 x=(x&~0xf)|vfpr(r);
1896 }
1729 }1897 }
1730 vtop->r=get_reg_ex(RC_FLOAT,r);1898 vtop->r=get_reg_ex(RC_FLOAT,r);
1731 if(!fneg)1899 if(!fneg)
@@ -1808,6 +1976,11 @@ void gen_opf(int op) · 76 unmodified lines
1808 r2=c2&0xf;1976 r2=c2&0xf;
1809 } else {1977 } else {
1810 r2=fpr(gv(RC_FLOAT));1978 r2=fpr(gv(RC_FLOAT));
1979 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
1980 vswap();
1981 r=fpr(gv(RC_FLOAT));
1982 vswap();
1983 }
1811 }1984 }
1812 break;1985 break;
1813 case '-':1986 case '-':
@@ -1829,6 +2002,11 @@ void gen_opf(int op) · 15 unmodified lines
1829 r=fpr(gv(RC_FLOAT));2002 r=fpr(gv(RC_FLOAT));
1830 vswap();2003 vswap();
1831 r2=fpr(gv(RC_FLOAT));2004 r2=fpr(gv(RC_FLOAT));
2005 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2006 vswap();
2007 r=fpr(gv(RC_FLOAT));
2008 vswap();
2009 }
1832 }2010 }
1833 break;2011 break;
1834 case '*':2012 case '*':
@@ -1841,8 +2019,14 @@ void gen_opf(int op) · 6 unmodified lines
1841 vswap();2019 vswap();
1842 if(c2 && c2<=0xf)2020 if(c2 && c2<=0xf)
1843 r2=c2;2021 r2=c2;
1844 else2022 else {
1845 r2=fpr(gv(RC_FLOAT));2023 r2=fpr(gv(RC_FLOAT));
2024 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2025 vswap();
2026 r=fpr(gv(RC_FLOAT));
2027 vswap();
2028 }
2029 }
1846 x|=0x100000; // muf2030 x|=0x100000; // muf
1847 break;2031 break;
1848 case '/':2032 case '/':
@@ -1863,6 +2047,11 @@ void gen_opf(int op) · 14 unmodified lines
1863 r=fpr(gv(RC_FLOAT));2047 r=fpr(gv(RC_FLOAT));
1864 vswap();2048 vswap();
1865 r2=fpr(gv(RC_FLOAT));2049 r2=fpr(gv(RC_FLOAT));
2050 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2051 vswap();
2052 r=fpr(gv(RC_FLOAT));
2053 vswap();
2054 }
1866 }2055 }
1867 break;2056 break;
1868 default:2057 default:
@@ -1915,6 +2104,11 @@ void gen_opf(int op) · 46 unmodified lines
1915 r2=c2&0xf;2104 r2=c2&0xf;
1916 } else {2105 } else {
1917 r2=fpr(gv(RC_FLOAT));2106 r2=fpr(gv(RC_FLOAT));
2107 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2108 vswap();
2109 r=fpr(gv(RC_FLOAT));
2110 vswap();
2111 }
1918 }2112 }
1919 --vtop;2113 --vtop;
1920 vset_VT_CMP(op);2114 vset_VT_CMP(op);
arm-link.c+1−1
@@ -155,7 +155,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 154 unmodified lines
155 while (p < p_end) {155 while (p < p_end) {
156 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */156 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
157 p += 4;157 p += 4;
158 add32le(p + 12, x + s1->plt->data - p);158 add32le(p + 12, x + (s1->plt->data - p));
159 p += 16;159 p += 16;
160 }160 }
161 }161 }
arm64-gen.c+164−7
@@ -81,6 +81,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 80 unmodified lines
81 RC_FLOAT | RC_F(7)81 RC_FLOAT | RC_F(7)
82};82};
83 83
84#if defined(CONFIG_TCC_BCHECK)
85static addr_t func_bound_offset;
86static unsigned long func_bound_ind;
87static int func_bound_add_epilog;
88#endif
89
84#define IS_FREG(x) ((x) >= TREG_F(0))90#define IS_FREG(x) ((x) >= TREG_F(0))
85 91
86static uint32_t intr(int r)92static uint32_t intr(int r)
@@ -454,7 +460,7 @@ static void arm64_load_cmp(int r, SValue *sv); · 367 unmodified lines
454ST_FUNC void load(int r, SValue *sv)460ST_FUNC void load(int r, SValue *sv)
455{461{
456 int svtt = sv->type.t;462 int svtt = sv->type.t;
457 int svr = sv->r;463 int svr = sv->r & ~VT_BOUNDED;
458 int svrv = svr & VT_VALMASK;464 int svrv = svr & VT_VALMASK;
459 uint64_t svcul = (uint32_t)sv->c.i;465 uint64_t svcul = (uint32_t)sv->c.i;
460 svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;466 svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;
@@ -554,7 +560,7 @@ ST_FUNC void load(int r, SValue *sv) · 93 unmodified lines
554ST_FUNC void store(int r, SValue *sv)560ST_FUNC void store(int r, SValue *sv)
555{561{
556 int svtt = sv->type.t;562 int svtt = sv->type.t;
557 int svr = sv->r;563 int svr = sv->r & ~VT_BOUNDED;
558 int svrv = svr & VT_VALMASK;564 int svrv = svr & VT_VALMASK;
559 uint64_t svcul = (uint32_t)sv->c.i;565 uint64_t svcul = (uint32_t)sv->c.i;
560 svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;566 svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;
@@ -594,11 +600,147 @@ static void arm64_gen_bl_or_b(int b) · 33 unmodified lines
594 assert(!b);600 assert(!b);
595 greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0);601 greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0);
596 o(0x94000000); // bl .602 o(0x94000000); // bl .
603#ifdef CONFIG_TCC_BCHECK
604 if (tcc_state->do_bounds_check &&
605 (vtop->sym->v == TOK_setjmp ||
606 vtop->sym->v == TOK__setjmp ||
607 vtop->sym->v == TOK_sigsetjmp ||
608 vtop->sym->v == TOK___sigsetjmp))
609 func_bound_add_epilog = 1;
610#endif
597 }611 }
598 else612 else {
613#ifdef CONFIG_TCC_BCHECK
614 vtop->r &= ~VT_MUSTBOUND;
615#endif
599 o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr616 o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr
617 }
618}
619
620#if defined(CONFIG_TCC_BCHECK)
621
622static void gen_bounds_call(int v)
623{
624 Sym *sym = external_global_sym(v, &func_old_type);
625
626 greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0);
627 o(0x94000000); // bl
600}628}
601 629
630/* generate a bounded pointer addition */
631ST_FUNC void gen_bounded_ptr_add(void)
632{
633 vpush_global_sym(&func_old_type, TOK___bound_ptr_add);
634 vrott(3);
635 gfunc_call(2);
636 vpushi(0);
637 /* returned pointer is in REG_IRET */
638 vtop->r = REG_IRET | VT_BOUNDED;
639 if (nocode_wanted)
640 return;
641 /* relocation offset of the bounding function call point */
642 vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela)));
643}
644
645/* patch pointer addition in vtop so that pointer dereferencing is
646 also tested */
647ST_FUNC void gen_bounded_ptr_deref(void)
648{
649 addr_t func;
650 int size, align;
651 ElfW(Rela) *rel;
652 Sym *sym;
653
654 if (nocode_wanted)
655 return;
656
657 size = type_size(&vtop->type, &align);
658 switch(size) {
659 case 1: func = TOK___bound_ptr_indir1; break;
660 case 2: func = TOK___bound_ptr_indir2; break;
661 case 4: func = TOK___bound_ptr_indir4; break;
662 case 8: func = TOK___bound_ptr_indir8; break;
663 case 12: func = TOK___bound_ptr_indir12; break;
664 case 16: func = TOK___bound_ptr_indir16; break;
665 default:
666 /* may happen with struct member access */
667 return;
668 //tcc_error("unhandled size when dereferencing bounded pointer");
669 //func = 0;
670 //break;
671 }
672 sym = external_global_sym(func, &func_old_type);
673 if (!sym->c)
674 put_extern_sym(sym, NULL, 0, 0);
675 /* patch relocation */
676 /* XXX: find a better solution ? */
677 rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i);
678 rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
679}
680
681static void gen_bounds_prolog(void)
682{
683 /* leave some room for bound checking code */
684 func_bound_offset = lbounds_section->data_offset;
685 func_bound_ind = ind;
686 func_bound_add_epilog = 0;
687 o(0xd503201f); /* nop -> mov x0,#0,lsl #0, lbound section pointer */
688 o(0xd503201f);
689 o(0xd503201f);
690 o(0xd503201f);
691 o(0xd503201f); /* nop -> call __bound_local_new */
692}
693
694static void gen_bounds_epilog(void)
695{
696 addr_t saved_ind;
697 addr_t *bounds_ptr;
698 Sym *sym_data;
699 int offset_modified = func_bound_offset != lbounds_section->data_offset;
700
701 if (!offset_modified && !func_bound_add_epilog)
702 return;
703
704 /* add end of table info */
705 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
706 *bounds_ptr = 0;
707
708 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
709 func_bound_offset, lbounds_section->data_offset);
710
711 /* generate bound local allocation */
712 if (offset_modified) {
713 saved_ind = ind;
714 ind = func_bound_ind;
715 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0);
716 o(0xd2800000); /* mov x0,#0,lsl #0, lbound section pointer */
717 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0);
718 o(0xf2a00000); /* movk x0,#0,lsl #16 */
719 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0);
720 o(0xf2c00000); /* movk x0,#0,lsl #32 */
721 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
722 o(0xf2e00000); /* movk x0,#0,lsl #48 */
723 gen_bounds_call(TOK___bound_local_new);
724 ind = saved_ind;
725 }
726
727 /* generate bound check local freeing */
728 o(0xf81f0fe0); /* str x0, [sp, #-16]! */
729 o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
730 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0);
731 o(0xd2800000); // mov x0,#0,lsl #0
732 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0);
733 o(0xf2a00000); // movk x0,#0,lsl #16
734 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0);
735 o(0xf2c00000); // movk x0,#0,lsl #32
736 greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
737 o(0xf2e00000); // movk x0,#0,lsl #48
738 gen_bounds_call(TOK___bound_local_delete);
739 o(0x3cc107e0); /* ldr q0, [sp], #16 */
740 o(0xf84107e0); /* ldr x0, [sp], #16 */
741}
742#endif
743
602static int arm64_hfa_aux(CType *type, int *fsize, int num)744static int arm64_hfa_aux(CType *type, int *fsize, int num)
603{745{
604 if (is_float(type->t)) {746 if (is_float(type->t)) {
@@ -642,7 +784,7 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 37 unmodified lines
642 return num;784 return num;
643 }785 }
644 }786 }
645 else if (type->t & VT_ARRAY) {787 else if ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR)) {
646 int num1;788 int num1;
647 if (!type->ref->c)789 if (!type->ref->c)
648 return num;790 return num;
@@ -659,7 +801,8 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 10 unmodified lines
659 801
660static int arm64_hfa(CType *type, int *fsize)802static int arm64_hfa(CType *type, int *fsize)
661{803{
662 if ((type->t & VT_BTYPE) == VT_STRUCT || (type->t & VT_ARRAY)) {804 if ((type->t & VT_BTYPE) == VT_STRUCT ||
805 ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR))) {
663 int sz = 0;806 int sz = 0;
664 int n = arm64_hfa_aux(type, &sz, 0);807 int n = arm64_hfa_aux(type, &sz, 0);
665 if (0 < n && n <= 4) {808 if (0 < n && n <= 4) {
@@ -839,6 +982,11 @@ ST_FUNC void gfunc_call(int nb_args) · 173 unmodified lines
839 unsigned long stack;982 unsigned long stack;
840 int i;983 int i;
841 984
985#ifdef CONFIG_TCC_BCHECK
986 if (tcc_state->do_bounds_check)
987 gbound_args(nb_args);
988#endif
989
842 return_type = &vtop[-nb_args].type.ref->type;990 return_type = &vtop[-nb_args].type.ref->type;
843 if ((return_type->t & VT_BTYPE) == VT_STRUCT)991 if ((return_type->t & VT_BTYPE) == VT_STRUCT)
844 --nb_args;992 --nb_args;
@@ -1014,8 +1162,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 169 unmodified lines
1014 1162
1015 for (sym = func_type->ref; sym; sym = sym->next)1163 for (sym = func_type->ref; sym; sym = sym->next)
1016 ++n;1164 ++n;
1017 t = tcc_malloc(n * sizeof(*t));1165 t = n ? tcc_malloc(n * sizeof(*t)) : NULL;
1018 a = tcc_malloc(n * sizeof(*a));1166 a = n ? tcc_malloc(n * sizeof(*a)) : NULL;
1019 1167
1020 for (sym = func_type->ref; sym; sym = sym->next)1168 for (sym = func_type->ref; sym; sym = sym->next)
1021 t[i++] = &sym->type;1169 t[i++] = &sym->type;
@@ -1076,6 +1224,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 54 unmodified lines
1076 o(0xd503201f); // nop1224 o(0xd503201f); // nop
1077 o(0xd503201f); // nop1225 o(0xd503201f); // nop
1078 loc = 0;1226 loc = 0;
1227#ifdef CONFIG_TCC_BCHECK
1228 if (tcc_state->do_bounds_check)
1229 gen_bounds_prolog();
1230#endif
1079}1231}
1080 1232
1081ST_FUNC void gen_va_start(void)1233ST_FUNC void gen_va_start(void)
@@ -1246,6 +1398,11 @@ ST_FUNC void gfunc_return(CType *func_type) · 164 unmodified lines
1246 1398
1247ST_FUNC void gfunc_epilog(void)1399ST_FUNC void gfunc_epilog(void)
1248{1400{
1401#ifdef CONFIG_TCC_BCHECK
1402 if (tcc_state->do_bounds_check)
1403 gen_bounds_epilog();
1404#endif
1405
1249 if (loc) {1406 if (loc) {
1250 // Insert instructions to subtract size of stack frame from SP.1407 // Insert instructions to subtract size of stack frame from SP.
1251 unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;1408 unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
arm64-link.c+8−2
@@ -37,6 +37,7 @@ int code_reloc (int reloc_type) · 36 unmodified lines
37 case R_AARCH64_ADD_ABS_LO12_NC:37 case R_AARCH64_ADD_ABS_LO12_NC:
38 case R_AARCH64_ADR_GOT_PAGE:38 case R_AARCH64_ADR_GOT_PAGE:
39 case R_AARCH64_LD64_GOT_LO12_NC:39 case R_AARCH64_LD64_GOT_LO12_NC:
40 case R_AARCH64_LDST64_ABS_LO12_NC:
40 case R_AARCH64_GLOB_DAT:41 case R_AARCH64_GLOB_DAT:
41 case R_AARCH64_COPY:42 case R_AARCH64_COPY:
42 return 0;43 return 0;
@@ -62,6 +63,7 @@ int gotplt_entry_type (int reloc_type) · 19 unmodified lines
62 case R_AARCH64_MOVW_UABS_G3:63 case R_AARCH64_MOVW_UABS_G3:
63 case R_AARCH64_ADR_PREL_PG_HI21:64 case R_AARCH64_ADR_PREL_PG_HI21:
64 case R_AARCH64_ADD_ABS_LO12_NC:65 case R_AARCH64_ADD_ABS_LO12_NC:
66 case R_AARCH64_LDST64_ABS_LO12_NC:
65 case R_AARCH64_GLOB_DAT:67 case R_AARCH64_GLOB_DAT:
66 case R_AARCH64_JUMP_SLOT:68 case R_AARCH64_JUMP_SLOT:
67 case R_AARCH64_COPY:69 case R_AARCH64_COPY:
@@ -157,10 +159,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 89 unmodified lines
157 159
158 switch(type) {160 switch(type) {
159 case R_AARCH64_ABS64:161 case R_AARCH64_ABS64:
160 write64le(ptr, val);162 add64le(ptr, val);
161 return;163 return;
162 case R_AARCH64_ABS32:164 case R_AARCH64_ABS32:
163 write32le(ptr, val);165 add32le(ptr, val);
164 return;166 return;
165 case R_AARCH64_PREL32:167 case R_AARCH64_PREL32:
166 write32le(ptr, val - addr);168 write32le(ptr, val - addr);
@@ -193,6 +195,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 26 unmodified lines
193 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |195 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
194 (val & 0xfff) << 10));196 (val & 0xfff) << 10));
195 return;197 return;
198 case R_AARCH64_LDST64_ABS_LO12_NC:
199 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
200 (val & 0xff8) << 7));
201 return;
196 case R_AARCH64_JUMP26:202 case R_AARCH64_JUMP26:
197 case R_AARCH64_CALL26:203 case R_AARCH64_CALL26:
198#ifdef DEBUG_RELOC204#ifdef DEBUG_RELOC
i386-gen.c+3−2
@@ -1089,8 +1089,9 @@ static void gen_bounds_epilog(void) · 1088 unmodified lines
1089 addr_t saved_ind;1089 addr_t saved_ind;
1090 addr_t *bounds_ptr;1090 addr_t *bounds_ptr;
1091 Sym *sym_data;1091 Sym *sym_data;
1092 int offset_modified = func_bound_offset != lbounds_section->data_offset;
1092 1093
1093 if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)1094 if (!offset_modified && !func_bound_add_epilog)
1094 return;1095 return;
1095 1096
1096 /* add end of table info */1097 /* add end of table info */
@@ -1101,7 +1102,7 @@ static void gen_bounds_epilog(void) · 4 unmodified lines
1101 func_bound_offset, lbounds_section->data_offset);1102 func_bound_offset, lbounds_section->data_offset);
1102 1103
1103 /* generate bound local allocation */1104 /* generate bound local allocation */
1104 if (func_bound_offset != lbounds_section->data_offset) {1105 if (offset_modified) {
1105 saved_ind = ind;1106 saved_ind = ind;
1106 ind = func_bound_ind;1107 ind = func_bound_ind;
1107 greloc(cur_text_section, sym_data, ind + 1, R_386_32);1108 greloc(cur_text_section, sym_data, ind + 1, R_386_32);
lib/Makefile+6−6
@@ -43,9 +43,9 @@ endif · 42 unmodified lines
43 43
44I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O)44I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O)
45X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O)45X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O)
46ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O)46ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O)
47ARM64_O = lib-arm64.o $(BT_O)47ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O)
48RISCV64_O = lib-arm64.o $(BT_O)48RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O)
49WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o49WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
50 50
51OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)51OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
@@ -53,15 +53,15 @@ OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O) · 1 unmodified line
53OBJ-x86_64-osx = $(X86_64_O) va_list.o53OBJ-x86_64-osx = $(X86_64_O) va_list.o
54OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)54OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)
55OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O)55OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O)
56OBJ-arm64 = $(ARM64_O) $(DSO_O)56OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O)
57OBJ-arm = $(ARM_O) $(DSO_O)57OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O)
58OBJ-arm-fpa = $(ARM_O) $(DSO_O)58OBJ-arm-fpa = $(ARM_O) $(DSO_O)
59OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)59OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)
60OBJ-arm-vfp = $(ARM_O) $(DSO_O)60OBJ-arm-vfp = $(ARM_O) $(DSO_O)
61OBJ-arm-eabi = $(ARM_O) $(DSO_O)61OBJ-arm-eabi = $(ARM_O) $(DSO_O)
62OBJ-arm-eabihf = $(ARM_O) $(DSO_O)62OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
63OBJ-arm-wince = $(ARM_O) $(WIN_O)63OBJ-arm-wince = $(ARM_O) $(WIN_O)
64OBJ-riscv64 = $(RISCV64_O) $(DSO_O)64OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
65 65
66OBJ-extra = $(filter $(B_O),$(OBJ-$T))66OBJ-extra = $(filter $(B_O),$(OBJ-$T))
67OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))67OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
lib/bcheck.c+86−11
@@ -163,7 +163,7 @@ typedef struct alloca_list_struct { · 162 unmodified lines
163#if defined(_WIN32)163#if defined(_WIN32)
164#define BOUND_TID_TYPE DWORD164#define BOUND_TID_TYPE DWORD
165#define BOUND_GET_TID GetCurrentThreadId()165#define BOUND_GET_TID GetCurrentThreadId()
166#elif defined(__i386__) || defined(__x86_64__)166#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__riscv)
167#define BOUND_TID_TYPE pid_t167#define BOUND_TID_TYPE pid_t
168#define BOUND_GET_TID syscall (SYS_gettid)168#define BOUND_GET_TID syscall (SYS_gettid)
169#else169#else
@@ -223,6 +223,19 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src); · 53 unmodified lines
223DLL_EXPORT char *__bound_strchr(const char *string, int ch);223DLL_EXPORT char *__bound_strchr(const char *string, int ch);
224DLL_EXPORT char *__bound_strdup(const char *s);224DLL_EXPORT char *__bound_strdup(const char *s);
225 225
226#if defined(__arm__)
227DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size);
228DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size);
229DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size);
230DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size);
231DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size);
232DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size);
233DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size);
234DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size);
235DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size);
236DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size);
237#endif
238
226#if MALLOC_REDIR239#if MALLOC_REDIR
227#define BOUND_MALLOC(a) malloc_redir(a)240#define BOUND_MALLOC(a) malloc_redir(a)
228#define BOUND_MEMALIGN(a,b) memalign_redir(a,b)241#define BOUND_MEMALIGN(a,b) memalign_redir(a,b)
@@ -320,6 +333,15 @@ static void fetch_and_add(signed char* variable, signed char value) · 91 unmodified lines
320 : // No input-only333 : // No input-only
321 : "memory"334 : "memory"
322 );335 );
336#elif defined __arm__
337 extern fetch_and_add_arm(signed char* variable, signed char value);
338 fetch_and_add_arm(variable, value);
339#elif defined __aarch64__
340 extern fetch_and_add_arm64(signed char* variable, signed char value);
341 fetch_and_add_arm64(variable, value);
342#elif defined __riscv
343 extern fetch_and_add_riscv64(signed char* variable, signed char value);
344 fetch_and_add_riscv64(variable, value);
323#else345#else
324 *variable += value;346 *variable += value;
325#endif347#endif
@@ -814,10 +836,10 @@ void __bound_init(size_t *p) · 488 unmodified lines
814 {836 {
815 FILE *fp;837 FILE *fp;
816 unsigned char found;838 unsigned char found;
817 unsigned long long start;839 unsigned long start;
818 unsigned long long end;840 unsigned long end;
819 unsigned long long ad =841 unsigned long ad =
820 (unsigned long long) __builtin_return_address(0);842 (unsigned long) __builtin_return_address(0);
821 char line[1000];843 char line[1000];
822 844
823 /* Display exec name. Usefull when a lot of code is compiled with tcc */845 /* Display exec name. Usefull when a lot of code is compiled with tcc */
@@ -835,7 +857,7 @@ void __bound_init(size_t *p) · 11 unmodified lines
835 fp = fopen ("/proc/self/maps", "r");857 fp = fopen ("/proc/self/maps", "r");
836 if (fp) {858 if (fp) {
837 while (fgets (line, sizeof(line), fp)) {859 while (fgets (line, sizeof(line), fp)) {
838 if (sscanf (line, "%Lx-%Lx", &start, &end) == 2 &&860 if (sscanf (line, "%lx-%lx", &start, &end) == 2 &&
839 ad >= start && ad < end) {861 ad >= start && ad < end) {
840 found = 1;862 found = 1;
841 break;863 break;
@@ -1099,7 +1121,7 @@ void *__bound_malloc(size_t size, const void *caller) · 257 unmodified lines
1099 INCR_COUNT(bound_malloc_count);1121 INCR_COUNT(bound_malloc_count);
1100 1122
1101 if (ptr) {1123 if (ptr) {
1102 tree = splay_insert ((size_t) ptr, size, tree);1124 tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
1103 if (tree && tree->start == (size_t) ptr)1125 if (tree && tree->start == (size_t) ptr)
1104 tree->type = TCC_TYPE_MALLOC;1126 tree->type = TCC_TYPE_MALLOC;
1105 }1127 }
@@ -1138,7 +1160,7 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 32 unmodified lines
1138 INCR_COUNT(bound_memalign_count);1160 INCR_COUNT(bound_memalign_count);
1139 1161
1140 if (ptr) {1162 if (ptr) {
1141 tree = splay_insert((size_t) ptr, size, tree);1163 tree = splay_insert((size_t) ptr, size ? size : size + 1, tree);
1142 if (tree && tree->start == (size_t) ptr)1164 if (tree && tree->start == (size_t) ptr)
1143 tree->type = TCC_TYPE_MEMALIGN;1165 tree->type = TCC_TYPE_MEMALIGN;
1144 }1166 }
@@ -1205,7 +1227,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller) · 60 unmodified lines
1205 return NULL;1227 return NULL;
1206 }1228 }
1207 1229
1208 new_ptr = BOUND_REALLOC (ptr, size);1230 new_ptr = BOUND_REALLOC (ptr, size + 1);
1209 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",1231 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
1210 __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);1232 __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
1211 1233
@@ -1216,7 +1238,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller) · 4 unmodified lines
1216 if (ptr)1238 if (ptr)
1217 tree = splay_delete ((size_t) ptr, tree);1239 tree = splay_delete ((size_t) ptr, tree);
1218 if (new_ptr) {1240 if (new_ptr) {
1219 tree = splay_insert ((size_t) new_ptr, size, tree);1241 tree = splay_insert ((size_t) new_ptr, size ? size : size + 1, tree);
1220 if (tree && tree->start == (size_t) new_ptr)1242 if (tree && tree->start == (size_t) new_ptr)
1221 tree->type = TCC_TYPE_REALLOC;1243 tree->type = TCC_TYPE_REALLOC;
1222 }1244 }
@@ -1259,7 +1281,7 @@ void *__bound_calloc(size_t nmemb, size_t size) · 36 unmodified lines
1259 if (no_checking == 0) {1281 if (no_checking == 0) {
1260 WAIT_SEM ();1282 WAIT_SEM ();
1261 INCR_COUNT(bound_calloc_count);1283 INCR_COUNT(bound_calloc_count);
1262 tree = splay_insert ((size_t) ptr, size, tree);1284 tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
1263 if (tree && tree->start == (size_t) ptr)1285 if (tree && tree->start == (size_t) ptr)
1264 tree->type = TCC_TYPE_CALLOC;1286 tree->type = TCC_TYPE_CALLOC;
1265 POST_SEM ();1287 POST_SEM ();
@@ -1387,6 +1409,59 @@ void *__bound_memset(void *s, int c, size_t n) · 121 unmodified lines
1387 return memset(s, c, n);1409 return memset(s, c, n);
1388}1410}
1389 1411
1412#if defined(__arm__)
1413void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n)
1414{
1415 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1416 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
1417 INCR_COUNT(bound_mempcy_count);
1418 __bound_check(dest, n, "memcpy dest");
1419 __bound_check(src, n, "memcpy src");
1420 if (check_overlap(dest, n, src, n, "memcpy"))
1421 return dest;
1422 return __aeabi_memcpy(dest, src, n);
1423}
1424
1425void *__bound___aeabi_memmove(void *dest, const void *src, size_t n)
1426{
1427 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1428 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
1429 INCR_COUNT(bound_memmove_count);
1430 __bound_check(dest, n, "memmove dest");
1431 __bound_check(src, n, "memmove src");
1432 return __aeabi_memmove(dest, src, n);
1433}
1434
1435void *__bound___aeabi_memmove4(void *dest, const void *src, size_t n)
1436{
1437 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1438 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
1439 INCR_COUNT(bound_memmove_count);
1440 __bound_check(dest, n, "memmove dest");
1441 __bound_check(src, n, "memmove src");
1442 return __aeabi_memmove4(dest, src, n);
1443}
1444
1445void *__bound___aeabi_memmove8(void *dest, const void *src, size_t n)
1446{
1447 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1448 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
1449 INCR_COUNT(bound_memmove_count);
1450 __bound_check(dest, n, "memmove dest");
1451 __bound_check(src, n, "memmove src");
1452 return __aeabi_memmove8(dest, src, n);
1453}
1454
1455void *__bound___aeabi_memset(void *s, int c, size_t n)
1456{
1457 dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
1458 __FILE__, __FUNCTION__, s, c, (unsigned long)n);
1459 INCR_COUNT(bound_memset_count);
1460 __bound_check(s, n, "memset");
1461 return __aeabi_memset(s, c, n);
1462}
1463#endif
1464
1390int __bound_strlen(const char *s)1465int __bound_strlen(const char *s)
1391{1466{
1392 const char *p = s;1467 const char *p = s;
lib/fetch_and_add_arm.S+16−0
@@ -0,0 +1,16 @@
1 .text
2 .align 2
3 .global fetch_and_add_arm
4 .type fetch_and_add_arm, %function
5fetch_and_add_arm:
6 .int 0xee070fba # mcr 15, 0, r0, cr7, cr10, {5}
7 .int 0xe1903f9f # ldrex r3, [r0]
8 .int 0xe2833001 # add r3, r3, #1
9 .int 0xe1802f93 # strex r2, r3, [r0]
10 .int 0xe3520000 # cmp r2, #0
11 .int 0x1afffffa # bne 4 <fetch_and_add_arm+0x4>
12 .int 0xee070fba # mcr 15, 0, r0, cr7, cr10, {5}
13 .int 0xe1a00003 # mov r0, r3
14 .int 0xe12fff1e # bx lr
15
16 .size fetch_and_add_arm, .-fetch_and_add_arm
lib/fetch_and_add_arm64.S+14−0
@@ -0,0 +1,14 @@
1 .text
2 .align 2
3 .global fetch_and_add_arm64
4 .type fetch_and_add_arm64, %function
5fetch_and_add_arm64:
6 .int 0x885f7c01 # ldxr w1, [x0]
7 .int 0x11000421 # add w1, w1, #0x1
8 .int 0x8802fc01 # stlxr w2, w1, [x0]
9 .int 0x35ffffa2 # cbnz w2, 0 <fetch_and_add_arm64>
10 .int 0xd5033bbf # dmb ish
11 .int 0x2a0103e0 # mov w0, w1
12 .int 0xd65f03c0 # ret
13
14 .size fetch_and_add_arm64, .-fetch_and_add_arm64
lib/fetch_and_add_riscv64.S+12−0
@@ -0,0 +1,12 @@
1 .text
2 .align 2
3 .global fetch_and_add_riscv64
4 .type fetch_and_add_riscv64, %function
5fetch_and_add_riscv64:
6 .short 0x4705 # li a4,1
7 .int 0x0f50000f # fence iorw,ow
8 .int 0x04e527af # amoadd.w.aq a5,a4,(a0)
9 .int 0x0017851b # addiw a0,a5,1
10 .short 0x8082 # ret
11
12 .size fetch_and_add_riscv64, .-fetch_and_add_riscv64
libtcc.c+2−0
@@ -34,6 +34,7 @@ · 33 unmodified lines
34#elif defined(TCC_TARGET_ARM64)34#elif defined(TCC_TARGET_ARM64)
35#include "arm64-gen.c"35#include "arm64-gen.c"
36#include "arm64-link.c"36#include "arm64-link.c"
37#include "arm-asm.c"
37#elif defined(TCC_TARGET_C67)38#elif defined(TCC_TARGET_C67)
38#include "c67-gen.c"39#include "c67-gen.c"
39#include "c67-link.c"40#include "c67-link.c"
@@ -45,6 +46,7 @@ · 5 unmodified lines
45#elif defined(TCC_TARGET_RISCV64)46#elif defined(TCC_TARGET_RISCV64)
46#include "riscv64-gen.c"47#include "riscv64-gen.c"
47#include "riscv64-link.c"48#include "riscv64-link.c"
49#include "riscv64-asm.c"
48#else50#else
49#error unknown target51#error unknown target
50#endif52#endif
riscv64-asm.c+94−0
@@ -0,0 +1,94 @@
1/*************************************************************/
2/*
3 * RISCV64 dummy assembler for TCC
4 *
5 */
6
7#ifdef TARGET_DEFS_ONLY
8
9#define CONFIG_TCC_ASM
10#define NB_ASM_REGS 32
11
12ST_FUNC void g(int c);
13ST_FUNC void gen_le16(int c);
14ST_FUNC void gen_le32(int c);
15
16/*************************************************************/
17#else
18/*************************************************************/
19#define USING_GLOBALS
20#include "tcc.h"
21
22static void asm_error(void)
23{
24 tcc_error("RISCV64 asm not implemented.");
25}
26
27/* XXX: make it faster ? */
28ST_FUNC void g(int c)
29{
30 int ind1;
31 if (nocode_wanted)
32 return;
33 ind1 = ind + 1;
34 if (ind1 > cur_text_section->data_allocated)
35 section_realloc(cur_text_section, ind1);
36 cur_text_section->data[ind] = c;
37 ind = ind1;
38}
39
40ST_FUNC void gen_le16 (int i)
41{
42 g(i);
43 g(i>>8);
44}
45
46ST_FUNC void gen_le32 (int i)
47{
48 gen_le16(i);
49 gen_le16(i>>16);
50}
51
52ST_FUNC void gen_expr32(ExprValue *pe)
53{
54 gen_le32(pe->v);
55}
56
57ST_FUNC void asm_opcode(TCCState *s1, int opcode)
58{
59 asm_error();
60}
61
62ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
63{
64 asm_error();
65}
66
67/* generate prolog and epilog code for asm statement */
68ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
69 int nb_outputs, int is_output,
70 uint8_t *clobber_regs,
71 int out_reg)
72{
73}
74
75ST_FUNC void asm_compute_constraints(ASMOperand *operands,
76 int nb_operands, int nb_outputs,
77 const uint8_t *clobber_regs,
78 int *pout_reg)
79{
80}
81
82ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
83{
84 asm_error();
85}
86
87ST_FUNC int asm_parse_regvar (int t)
88{
89 asm_error();
90 return -1;
91}
92
93/*************************************************************/
94#endif /* ndef TARGET_DEFS_ONLY */
riscv64-gen.c+155−0
@@ -2,6 +2,8 @@ · 1 unmodified line
2 2
3// Number of registers available to allocator:3// Number of registers available to allocator:
4#define NB_REGS 19 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7, xxx, ra, sp4#define NB_REGS 19 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7, xxx, ra, sp
5#define NB_ASM_REGS 32
6#define CONFIG_TCC_ASM
5 7
6#define TREG_R(x) (x) // x = 0..78#define TREG_R(x) (x) // x = 0..7
7#define TREG_F(x) (x + 8) // x = 0..79#define TREG_F(x) (x + 8) // x = 0..7
@@ -61,6 +63,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 53 unmodified lines
61 1 << TREG_SP63 1 << TREG_SP
62};64};
63 65
66#if defined(CONFIG_TCC_BCHECK)
67static addr_t func_bound_offset;
68static unsigned long func_bound_ind;
69static int func_bound_add_epilog;
70#endif
71
64static int ireg(int r)72static int ireg(int r)
65{73{
66 if (r == TREG_RA)74 if (r == TREG_RA)
@@ -377,6 +385,14 @@ static void gcall_or_jmp(int docall) · 310 unmodified lines
377 R_RISCV_CALL_PLT, (int)vtop->c.i);385 R_RISCV_CALL_PLT, (int)vtop->c.i);
378 o(0x17 | (tr << 7)); // auipc TR, 0 %call(func)386 o(0x17 | (tr << 7)); // auipc TR, 0 %call(func)
379 EI(0x67, 0, tr, tr, 0);// jalr TR, r(TR)387 EI(0x67, 0, tr, tr, 0);// jalr TR, r(TR)
388#ifdef CONFIG_TCC_BCHECK
389 if (tcc_state->do_bounds_check &&
390 (vtop->sym->v == TOK_setjmp ||
391 vtop->sym->v == TOK__setjmp ||
392 vtop->sym->v == TOK_sigsetjmp ||
393 vtop->sym->v == TOK___sigsetjmp))
394 func_bound_add_epilog = 1;
395#endif
380 } else if (vtop->r < VT_CONST) {396 } else if (vtop->r < VT_CONST) {
381 int r = ireg(vtop->r);397 int r = ireg(vtop->r);
382 EI(0x67, 0, tr, r, 0); // jalr TR, 0(R)398 EI(0x67, 0, tr, r, 0); // jalr TR, 0(R)
@@ -388,6 +404,130 @@ static void gcall_or_jmp(int docall) · 5 unmodified lines
388 }404 }
389}405}
390 406
407#if defined(CONFIG_TCC_BCHECK)
408
409static void gen_bounds_call(int v)
410{
411 Sym *sym = external_global_sym(v, &func_old_type);
412
413 greloca(cur_text_section, sym, ind, R_RISCV_CALL_PLT, 0);
414 o(0x17 | (1 << 7)); // auipc TR, 0 %call(func)
415 EI(0x67, 0, 1, 1, 0); // jalr TR, r(TR)
416}
417
418/* generate a bounded pointer addition */
419ST_FUNC void gen_bounded_ptr_add(void)
420{
421 vpush_global_sym(&func_old_type, TOK___bound_ptr_add);
422 vrott(3);
423 gfunc_call(2);
424 vpushi(0);
425 /* returned pointer is in REG_IRET */
426 vtop->r = REG_IRET | VT_BOUNDED;
427 if (nocode_wanted)
428 return;
429 /* relocation offset of the bounding function call point */
430 vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela)));
431}
432
433/* patch pointer addition in vtop so that pointer dereferencing is
434 also tested */
435ST_FUNC void gen_bounded_ptr_deref(void)
436{
437 addr_t func;
438 int size, align;
439 ElfW(Rela) *rel;
440 Sym *sym;
441
442 if (nocode_wanted)
443 return;
444
445 size = type_size(&vtop->type, &align);
446 switch(size) {
447 case 1: func = TOK___bound_ptr_indir1; break;
448 case 2: func = TOK___bound_ptr_indir2; break;
449 case 4: func = TOK___bound_ptr_indir4; break;
450 case 8: func = TOK___bound_ptr_indir8; break;
451 case 12: func = TOK___bound_ptr_indir12; break;
452 case 16: func = TOK___bound_ptr_indir16; break;
453 default:
454 /* may happen with struct member access */
455 return;
456 //tcc_error("unhandled size when dereferencing bounded pointer");
457 //func = 0;
458 //break;
459 }
460 sym = external_global_sym(func, &func_old_type);
461 if (!sym->c)
462 put_extern_sym(sym, NULL, 0, 0);
463 /* patch relocation */
464 /* XXX: find a better solution ? */
465 rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i);
466 rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
467}
468
469static void gen_bounds_prolog(void)
470{
471 /* leave some room for bound checking code */
472 func_bound_offset = lbounds_section->data_offset;
473 func_bound_ind = ind;
474 func_bound_add_epilog = 0;
475 o(0x00000013); /* ld a0,#lbound section pointer */
476 o(0x00000013);
477 o(0x00000013); /* nop -> call __bound_local_new */
478 o(0x00000013);
479}
480
481static void gen_bounds_epilog(void)
482{
483 static Sym label;
484 addr_t saved_ind;
485 addr_t *bounds_ptr;
486 Sym *sym_data;
487 int offset_modified = func_bound_offset != lbounds_section->data_offset;
488
489 if (!offset_modified && !func_bound_add_epilog)
490 return;
491
492 /* add end of table info */
493 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
494 *bounds_ptr = 0;
495
496 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
497 func_bound_offset, lbounds_section->data_offset);
498
499 if (!label.v) {
500 label.v = tok_alloc(".LB0 ", 4)->tok;
501 label.type.t = VT_VOID | VT_STATIC;
502 }
503 /* generate bound local allocation */
504 if (offset_modified) {
505 saved_ind = ind;
506 ind = func_bound_ind;
507 label.c = 0; /* force new local ELF symbol */
508 put_extern_sym(&label, cur_text_section, ind, 0);
509 greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
510 o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
511 greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
512 EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
513 gen_bounds_call(TOK___bound_local_new);
514 ind = saved_ind;
515 }
516
517 /* generate bound check local freeing */
518 o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
519 o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
520 label.c = 0; /* force new local ELF symbol */
521 put_extern_sym(&label, cur_text_section, ind, 0);
522 greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
523 o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
524 greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
525 EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
526 gen_bounds_call(TOK___bound_local_delete);
527 o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
528 o(0x61052542); /* fld fa0,16(sp) addi sp,sp,32 */
529}
530#endif
391static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs)531static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs)
392{532{
393 if ((type->t & VT_BTYPE) == VT_STRUCT) {533 if ((type->t & VT_BTYPE) == VT_STRUCT) {
@@ -440,6 +580,12 @@ ST_FUNC void gfunc_call(int nb_args) · 46 unmodified lines
440 int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;580 int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;
441 SValue *sv;581 SValue *sv;
442 Sym *sa;582 Sym *sa;
583
584#ifdef CONFIG_TCC_BCHECK
585 if (tcc_state->do_bounds_check)
586 gbound_args(nb_args);
587#endif
588
443 areg[0] = 0; /* int arg regs */589 areg[0] = 0; /* int arg regs */
444 areg[1] = 8; /* float arg regs */590 areg[1] = 8; /* float arg regs */
445 sa = vtop[-nb_args].type.ref->next;591 sa = vtop[-nb_args].type.ref->next;
@@ -691,6 +837,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 245 unmodified lines
691 ES(0x23, 3, 8, 10 + areg[0], -8 + num_va_regs * 8); // sd aX, loc(s0)837 ES(0x23, 3, 8, 10 + areg[0], -8 + num_va_regs * 8); // sd aX, loc(s0)
692 }838 }
693 }839 }
840#ifdef CONFIG_TCC_BCHECK
841 if (tcc_state->do_bounds_check)
842 gen_bounds_prolog();
843#endif
694}844}
695 845
696ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,846ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
@@ -732,6 +882,11 @@ ST_FUNC void gfunc_epilog(void) · 35 unmodified lines
732{882{
733 int v, saved_ind, d, large_ofs_ind;883 int v, saved_ind, d, large_ofs_ind;
734 884
885#ifdef CONFIG_TCC_BCHECK
886 if (tcc_state->do_bounds_check)
887 gen_bounds_epilog();
888#endif
889
735 loc = (loc - num_va_regs * 8);890 loc = (loc - num_va_regs * 8);
736 d = v = (-loc + 15) & -16;891 d = v = (-loc + 15) & -16;
737 892
riscv64-link.c+2−2
@@ -284,11 +284,11 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 283 unmodified lines
284 return;284 return;
285 285
286 case R_RISCV_32:286 case R_RISCV_32:
287 write32le(ptr, val);287 add32le(ptr, val);
288 return;288 return;
289 case R_RISCV_JUMP_SLOT:289 case R_RISCV_JUMP_SLOT:
290 case R_RISCV_64:290 case R_RISCV_64:
291 write64le(ptr, val);291 add64le(ptr, val);
292 return;292 return;
293 case R_RISCV_ADD64:293 case R_RISCV_ADD64:
294 write64le(ptr, read64le(ptr) + val);294 write64le(ptr, read64le(ptr) + val);
tcc-doc.texi+1−1
@@ -370,7 +370,7 @@ Print statistic information at exit of program. · 369 unmodified lines
370Try to continue in case of a bound checking error.370Try to continue in case of a bound checking error.
371@end table371@end table
372 372
373Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment.373Note: @option{-b} is only available on i386 (linux and windows), x86_64 (linux and windows), arm, arm64 and riscv64 for the moment.
374 374
375@item -bt[N]375@item -bt[N]
376Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.376Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.
tcc.h+5−1
@@ -184,7 +184,9 @@ extern long double strtold (const char *__nptr, char **__endptr); · 183 unmodified lines
184 184
185#if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT185#if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT
186# define CONFIG_TCC_BACKTRACE186# define CONFIG_TCC_BACKTRACE
187# if (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) \187# if (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \
188 defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64) || \
189 defined TCC_TARGET_RISCV64 \
188 && !defined TCC_UCLIBC && !defined TCC_MUSL190 && !defined TCC_UCLIBC && !defined TCC_MUSL
189# define CONFIG_TCC_BCHECK /* enable bound checking code */191# define CONFIG_TCC_BCHECK /* enable bound checking code */
190# endif192# endif
@@ -354,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 163 unmodified lines
354#elif defined TCC_TARGET_ARM64356#elif defined TCC_TARGET_ARM64
355# include "arm64-gen.c"357# include "arm64-gen.c"
356# include "arm64-link.c"358# include "arm64-link.c"
359# include "arm-asm.c"
357#elif defined TCC_TARGET_C67360#elif defined TCC_TARGET_C67
358# define TCC_TARGET_COFF361# define TCC_TARGET_COFF
359# include "coff.h"362# include "coff.h"
@@ -362,6 +365,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 2 unmodified lines
362#elif defined(TCC_TARGET_RISCV64)365#elif defined(TCC_TARGET_RISCV64)
363# include "riscv64-gen.c"366# include "riscv64-gen.c"
364# include "riscv64-link.c"367# include "riscv64-link.c"
368# include "riscv64-asm.c"
365#else369#else
366#error unknown target370#error unknown target
367#endif371#endif
tccelf.c+1−1
@@ -3123,7 +3123,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 3122 unmodified lines
3123 /* test CPU specific stuff */3123 /* test CPU specific stuff */
3124 if (ehdr.e_ident[5] != ELFDATA2LSB ||3124 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3125 ehdr.e_machine != EM_TCC_TARGET) {3125 ehdr.e_machine != EM_TCC_TARGET) {
3126 tcc_error_noabort("bad architecture");3126 tcc_error_noabort("bad architecture: %s", filename);
3127 return -1;3127 return -1;
3128 }3128 }
3129 3129
tccgen.c+29−2
@@ -886,6 +886,12 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 885 unmodified lines
886 /* XXX: avoid doing that for statics ? */886 /* XXX: avoid doing that for statics ? */
887 /* if bound checking is activated, we change some function887 /* if bound checking is activated, we change some function
888 names by adding the "__bound" prefix */888 names by adding the "__bound" prefix */
889#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
890 if (strcmp (name, "memcpy") == 0 ||
891 strcmp (name, "memmove") == 0 ||
892 strcmp (name, "memset") == 0)
893 goto add_bound;
894#endif
889 switch(sym->v) {895 switch(sym->v) {
890#ifdef TCC_TARGET_PE896#ifdef TCC_TARGET_PE
891 /* XXX: we rely only on malloc hooks */897 /* XXX: we rely only on malloc hooks */
@@ -897,6 +903,10 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 5 unmodified lines
897#endif903#endif
898 case TOK_memcpy:904 case TOK_memcpy:
899 case TOK_memmove:905 case TOK_memmove:
906#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
907 case TOK_memmove4:
908 case TOK_memmove8:
909#endif
900 case TOK_memset:910 case TOK_memset:
901 case TOK_memcmp:911 case TOK_memcmp:
902 case TOK_strlen:912 case TOK_strlen:
@@ -907,12 +917,17 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 4 unmodified lines
907 case TOK_strcat:917 case TOK_strcat:
908 case TOK_strchr:918 case TOK_strchr:
909 case TOK_strdup:919 case TOK_strdup:
920#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
910 case TOK_alloca:921 case TOK_alloca:
922#endif
911 case TOK_mmap:923 case TOK_mmap:
912 case TOK_munmap:924 case TOK_munmap:
913 case TOK_longjmp:925 case TOK_longjmp:
914#ifndef TCC_TARGET_PE926#ifndef TCC_TARGET_PE
915 case TOK_siglongjmp:927 case TOK_siglongjmp:
928#endif
929#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
930add_bound:
916#endif931#endif
917 strcpy(buf, "__bound_");932 strcpy(buf, "__bound_");
918 strcat(buf, name);933 strcat(buf, name);
@@ -3820,9 +3835,9 @@ ST_FUNC void vstore(void) · 2901 unmodified lines
3820 /* address of memcpy() */3835 /* address of memcpy() */
3821#ifdef TCC_ARM_EABI3836#ifdef TCC_ARM_EABI
3822 if(!(align & 7))3837 if(!(align & 7))
3823 vpush_global_sym(&func_old_type, TOK_memcpy8);3838 vpush_global_sym(&func_old_type, TOK_memmove8);
3824 else if(!(align & 3))3839 else if(!(align & 3))
3825 vpush_global_sym(&func_old_type, TOK_memcpy4);3840 vpush_global_sym(&func_old_type, TOK_memmove4);
3826 else3841 else
3827#endif3842#endif
3828 /* Use memmove, rather than memcpy, as dest and src may be same: */3843 /* Use memmove, rather than memcpy, as dest and src may be same: */
@@ -5636,13 +5651,25 @@ ST_FUNC void unary(void) · 1807 unmodified lines
5636 mk_pointer(&type);5651 mk_pointer(&type);
5637 vset(&type, VT_LOCAL, 0); /* local frame */5652 vset(&type, VT_LOCAL, 0); /* local frame */
5638 while (level--) {5653 while (level--) {
5654#ifdef TCC_TARGET_RISCV64
5655 vpushi(2*PTR_SIZE);
5656 gen_op('-');
5657#endif
5639 mk_pointer(&vtop->type);5658 mk_pointer(&vtop->type);
5640 indir(); /* -> parent frame */5659 indir(); /* -> parent frame */
5641 }5660 }
5642 if (tok1 == TOK_builtin_return_address) {5661 if (tok1 == TOK_builtin_return_address) {
5643 // assume return address is just above frame pointer on stack5662 // assume return address is just above frame pointer on stack
5663#ifdef TCC_TARGET_ARM
5664 vpushi(2*PTR_SIZE);
5665 gen_op('+');
5666#elif defined TCC_TARGET_RISCV64
5667 vpushi(PTR_SIZE);
5668 gen_op('-');
5669#else
5644 vpushi(PTR_SIZE);5670 vpushi(PTR_SIZE);
5645 gen_op('+');5671 gen_op('+');
5672#endif
5646 mk_pointer(&vtop->type);5673 mk_pointer(&vtop->type);
5647 indir();5674 indir();
5648 }5675 }
tccrun.c+21−18
@@ -648,10 +648,12 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc) · 647 unmodified lines
648#elif defined(__arm__)648#elif defined(__arm__)
649 rc->ip = uc->uc_mcontext.arm_pc;649 rc->ip = uc->uc_mcontext.arm_pc;
650 rc->fp = uc->uc_mcontext.arm_fp;650 rc->fp = uc->uc_mcontext.arm_fp;
651 rc->sp = uc->uc_mcontext.arm_sp;
652#elif defined(__aarch64__)651#elif defined(__aarch64__)
653 rc->ip = uc->uc_mcontext.pc;652 rc->ip = uc->uc_mcontext.pc;
654 rc->fp = uc->uc_mcontext.regs[29];653 rc->fp = uc->uc_mcontext.regs[29];
654#elif defined(__riscv)
655 rc->ip = uc->uc_mcontext.__gregs[REG_PC];
656 rc->fp = uc->uc_mcontext.__gregs[REG_S0];
655#endif657#endif
656}658}
657 659
@@ -805,22 +807,9 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 147 unmodified lines
805 *paddr = rc->ip;807 *paddr = rc->ip;
806 } else {808 } else {
807 addr_t fp = rc->fp;809 addr_t fp = rc->fp;
808 addr_t sp = rc->sp;810 while (--level)
809 if (sp < 0x1000)811 fp = ((addr_t *)fp)[0];
810 sp = 0x1000;812 *paddr = ((addr_t *)fp)[2];
811 /* XXX: specific to tinycc stack frames */
812 if (fp < sp + 12 || fp & 3)
813 return -1;
814 while (--level) {
815 sp = ((addr_t *)fp)[-2];
816 if (sp < fp || sp - fp > 16 || sp & 3)
817 return -1;
818 fp = ((addr_t *)fp)[-3];
819 if (fp <= sp || fp - sp < 12 || fp & 3)
820 return -1;
821 }
822 /* XXX: check address validity with program info */
823 *paddr = ((addr_t *)fp)[-1];
824 }813 }
825 return 0;814 return 0;
826#endif815#endif
@@ -829,7 +818,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 2 unmodified lines
829#elif defined(__aarch64__)818#elif defined(__aarch64__)
830static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)819static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
831{820{
832 if (level == 0) {821 if (level == 0) {
833 *paddr = rc->ip;822 *paddr = rc->ip;
834 } else {823 } else {
835 addr_t *fp = (addr_t*)rc->fp;824 addr_t *fp = (addr_t*)rc->fp;
@@ -840,6 +829,20 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 4 unmodified lines
840 return 0;829 return 0;
841}830}
842 831
832#elif defined(__riscv)
833static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
834{
835 if (level == 0) {
836 *paddr = rc->ip;
837 } else {
838 addr_t *fp = (addr_t*)rc->fp;
839 while (--level)
840 fp = (addr_t *)fp[-2];
841 *paddr = fp[-1];
842 }
843 return 0;
844}
845
843#else846#else
844#warning add arch specific rt_get_caller_pc()847#warning add arch specific rt_get_caller_pc()
845static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)848static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
tcctok.h+2−2
@@ -205,9 +205,9 @@ · 204 unmodified lines
205#if defined TCC_TARGET_ARM205#if defined TCC_TARGET_ARM
206# ifdef TCC_ARM_EABI206# ifdef TCC_ARM_EABI
207 DEF(TOK_memcpy, "__aeabi_memcpy")207 DEF(TOK_memcpy, "__aeabi_memcpy")
208 DEF(TOK_memcpy4, "__aeabi_memcpy4")
209 DEF(TOK_memcpy8, "__aeabi_memcpy8")
210 DEF(TOK_memmove, "__aeabi_memmove")208 DEF(TOK_memmove, "__aeabi_memmove")
209 DEF(TOK_memmove4, "__aeabi_memmove4")
210 DEF(TOK_memmove8, "__aeabi_memmove8")
211 DEF(TOK_memset, "__aeabi_memset")211 DEF(TOK_memset, "__aeabi_memset")
212 DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")212 DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
213 DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")213 DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
tests/Makefile+9−0
@@ -35,6 +35,15 @@ endif · 34 unmodified lines
35ifeq ($(ARCH),x86_64)35ifeq ($(ARCH),x86_64)
36 TESTS += $(BTESTS)36 TESTS += $(BTESTS)
37endif37endif
38ifeq ($(ARCH),arm)
39 TESTS += $(BTESTS)
40endif
41ifeq ($(ARCH),arm64)
42 TESTS += $(BTESTS)
43endif
44ifeq ($(ARCH),riscv64)
45 TESTS += $(BTESTS)
46endif
38endif47endif
39ifdef CONFIG_OSX # -run only48ifdef CONFIG_OSX # -run only
40 TESTS := hello-run libtest tests2-dir pp-dir49 TESTS := hello-run libtest tests2-dir pp-dir
tests/boundtest.c+17−2
@@ -169,21 +169,34 @@ int test13(void) · 168 unmodified lines
169 return strlen(tab);169 return strlen(tab);
170}170}
171 171
172#if defined __i386__ || defined __x86_64__
173#define allocf(x)
174#else
175#define alloca(x) malloc(x)
176#define allocf(x) free(x)
177#endif
178
172int test14(void)179int test14(void)
173{180{
174 char *p = alloca(TAB_SIZE);181 char *p = alloca(TAB_SIZE);
182 size_t ret;
175 memset(p, 'a', TAB_SIZE);183 memset(p, 'a', TAB_SIZE);
176 p[TAB_SIZE-1] = 0;184 p[TAB_SIZE-1] = 0;
177 return strlen(p);185 ret = strlen(p);
186 allocf(p);
187 return ret;
178}188}
179 189
180/* error */190/* error */
181int test15(void)191int test15(void)
182{192{
183 char *p = alloca(TAB_SIZE-1);193 char *p = alloca(TAB_SIZE-1);
194 size_t ret;
184 memset(p, 'a', TAB_SIZE);195 memset(p, 'a', TAB_SIZE);
185 p[TAB_SIZE-1] = 0;196 p[TAB_SIZE-1] = 0;
186 return strlen(p);197 ret = strlen(p);
198 allocf(p);
199 return ret;
187}200}
188 201
189/* ok */202/* ok */
@@ -194,6 +207,7 @@ int test16() · 4 unmodified lines
194 207
195 p = alloca(16);208 p = alloca(16);
196 strcpy(p,"12345678901234");209 strcpy(p,"12345678901234");
210 allocf(p);
197 211
198 /* Test alloca embedded in a larger expression */212 /* Test alloca embedded in a larger expression */
199 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );213 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );
@@ -209,6 +223,7 @@ int test17() · 9 unmodified lines
209 223
210 p = alloca(16);224 p = alloca(16);
211 strcpy(p,"12345678901234");225 strcpy(p,"12345678901234");
226 allocf(p);
212 227
213 /* Test alloca embedded in a larger expression */228 /* Test alloca embedded in a larger expression */
214 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );229 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );
tests/tests2/Makefile+6−3
@@ -23,8 +23,11 @@ ifeq (,$(filter i386,$(ARCH))) · 22 unmodified lines
23 SKIP += 98_al_ax_extend.test 99_fastcall.test23 SKIP += 98_al_ax_extend.test 99_fastcall.test
24endif24endif
25ifeq (,$(filter i386 x86_64,$(ARCH)))25ifeq (,$(filter i386 x86_64,$(ARCH)))
26 SKIP += 85_asm-outside-function.test26 SKIP += 85_asm-outside-function.test # x86 asm
27 SKIP += 112_backtrace.test 113_btdll.test27 SKIP += 113_btdll.test # dll support needed
28endif
29ifeq (,$(filter i386 x86_64 arm arm64 riscv64,$(ARCH)))
30 SKIP += 112_backtrace.test
28 SKIP += 114_bound_signal.test31 SKIP += 114_bound_signal.test
29 SKIP += 115_bound_setjmp.test32 SKIP += 115_bound_setjmp.test
30 SKIP += 116_bound_setjmp2.test33 SKIP += 116_bound_setjmp2.test
@@ -82,7 +85,7 @@ GEN-ALWAYS = · 51 unmodified lines
82 85
83112_backtrace.test: FLAGS += -dt -b86112_backtrace.test: FLAGS += -dt -b
84112_backtrace.test 113_btdll.test: FILTER += \87112_backtrace.test 113_btdll.test: FILTER += \
85 -e 's;[0-9A-Fa-fx]\{8,\};........;g' \88 -e 's;[0-9A-Fa-fx]\{5,\};........;g' \
86 -e 's;0x[0-9A-Fa-f]\+;0x?;g'89 -e 's;0x[0-9A-Fa-f]\+;0x?;g'
87 90
88# this test creates two DLLs and an EXE91# this test creates two DLLs and an EXE
x86_64-gen.c+3−2
@@ -744,8 +744,9 @@ static void gen_bounds_epilog(void) · 743 unmodified lines
744 addr_t saved_ind;744 addr_t saved_ind;
745 addr_t *bounds_ptr;745 addr_t *bounds_ptr;
746 Sym *sym_data;746 Sym *sym_data;
747 int offset_modified = func_bound_offset != lbounds_section->data_offset;
747 748
748 if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)749 if (!offset_modified && !func_bound_add_epilog)
749 return;750 return;
750 751
751 /* add end of table info */752 /* add end of table info */
@@ -756,7 +757,7 @@ static void gen_bounds_epilog(void) · 4 unmodified lines
756 func_bound_offset, lbounds_section->data_offset);757 func_bound_offset, lbounds_section->data_offset);
757 758
758 /* generate bound local allocation */759 /* generate bound local allocation */
759 if (func_bound_offset != lbounds_section->data_offset) {760 if (offset_modified) {
760 saved_ind = ind;761 saved_ind = ind;
761 ind = func_bound_ind;762 ind = func_bound_ind;
762 greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);763 greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 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