Skip to content

Commit 41da013

Browse files
committed
Define __stack_base and __stack_limit globals in debug mode for stack overflow detection
That enables VMs to implement stack overflow detection or using passes like https://github.com/WebAssembly/binaryen/blob/main/src/passes/StackCheck.cpp
1 parent 16a6940 commit 41da013

File tree

4 files changed

+83
-37
lines changed

4 files changed

+83
-37
lines changed

Makefile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ NM ?= $(patsubst %clang,%llvm-nm,$(filter-out ccache sccache,$(CC)))
88
ifeq ($(origin AR), default)
99
AR = $(patsubst %clang,%llvm-ar,$(filter-out ccache sccache,$(CC)))
1010
endif
11-
EXTRA_CFLAGS ?= -O2 -DNDEBUG
11+
DEFAULT_EXTRA_CFLAGS = -O2 -DNDEBUG
12+
EXTRA_CFLAGS ?= $(DEFAULT_EXTRA_CFLAGS)
1213
# The directory where we build the sysroot.
1314
SYSROOT ?= $(CURDIR)/sysroot
1415
# A directory to install to for "make install".
@@ -269,7 +270,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
269270
thread/sem_timedwait.c \
270271
thread/sem_trywait.c \
271272
thread/sem_wait.c \
272-
thread/wasm32/wasi_thread_start.s \
273+
thread/wasm32/wasi_thread_start.S \
273274
)
274275
endif
275276

@@ -341,7 +342,7 @@ CFLAGS += -isystem "$(SYSROOT_INC)"
341342
# These variables describe the locations of various files and directories in
342343
# the build tree.
343344
objs = $(patsubst $(CURDIR)/%.c,$(OBJDIR)/%.o,$(1))
344-
asmobjs = $(patsubst $(CURDIR)/%.s,$(OBJDIR)/%.o,$(1))
345+
asmobjs = $(patsubst $(CURDIR)/%.S,$(OBJDIR)/%.o,$(1))
345346
DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES))
346347
EMMALLOC_OBJS = $(call objs,$(EMMALLOC_SOURCES))
347348
LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES))
@@ -520,7 +521,7 @@ $(OBJDIR)/%.o: $(CURDIR)/%.c include_dirs
520521
@mkdir -p "$(@D)"
521522
$(CC) $(CFLAGS) -MD -MP -o $@ -c $<
522523

523-
$(OBJDIR)/%.o: $(CURDIR)/%.s include_dirs
524+
$(OBJDIR)/%.o: $(CURDIR)/%.S include_dirs
524525
@mkdir -p "$(@D)"
525526
$(CC) $(ASMFLAGS) -o $@ -c $<
526527

@@ -704,9 +705,13 @@ check-symbols: startup_files libc
704705
| grep -v '^#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_\(1\|2\|4\|8\)' \
705706
> "$(SYSROOT_SHARE)/predefined-macros.txt"
706707

708+
# Only verify metadata for default set of extra cflags; otherwise, it
709+
# most likely won't match.
710+
ifeq ($(EXTRA_CFLAGS),$(DEFAULT_EXTRA_CFLAGS))
707711
# Check that the computed metadata matches the expected metadata.
708712
# This ignores whitespace because on Windows the output has CRLF line endings.
709713
diff -wur "$(CURDIR)/expected/$(TARGET_TRIPLE)" "$(SYSROOT_SHARE)"
714+
endif
710715

711716
install: finish
712717
mkdir -p "$(INSTALL_DIR)"

libc-top-half/musl/src/thread/pthread_create.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,14 @@ struct start_args {
239239
unsigned long sig_mask[_NSIG/8/sizeof(long)];
240240
#else
241241
/*
242-
* Note: the offset of the "stack" and "tls_base" members
242+
* Note: the offset of the "stack", "stack_limit" and "tls_base" members
243243
* in this structure is hardcoded in wasi_thread_start.
244244
*/
245245
void *stack;
246246
void *tls_base;
247+
#ifndef NDEBUG
248+
void *stack_limit;
249+
#endif
247250
void *(*start_func)(void *);
248251
void *start_arg;
249252
#endif
@@ -501,7 +504,12 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
501504
/* Correct the stack size */
502505
new->stack_size = stack - stack_limit;
503506

504-
args->stack = new->stack; /* just for convenience of asm trampoline */
507+
/* just for convenience of asm trampoline */
508+
args->stack = new->stack;
509+
#ifndef NDEBUG
510+
args->stack_limit = stack_limit;
511+
#endif
512+
505513
args->start_func = entry;
506514
args->start_arg = arg;
507515
args->tls_base = (void*)new_tls_base;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#define PTR i32
2+
#define PTRSIZE 4
3+
# Preprocessor's define directive doesn't resolve math expressions,
4+
# so we hardcode the result of PTRSIZE * 2 operation
5+
#define DOUBLE_PTRSIZE 8
6+
7+
.text
8+
9+
.export_name wasi_thread_start, wasi_thread_start
10+
11+
.globaltype __stack_pointer, PTR
12+
.globaltype __tls_base, PTR
13+
14+
#ifndef NDEBUG
15+
.globaltype __stack_base, PTR
16+
.globaltype __stack_limit, PTR
17+
#endif
18+
19+
.functype __wasi_thread_start_C (i32, PTR) -> ()
20+
21+
.hidden wasi_thread_start
22+
.globl wasi_thread_start
23+
.type wasi_thread_start,@function
24+
25+
wasi_thread_start:
26+
.functype wasi_thread_start (i32, PTR) -> ()
27+
28+
# Set up the minimum C environment.
29+
# Note: offsetof(start_arg, stack) == 0
30+
local.get 1 # start_arg
31+
PTR.load 0 # stack
32+
global.set __stack_pointer
33+
34+
local.get 1 # start_arg
35+
PTR.load PTRSIZE # tls_base
36+
global.set __tls_base
37+
38+
#ifndef NDEBUG
39+
# configure __stack_base and __stack_limit in debug mode
40+
# to allow for stack overflow detection
41+
local.get 1 # start_arg
42+
PTR.load 0 # stack
43+
global.set __stack_base
44+
45+
local.get 1 # start_arg
46+
PTR.load DOUBLE_PTRSIZE # stack_limit
47+
global.set __stack_limit
48+
#endif
49+
50+
# Make the C function do the rest of work.
51+
local.get 0 # tid
52+
local.get 1 # start_arg
53+
call __wasi_thread_start_C
54+
55+
end_function
56+
57+
#ifndef NDEBUG
58+
.section .data,"",@
59+
60+
__stack_base:
61+
62+
__stack_limit:
63+
64+
#endif

libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)