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
Unified · Split
| @@ -176,9 +176,9 @@ arm-fpa-ld_FILES = $(arm_FILES) · 175 unmodified lines | |||
| 176 | arm-vfp_FILES = $(arm_FILES) | 176 | arm-vfp_FILES = $(arm_FILES) |
| 177 | arm-eabi_FILES = $(arm_FILES) | 177 | arm-eabi_FILES = $(arm_FILES) |
| 178 | arm-eabihf_FILES = $(arm_FILES) | 178 | arm-eabihf_FILES = $(arm_FILES) |
| 179 | arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c | 179 | arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c arm-asm.c |
| 180 | c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c | 180 | c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c |
| 181 | riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c | 181 | riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c riscv64-asm.c |
| 182 | 182 | ||
| 183 | # libtcc sources | 183 | # libtcc sources |
| 184 | LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES))) | 184 | LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES))) |
| @@ -158,6 +158,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 157 unmodified lines | |||
| 158 | static int func_sub_sp_offset, last_itod_magic; | 158 | static int func_sub_sp_offset, last_itod_magic; |
| 159 | static int leaffunc; | 159 | static int leaffunc; |
| 160 | 160 | ||
| 161 | #if defined(CONFIG_TCC_BCHECK) | ||
| 162 | static addr_t func_bound_offset; | ||
| 163 | static unsigned long func_bound_ind; | ||
| 164 | static 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) |
| 162 | static CType float_type, double_type, func_float_type, func_double_type; | 168 | static CType float_type, double_type, func_float_type, func_double_type; |
| 163 | ST_FUNC void arm_init(struct TCCState *s) | 169 | ST_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 | #endif | 200 | #endif |
| 195 | 201 | ||
| 202 | #define CHECK_R(r) ((r) >= TREG_R0 && (r) <= TREG_LR) | ||
| 203 | |||
| 196 | static int two2mask(int a,int b) { | 204 | static 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 | ||
| 200 | static int regmask(int r) { | 210 | static 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,#4 | 776 | 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,pc | 787 | 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 | |||
| 794 | static 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 */ | ||
| 803 | ST_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 */ | ||
| 819 | ST_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 | |||
| 853 | static 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 | |||
| 865 | static 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 | |||
| 769 | static int unalias_ldbl(int btype) | 907 | static int unalias_ldbl(int btype) |
| 770 | { | 908 | { |
| 771 | #if LDOUBLE_SIZE == 8 | 909 | #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_EABI | 1356 | #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 and | 1530 | /* 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); |
| 1598 | done: | 1756 | done: |
| 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 | else | 2022 | 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; // muf | 2030 | 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); |
| @@ -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 | } |
| @@ -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) | ||
| 85 | static addr_t func_bound_offset; | ||
| 86 | static unsigned long func_bound_ind; | ||
| 87 | static 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 | ||
| 86 | static uint32_t intr(int r) | 92 | static uint32_t intr(int r) |
| @@ -454,7 +460,7 @@ static void arm64_load_cmp(int r, SValue *sv); · 367 unmodified lines | |||
| 454 | ST_FUNC void load(int r, SValue *sv) | 460 | ST_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 | |||
| 554 | ST_FUNC void store(int r, SValue *sv) | 560 | ST_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 | else | 612 | 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/blr | 616 | o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr |
| 617 | } | ||
| 618 | } | ||
| 619 | |||
| 620 | #if defined(CONFIG_TCC_BCHECK) | ||
| 621 | |||
| 622 | static 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 */ | ||
| 631 | ST_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 */ | ||
| 647 | ST_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 | |||
| 681 | static 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 | |||
| 694 | static 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 | |||
| 602 | static int arm64_hfa_aux(CType *type, int *fsize, int num) | 744 | static 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 | ||
| 660 | static int arm64_hfa(CType *type, int *fsize) | 802 | static 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); // nop | 1224 | o(0xd503201f); // nop |
| 1077 | o(0xd503201f); // nop | 1225 | 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 | ||
| 1081 | ST_FUNC void gen_va_start(void) | 1233 | ST_FUNC void gen_va_start(void) |
| @@ -1246,6 +1398,11 @@ ST_FUNC void gfunc_return(CType *func_type) · 164 unmodified lines | |||
| 1246 | 1398 | ||
| 1247 | ST_FUNC void gfunc_epilog(void) | 1399 | ST_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; |
| @@ -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_RELOC | 204 | #ifdef DEBUG_RELOC |
| @@ -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); |
| @@ -43,9 +43,9 @@ endif · 42 unmodified lines | |||
| 43 | 43 | ||
| 44 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) | 44 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) |
| 45 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) | 45 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) |
| 46 | ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O) | 46 | ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O) |
| 47 | ARM64_O = lib-arm64.o $(BT_O) | 47 | ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O) |
| 48 | RISCV64_O = lib-arm64.o $(BT_O) | 48 | RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O) |
| 49 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o | 49 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o |
| 50 | 50 | ||
| 51 | OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O) | 51 | OBJ-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 | |||
| 53 | OBJ-x86_64-osx = $(X86_64_O) va_list.o | 53 | OBJ-x86_64-osx = $(X86_64_O) va_list.o |
| 54 | OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O) | 54 | OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O) |
| 55 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O) | 55 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O) |
| 56 | OBJ-arm64 = $(ARM64_O) $(DSO_O) | 56 | OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O) |
| 57 | OBJ-arm = $(ARM_O) $(DSO_O) | 57 | OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O) |
| 58 | OBJ-arm-fpa = $(ARM_O) $(DSO_O) | 58 | OBJ-arm-fpa = $(ARM_O) $(DSO_O) |
| 59 | OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O) | 59 | OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O) |
| 60 | OBJ-arm-vfp = $(ARM_O) $(DSO_O) | 60 | OBJ-arm-vfp = $(ARM_O) $(DSO_O) |
| 61 | OBJ-arm-eabi = $(ARM_O) $(DSO_O) | 61 | OBJ-arm-eabi = $(ARM_O) $(DSO_O) |
| 62 | OBJ-arm-eabihf = $(ARM_O) $(DSO_O) | 62 | OBJ-arm-eabihf = $(ARM_O) $(DSO_O) |
| 63 | OBJ-arm-wince = $(ARM_O) $(WIN_O) | 63 | OBJ-arm-wince = $(ARM_O) $(WIN_O) |
| 64 | OBJ-riscv64 = $(RISCV64_O) $(DSO_O) | 64 | OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O) |
| 65 | 65 | ||
| 66 | OBJ-extra = $(filter $(B_O),$(OBJ-$T)) | 66 | OBJ-extra = $(filter $(B_O),$(OBJ-$T)) |
| 67 | OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) | 67 | OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) |
| @@ -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 DWORD | 164 | #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_t | 167 | #define BOUND_TID_TYPE pid_t |
| 168 | #define BOUND_GET_TID syscall (SYS_gettid) | 168 | #define BOUND_GET_TID syscall (SYS_gettid) |
| 169 | #else | 169 | #else |
| @@ -223,6 +223,19 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src); · 53 unmodified lines | |||
| 223 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); | 223 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); |
| 224 | DLL_EXPORT char *__bound_strdup(const char *s); | 224 | DLL_EXPORT char *__bound_strdup(const char *s); |
| 225 | 225 | ||
| 226 | #if defined(__arm__) | ||
| 227 | DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size); | ||
| 228 | DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size); | ||
| 229 | DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size); | ||
| 230 | DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size); | ||
| 231 | DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size); | ||
| 232 | DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size); | ||
| 233 | DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size); | ||
| 234 | DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size); | ||
| 235 | DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size); | ||
| 236 | DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size); | ||
| 237 | #endif | ||
| 238 | |||
| 226 | #if MALLOC_REDIR | 239 | #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-only | 333 | : // 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 | #else | 345 | #else |
| 324 | *variable += value; | 346 | *variable += value; |
| 325 | #endif | 347 | #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__) | ||
| 1413 | void *__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 | |||
| 1425 | void *__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 | |||
| 1435 | void *__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 | |||
| 1445 | void *__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 | |||
| 1455 | void *__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 | |||
| 1390 | int __bound_strlen(const char *s) | 1465 | int __bound_strlen(const char *s) |
| 1391 | { | 1466 | { |
| 1392 | const char *p = s; | 1467 | const char *p = s; |
| @@ -0,0 +1,16 @@ | |||
| 1 | .text | ||
| 2 | .align 2 | ||
| 3 | .global fetch_and_add_arm | ||
| 4 | .type fetch_and_add_arm, %function | ||
| 5 | fetch_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 | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | .text | ||
| 2 | .align 2 | ||
| 3 | .global fetch_and_add_arm64 | ||
| 4 | .type fetch_and_add_arm64, %function | ||
| 5 | fetch_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 | ||
| @@ -0,0 +1,12 @@ | |||
| 1 | .text | ||
| 2 | .align 2 | ||
| 3 | .global fetch_and_add_riscv64 | ||
| 4 | .type fetch_and_add_riscv64, %function | ||
| 5 | fetch_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 | ||
| @@ -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 | #else | 50 | #else |
| 49 | #error unknown target | 51 | #error unknown target |
| 50 | #endif | 52 | #endif |
| @@ -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 | |||
| 12 | ST_FUNC void g(int c); | ||
| 13 | ST_FUNC void gen_le16(int c); | ||
| 14 | ST_FUNC void gen_le32(int c); | ||
| 15 | |||
| 16 | /*************************************************************/ | ||
| 17 | #else | ||
| 18 | /*************************************************************/ | ||
| 19 | #define USING_GLOBALS | ||
| 20 | #include "tcc.h" | ||
| 21 | |||
| 22 | static void asm_error(void) | ||
| 23 | { | ||
| 24 | tcc_error("RISCV64 asm not implemented."); | ||
| 25 | } | ||
| 26 | |||
| 27 | /* XXX: make it faster ? */ | ||
| 28 | ST_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 | |||
| 40 | ST_FUNC void gen_le16 (int i) | ||
| 41 | { | ||
| 42 | g(i); | ||
| 43 | g(i>>8); | ||
| 44 | } | ||
| 45 | |||
| 46 | ST_FUNC void gen_le32 (int i) | ||
| 47 | { | ||
| 48 | gen_le16(i); | ||
| 49 | gen_le16(i>>16); | ||
| 50 | } | ||
| 51 | |||
| 52 | ST_FUNC void gen_expr32(ExprValue *pe) | ||
| 53 | { | ||
| 54 | gen_le32(pe->v); | ||
| 55 | } | ||
| 56 | |||
| 57 | ST_FUNC void asm_opcode(TCCState *s1, int opcode) | ||
| 58 | { | ||
| 59 | asm_error(); | ||
| 60 | } | ||
| 61 | |||
| 62 | ST_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 */ | ||
| 68 | ST_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 | |||
| 75 | ST_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 | |||
| 82 | ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str) | ||
| 83 | { | ||
| 84 | asm_error(); | ||
| 85 | } | ||
| 86 | |||
| 87 | ST_FUNC int asm_parse_regvar (int t) | ||
| 88 | { | ||
| 89 | asm_error(); | ||
| 90 | return -1; | ||
| 91 | } | ||
| 92 | |||
| 93 | /*************************************************************/ | ||
| 94 | #endif /* ndef TARGET_DEFS_ONLY */ | ||
| @@ -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, sp | 4 | #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..7 | 8 | #define TREG_R(x) (x) // x = 0..7 |
| 7 | #define TREG_F(x) (x + 8) // x = 0..7 | 9 | #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_SP | 63 | 1 << TREG_SP |
| 62 | }; | 64 | }; |
| 63 | 65 | ||
| 66 | #if defined(CONFIG_TCC_BCHECK) | ||
| 67 | static addr_t func_bound_offset; | ||
| 68 | static unsigned long func_bound_ind; | ||
| 69 | static int func_bound_add_epilog; | ||
| 70 | #endif | ||
| 71 | |||
| 64 | static int ireg(int r) | 72 | static 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 | |||
| 409 | static 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 */ | ||
| 419 | ST_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 */ | ||
| 435 | ST_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 | |||
| 469 | static 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 | |||
| 481 | static 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 | ||
| 391 | static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs) | 531 | static 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 | ||
| 696 | ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, | 846 | ST_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 | ||
| @@ -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); |
| @@ -370,7 +370,7 @@ Print statistic information at exit of program. · 369 unmodified lines | |||
| 370 | Try to continue in case of a bound checking error. | 370 | Try to continue in case of a bound checking error. |
| 371 | @end table | 371 | @end table |
| 372 | 372 | ||
| 373 | Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment. | 373 | Note: @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] |
| 376 | Display N callers in stack traces. This is useful with @option{-g} or @option{-b}. | 376 | Display N callers in stack traces. This is useful with @option{-g} or @option{-b}. |
| @@ -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_TCCBOOT | 185 | #if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT |
| 186 | # define CONFIG_TCC_BACKTRACE | 186 | # 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_MUSL | 190 | && !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 | # endif | 192 | # endif |
| @@ -354,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 163 unmodified lines | |||
| 354 | #elif defined TCC_TARGET_ARM64 | 356 | #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_C67 | 360 | #elif defined TCC_TARGET_C67 |
| 358 | # define TCC_TARGET_COFF | 361 | # 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 | #else | 369 | #else |
| 366 | #error unknown target | 370 | #error unknown target |
| 367 | #endif | 371 | #endif |
| @@ -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 | ||
| @@ -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 function | 887 | /* 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_PE | 896 | #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 | #endif | 903 | #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_PE | 926 | #ifndef TCC_TARGET_PE |
| 915 | case TOK_siglongjmp: | 927 | case TOK_siglongjmp: |
| 928 | #endif | ||
| 929 | #if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI) | ||
| 930 | add_bound: | ||
| 916 | #endif | 931 | #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_EABI | 3836 | #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 | else | 3841 | else |
| 3827 | #endif | 3842 | #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 stack | 5662 | // 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 | } |
| @@ -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 | #endif | 657 | #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 | #endif | 815 | #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__) |
| 830 | static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) | 819 | static 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) | ||
| 833 | static 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 | #else | 846 | #else |
| 844 | #warning add arch specific rt_get_caller_pc() | 847 | #warning add arch specific rt_get_caller_pc() |
| 845 | static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) | 848 | static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) |
| @@ -205,9 +205,9 @@ · 204 unmodified lines | |||
| 205 | #if defined TCC_TARGET_ARM | 205 | #if defined TCC_TARGET_ARM |
| 206 | # ifdef TCC_ARM_EABI | 206 | # 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") |
| @@ -35,6 +35,15 @@ endif · 34 unmodified lines | |||
| 35 | ifeq ($(ARCH),x86_64) | 35 | ifeq ($(ARCH),x86_64) |
| 36 | TESTS += $(BTESTS) | 36 | TESTS += $(BTESTS) |
| 37 | endif | 37 | endif |
| 38 | ifeq ($(ARCH),arm) | ||
| 39 | TESTS += $(BTESTS) | ||
| 40 | endif | ||
| 41 | ifeq ($(ARCH),arm64) | ||
| 42 | TESTS += $(BTESTS) | ||
| 43 | endif | ||
| 44 | ifeq ($(ARCH),riscv64) | ||
| 45 | TESTS += $(BTESTS) | ||
| 46 | endif | ||
| 38 | endif | 47 | endif |
| 39 | ifdef CONFIG_OSX # -run only | 48 | ifdef CONFIG_OSX # -run only |
| 40 | TESTS := hello-run libtest tests2-dir pp-dir | 49 | TESTS := hello-run libtest tests2-dir pp-dir |
| @@ -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 | |||
| 172 | int test14(void) | 179 | int 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 */ |
| 181 | int test15(void) | 191 | int 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) ); |
| @@ -23,8 +23,11 @@ ifeq (,$(filter i386,$(ARCH))) · 22 unmodified lines | |||
| 23 | SKIP += 98_al_ax_extend.test 99_fastcall.test | 23 | SKIP += 98_al_ax_extend.test 99_fastcall.test |
| 24 | endif | 24 | endif |
| 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) | 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) |
| 26 | SKIP += 85_asm-outside-function.test | 26 | SKIP += 85_asm-outside-function.test # x86 asm |
| 27 | SKIP += 112_backtrace.test 113_btdll.test | 27 | SKIP += 113_btdll.test # dll support needed |
| 28 | endif | ||
| 29 | ifeq (,$(filter i386 x86_64 arm arm64 riscv64,$(ARCH))) | ||
| 30 | SKIP += 112_backtrace.test | ||
| 28 | SKIP += 114_bound_signal.test | 31 | SKIP += 114_bound_signal.test |
| 29 | SKIP += 115_bound_setjmp.test | 32 | SKIP += 115_bound_setjmp.test |
| 30 | SKIP += 116_bound_setjmp2.test | 33 | SKIP += 116_bound_setjmp2.test |
| @@ -82,7 +85,7 @@ GEN-ALWAYS = · 51 unmodified lines | |||
| 82 | 85 | ||
| 83 | 112_backtrace.test: FLAGS += -dt -b | 86 | 112_backtrace.test: FLAGS += -dt -b |
| 84 | 112_backtrace.test 113_btdll.test: FILTER += \ | 87 | 112_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 EXE | 91 | # this test creates two DLLs and an EXE |
| @@ -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); |