Skip to content

Commit 6da4594

Browse files
committed
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)
1 parent fc424c9 commit 6da4594

File tree

12 files changed

+142
-59
lines changed

12 files changed

+142
-59
lines changed

include/stddef.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ typedef union { long long __ll; long double __ld; } max_align_t;
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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,8 @@
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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ endif
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

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,109 @@ p3:
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

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -70,25 +70,18 @@ p3:
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:
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:
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,23 @@ static void asm_parse_directive(TCCState *s1, int global)
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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,10 +1701,8 @@ ST_FUNC void gbound_args(int nb_args)
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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,7 @@
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 @@
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

0 commit comments

Comments
 (0)