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 | 176 | arm-vfp_FILES = $(arm_FILES) |
| 177 | 177 | arm-eabi_FILES = $(arm_FILES) |
| 178 | 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 | 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 | 183 | # libtcc sources |
| 184 | 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 | 158 | static int func_sub_sp_offset, last_itod_magic; |
| 159 | 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 | 167 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
| 162 | 168 | static CType float_type, double_type, func_float_type, func_double_type; |
| 163 | 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 | 200 | #endif |
| 195 | 201 | |
| 202 | +#define CHECK_R(r) ((r) >= TREG_R0 && (r) <= TREG_LR) | |
| 203 | + | |
| 196 | 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 | 207 | return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); |
| 198 | 208 | } |
| 199 | 209 | |
| 200 | 210 | static int regmask(int r) { |
| 211 | + if (!CHECK_R(r)) | |
| 212 | + tcc_error("compiler error! register %i is not valid",r); | |
| 201 | 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 | 763 | greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); |
| 752 | 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 | 774 | }else{ |
| 755 | 775 | if(!is_jmp) |
| 756 | 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 | 780 | } else { |
| 761 | 781 | /* otherwise, indirect call */ |
| 782 | +#ifdef CONFIG_TCC_BCHECK | |
| 783 | + vtop->r &= ~VT_MUSTBOUND; | |
| 784 | +#endif | |
| 762 | 785 | r = gv(RC_INT); |
| 763 | 786 | if(!is_jmp) |
| 764 | 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 | 907 | static int unalias_ldbl(int btype) |
| 770 | 908 | { |
| 771 | 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 | 1095 | ncrn = nsaa = 0; |
| 958 | 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 | 1098 | memset(plan->clsplans, 0, sizeof(plan->clsplans)); |
| 961 | 1099 | for(i = nb_args; i-- ;) { |
| 962 | 1100 | int j, start_vfpreg = 0; |
| @@ -1215,10 +1353,16 @@ void gfunc_call(int nb_args) · 252 unmodified lines | ||
| 1215 | 1353 | int def_float_abi = float_abi; |
| 1216 | 1354 | int todo; |
| 1217 | 1355 | struct plan plan; |
| 1218 | − | |
| 1219 | 1356 | #ifdef TCC_ARM_EABI |
| 1220 | 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 | 1366 | if (float_abi == ARM_HARD_FLOAT) { |
| 1223 | 1367 | variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); |
| 1224 | 1368 | if (variadic || floats_in_core_regs(&vtop[-nb_args])) |
| @@ -1367,6 +1511,10 @@ from_stack: · 142 unmodified lines | ||
| 1367 | 1511 | last_itod_magic=0; |
| 1368 | 1512 | leaffunc = 1; |
| 1369 | 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 | 1520 | /* generate function epilog */ |
| @@ -1374,6 +1522,11 @@ void gfunc_epilog(void) · 1 unmodified line | ||
| 1374 | 1522 | { |
| 1375 | 1523 | uint32_t x; |
| 1376 | 1524 | int diff; |
| 1525 | + | |
| 1526 | +#ifdef CONFIG_TCC_BCHECK | |
| 1527 | + if (tcc_state->do_bounds_check) | |
| 1528 | + gen_bounds_epilog(); | |
| 1529 | +#endif | |
| 1377 | 1530 | /* Copy float return value to core register if base standard is used and |
| 1378 | 1531 | float computation is made with VFP */ |
| 1379 | 1532 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
| @@ -1582,10 +1735,10 @@ void gen_opi(int op) · 202 unmodified lines | ||
| 1582 | 1735 | vswap(); |
| 1583 | 1736 | c=intr(gv(RC_INT)); |
| 1584 | 1737 | vswap(); |
| 1585 | − opc=0xE0000000|(opc<<20)|(c<<16); | |
| 1738 | + opc=0xE0000000|(opc<<20); | |
| 1586 | 1739 | if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 1587 | 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 | 1742 | if(x) { |
| 1590 | 1743 | r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); |
| 1591 | 1744 | o(x|(r<<12)); |
| @@ -1593,8 +1746,13 @@ void gen_opi(int op) · 1 unmodified line | ||
| 1593 | 1746 | } |
| 1594 | 1747 | } |
| 1595 | 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 | 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 | 1756 | done: |
| 1599 | 1757 | vtop--; |
| 1600 | 1758 | if (op >= TOK_ULT && op <= TOK_GT) |
| @@ -1608,15 +1766,19 @@ done: · 7 unmodified lines | ||
| 1608 | 1766 | vswap(); |
| 1609 | 1767 | r=intr(gv(RC_INT)); |
| 1610 | 1768 | vswap(); |
| 1611 | − opc|=r; | |
| 1612 | 1769 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 1613 | 1770 | fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); |
| 1614 | 1771 | c = vtop->c.i & 0x1f; |
| 1615 | − o(opc|(c<<7)|(fr<<12)); | |
| 1772 | + o(opc|r|(c<<7)|(fr<<12)); | |
| 1616 | 1773 | } else { |
| 1617 | 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 | 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 | 1783 | vtop--; |
| 1622 | 1784 | break; |
| @@ -1701,9 +1863,9 @@ void gen_opf(int op) · 78 unmodified lines | ||
| 1701 | 1863 | vtop--; |
| 1702 | 1864 | o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */ |
| 1703 | 1865 | } else { |
| 1704 | − x|=vfpr(gv(RC_FLOAT)); | |
| 1705 | − vswap(); | |
| 1706 | − o(x|(vfpr(gv(RC_FLOAT))<<12)); | |
| 1866 | + gv2(RC_FLOAT,RC_FLOAT); | |
| 1867 | + x|=vfpr(vtop[0].r); | |
| 1868 | + o(x|(vfpr(vtop[-1].r) << 12)); | |
| 1707 | 1869 | vtop--; |
| 1708 | 1870 | } |
| 1709 | 1871 | o(0xEEF1FA10); /* fmstat */ |
| @@ -1726,6 +1888,12 @@ void gen_opf(int op) · 16 unmodified lines | ||
| 1726 | 1888 | r2=gv(RC_FLOAT); |
| 1727 | 1889 | x|=vfpr(r2)<<16; |
| 1728 | 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 | 1898 | vtop->r=get_reg_ex(RC_FLOAT,r); |
| 1731 | 1899 | if(!fneg) |
| @@ -1808,6 +1976,11 @@ void gen_opf(int op) · 76 unmodified lines | ||
| 1808 | 1976 | r2=c2&0xf; |
| 1809 | 1977 | } else { |
| 1810 | 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 | 1985 | break; |
| 1813 | 1986 | case '-': |
| @@ -1829,6 +2002,11 @@ void gen_opf(int op) · 15 unmodified lines | ||
| 1829 | 2002 | r=fpr(gv(RC_FLOAT)); |
| 1830 | 2003 | vswap(); |
| 1831 | 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 | 2011 | break; |
| 1834 | 2012 | case '*': |
| @@ -1841,8 +2019,14 @@ void gen_opf(int op) · 6 unmodified lines | ||
| 1841 | 2019 | vswap(); |
| 1842 | 2020 | if(c2 && c2<=0xf) |
| 1843 | 2021 | r2=c2; |
| 1844 | − else | |
| 2022 | + else { | |
| 1845 | 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 | 2030 | x|=0x100000; // muf |
| 1847 | 2031 | break; |
| 1848 | 2032 | case '/': |
| @@ -1863,6 +2047,11 @@ void gen_opf(int op) · 14 unmodified lines | ||
| 1863 | 2047 | r=fpr(gv(RC_FLOAT)); |
| 1864 | 2048 | vswap(); |
| 1865 | 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 | 2056 | break; |
| 1868 | 2057 | default: |
| @@ -1915,6 +2104,11 @@ void gen_opf(int op) · 46 unmodified lines | ||
| 1915 | 2104 | r2=c2&0xf; |
| 1916 | 2105 | } else { |
| 1917 | 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 | 2113 | --vtop; |
| 1920 | 2114 | vset_VT_CMP(op); |
| @@ -155,7 +155,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 154 unmodified lines | ||
| 155 | 155 | while (p < p_end) { |
| 156 | 156 | if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */ |
| 157 | 157 | p += 4; |
| 158 | − add32le(p + 12, x + s1->plt->data - p); | |
| 158 | + add32le(p + 12, x + (s1->plt->data - p)); | |
| 159 | 159 | p += 16; |
| 160 | 160 | } |
| 161 | 161 | } |
| @@ -81,6 +81,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 80 unmodified lines | ||
| 81 | 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 | 90 | #define IS_FREG(x) ((x) >= TREG_F(0)) |
| 85 | 91 | |
| 86 | 92 | static uint32_t intr(int r) |
| @@ -454,7 +460,7 @@ static void arm64_load_cmp(int r, SValue *sv); · 367 unmodified lines | ||
| 454 | 460 | ST_FUNC void load(int r, SValue *sv) |
| 455 | 461 | { |
| 456 | 462 | int svtt = sv->type.t; |
| 457 | − int svr = sv->r; | |
| 463 | + int svr = sv->r & ~VT_BOUNDED; | |
| 458 | 464 | int svrv = svr & VT_VALMASK; |
| 459 | 465 | uint64_t svcul = (uint32_t)sv->c.i; |
| 460 | 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 | 560 | ST_FUNC void store(int r, SValue *sv) |
| 555 | 561 | { |
| 556 | 562 | int svtt = sv->type.t; |
| 557 | − int svr = sv->r; | |
| 563 | + int svr = sv->r & ~VT_BOUNDED; | |
| 558 | 564 | int svrv = svr & VT_VALMASK; |
| 559 | 565 | uint64_t svcul = (uint32_t)sv->c.i; |
| 560 | 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 | 600 | assert(!b); |
| 595 | 601 | greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0); |
| 596 | 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 | 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 | 744 | static int arm64_hfa_aux(CType *type, int *fsize, int num) |
| 603 | 745 | { |
| 604 | 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 | 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 | 788 | int num1; |
| 647 | 789 | if (!type->ref->c) |
| 648 | 790 | return num; |
| @@ -659,7 +801,8 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 10 unmodified lines | ||
| 659 | 801 | |
| 660 | 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 | 806 | int sz = 0; |
| 664 | 807 | int n = arm64_hfa_aux(type, &sz, 0); |
| 665 | 808 | if (0 < n && n <= 4) { |
| @@ -839,6 +982,11 @@ ST_FUNC void gfunc_call(int nb_args) · 173 unmodified lines | ||
| 839 | 982 | unsigned long stack; |
| 840 | 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 | 990 | return_type = &vtop[-nb_args].type.ref->type; |
| 843 | 991 | if ((return_type->t & VT_BTYPE) == VT_STRUCT) |
| 844 | 992 | --nb_args; |
| @@ -1014,8 +1162,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 169 unmodified lines | ||
| 1014 | 1162 | |
| 1015 | 1163 | for (sym = func_type->ref; sym; sym = sym->next) |
| 1016 | 1164 | ++n; |
| 1017 | − t = tcc_malloc(n * sizeof(*t)); | |
| 1018 | − a = tcc_malloc(n * sizeof(*a)); | |
| 1165 | + t = n ? tcc_malloc(n * sizeof(*t)) : NULL; | |
| 1166 | + a = n ? tcc_malloc(n * sizeof(*a)) : NULL; | |
| 1019 | 1167 | |
| 1020 | 1168 | for (sym = func_type->ref; sym; sym = sym->next) |
| 1021 | 1169 | t[i++] = &sym->type; |
| @@ -1076,6 +1224,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 54 unmodified lines | ||
| 1076 | 1224 | o(0xd503201f); // nop |
| 1077 | 1225 | o(0xd503201f); // nop |
| 1078 | 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 | 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 | 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 | 1406 | if (loc) { |
| 1250 | 1407 | // Insert instructions to subtract size of stack frame from SP. |
| 1251 | 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 | 37 | case R_AARCH64_ADD_ABS_LO12_NC: |
| 38 | 38 | case R_AARCH64_ADR_GOT_PAGE: |
| 39 | 39 | case R_AARCH64_LD64_GOT_LO12_NC: |
| 40 | + case R_AARCH64_LDST64_ABS_LO12_NC: | |
| 40 | 41 | case R_AARCH64_GLOB_DAT: |
| 41 | 42 | case R_AARCH64_COPY: |
| 42 | 43 | return 0; |
| @@ -62,6 +63,7 @@ int gotplt_entry_type (int reloc_type) · 19 unmodified lines | ||
| 62 | 63 | case R_AARCH64_MOVW_UABS_G3: |
| 63 | 64 | case R_AARCH64_ADR_PREL_PG_HI21: |
| 64 | 65 | case R_AARCH64_ADD_ABS_LO12_NC: |
| 66 | + case R_AARCH64_LDST64_ABS_LO12_NC: | |
| 65 | 67 | case R_AARCH64_GLOB_DAT: |
| 66 | 68 | case R_AARCH64_JUMP_SLOT: |
| 67 | 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 | 160 | switch(type) { |
| 159 | 161 | case R_AARCH64_ABS64: |
| 160 | − write64le(ptr, val); | |
| 162 | + add64le(ptr, val); | |
| 161 | 163 | return; |
| 162 | 164 | case R_AARCH64_ABS32: |
| 163 | − write32le(ptr, val); | |
| 165 | + add32le(ptr, val); | |
| 164 | 166 | return; |
| 165 | 167 | case R_AARCH64_PREL32: |
| 166 | 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 | 195 | write32le(ptr, ((read32le(ptr) & 0xffc003ff) | |
| 194 | 196 | (val & 0xfff) << 10)); |
| 195 | 197 | return; |
| 198 | + case R_AARCH64_LDST64_ABS_LO12_NC: | |
| 199 | + write32le(ptr, ((read32le(ptr) & 0xffc003ff) | | |
| 200 | + (val & 0xff8) << 7)); | |
| 201 | + return; | |
| 196 | 202 | case R_AARCH64_JUMP26: |
| 197 | 203 | case R_AARCH64_CALL26: |
| 198 | 204 | #ifdef DEBUG_RELOC |
| @@ -1089,8 +1089,9 @@ static void gen_bounds_epilog(void) · 1088 unmodified lines | ||
| 1089 | 1089 | addr_t saved_ind; |
| 1090 | 1090 | addr_t *bounds_ptr; |
| 1091 | 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 | 1095 | return; |
| 1095 | 1096 | |
| 1096 | 1097 | /* add end of table info */ |
| @@ -1101,7 +1102,7 @@ static void gen_bounds_epilog(void) · 4 unmodified lines | ||
| 1101 | 1102 | func_bound_offset, lbounds_section->data_offset); |
| 1102 | 1103 | |
| 1103 | 1104 | /* generate bound local allocation */ |
| 1104 | − if (func_bound_offset != lbounds_section->data_offset) { | |
| 1105 | + if (offset_modified) { | |
| 1105 | 1106 | saved_ind = ind; |
| 1106 | 1107 | ind = func_bound_ind; |
| 1107 | 1108 | greloc(cur_text_section, sym_data, ind + 1, R_386_32); |
| @@ -43,9 +43,9 @@ endif · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) |
| 45 | 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) | |
| 47 | −ARM64_O = lib-arm64.o $(BT_O) | |
| 48 | −RISCV64_O = lib-arm64.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 fetch_and_add_arm64.o $(BT_O) | |
| 48 | +RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O) | |
| 49 | 49 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o |
| 50 | 50 | |
| 51 | 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 | 53 | OBJ-x86_64-osx = $(X86_64_O) va_list.o |
| 54 | 54 | OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O) |
| 55 | 55 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O) |
| 56 | −OBJ-arm64 = $(ARM64_O) $(DSO_O) | |
| 57 | −OBJ-arm = $(ARM_O) $(DSO_O) | |
| 56 | +OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O) | |
| 57 | +OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O) | |
| 58 | 58 | OBJ-arm-fpa = $(ARM_O) $(DSO_O) |
| 59 | 59 | OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O) |
| 60 | 60 | OBJ-arm-vfp = $(ARM_O) $(DSO_O) |
| 61 | 61 | OBJ-arm-eabi = $(ARM_O) $(DSO_O) |
| 62 | 62 | OBJ-arm-eabihf = $(ARM_O) $(DSO_O) |
| 63 | 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 | 66 | OBJ-extra = $(filter $(B_O),$(OBJ-$T)) |
| 67 | 67 | OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) |
| @@ -163,7 +163,7 @@ typedef struct alloca_list_struct { · 162 unmodified lines | ||
| 163 | 163 | #if defined(_WIN32) |
| 164 | 164 | #define BOUND_TID_TYPE DWORD |
| 165 | 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 | 167 | #define BOUND_TID_TYPE pid_t |
| 168 | 168 | #define BOUND_GET_TID syscall (SYS_gettid) |
| 169 | 169 | #else |
| @@ -223,6 +223,19 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src); · 53 unmodified lines | ||
| 223 | 223 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); |
| 224 | 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 | 239 | #if MALLOC_REDIR |
| 227 | 240 | #define BOUND_MALLOC(a) malloc_redir(a) |
| 228 | 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 | 333 | : // No input-only |
| 321 | 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 | 345 | #else |
| 324 | 346 | *variable += value; |
| 325 | 347 | #endif |
| @@ -814,10 +836,10 @@ void __bound_init(size_t *p) · 488 unmodified lines | ||
| 814 | 836 | { |
| 815 | 837 | FILE *fp; |
| 816 | 838 | unsigned char found; |
| 817 | − unsigned long long start; | |
| 818 | − unsigned long long end; | |
| 819 | − unsigned long long ad = | |
| 820 | − (unsigned long long) __builtin_return_address(0); | |
| 839 | + unsigned long start; | |
| 840 | + unsigned long end; | |
| 841 | + unsigned long ad = | |
| 842 | + (unsigned long) __builtin_return_address(0); | |
| 821 | 843 | char line[1000]; |
| 822 | 844 | |
| 823 | 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 | 857 | fp = fopen ("/proc/self/maps", "r"); |
| 836 | 858 | if (fp) { |
| 837 | 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 | 861 | ad >= start && ad < end) { |
| 840 | 862 | found = 1; |
| 841 | 863 | break; |
| @@ -1099,7 +1121,7 @@ void *__bound_malloc(size_t size, const void *caller) · 257 unmodified lines | ||
| 1099 | 1121 | INCR_COUNT(bound_malloc_count); |
| 1100 | 1122 | |
| 1101 | 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 | 1125 | if (tree && tree->start == (size_t) ptr) |
| 1104 | 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 | 1160 | INCR_COUNT(bound_memalign_count); |
| 1139 | 1161 | |
| 1140 | 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 | 1164 | if (tree && tree->start == (size_t) ptr) |
| 1143 | 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 | 1227 | return NULL; |
| 1206 | 1228 | } |
| 1207 | 1229 | |
| 1208 | − new_ptr = BOUND_REALLOC (ptr, size); | |
| 1230 | + new_ptr = BOUND_REALLOC (ptr, size + 1); | |
| 1209 | 1231 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| 1210 | 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 | 1238 | if (ptr) |
| 1217 | 1239 | tree = splay_delete ((size_t) ptr, tree); |
| 1218 | 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 | 1242 | if (tree && tree->start == (size_t) new_ptr) |
| 1221 | 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 | 1281 | if (no_checking == 0) { |
| 1260 | 1282 | WAIT_SEM (); |
| 1261 | 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 | 1285 | if (tree && tree->start == (size_t) ptr) |
| 1264 | 1286 | tree->type = TCC_TYPE_CALLOC; |
| 1265 | 1287 | POST_SEM (); |
| @@ -1387,6 +1409,59 @@ void *__bound_memset(void *s, int c, size_t n) · 121 unmodified lines | ||
| 1387 | 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 | 1465 | int __bound_strlen(const char *s) |
| 1391 | 1466 | { |
| 1392 | 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 | 34 | #elif defined(TCC_TARGET_ARM64) |
| 35 | 35 | #include "arm64-gen.c" |
| 36 | 36 | #include "arm64-link.c" |
| 37 | +#include "arm-asm.c" | |
| 37 | 38 | #elif defined(TCC_TARGET_C67) |
| 38 | 39 | #include "c67-gen.c" |
| 39 | 40 | #include "c67-link.c" |
| @@ -45,6 +46,7 @@ · 5 unmodified lines | ||
| 45 | 46 | #elif defined(TCC_TARGET_RISCV64) |
| 46 | 47 | #include "riscv64-gen.c" |
| 47 | 48 | #include "riscv64-link.c" |
| 49 | +#include "riscv64-asm.c" | |
| 48 | 50 | #else |
| 49 | 51 | #error unknown target |
| 50 | 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 | 3 | // Number of registers available to allocator: |
| 4 | 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 | 8 | #define TREG_R(x) (x) // x = 0..7 |
| 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 | 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 | 72 | static int ireg(int r) |
| 65 | 73 | { |
| 66 | 74 | if (r == TREG_RA) |
| @@ -377,6 +385,14 @@ static void gcall_or_jmp(int docall) · 310 unmodified lines | ||
| 377 | 385 | R_RISCV_CALL_PLT, (int)vtop->c.i); |
| 378 | 386 | o(0x17 | (tr << 7)); // auipc TR, 0 %call(func) |
| 379 | 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 | 396 | } else if (vtop->r < VT_CONST) { |
| 381 | 397 | int r = ireg(vtop->r); |
| 382 | 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 | 531 | static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs) |
| 392 | 532 | { |
| 393 | 533 | if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| @@ -440,6 +580,12 @@ ST_FUNC void gfunc_call(int nb_args) · 46 unmodified lines | ||
| 440 | 580 | int stack_adj = 0, tempspace = 0, ofs, splitofs = 0; |
| 441 | 581 | SValue *sv; |
| 442 | 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 | 589 | areg[0] = 0; /* int arg regs */ |
| 444 | 590 | areg[1] = 8; /* float arg regs */ |
| 445 | 591 | sa = vtop[-nb_args].type.ref->next; |
| @@ -691,6 +837,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 245 unmodified lines | ||
| 691 | 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 | 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 | 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 | 890 | loc = (loc - num_va_regs * 8); |
| 736 | 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 | 284 | return; |
| 285 | 285 | |
| 286 | 286 | case R_RISCV_32: |
| 287 | − write32le(ptr, val); | |
| 287 | + add32le(ptr, val); | |
| 288 | 288 | return; |
| 289 | 289 | case R_RISCV_JUMP_SLOT: |
| 290 | 290 | case R_RISCV_64: |
| 291 | − write64le(ptr, val); | |
| 291 | + add64le(ptr, val); | |
| 292 | 292 | return; |
| 293 | 293 | case R_RISCV_ADD64: |
| 294 | 294 | write64le(ptr, read64le(ptr) + val); |
| @@ -370,7 +370,7 @@ Print statistic information at exit of program. · 369 unmodified lines | ||
| 370 | 370 | Try to continue in case of a bound checking error. |
| 371 | 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 | 375 | @item -bt[N] |
| 376 | 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 | 185 | #if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT |
| 186 | 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 | 190 | && !defined TCC_UCLIBC && !defined TCC_MUSL |
| 189 | 191 | # define CONFIG_TCC_BCHECK /* enable bound checking code */ |
| 190 | 192 | # endif |
| @@ -354,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 163 unmodified lines | ||
| 354 | 356 | #elif defined TCC_TARGET_ARM64 |
| 355 | 357 | # include "arm64-gen.c" |
| 356 | 358 | # include "arm64-link.c" |
| 359 | +# include "arm-asm.c" | |
| 357 | 360 | #elif defined TCC_TARGET_C67 |
| 358 | 361 | # define TCC_TARGET_COFF |
| 359 | 362 | # include "coff.h" |
| @@ -362,6 +365,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 2 unmodified lines | ||
| 362 | 365 | #elif defined(TCC_TARGET_RISCV64) |
| 363 | 366 | # include "riscv64-gen.c" |
| 364 | 367 | # include "riscv64-link.c" |
| 368 | +# include "riscv64-asm.c" | |
| 365 | 369 | #else |
| 366 | 370 | #error unknown target |
| 367 | 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 | 3123 | /* test CPU specific stuff */ |
| 3124 | 3124 | if (ehdr.e_ident[5] != ELFDATA2LSB || |
| 3125 | 3125 | ehdr.e_machine != EM_TCC_TARGET) { |
| 3126 | − tcc_error_noabort("bad architecture"); | |
| 3126 | + tcc_error_noabort("bad architecture: %s", filename); | |
| 3127 | 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 | 886 | /* XXX: avoid doing that for statics ? */ |
| 887 | 887 | /* if bound checking is activated, we change some function |
| 888 | 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 | 895 | switch(sym->v) { |
| 890 | 896 | #ifdef TCC_TARGET_PE |
| 891 | 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 | 903 | #endif |
| 898 | 904 | case TOK_memcpy: |
| 899 | 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 | 910 | case TOK_memset: |
| 901 | 911 | case TOK_memcmp: |
| 902 | 912 | case TOK_strlen: |
| @@ -907,12 +917,17 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 4 unmodified lines | ||
| 907 | 917 | case TOK_strcat: |
| 908 | 918 | case TOK_strchr: |
| 909 | 919 | case TOK_strdup: |
| 920 | +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | |
| 910 | 921 | case TOK_alloca: |
| 922 | +#endif | |
| 911 | 923 | case TOK_mmap: |
| 912 | 924 | case TOK_munmap: |
| 913 | 925 | case TOK_longjmp: |
| 914 | 926 | #ifndef TCC_TARGET_PE |
| 915 | 927 | case TOK_siglongjmp: |
| 928 | +#endif | |
| 929 | +#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI) | |
| 930 | +add_bound: | |
| 916 | 931 | #endif |
| 917 | 932 | strcpy(buf, "__bound_"); |
| 918 | 933 | strcat(buf, name); |
| @@ -3820,9 +3835,9 @@ ST_FUNC void vstore(void) · 2901 unmodified lines | ||
| 3820 | 3835 | /* address of memcpy() */ |
| 3821 | 3836 | #ifdef TCC_ARM_EABI |
| 3822 | 3837 | if(!(align & 7)) |
| 3823 | − vpush_global_sym(&func_old_type, TOK_memcpy8); | |
| 3838 | + vpush_global_sym(&func_old_type, TOK_memmove8); | |
| 3824 | 3839 | else if(!(align & 3)) |
| 3825 | − vpush_global_sym(&func_old_type, TOK_memcpy4); | |
| 3840 | + vpush_global_sym(&func_old_type, TOK_memmove4); | |
| 3826 | 3841 | else |
| 3827 | 3842 | #endif |
| 3828 | 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 | 5651 | mk_pointer(&type); |
| 5637 | 5652 | vset(&type, VT_LOCAL, 0); /* local frame */ |
| 5638 | 5653 | while (level--) { |
| 5654 | +#ifdef TCC_TARGET_RISCV64 | |
| 5655 | + vpushi(2*PTR_SIZE); | |
| 5656 | + gen_op('-'); | |
| 5657 | +#endif | |
| 5639 | 5658 | mk_pointer(&vtop->type); |
| 5640 | 5659 | indir(); /* -> parent frame */ |
| 5641 | 5660 | } |
| 5642 | 5661 | if (tok1 == TOK_builtin_return_address) { |
| 5643 | 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 | 5670 | vpushi(PTR_SIZE); |
| 5645 | 5671 | gen_op('+'); |
| 5672 | +#endif | |
| 5646 | 5673 | mk_pointer(&vtop->type); |
| 5647 | 5674 | indir(); |
| 5648 | 5675 | } |
| @@ -648,10 +648,12 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc) · 647 unmodified lines | ||
| 648 | 648 | #elif defined(__arm__) |
| 649 | 649 | rc->ip = uc->uc_mcontext.arm_pc; |
| 650 | 650 | rc->fp = uc->uc_mcontext.arm_fp; |
| 651 | − rc->sp = uc->uc_mcontext.arm_sp; | |
| 652 | 651 | #elif defined(__aarch64__) |
| 653 | 652 | rc->ip = uc->uc_mcontext.pc; |
| 654 | 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 | 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 | 807 | *paddr = rc->ip; |
| 806 | 808 | } else { |
| 807 | 809 | addr_t fp = rc->fp; |
| 808 | − addr_t sp = rc->sp; | |
| 809 | − if (sp < 0x1000) | |
| 810 | − sp = 0x1000; | |
| 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]; | |
| 810 | + while (--level) | |
| 811 | + fp = ((addr_t *)fp)[0]; | |
| 812 | + *paddr = ((addr_t *)fp)[2]; | |
| 824 | 813 | } |
| 825 | 814 | return 0; |
| 826 | 815 | #endif |
| @@ -829,7 +818,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 2 unmodified lines | ||
| 829 | 818 | #elif defined(__aarch64__) |
| 830 | 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 | 822 | *paddr = rc->ip; |
| 834 | 823 | } else { |
| 835 | 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 | 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 | 846 | #else |
| 844 | 847 | #warning add arch specific rt_get_caller_pc() |
| 845 | 848 | static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) |
| @@ -205,9 +205,9 @@ · 204 unmodified lines | ||
| 205 | 205 | #if defined TCC_TARGET_ARM |
| 206 | 206 | # ifdef TCC_ARM_EABI |
| 207 | 207 | DEF(TOK_memcpy, "__aeabi_memcpy") |
| 208 | − DEF(TOK_memcpy4, "__aeabi_memcpy4") | |
| 209 | − DEF(TOK_memcpy8, "__aeabi_memcpy8") | |
| 210 | 208 | DEF(TOK_memmove, "__aeabi_memmove") |
| 209 | + DEF(TOK_memmove4, "__aeabi_memmove4") | |
| 210 | + DEF(TOK_memmove8, "__aeabi_memmove8") | |
| 211 | 211 | DEF(TOK_memset, "__aeabi_memset") |
| 212 | 212 | DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod") |
| 213 | 213 | DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod") |
| @@ -35,6 +35,15 @@ endif · 34 unmodified lines | ||
| 35 | 35 | ifeq ($(ARCH),x86_64) |
| 36 | 36 | TESTS += $(BTESTS) |
| 37 | 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 | 47 | endif |
| 39 | 48 | ifdef CONFIG_OSX # -run only |
| 40 | 49 | TESTS := hello-run libtest tests2-dir pp-dir |
| @@ -169,21 +169,34 @@ int test13(void) · 168 unmodified lines | ||
| 169 | 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 | 179 | int test14(void) |
| 173 | 180 | { |
| 174 | 181 | char *p = alloca(TAB_SIZE); |
| 182 | + size_t ret; | |
| 175 | 183 | memset(p, 'a', TAB_SIZE); |
| 176 | 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 | 190 | /* error */ |
| 181 | 191 | int test15(void) |
| 182 | 192 | { |
| 183 | 193 | char *p = alloca(TAB_SIZE-1); |
| 194 | + size_t ret; | |
| 184 | 195 | memset(p, 'a', TAB_SIZE); |
| 185 | 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 | 202 | /* ok */ |
| @@ -194,6 +207,7 @@ int test16() · 4 unmodified lines | ||
| 194 | 207 | |
| 195 | 208 | p = alloca(16); |
| 196 | 209 | strcpy(p,"12345678901234"); |
| 210 | + allocf(p); | |
| 197 | 211 | |
| 198 | 212 | /* Test alloca embedded in a larger expression */ |
| 199 | 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 | 224 | p = alloca(16); |
| 211 | 225 | strcpy(p,"12345678901234"); |
| 226 | + allocf(p); | |
| 212 | 227 | |
| 213 | 228 | /* Test alloca embedded in a larger expression */ |
| 214 | 229 | printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) ); |
| @@ -23,8 +23,11 @@ ifeq (,$(filter i386,$(ARCH))) · 22 unmodified lines | ||
| 23 | 23 | SKIP += 98_al_ax_extend.test 99_fastcall.test |
| 24 | 24 | endif |
| 25 | 25 | ifeq (,$(filter i386 x86_64,$(ARCH))) |
| 26 | − SKIP += 85_asm-outside-function.test | |
| 27 | − SKIP += 112_backtrace.test 113_btdll.test | |
| 26 | + SKIP += 85_asm-outside-function.test # x86 asm | |
| 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 | 31 | SKIP += 114_bound_signal.test |
| 29 | 32 | SKIP += 115_bound_setjmp.test |
| 30 | 33 | SKIP += 116_bound_setjmp2.test |
| @@ -82,7 +85,7 @@ GEN-ALWAYS = · 51 unmodified lines | ||
| 82 | 85 | |
| 83 | 86 | 112_backtrace.test: FLAGS += -dt -b |
| 84 | 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 | 89 | -e 's;0x[0-9A-Fa-f]\+;0x?;g' |
| 87 | 90 | |
| 88 | 91 | # this test creates two DLLs and an EXE |
| @@ -744,8 +744,9 @@ static void gen_bounds_epilog(void) · 743 unmodified lines | ||
| 744 | 744 | addr_t saved_ind; |
| 745 | 745 | addr_t *bounds_ptr; |
| 746 | 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 | 750 | return; |
| 750 | 751 | |
| 751 | 752 | /* add end of table info */ |
| @@ -756,7 +757,7 @@ static void gen_bounds_epilog(void) · 4 unmodified lines | ||
| 756 | 757 | func_bound_offset, lbounds_section->data_offset); |
| 757 | 758 | |
| 758 | 759 | /* generate bound local allocation */ |
| 759 | − if (func_bound_offset != lbounds_section->data_offset) { | |
| 760 | + if (offset_modified) { | |
| 760 | 761 | saved_ind = ind; |
| 761 | 762 | ind = func_bound_ind; |
| 762 | 763 | greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0); |