History

Add bound check support for alloca on all targets

stddef.h, tccdefs.h, tccgen.c, tests/boundtest.c, tests/tcctest.c: - remove ifdef arround alloca lib/Makefile: - move alloca-bt.o to COMMON_O lib/alloca-bt.S: - add alloca bound check code for arm, arm64, riscv64 lib/alloca.S: - check for leading underscore tcc.h, libtcc.c: - include arm64-asm.c instead of arm-asm.c for arm64 tcctok.h, tccasm.c: - add simple reloc support (only for R_AARCH64_CALL26)

herman ten brugge committed 11 months ago

Commit 6da45941 parent fc424c912 files · +142 −59Browse files

Unified · Split

12 files
  1. include/stddef.h +0 −2
  2. include/tccdefs.h +0 −4
  3. lib/Makefile +3 −3
  4. lib/alloca-bt.S +104 −0
  5. lib/alloca.S +15 −26
  6. libtcc.c +1 −1
  7. tcc.h +1 −1
  8. tccasm.c +17 −0
  9. tccgen.c +0 −2
  10. tcctok.h +1 −2
  11. tests/boundtest.c +0 −14
  12. tests/tcctest.c +0 −4
include/stddef.h+0−2
@@ -19,9 +19,7 @@ typedef union { long long __ll; long double __ld; } max_align_t; · 18 unmodified lines
1919 #undef offsetof
2020 #define offsetof(type, field) __builtin_offsetof(type, field)
2121
22−#if defined __i386__ || defined __x86_64__
2322 void *alloca(size_t size);
24−#endif
2523
2624 #endif
2725
include/tccdefs.h+0−4
@@ -347,12 +347,8 @@ · 346 unmodified lines
347347 __MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
348348 __MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
349349 __MAYBE_REDIR(void, free, (void*))
350−#if defined __i386__ || defined __x86_64__
351350 __BOTH(void*, alloca, (__SIZE_TYPE__))
352351 void *alloca(__SIZE_TYPE__);
353−#else
354− __BUILTIN(void*, alloca, (__SIZE_TYPE__))
355−#endif
356352 __BUILTIN(void, abort, (void))
357353 __BOUND(void, longjmp, ())
358354 #if !defined _WIN32
lib/Makefile+3−3
@@ -35,12 +35,12 @@ endif · 34 unmodified lines
3535
3636 XFLAGS += -I$(TOP)
3737
38−I386_O = libtcc1.o alloca-bt.o $(COMMON_O)
39−X86_64_O = libtcc1.o alloca-bt.o $(COMMON_O)
38+I386_O = libtcc1.o $(COMMON_O)
39+X86_64_O = libtcc1.o $(COMMON_O)
4040 ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
4141 ARM64_O = lib-arm64.o $(COMMON_O)
4242 RISCV64_O = lib-arm64.o $(COMMON_O)
43−COMMON_O = stdatomic.o atomic.o builtin.o alloca.o
43+COMMON_O = stdatomic.o atomic.o builtin.o alloca.o alloca-bt.o
4444 WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
4545 LIN_O = dsohandle.o
4646 OSX_O =
lib/alloca-bt.S+104−0
@@ -92,5 +92,109 @@ p3: · 91 unmodified lines
9292 ret
9393 #endif
9494
95+/* ---------------------------------------------- */
96+#elif defined __arm__
97+
98+.globl _(__bound_alloca)
99+_(__bound_alloca):
100+ mov r1, r0
101+ add r0, r0, #1
102+ rsb sp, r0, sp
103+ bic sp, sp, #7
104+ mov r0, sp
105+ push { lr }
106+ bl _(__bound_new_region)
107+ pop { lr }
108+ mov r0, sp
109+ mov pc, lr
110+
111+/* ---------------------------------------------- */
112+#elif defined __aarch64__ || defined __arm64__
113+
114+.globl _(__bound_alloca)
115+_(__bound_alloca):
116+#ifdef __TINYC__
117+ .int 0xaa0003e1
118+ .int 0x91004000
119+ .int 0x927cec00
120+#ifdef _WIN32
121+ .int 0xb4000160
122+ .int 0xd2820002
123+ .int 0xeb02001f
124+ .int 0x540000c3
125+ .int 0xcb2263e3
126+ .int 0xf940007f
127+ .int 0xcb2263ff
128+ .int 0xcb020000
129+ .int 0x17fffffa
130+ .int 0xb4000040
131+#endif
132+ .int 0xcb2063ff
133+ .int 0x910003e0
134+ .int 0xa9bf7bfd
135+ .reloc ., R_AARCH64_CALL26, _(__bound_new_region)
136+ .int 0x94000000
137+ .int 0xa8c17bfd
138+ .int 0x910003e0
139+ .int 0xd65f03c0
140+#else
141+ mov x1, x0
142+ add x0, x0, #16 // Round up to 16-byte boundary
143+ and x0, x0, #-16 // Ensure 16-byte alignment
144+#ifdef _WIN32
145+ cbz x0, p100 // If size is 0, skip to return
146+ // Windows requires page-wise allocation with stack probing
147+ mov x2, #4096 // Page size = 4096 bytes
148+
149+p101:
150+ cmp x0, x2 // Compare remaining size with page size
151+ b.lo p102 // If less than page, jump to remainder
152+
153+ // Probe first, then allocate
154+ sub x3, sp, x2 // Calculate guard page address (sp - 4096)
155+ ldr xzr, [x3] // Touch guard page FIRST
156+ sub sp, sp, x2 // THEN allocate the page
157+
158+ sub x0, x0, x2 // Decrement remaining size
159+ b p101 // Continue loop
160+
161+p102:
162+ // Allocate remaining bytes (less than one page)
163+ cbz x0, p100 // If no remaining bytes, skip
164+ sub sp, sp, x0 // Allocate remaining space
165+#else
166+ // Non-Windows: simple one-time allocation
167+ sub sp, sp, x0 // Allocate space on stack
168+#endif
169+
170+p100:
171+ mov x0, sp // Return allocated address
172+ stp x29, x30, [sp, #-16]!
173+ bl _(__bound_new_region)
174+ ldp x29, x30, [sp], #16
175+ mov x0, sp // Return allocated address
176+ ret // Return to caller
177+#endif
178+
179+/* ---------------------------------------------- */
180+#elif defined __riscv
181+
182+.globl _(__bound_alloca)
183+_(__bound_alloca):
184+ mv a1, a0
185+ sub sp, sp, a0
186+ addi sp, sp, -16
187+ andi sp, sp, -16
188+ add a0, sp, zero
189+ addi sp,sp,-16
190+ sd s0,0(sp)
191+ sd ra,8(sp)
192+ jal _(__bound_new_region)
193+ ld s0,0(sp)
194+ ld ra,8(sp)
195+ addi sp,sp,16
196+ add a0, sp, zero
197+ ret
198+
95199 /* ---------------------------------------------- */
96200 #endif
lib/alloca.S+15−26
@@ -70,25 +70,18 @@ p3: · 69 unmodified lines
7070 /* ---------------------------------------------- */
7171 #elif defined __arm__
7272
73− .text
74− .align 2
75− .global alloca
76− .type alloca, %function
77−alloca:
73+.globl _(alloca)
74+_(alloca):
7875 rsb sp, r0, sp
7976 bic sp, sp, #7
8077 mov r0, sp
8178 mov pc, lr
82− .size alloca, .-alloca
8379
8480 /* ---------------------------------------------- */
8581 #elif defined __aarch64__ || defined __arm64__
8682
87− .text
88− .align 2
89− .global alloca
90− .type alloca, %function
91−alloca:
83+.globl _(alloca)
84+_(alloca):
9285 #ifdef __TINYC__
9386 .int 0x91003c00
9487 .int 0x927cec00
@@ -102,16 +95,16 @@ alloca: · 7 unmodified lines
10295 .int 0xcb2163ff
10396 .int 0xcb010000
10497 .int 0x17fffffa
105−#endif
10698 .int 0xb4000040
99+#endif
107100 .int 0xcb2063ff
108101 .int 0x910003e0
109102 .int 0xd65f03c0
110103 #else
111104 add x0, x0, #15 // Round up to 16-byte boundary
112105 and x0, x0, #-16 // Ensure 16-byte alignment
113− cbz x0, p100 // If size is 0, skip to return
114106 #ifdef _WIN32
107+ cbz x0, p100 // If size is 0, skip to return
115108 // Windows requires page-wise allocation with stack probing
116109 mov x1, #4096 // Page size = 4096 bytes
117110
@@ -140,20 +133,16 @@ p100: · 22 unmodified lines
140133 mov x0, sp // Return allocated address
141134 ret // Return to caller
142135 #endif
143− .size alloca, .-alloca
136+
144137 /* ---------------------------------------------- */
145138 #elif defined __riscv
146139
147− .text
148− .align 2
149− .global alloca
150− .type alloca, %function
151−alloca:
152− sub sp, sp, a0
153− addi sp, sp, -15
154− andi sp, sp, -16
155− add a0, sp, zero
156− ret
157− .size alloca, .-alloca
158−/* ---------------------------------------------- */
140+.globl _(alloca)
141+_(alloca):
142+ sub sp, sp, a0
143+ addi sp, sp, -15
144+ andi sp, sp, -16
145+ add a0, sp, zero
146+ ret
147+
159148 #endif
libtcc.c+1−1
@@ -40,7 +40,7 @@ · 39 unmodified lines
4040 #elif defined(TCC_TARGET_ARM64)
4141 #include "arm64-gen.c"
4242 #include "arm64-link.c"
43−#include "arm-asm.c"
43+#include "arm64-asm.c"
4444 #elif defined(TCC_TARGET_C67)
4545 #include "c67-gen.c"
4646 #include "c67-link.c"
tcc.h+1−1
@@ -385,7 +385,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 384 unmodified lines
385385 #elif defined TCC_TARGET_ARM64
386386 # include "arm64-gen.c"
387387 # include "arm64-link.c"
388−# include "arm-asm.c"
388+# include "arm64-asm.c"
389389 #elif defined TCC_TARGET_C67
390390 # define TCC_TARGET_COFF
391391 # include "coff.h"
tccasm.c+17−0
@@ -984,6 +984,23 @@ static void asm_parse_directive(TCCState *s1, int global) · 983 unmodified lines
984984 skip('@');
985985 next();
986986 break;
987+ case TOK_ASMDIR_reloc:
988+ {
989+ ExprValue e;
990+
991+ next();
992+ asm_expr(s1, &e);
993+ skip(',');
994+#ifdef __aarch64__
995+ if (strcmp(get_tok_str(tok, NULL), "R_AARCH64_CALL26"))
996+#endif
997+ tcc_error("unimp: reloc '%s' unknown", get_tok_str(tok, NULL));
998+ next();
999+ skip(',');
1000+ greloca(cur_text_section, get_asm_sym(tok, NULL), e.v, R_AARCH64_CALL26, 0);
1001+ next();
1002+ }
1003+ break;
9871004 default:
9881005 tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
9891006 break;
tccgen.c+0−2
@@ -1701,10 +1701,8 @@ ST_FUNC void gbound_args(int nb_args) · 1700 unmodified lines
17011701 gfunc_call(1);
17021702 func_bound_add_epilog = 1;
17031703 }
1704−#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
17051704 if (v == TOK_alloca)
17061705 func_bound_add_epilog = 1;
1707−#endif
17081706 #if TARGETOS_NetBSD
17091707 if (v == TOK_longjmp) /* undo rename to __longjmp14 */
17101708 sv->sym->asm_label = TOK___bound_longjmp;
tcctok.h+1−2
@@ -301,9 +301,7 @@ · 300 unmodified lines
301301 DEF(TOK___fixxfdi, "__fixxfdi")
302302 #endif
303303
304−#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
305304 DEF(TOK_alloca, "alloca")
306−#endif
307305
308306 #if defined TCC_TARGET_PE
309307 DEF(TOK___chkstk, "__chkstk")
@@ -415,6 +413,7 @@ · 105 unmodified lines
415413 DEF_ASMDIR(long)
416414 DEF_ASMDIR(int)
417415 DEF_ASMDIR(symver)
416+ DEF_ASMDIR(reloc)
418417 DEF_ASMDIR(section) /* must be last directive */
419418
420419 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
tests/boundtest.c+0−14
@@ -169,14 +169,6 @@ 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−#undef alloca
176−#define alloca(x) malloc(x)
177−#define allocf(x) free(x)
178−#endif
179−
180172 int test14(void)
181173 {
182174 char *p = alloca(TAB_SIZE);
@@ -184,7 +176,6 @@ int test14(void) · 1 unmodified line
184176 memset(p, 'a', TAB_SIZE);
185177 p[TAB_SIZE-1] = 0;
186178 ret = strlen(p);
187− allocf(p);
188179 return ret;
189180 }
190181
@@ -196,7 +187,6 @@ int test15(void) · 5 unmodified lines
196187 memset(p, 'a', TAB_SIZE);
197188 p[TAB_SIZE-1] = 0;
198189 ret = strlen(p);
199− allocf(p);
200190 return ret;
201191 }
202192
@@ -211,8 +201,6 @@ int test16() · 8 unmodified lines
211201
212202 /* Test alloca embedded in a larger expression */
213203 printf("alloca : %s : %s\n", p, strcpy(q=alloca(strlen(demo)+1),demo) );
214− allocf(p);
215− allocf(q);
216204
217205 return 0;
218206 }
@@ -228,8 +216,6 @@ int test17() · 9 unmodified lines
228216
229217 /* Test alloca embedded in a larger expression */
230218 printf("alloca : %s : %s\n", p, strcpy(q=alloca(strlen(demo)),demo) );
231− allocf(p);
232− allocf(q);
233219
234220 return 0;
235221 }
tests/tcctest.c+0−4
@@ -2941,14 +2941,12 @@ void old_style_function_test(void) · 2940 unmodified lines
29412941
29422942 void alloca_test()
29432943 {
2944−#if defined __i386__ || defined __x86_64__ || defined __arm__
29452944 char *p = alloca(16);
29462945 strcpy(p,"123456789012345");
29472946 printf("alloca: p is %s\n", p);
29482947 char *demo = "This is only a test.\n";
29492948 /* Test alloca embedded in a larger expression */
29502949 printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
2951−#endif
29522950 }
29532951
29542952 void *bounds_checking_is_enabled()
@@ -4208,7 +4206,6 @@ double get100 () { return 100.0; } · 1253 unmodified lines
42084206
42094207 void callsave_test(void)
42104208 {
4211−#if defined __i386__ || defined __x86_64__ || defined __arm__
42124209 int i, s; double *d; double t;
42134210 s = sizeof (double);
42144211 printf ("callsavetest: %d\n", s);
@@ -4221,7 +4218,6 @@ void callsave_test(void) · 6 unmodified lines
42214218 generates a segfault. */
42224219 i = d[0] > get100 ();
42234220 printf ("%d\n", i);
4224−#endif
42254221 }
42264222
42274223

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