diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 83c2751fd..0f0d9dc14 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -98,6 +98,13 @@ jobs: shell: bash run: make -j4 THREAD_MODEL=posix + - name: Build libc + threads in debug mode + # There are features like stack boundary exposure that + # only compile in debug mode (i.e. when NDEBUG is not defined). + if: matrix.clang_version != '10.0.0' + shell: bash + run: make -j4 THREAD_MODEL=posix EXTRA_CFLAGS= + # Disable the headerstest job for now, while WASI transitions from the # witx snapshots to wit proposals, and we have a few manual edits to the # generated header to make life easier for folks. diff --git a/Makefile b/Makefile index 27f6760f9..9a5cf8324 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ NM ?= $(patsubst %clang,%llvm-nm,$(filter-out ccache sccache,$(CC))) ifeq ($(origin AR), default) AR = $(patsubst %clang,%llvm-ar,$(filter-out ccache sccache,$(CC))) endif -EXTRA_CFLAGS ?= -O2 -DNDEBUG +DEFAULT_EXTRA_CFLAGS = -O2 -DNDEBUG +EXTRA_CFLAGS ?= $(DEFAULT_EXTRA_CFLAGS) # The directory where we build the sysroot. SYSROOT ?= $(CURDIR)/sysroot # A directory to install to for "make install". @@ -269,7 +270,7 @@ LIBC_TOP_HALF_MUSL_SOURCES += \ thread/sem_timedwait.c \ thread/sem_trywait.c \ thread/sem_wait.c \ - thread/wasm32/wasi_thread_start.s \ + thread/wasm32/wasi_thread_start.S \ ) endif @@ -341,7 +342,7 @@ CFLAGS += -isystem "$(SYSROOT_INC)" # These variables describe the locations of various files and directories in # the build tree. objs = $(patsubst $(CURDIR)/%.c,$(OBJDIR)/%.o,$(1)) -asmobjs = $(patsubst $(CURDIR)/%.s,$(OBJDIR)/%.o,$(1)) +asmobjs = $(patsubst $(CURDIR)/%.S,$(OBJDIR)/%.o,$(1)) DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES)) EMMALLOC_OBJS = $(call objs,$(EMMALLOC_SOURCES)) LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES)) @@ -520,7 +521,7 @@ $(OBJDIR)/%.o: $(CURDIR)/%.c include_dirs @mkdir -p "$(@D)" $(CC) $(CFLAGS) -MD -MP -o $@ -c $< -$(OBJDIR)/%.o: $(CURDIR)/%.s include_dirs +$(OBJDIR)/%.o: $(CURDIR)/%.S include_dirs @mkdir -p "$(@D)" $(CC) $(ASMFLAGS) -o $@ -c $< @@ -704,9 +705,13 @@ check-symbols: startup_files libc | grep -v '^#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_\(1\|2\|4\|8\)' \ > "$(SYSROOT_SHARE)/predefined-macros.txt" + # Only verify metadata for default set of extra cflags; otherwise, it + # most likely won't match. +ifeq ($(EXTRA_CFLAGS),$(DEFAULT_EXTRA_CFLAGS)) # Check that the computed metadata matches the expected metadata. # This ignores whitespace because on Windows the output has CRLF line endings. diff -wur "$(CURDIR)/expected/$(TARGET_TRIPLE)" "$(SYSROOT_SHARE)" +endif install: finish mkdir -p "$(INSTALL_DIR)" diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c index 676e2ccf9..6c85e2af5 100644 --- a/libc-top-half/musl/src/thread/pthread_create.c +++ b/libc-top-half/musl/src/thread/pthread_create.c @@ -239,11 +239,14 @@ struct start_args { unsigned long sig_mask[_NSIG/8/sizeof(long)]; #else /* - * Note: the offset of the "stack" and "tls_base" members + * Note: the offset of the "stack", "stack_limit" and "tls_base" members * in this structure is hardcoded in wasi_thread_start. */ void *stack; void *tls_base; +#ifndef NDEBUG + void *stack_limit; +#endif void *(*start_func)(void *); void *start_arg; #endif @@ -501,7 +504,12 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att /* Correct the stack size */ new->stack_size = stack - stack_limit; - args->stack = new->stack; /* just for convenience of asm trampoline */ + /* just for convenience of asm trampoline */ + args->stack = new->stack; +#ifndef NDEBUG + args->stack_limit = stack_limit; +#endif + args->start_func = entry; args->start_arg = arg; args->tls_base = (void*)new_tls_base; diff --git a/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.S b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.S new file mode 100644 index 000000000..acd3cd454 --- /dev/null +++ b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.S @@ -0,0 +1,64 @@ +#define PTR i32 +#define PTRSIZE 4 +# Preprocessor's define directive doesn't resolve math expressions, +# so we hardcode the result of PTRSIZE * 2 operation +#define DOUBLE_PTRSIZE 8 + + .text + + .export_name wasi_thread_start, wasi_thread_start + + .globaltype __stack_pointer, PTR + .globaltype __tls_base, PTR + +#ifndef NDEBUG + .globaltype __stack_base, PTR + .globaltype __stack_limit, PTR +#endif + + .functype __wasi_thread_start_C (i32, PTR) -> () + + .hidden wasi_thread_start + .globl wasi_thread_start + .type wasi_thread_start,@function + +wasi_thread_start: + .functype wasi_thread_start (i32, PTR) -> () + + # Set up the minimum C environment. + # Note: offsetof(start_arg, stack) == 0 + local.get 1 # start_arg + PTR.load 0 # stack + global.set __stack_pointer + + local.get 1 # start_arg + PTR.load PTRSIZE # tls_base + global.set __tls_base + +#ifndef NDEBUG + # configure __stack_base and __stack_limit in debug mode + # to allow for stack overflow detection + local.get 1 # start_arg + PTR.load 0 # stack + global.set __stack_base + + local.get 1 # start_arg + PTR.load DOUBLE_PTRSIZE # stack_limit + global.set __stack_limit +#endif + + # Make the C function do the rest of work. + local.get 0 # tid + local.get 1 # start_arg + call __wasi_thread_start_C + + end_function + +#ifndef NDEBUG +.section .data,"",@ + +__stack_base: + +__stack_limit: + +#endif diff --git a/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s deleted file mode 100644 index 0fe9854e9..000000000 --- a/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s +++ /dev/null @@ -1,31 +0,0 @@ - .text - - .export_name wasi_thread_start, wasi_thread_start - - .globaltype __stack_pointer, i32 - .globaltype __tls_base, i32 - .functype __wasi_thread_start_C (i32, i32) -> () - - .hidden wasi_thread_start - .globl wasi_thread_start - .type wasi_thread_start,@function - -wasi_thread_start: - .functype wasi_thread_start (i32, i32) -> () - - # Set up the minimum C environment. - # Note: offsetof(start_arg, stack) == 0 - local.get 1 # start_arg - i32.load 0 # stack - global.set __stack_pointer - - local.get 1 # start_arg - i32.load 4 # tls_base - global.set __tls_base - - # Make the C function do the rest of work. - local.get 0 # tid - local.get 1 # start_arg - call __wasi_thread_start_C - - end_function