History

Add bound checking to arm, arm64 and riscv64

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

herman ten brugge committed 6 years ago

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

Unified · Split

25 files
  1. Makefile +2 −2
  2. arm-gen.c +206 −12
  3. arm-link.c +1 −1
  4. arm64-gen.c +164 −7
  5. arm64-link.c +8 −2
  6. i386-gen.c +3 −2
  7. lib/Makefile +6 −6
  8. lib/bcheck.c +86 −11
  9. lib/fetch_and_add_arm.S +16 −0
  10. lib/fetch_and_add_arm64.S +14 −0
  11. lib/fetch_and_add_riscv64.S +12 −0
  12. libtcc.c +2 −0
  13. riscv64-asm.c +94 −0
  14. riscv64-gen.c +155 −0
  15. riscv64-link.c +2 −2
  16. tcc-doc.texi +1 −1
  17. tcc.h +5 −1
  18. tccelf.c +1 −1
  19. tccgen.c +29 −2
  20. tccrun.c +21 −18
  21. tcctok.h +2 −2
  22. tests/Makefile +9 −0
  23. tests/boundtest.c +17 −2
  24. tests/tests2/Makefile +6 −3
  25. x86_64-gen.c +3 −2
Makefile+2−2
@@ -176,9 +176,9 @@ arm-fpa-ld_FILES = $(arm_FILES) · 175 unmodified lines
176176 arm-vfp_FILES = $(arm_FILES)
177177 arm-eabi_FILES = $(arm_FILES)
178178 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
180180 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
182182
183183 # libtcc sources
184184 LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
arm-gen.c+206−12
@@ -158,6 +158,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 157 unmodified lines
158158 static int func_sub_sp_offset, last_itod_magic;
159159 static int leaffunc;
160160
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+
161167 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
162168 static CType float_type, double_type, func_float_type, func_double_type;
163169 ST_FUNC void arm_init(struct TCCState *s)
@@ -193,11 +199,17 @@ ST_FUNC void arm_init(struct TCCState *s) · 29 unmodified lines
193199 }
194200 #endif
195201
202+#define CHECK_R(r) ((r) >= TREG_R0 && (r) <= TREG_LR)
203+
196204 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);
197207 return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
198208 }
199209
200210 static int regmask(int r) {
211+ if (!CHECK_R(r))
212+ tcc_error("compiler error! register %i is not valid",r);
201213 return reg_classes[r]&~(RC_INT|RC_FLOAT);
202214 }
203215
@@ -751,6 +763,14 @@ static void gcall_or_jmp(int is_jmp) · 547 unmodified lines
751763 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
752764 o(vtop->c.i);
753765 }
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
754774 }else{
755775 if(!is_jmp)
756776 o(0xE28FE004); // add lr,pc,#4
@@ -759,6 +779,9 @@ static void gcall_or_jmp(int is_jmp) · 2 unmodified lines
759779 }
760780 } else {
761781 /* otherwise, indirect call */
782+#ifdef CONFIG_TCC_BCHECK
783+ vtop->r &= ~VT_MUSTBOUND;
784+#endif
762785 r = gv(RC_INT);
763786 if(!is_jmp)
764787 o(0xE1A0E00F); // mov lr,pc
@@ -766,6 +789,121 @@ static void gcall_or_jmp(int is_jmp) · 1 unmodified line
766789 }
767790 }
768791
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+
769907 static int unalias_ldbl(int btype)
770908 {
771909 #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
9561094
9571095 ncrn = nsaa = 0;
9581096 *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;
9601098 memset(plan->clsplans, 0, sizeof(plan->clsplans));
9611099 for(i = nb_args; i-- ;) {
9621100 int j, start_vfpreg = 0;
@@ -1215,10 +1353,16 @@ void gfunc_call(int nb_args) · 252 unmodified lines
12151353 int def_float_abi = float_abi;
12161354 int todo;
12171355 struct plan plan;
1218−
12191356 #ifdef TCC_ARM_EABI
12201357 int variadic;
1358+#endif
12211359
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
12221366 if (float_abi == ARM_HARD_FLOAT) {
12231367 variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);
12241368 if (variadic || floats_in_core_regs(&vtop[-nb_args]))
@@ -1367,6 +1511,10 @@ from_stack: · 142 unmodified lines
13671511 last_itod_magic=0;
13681512 leaffunc = 1;
13691513 loc = 0;
1514+#ifdef CONFIG_TCC_BCHECK
1515+ if (tcc_state->do_bounds_check)
1516+ gen_bounds_prolog();
1517+#endif
13701518 }
13711519
13721520 /* generate function epilog */
@@ -1374,6 +1522,11 @@ void gfunc_epilog(void) · 1 unmodified line
13741522 {
13751523 uint32_t x;
13761524 int diff;
1525+
1526+#ifdef CONFIG_TCC_BCHECK
1527+ if (tcc_state->do_bounds_check)
1528+ gen_bounds_epilog();
1529+#endif
13771530 /* Copy float return value to core register if base standard is used and
13781531 float computation is made with VFP */
13791532 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
@@ -1582,10 +1735,10 @@ void gen_opi(int op) · 202 unmodified lines
15821735 vswap();
15831736 c=intr(gv(RC_INT));
15841737 vswap();
1585− opc=0xE0000000|(opc<<20)|(c<<16);
1738+ opc=0xE0000000|(opc<<20);
15861739 if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
15871740 uint32_t x;
1588− x=stuff_const(opc|0x2000000,vtop->c.i);
1741+ x=stuff_const(opc|0x2000000|(c<<16),vtop->c.i);
15891742 if(x) {
15901743 r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
15911744 o(x|(r<<12));
@@ -1593,8 +1746,13 @@ void gen_opi(int op) · 1 unmodified line
15931746 }
15941747 }
15951748 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+ }
15961754 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);
15981756 done:
15991757 vtop--;
16001758 if (op >= TOK_ULT && op <= TOK_GT)
@@ -1608,15 +1766,19 @@ done: · 7 unmodified lines
16081766 vswap();
16091767 r=intr(gv(RC_INT));
16101768 vswap();
1611− opc|=r;
16121769 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
16131770 fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
16141771 c = vtop->c.i & 0x1f;
1615− o(opc|(c<<7)|(fr<<12));
1772+ o(opc|r|(c<<7)|(fr<<12));
16161773 } else {
16171774 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+ }
16181780 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);
16201782 }
16211783 vtop--;
16221784 break;
@@ -1701,9 +1863,9 @@ void gen_opf(int op) · 78 unmodified lines
17011863 vtop--;
17021864 o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
17031865 } 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));
17071869 vtop--;
17081870 }
17091871 o(0xEEF1FA10); /* fmstat */
@@ -1726,6 +1888,12 @@ void gen_opf(int op) · 16 unmodified lines
17261888 r2=gv(RC_FLOAT);
17271889 x|=vfpr(r2)<<16;
17281890 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+ }
17291897 }
17301898 vtop->r=get_reg_ex(RC_FLOAT,r);
17311899 if(!fneg)
@@ -1808,6 +1976,11 @@ void gen_opf(int op) · 76 unmodified lines
18081976 r2=c2&0xf;
18091977 } else {
18101978 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+ }
18111984 }
18121985 break;
18131986 case '-':
@@ -1829,6 +2002,11 @@ void gen_opf(int op) · 15 unmodified lines
18292002 r=fpr(gv(RC_FLOAT));
18302003 vswap();
18312004 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+ }
18322010 }
18332011 break;
18342012 case '*':
@@ -1841,8 +2019,14 @@ void gen_opf(int op) · 6 unmodified lines
18412019 vswap();
18422020 if(c2 && c2<=0xf)
18432021 r2=c2;
1844− else
2022+ else {
18452023 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+ }
18462030 x|=0x100000; // muf
18472031 break;
18482032 case '/':
@@ -1863,6 +2047,11 @@ void gen_opf(int op) · 14 unmodified lines
18632047 r=fpr(gv(RC_FLOAT));
18642048 vswap();
18652049 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+ }
18662055 }
18672056 break;
18682057 default:
@@ -1915,6 +2104,11 @@ void gen_opf(int op) · 46 unmodified lines
19152104 r2=c2&0xf;
19162105 } else {
19172106 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+ }
19182112 }
19192113 --vtop;
19202114 vset_VT_CMP(op);
arm-link.c+1−1
@@ -155,7 +155,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 154 unmodified lines
155155 while (p < p_end) {
156156 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
157157 p += 4;
158− add32le(p + 12, x + s1->plt->data - p);
158+ add32le(p + 12, x + (s1->plt->data - p));
159159 p += 16;
160160 }
161161 }
arm64-gen.c+164−7
@@ -81,6 +81,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 80 unmodified lines
8181 RC_FLOAT | RC_F(7)
8282 };
8383
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+
8490 #define IS_FREG(x) ((x) >= TREG_F(0))
8591
8692 static uint32_t intr(int r)
@@ -454,7 +460,7 @@ static void arm64_load_cmp(int r, SValue *sv); · 367 unmodified lines
454460 ST_FUNC void load(int r, SValue *sv)
455461 {
456462 int svtt = sv->type.t;
457− int svr = sv->r;
463+ int svr = sv->r & ~VT_BOUNDED;
458464 int svrv = svr & VT_VALMASK;
459465 uint64_t svcul = (uint32_t)sv->c.i;
460466 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
554560 ST_FUNC void store(int r, SValue *sv)
555561 {
556562 int svtt = sv->type.t;
557− int svr = sv->r;
563+ int svr = sv->r & ~VT_BOUNDED;
558564 int svrv = svr & VT_VALMASK;
559565 uint64_t svcul = (uint32_t)sv->c.i;
560566 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
594600 assert(!b);
595601 greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0);
596602 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
597611 }
598− else
612+ else {
613+#ifdef CONFIG_TCC_BCHECK
614+ vtop->r &= ~VT_MUSTBOUND;
615+#endif
599616 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
600628 }
601629
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+
602744 static int arm64_hfa_aux(CType *type, int *fsize, int num)
603745 {
604746 if (is_float(type->t)) {
@@ -642,7 +784,7 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 37 unmodified lines
642784 return num;
643785 }
644786 }
645− else if (type->t & VT_ARRAY) {
787+ else if ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR)) {
646788 int num1;
647789 if (!type->ref->c)
648790 return num;
@@ -659,7 +801,8 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 10 unmodified lines
659801
660802 static int arm64_hfa(CType *type, int *fsize)
661803 {
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))) {
663806 int sz = 0;
664807 int n = arm64_hfa_aux(type, &sz, 0);
665808 if (0 < n && n <= 4) {
@@ -839,6 +982,11 @@ ST_FUNC void gfunc_call(int nb_args) · 173 unmodified lines
839982 unsigned long stack;
840983 int i;
841984
985+#ifdef CONFIG_TCC_BCHECK
986+ if (tcc_state->do_bounds_check)
987+ gbound_args(nb_args);
988+#endif
989+
842990 return_type = &vtop[-nb_args].type.ref->type;
843991 if ((return_type->t & VT_BTYPE) == VT_STRUCT)
844992 --nb_args;
@@ -1014,8 +1162,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 169 unmodified lines
10141162
10151163 for (sym = func_type->ref; sym; sym = sym->next)
10161164 ++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;
10191167
10201168 for (sym = func_type->ref; sym; sym = sym->next)
10211169 t[i++] = &sym->type;
@@ -1076,6 +1224,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 54 unmodified lines
10761224 o(0xd503201f); // nop
10771225 o(0xd503201f); // nop
10781226 loc = 0;
1227+#ifdef CONFIG_TCC_BCHECK
1228+ if (tcc_state->do_bounds_check)
1229+ gen_bounds_prolog();
1230+#endif
10791231 }
10801232
10811233 ST_FUNC void gen_va_start(void)
@@ -1246,6 +1398,11 @@ ST_FUNC void gfunc_return(CType *func_type) · 164 unmodified lines
12461398
12471399 ST_FUNC void gfunc_epilog(void)
12481400 {
1401+#ifdef CONFIG_TCC_BCHECK
1402+ if (tcc_state->do_bounds_check)
1403+ gen_bounds_epilog();
1404+#endif
1405+
12491406 if (loc) {
12501407 // Insert instructions to subtract size of stack frame from SP.
12511408 unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
arm64-link.c+8−2
@@ -37,6 +37,7 @@ int code_reloc (int reloc_type) · 36 unmodified lines
3737 case R_AARCH64_ADD_ABS_LO12_NC:
3838 case R_AARCH64_ADR_GOT_PAGE:
3939 case R_AARCH64_LD64_GOT_LO12_NC:
40+ case R_AARCH64_LDST64_ABS_LO12_NC:
4041 case R_AARCH64_GLOB_DAT:
4142 case R_AARCH64_COPY:
4243 return 0;
@@ -62,6 +63,7 @@ int gotplt_entry_type (int reloc_type) · 19 unmodified lines
6263 case R_AARCH64_MOVW_UABS_G3:
6364 case R_AARCH64_ADR_PREL_PG_HI21:
6465 case R_AARCH64_ADD_ABS_LO12_NC:
66+ case R_AARCH64_LDST64_ABS_LO12_NC:
6567 case R_AARCH64_GLOB_DAT:
6668 case R_AARCH64_JUMP_SLOT:
6769 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
157159
158160 switch(type) {
159161 case R_AARCH64_ABS64:
160− write64le(ptr, val);
162+ add64le(ptr, val);
161163 return;
162164 case R_AARCH64_ABS32:
163− write32le(ptr, val);
165+ add32le(ptr, val);
164166 return;
165167 case R_AARCH64_PREL32:
166168 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
193195 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
194196 (val & 0xfff) << 10));
195197 return;
198+ case R_AARCH64_LDST64_ABS_LO12_NC:
199+ write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
200+ (val & 0xff8) << 7));
201+ return;
196202 case R_AARCH64_JUMP26:
197203 case R_AARCH64_CALL26:
198204 #ifdef DEBUG_RELOC
i386-gen.c+3−2
@@ -1089,8 +1089,9 @@ static void gen_bounds_epilog(void) · 1088 unmodified lines
10891089 addr_t saved_ind;
10901090 addr_t *bounds_ptr;
10911091 Sym *sym_data;
1092+ int offset_modified = func_bound_offset != lbounds_section->data_offset;
10921093
1093− if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)
1094+ if (!offset_modified && !func_bound_add_epilog)
10941095 return;
10951096
10961097 /* add end of table info */
@@ -1101,7 +1102,7 @@ static void gen_bounds_epilog(void) · 4 unmodified lines
11011102 func_bound_offset, lbounds_section->data_offset);
11021103
11031104 /* generate bound local allocation */
1104− if (func_bound_offset != lbounds_section->data_offset) {
1105+ if (offset_modified) {
11051106 saved_ind = ind;
11061107 ind = func_bound_ind;
11071108 greloc(cur_text_section, sym_data, ind + 1, R_386_32);
lib/Makefile+6−6
@@ -43,9 +43,9 @@ endif · 42 unmodified lines
4343
4444 I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O)
4545 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)
4949 WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
5050
5151 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
5353 OBJ-x86_64-osx = $(X86_64_O) va_list.o
5454 OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)
5555 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)
5858 OBJ-arm-fpa = $(ARM_O) $(DSO_O)
5959 OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)
6060 OBJ-arm-vfp = $(ARM_O) $(DSO_O)
6161 OBJ-arm-eabi = $(ARM_O) $(DSO_O)
6262 OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
6363 OBJ-arm-wince = $(ARM_O) $(WIN_O)
64−OBJ-riscv64 = $(RISCV64_O) $(DSO_O)
64+OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
6565
6666 OBJ-extra = $(filter $(B_O),$(OBJ-$T))
6767 OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
lib/bcheck.c+86−11
@@ -163,7 +163,7 @@ typedef struct alloca_list_struct { · 162 unmodified lines
163163 #if defined(_WIN32)
164164 #define BOUND_TID_TYPE DWORD
165165 #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)
167167 #define BOUND_TID_TYPE pid_t
168168 #define BOUND_GET_TID syscall (SYS_gettid)
169169 #else
@@ -223,6 +223,19 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src); · 53 unmodified lines
223223 DLL_EXPORT char *__bound_strchr(const char *string, int ch);
224224 DLL_EXPORT char *__bound_strdup(const char *s);
225225
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+
226239 #if MALLOC_REDIR
227240 #define BOUND_MALLOC(a) malloc_redir(a)
228241 #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
320333 : // No input-only
321334 : "memory"
322335 );
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);
323345 #else
324346 *variable += value;
325347 #endif
@@ -814,10 +836,10 @@ void __bound_init(size_t *p) · 488 unmodified lines
814836 {
815837 FILE *fp;
816838 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);
821843 char line[1000];
822844
823845 /* 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
835857 fp = fopen ("/proc/self/maps", "r");
836858 if (fp) {
837859 while (fgets (line, sizeof(line), fp)) {
838− if (sscanf (line, "%Lx-%Lx", &start, &end) == 2 &&
860+ if (sscanf (line, "%lx-%lx", &start, &end) == 2 &&
839861 ad >= start && ad < end) {
840862 found = 1;
841863 break;
@@ -1099,7 +1121,7 @@ void *__bound_malloc(size_t size, const void *caller) · 257 unmodified lines
10991121 INCR_COUNT(bound_malloc_count);
11001122
11011123 if (ptr) {
1102− tree = splay_insert ((size_t) ptr, size, tree);
1124+ tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
11031125 if (tree && tree->start == (size_t) ptr)
11041126 tree->type = TCC_TYPE_MALLOC;
11051127 }
@@ -1138,7 +1160,7 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 32 unmodified lines
11381160 INCR_COUNT(bound_memalign_count);
11391161
11401162 if (ptr) {
1141− tree = splay_insert((size_t) ptr, size, tree);
1163+ tree = splay_insert((size_t) ptr, size ? size : size + 1, tree);
11421164 if (tree && tree->start == (size_t) ptr)
11431165 tree->type = TCC_TYPE_MEMALIGN;
11441166 }
@@ -1205,7 +1227,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller) · 60 unmodified lines
12051227 return NULL;
12061228 }
12071229
1208− new_ptr = BOUND_REALLOC (ptr, size);
1230+ new_ptr = BOUND_REALLOC (ptr, size + 1);
12091231 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
12101232 __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
12111233
@@ -1216,7 +1238,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller) · 4 unmodified lines
12161238 if (ptr)
12171239 tree = splay_delete ((size_t) ptr, tree);
12181240 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);
12201242 if (tree && tree->start == (size_t) new_ptr)
12211243 tree->type = TCC_TYPE_REALLOC;
12221244 }
@@ -1259,7 +1281,7 @@ void *__bound_calloc(size_t nmemb, size_t size) · 36 unmodified lines
12591281 if (no_checking == 0) {
12601282 WAIT_SEM ();
12611283 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);
12631285 if (tree && tree->start == (size_t) ptr)
12641286 tree->type = TCC_TYPE_CALLOC;
12651287 POST_SEM ();
@@ -1387,6 +1409,59 @@ void *__bound_memset(void *s, int c, size_t n) · 121 unmodified lines
13871409 return memset(s, c, n);
13881410 }
13891411
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+
13901465 int __bound_strlen(const char *s)
13911466 {
13921467 const char *p = s;
lib/fetch_and_add_arm.S+16−0
@@ -0,0 +1,16 @@
1+ .text
2+ .align 2
3+ .global fetch_and_add_arm
4+ .type fetch_and_add_arm, %function
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
lib/fetch_and_add_arm64.S+14−0
@@ -0,0 +1,14 @@
1+ .text
2+ .align 2
3+ .global fetch_and_add_arm64
4+ .type fetch_and_add_arm64, %function
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
lib/fetch_and_add_riscv64.S+12−0
@@ -0,0 +1,12 @@
1+ .text
2+ .align 2
3+ .global fetch_and_add_riscv64
4+ .type fetch_and_add_riscv64, %function
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
libtcc.c+2−0
@@ -34,6 +34,7 @@ · 33 unmodified lines
3434 #elif defined(TCC_TARGET_ARM64)
3535 #include "arm64-gen.c"
3636 #include "arm64-link.c"
37+#include "arm-asm.c"
3738 #elif defined(TCC_TARGET_C67)
3839 #include "c67-gen.c"
3940 #include "c67-link.c"
@@ -45,6 +46,7 @@ · 5 unmodified lines
4546 #elif defined(TCC_TARGET_RISCV64)
4647 #include "riscv64-gen.c"
4748 #include "riscv64-link.c"
49+#include "riscv64-asm.c"
4850 #else
4951 #error unknown target
5052 #endif
riscv64-asm.c+94−0
@@ -0,0 +1,94 @@
1+/*************************************************************/
2+/*
3+ * RISCV64 dummy assembler for TCC
4+ *
5+ */
6+
7+#ifdef TARGET_DEFS_ONLY
8+
9+#define CONFIG_TCC_ASM
10+#define NB_ASM_REGS 32
11+
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 */
riscv64-gen.c+155−0
@@ -2,6 +2,8 @@ · 1 unmodified line
22
33 // Number of registers available to allocator:
44 #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
57
68 #define TREG_R(x) (x) // x = 0..7
79 #define TREG_F(x) (x + 8) // x = 0..7
@@ -61,6 +63,12 @@ ST_DATA const int reg_classes[NB_REGS] = { · 53 unmodified lines
6163 1 << TREG_SP
6264 };
6365
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+
6472 static int ireg(int r)
6573 {
6674 if (r == TREG_RA)
@@ -377,6 +385,14 @@ static void gcall_or_jmp(int docall) · 310 unmodified lines
377385 R_RISCV_CALL_PLT, (int)vtop->c.i);
378386 o(0x17 | (tr << 7)); // auipc TR, 0 %call(func)
379387 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
380396 } else if (vtop->r < VT_CONST) {
381397 int r = ireg(vtop->r);
382398 EI(0x67, 0, tr, r, 0); // jalr TR, 0(R)
@@ -388,6 +404,130 @@ static void gcall_or_jmp(int docall) · 5 unmodified lines
388404 }
389405 }
390406
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
391531 static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs)
392532 {
393533 if ((type->t & VT_BTYPE) == VT_STRUCT) {
@@ -440,6 +580,12 @@ ST_FUNC void gfunc_call(int nb_args) · 46 unmodified lines
440580 int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;
441581 SValue *sv;
442582 Sym *sa;
583+
584+#ifdef CONFIG_TCC_BCHECK
585+ if (tcc_state->do_bounds_check)
586+ gbound_args(nb_args);
587+#endif
588+
443589 areg[0] = 0; /* int arg regs */
444590 areg[1] = 8; /* float arg regs */
445591 sa = vtop[-nb_args].type.ref->next;
@@ -691,6 +837,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 245 unmodified lines
691837 ES(0x23, 3, 8, 10 + areg[0], -8 + num_va_regs * 8); // sd aX, loc(s0)
692838 }
693839 }
840+#ifdef CONFIG_TCC_BCHECK
841+ if (tcc_state->do_bounds_check)
842+ gen_bounds_prolog();
843+#endif
694844 }
695845
696846 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
@@ -732,6 +882,11 @@ ST_FUNC void gfunc_epilog(void) · 35 unmodified lines
732882 {
733883 int v, saved_ind, d, large_ofs_ind;
734884
885+#ifdef CONFIG_TCC_BCHECK
886+ if (tcc_state->do_bounds_check)
887+ gen_bounds_epilog();
888+#endif
889+
735890 loc = (loc - num_va_regs * 8);
736891 d = v = (-loc + 15) & -16;
737892
riscv64-link.c+2−2
@@ -284,11 +284,11 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 283 unmodified lines
284284 return;
285285
286286 case R_RISCV_32:
287− write32le(ptr, val);
287+ add32le(ptr, val);
288288 return;
289289 case R_RISCV_JUMP_SLOT:
290290 case R_RISCV_64:
291− write64le(ptr, val);
291+ add64le(ptr, val);
292292 return;
293293 case R_RISCV_ADD64:
294294 write64le(ptr, read64le(ptr) + val);
tcc-doc.texi+1−1
@@ -370,7 +370,7 @@ Print statistic information at exit of program. · 369 unmodified lines
370370 Try to continue in case of a bound checking error.
371371 @end table
372372
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.
374374
375375 @item -bt[N]
376376 Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.
tcc.h+5−1
@@ -184,7 +184,9 @@ extern long double strtold (const char *__nptr, char **__endptr); · 183 unmodified lines
184184
185185 #if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT
186186 # 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 \
188190 && !defined TCC_UCLIBC && !defined TCC_MUSL
189191 # define CONFIG_TCC_BCHECK /* enable bound checking code */
190192 # endif
@@ -354,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 163 unmodified lines
354356 #elif defined TCC_TARGET_ARM64
355357 # include "arm64-gen.c"
356358 # include "arm64-link.c"
359+# include "arm-asm.c"
357360 #elif defined TCC_TARGET_C67
358361 # define TCC_TARGET_COFF
359362 # include "coff.h"
@@ -362,6 +365,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 2 unmodified lines
362365 #elif defined(TCC_TARGET_RISCV64)
363366 # include "riscv64-gen.c"
364367 # include "riscv64-link.c"
368+# include "riscv64-asm.c"
365369 #else
366370 #error unknown target
367371 #endif
tccelf.c+1−1
@@ -3123,7 +3123,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 3122 unmodified lines
31233123 /* test CPU specific stuff */
31243124 if (ehdr.e_ident[5] != ELFDATA2LSB ||
31253125 ehdr.e_machine != EM_TCC_TARGET) {
3126− tcc_error_noabort("bad architecture");
3126+ tcc_error_noabort("bad architecture: %s", filename);
31273127 return -1;
31283128 }
31293129
tccgen.c+29−2
@@ -886,6 +886,12 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 885 unmodified lines
886886 /* XXX: avoid doing that for statics ? */
887887 /* if bound checking is activated, we change some function
888888 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
889895 switch(sym->v) {
890896 #ifdef TCC_TARGET_PE
891897 /* 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
897903 #endif
898904 case TOK_memcpy:
899905 case TOK_memmove:
906+#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
907+ case TOK_memmove4:
908+ case TOK_memmove8:
909+#endif
900910 case TOK_memset:
901911 case TOK_memcmp:
902912 case TOK_strlen:
@@ -907,12 +917,17 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, · 4 unmodified lines
907917 case TOK_strcat:
908918 case TOK_strchr:
909919 case TOK_strdup:
920+#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
910921 case TOK_alloca:
922+#endif
911923 case TOK_mmap:
912924 case TOK_munmap:
913925 case TOK_longjmp:
914926 #ifndef TCC_TARGET_PE
915927 case TOK_siglongjmp:
928+#endif
929+#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
930+add_bound:
916931 #endif
917932 strcpy(buf, "__bound_");
918933 strcat(buf, name);
@@ -3820,9 +3835,9 @@ ST_FUNC void vstore(void) · 2901 unmodified lines
38203835 /* address of memcpy() */
38213836 #ifdef TCC_ARM_EABI
38223837 if(!(align & 7))
3823− vpush_global_sym(&func_old_type, TOK_memcpy8);
3838+ vpush_global_sym(&func_old_type, TOK_memmove8);
38243839 else if(!(align & 3))
3825− vpush_global_sym(&func_old_type, TOK_memcpy4);
3840+ vpush_global_sym(&func_old_type, TOK_memmove4);
38263841 else
38273842 #endif
38283843 /* Use memmove, rather than memcpy, as dest and src may be same: */
@@ -5636,13 +5651,25 @@ ST_FUNC void unary(void) · 1807 unmodified lines
56365651 mk_pointer(&type);
56375652 vset(&type, VT_LOCAL, 0); /* local frame */
56385653 while (level--) {
5654+#ifdef TCC_TARGET_RISCV64
5655+ vpushi(2*PTR_SIZE);
5656+ gen_op('-');
5657+#endif
56395658 mk_pointer(&vtop->type);
56405659 indir(); /* -> parent frame */
56415660 }
56425661 if (tok1 == TOK_builtin_return_address) {
56435662 // 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
56445670 vpushi(PTR_SIZE);
56455671 gen_op('+');
5672+#endif
56465673 mk_pointer(&vtop->type);
56475674 indir();
56485675 }
tccrun.c+21−18
@@ -648,10 +648,12 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc) · 647 unmodified lines
648648 #elif defined(__arm__)
649649 rc->ip = uc->uc_mcontext.arm_pc;
650650 rc->fp = uc->uc_mcontext.arm_fp;
651− rc->sp = uc->uc_mcontext.arm_sp;
652651 #elif defined(__aarch64__)
653652 rc->ip = uc->uc_mcontext.pc;
654653 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];
655657 #endif
656658 }
657659
@@ -805,22 +807,9 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 147 unmodified lines
805807 *paddr = rc->ip;
806808 } else {
807809 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];
824813 }
825814 return 0;
826815 #endif
@@ -829,7 +818,7 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) · 2 unmodified lines
829818 #elif defined(__aarch64__)
830819 static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
831820 {
832− if (level == 0) {
821+ if (level == 0) {
833822 *paddr = rc->ip;
834823 } else {
835824 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
840829 return 0;
841830 }
842831
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+
843846 #else
844847 #warning add arch specific rt_get_caller_pc()
845848 static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
tcctok.h+2−2
@@ -205,9 +205,9 @@ · 204 unmodified lines
205205 #if defined TCC_TARGET_ARM
206206 # ifdef TCC_ARM_EABI
207207 DEF(TOK_memcpy, "__aeabi_memcpy")
208− DEF(TOK_memcpy4, "__aeabi_memcpy4")
209− DEF(TOK_memcpy8, "__aeabi_memcpy8")
210208 DEF(TOK_memmove, "__aeabi_memmove")
209+ DEF(TOK_memmove4, "__aeabi_memmove4")
210+ DEF(TOK_memmove8, "__aeabi_memmove8")
211211 DEF(TOK_memset, "__aeabi_memset")
212212 DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
213213 DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
tests/Makefile+9−0
@@ -35,6 +35,15 @@ endif · 34 unmodified lines
3535 ifeq ($(ARCH),x86_64)
3636 TESTS += $(BTESTS)
3737 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
3847 endif
3948 ifdef CONFIG_OSX # -run only
4049 TESTS := hello-run libtest tests2-dir pp-dir
tests/boundtest.c+17−2
@@ -169,21 +169,34 @@ int test13(void) · 168 unmodified lines
169169 return strlen(tab);
170170 }
171171
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+
172179 int test14(void)
173180 {
174181 char *p = alloca(TAB_SIZE);
182+ size_t ret;
175183 memset(p, 'a', TAB_SIZE);
176184 p[TAB_SIZE-1] = 0;
177− return strlen(p);
185+ ret = strlen(p);
186+ allocf(p);
187+ return ret;
178188 }
179189
180190 /* error */
181191 int test15(void)
182192 {
183193 char *p = alloca(TAB_SIZE-1);
194+ size_t ret;
184195 memset(p, 'a', TAB_SIZE);
185196 p[TAB_SIZE-1] = 0;
186− return strlen(p);
197+ ret = strlen(p);
198+ allocf(p);
199+ return ret;
187200 }
188201
189202 /* ok */
@@ -194,6 +207,7 @@ int test16() · 4 unmodified lines
194207
195208 p = alloca(16);
196209 strcpy(p,"12345678901234");
210+ allocf(p);
197211
198212 /* Test alloca embedded in a larger expression */
199213 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );
@@ -209,6 +223,7 @@ int test17() · 9 unmodified lines
209223
210224 p = alloca(16);
211225 strcpy(p,"12345678901234");
226+ allocf(p);
212227
213228 /* Test alloca embedded in a larger expression */
214229 printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );
tests/tests2/Makefile+6−3
@@ -23,8 +23,11 @@ ifeq (,$(filter i386,$(ARCH))) · 22 unmodified lines
2323 SKIP += 98_al_ax_extend.test 99_fastcall.test
2424 endif
2525 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
2831 SKIP += 114_bound_signal.test
2932 SKIP += 115_bound_setjmp.test
3033 SKIP += 116_bound_setjmp2.test
@@ -82,7 +85,7 @@ GEN-ALWAYS = · 51 unmodified lines
8285
8386 112_backtrace.test: FLAGS += -dt -b
8487 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' \
8689 -e 's;0x[0-9A-Fa-f]\+;0x?;g'
8790
8891 # this test creates two DLLs and an EXE
x86_64-gen.c+3−2
@@ -744,8 +744,9 @@ static void gen_bounds_epilog(void) · 743 unmodified lines
744744 addr_t saved_ind;
745745 addr_t *bounds_ptr;
746746 Sym *sym_data;
747+ int offset_modified = func_bound_offset != lbounds_section->data_offset;
747748
748− if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)
749+ if (!offset_modified && !func_bound_add_epilog)
749750 return;
750751
751752 /* add end of table info */
@@ -756,7 +757,7 @@ static void gen_bounds_epilog(void) · 4 unmodified lines
756757 func_bound_offset, lbounds_section->data_offset);
757758
758759 /* generate bound local allocation */
759− if (func_bound_offset != lbounds_section->data_offset) {
760+ if (offset_modified) {
760761 saved_ind = ind;
761762 ind = func_bound_ind;
762763 greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t