diff options
Diffstat (limited to 'libc-top-half')
-rw-r--r-- | libc-top-half/musl/arch/wasm32/bits/setjmp.h | 1 | ||||
-rw-r--r-- | libc-top-half/musl/include/dlfcn.h | 12 | ||||
-rw-r--r-- | libc-top-half/musl/include/netdb.h | 5 | ||||
-rw-r--r-- | libc-top-half/musl/include/pthread.h | 2 | ||||
-rw-r--r-- | libc-top-half/musl/include/setjmp.h | 10 | ||||
-rw-r--r-- | libc-top-half/musl/include/stdlib.h | 2 | ||||
-rw-r--r-- | libc-top-half/musl/include/sys/socket.h | 18 | ||||
-rw-r--r-- | libc-top-half/musl/include/sys/stat.h | 2 | ||||
-rw-r--r-- | libc-top-half/musl/src/env/__init_tls.c | 36 | ||||
-rw-r--r-- | libc-top-half/musl/src/internal/locale_impl.h | 8 | ||||
-rw-r--r-- | libc-top-half/musl/src/misc/dl.c | 45 | ||||
-rw-r--r-- | libc-top-half/musl/src/setjmp/wasm32/rt.c | 83 | ||||
-rw-r--r-- | libc-top-half/musl/src/thread/pthread_create.c | 17 | ||||
-rw-r--r-- | libc-top-half/musl/src/thread/pthread_getattr_np.c | 6 |
14 files changed, 216 insertions, 31 deletions
diff --git a/libc-top-half/musl/arch/wasm32/bits/setjmp.h b/libc-top-half/musl/arch/wasm32/bits/setjmp.h new file mode 100644 index 0000000..63973a8 --- /dev/null +++ b/libc-top-half/musl/arch/wasm32/bits/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long __jmp_buf[8]; diff --git a/libc-top-half/musl/include/dlfcn.h b/libc-top-half/musl/include/dlfcn.h index 13ab71d..e802de8 100644 --- a/libc-top-half/musl/include/dlfcn.h +++ b/libc-top-half/musl/include/dlfcn.h @@ -12,19 +12,29 @@ extern "C" { #define RTLD_NOLOAD 4 #define RTLD_NODELETE 4096 #define RTLD_GLOBAL 256 +#ifdef __wasilibc_unmodified_upstream #define RTLD_LOCAL 0 +#else +/* For WASI, we give `RTLD_LOCAL` a non-zero value, avoiding ambiguity and + * allowing us to defer the decision of whether `RTLD_LOCAL` or `RTLD_GLOBAL` + * should be the default when neither is specified. + */ +#define RTLD_LOCAL 8 +#endif #define RTLD_NEXT ((void *)-1) #define RTLD_DEFAULT ((void *)0) +#ifdef __wasilibc_unmodified_upstream #define RTLD_DI_LINKMAP 2 +#endif int dlclose(void *); char *dlerror(void); void *dlopen(const char *, int); void *dlsym(void *__restrict, const char *__restrict); -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#if defined(__wasilibc_unmodified_upstream) && (defined(_GNU_SOURCE) || defined(_BSD_SOURCE)) typedef struct { const char *dli_fname; void *dli_fbase; diff --git a/libc-top-half/musl/include/netdb.h b/libc-top-half/musl/include/netdb.h index d096c78..f9797bc 100644 --- a/libc-top-half/musl/include/netdb.h +++ b/libc-top-half/musl/include/netdb.h @@ -118,8 +118,13 @@ struct hostent *gethostbyaddr (const void *, socklen_t, int); #ifdef __GNUC__ __attribute__((const)) #endif +#ifdef __wasilibc_unmodified_upstream int *__h_errno_location(void); #define h_errno (*__h_errno_location()) +#elif (defined __wasilibc_use_wasip2) +extern _Thread_local int h_errno; +#define h_errno h_errno +#endif #define HOST_NOT_FOUND 1 #define TRY_AGAIN 2 #define NO_RECOVERY 3 diff --git a/libc-top-half/musl/include/pthread.h b/libc-top-half/musl/include/pthread.h index 05101e8..2c35d0b 100644 --- a/libc-top-half/musl/include/pthread.h +++ b/libc-top-half/musl/include/pthread.h @@ -97,7 +97,9 @@ int pthread_equal(pthread_t, pthread_t); int pthread_setcancelstate(int, int *); int pthread_setcanceltype(int, int *); void pthread_testcancel(void); +#ifdef __wasilibc_unmodified_upstream /* WASI has no cancellation support. */ int pthread_cancel(pthread_t); +#endif #ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */ int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict); diff --git a/libc-top-half/musl/include/setjmp.h b/libc-top-half/musl/include/setjmp.h index f505f8e..b57999e 100644 --- a/libc-top-half/musl/include/setjmp.h +++ b/libc-top-half/musl/include/setjmp.h @@ -7,7 +7,12 @@ extern "C" { #include <features.h> -#ifdef __wasilibc_unmodified_upstream /* WASI has no setjmp */ +#ifndef __wasilibc_unmodified_upstream +/* WASI has no setjmp */ +#if !defined(__wasm_exception_handling__) +#error Setjmp/longjmp support requires Exception handling support, which is [not yet standardized](https://github.com/WebAssembly/proposals?tab=readme-ov-file#phase-3---implementation-phase-cg--wg). To enable it, compile with `-mllvm -wasm-enable-sjlj` and use an engine that implements the Exception handling proposal. +#endif +#endif #include <bits/setjmp.h> typedef struct __jmp_buf_tag { @@ -40,9 +45,6 @@ int setjmp (jmp_buf) __setjmp_attr; _Noreturn void longjmp (jmp_buf, int); #define setjmp setjmp -#else -#warning setjmp is not yet implemented for WASI -#endif #undef __setjmp_attr diff --git a/libc-top-half/musl/include/stdlib.h b/libc-top-half/musl/include/stdlib.h index 1bcb9ab..553e9ae 100644 --- a/libc-top-half/musl/include/stdlib.h +++ b/libc-top-half/musl/include/stdlib.h @@ -128,9 +128,7 @@ int rand_r (unsigned *); #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ || defined(_BSD_SOURCE) -#ifdef __wasilibc_unmodified_upstream /* WASI has no absolute paths */ char *realpath (const char *__restrict, char *__restrict); -#endif long int random (void); void srandom (unsigned int); char *initstate (unsigned int, char *, size_t); diff --git a/libc-top-half/musl/include/sys/socket.h b/libc-top-half/musl/include/sys/socket.h index 4d574c6..29189e3 100644 --- a/libc-top-half/musl/include/sys/socket.h +++ b/libc-top-half/musl/include/sys/socket.h @@ -1,5 +1,8 @@ #ifndef _SYS_SOCKET_H #define _SYS_SOCKET_H + +#include <__wasi_snapshot.h> + #ifdef __wasilibc_unmodified_upstream /* Use alternate WASI libc headers */ #else #include <__header_sys_socket.h> @@ -395,30 +398,33 @@ struct sockaddr_storage { #include <__struct_sockaddr_storage.h> #endif -#ifdef __wasilibc_unmodified_upstream /* WASI has no socket/socketpair */ +#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) int socket (int, int, int); +#endif + +#ifdef __wasilibc_unmodified_upstream /* WASI has no socketpair */ int socketpair (int, int, int, int [2]); #endif int shutdown (int, int); -#ifdef __wasilibc_unmodified_upstream /* WASI has no bind/connect/listen/accept */ -int bind (int, const struct sockaddr *, socklen_t); +#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) int connect (int, const struct sockaddr *, socklen_t); +int bind (int, const struct sockaddr *, socklen_t); int listen (int, int); #endif int accept (int, struct sockaddr *__restrict, socklen_t *__restrict); int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int); -#ifdef __wasilibc_unmodified_upstream /* WASI has no getsockname/getpeername */ +#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict); int getpeername (int, struct sockaddr *__restrict, socklen_t *__restrict); #endif ssize_t send (int, const void *, size_t, int); ssize_t recv (int, void *, size_t, int); -#ifdef __wasilibc_unmodified_upstream /* WASI has no sendto/recvfrom */ +#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) ssize_t sendto (int, const void *, size_t, int, const struct sockaddr *, socklen_t); ssize_t recvfrom (int, void *__restrict, size_t, int, struct sockaddr *__restrict, socklen_t *__restrict); #endif @@ -428,7 +434,7 @@ ssize_t recvmsg (int, struct msghdr *, int); #endif int getsockopt (int, int, int, void *__restrict, socklen_t *__restrict); -#ifdef __wasilibc_unmodified_upstream /* WASI has no setsockopt */ +#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) int setsockopt (int, int, int, const void *, socklen_t); #endif diff --git a/libc-top-half/musl/include/sys/stat.h b/libc-top-half/musl/include/sys/stat.h index 72e1626..c0090f7 100644 --- a/libc-top-half/musl/include/sys/stat.h +++ b/libc-top-half/musl/include/sys/stat.h @@ -78,11 +78,9 @@ int stat(const char *__restrict, struct stat *__restrict); int fstat(int, struct stat *); int lstat(const char *__restrict, struct stat *__restrict); int fstatat(int, const char *__restrict, struct stat *__restrict, int); -#ifdef __wasilibc_unmodified_upstream /* WASI has no chmod */ int chmod(const char *, mode_t); int fchmod(int, mode_t); int fchmodat(int, const char *, mode_t, int); -#endif #ifdef __wasilibc_unmodified_upstream /* WASI has no umask */ mode_t umask(mode_t); #endif diff --git a/libc-top-half/musl/src/env/__init_tls.c b/libc-top-half/musl/src/env/__init_tls.c index c3e407c..4f4c221 100644 --- a/libc-top-half/musl/src/env/__init_tls.c +++ b/libc-top-half/musl/src/env/__init_tls.c @@ -31,25 +31,35 @@ extern unsigned char __global_base; extern weak unsigned char __stack_high; extern weak unsigned char __stack_low; -static inline void setup_default_stack_size() +struct stack_bounds { + void *base; + size_t size; +}; + +static inline struct stack_bounds get_stack_bounds() { - ptrdiff_t stack_size; + struct stack_bounds bounds; - if (&__stack_high) - stack_size = &__stack_high - &__stack_low; - else { + if (&__stack_high) { + bounds.base = &__stack_high; + bounds.size = &__stack_high - &__stack_low; + } else { unsigned char *sp; __asm__( ".globaltype __stack_pointer, i32\n" "global.get __stack_pointer\n" "local.set %0\n" : "=r"(sp)); - stack_size = sp > &__global_base ? &__heap_base - &__data_end : (ptrdiff_t)&__global_base; + if (sp > &__global_base) { + bounds.base = &__heap_base; + bounds.size = &__heap_base - &__data_end; + } else { + bounds.base = &__global_base; + bounds.size = (size_t)&__global_base; + } } - __default_stacksize = - stack_size < DEFAULT_STACK_MAX ? - stack_size : DEFAULT_STACK_MAX; + return bounds; } void __wasi_init_tp() { @@ -68,8 +78,14 @@ int __init_tp(void *p) td->detach_state = DT_JOINABLE; td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock); #else - setup_default_stack_size(); + struct stack_bounds bounds = get_stack_bounds(); + __default_stacksize = + bounds.size < DEFAULT_STACK_MAX ? + bounds.size : DEFAULT_STACK_MAX; td->detach_state = DT_JOINABLE; + td->stack = bounds.base; + td->stack_size = bounds.size; + td->guard_size = 0; /* * Initialize the TID to a value which doesn't conflict with * host-allocated TIDs, so that TID-based locks can work. diff --git a/libc-top-half/musl/src/internal/locale_impl.h b/libc-top-half/musl/src/internal/locale_impl.h index 7f79b7f..4649a43 100644 --- a/libc-top-half/musl/src/internal/locale_impl.h +++ b/libc-top-half/musl/src/internal/locale_impl.h @@ -28,7 +28,15 @@ extern hidden const struct __locale_struct __c_dot_utf8_locale; hidden const struct __locale_map *__get_locale(int, const char *); hidden const char *__mo_lookup(const void *, size_t, const char *); hidden const char *__lctrans(const char *, const struct __locale_map *); +#ifdef __wasilibc_unmodified_upstream hidden const char *__lctrans_cur(const char *); +#else +// We make this visible in the wasi-libc build because +// libwasi-emulated-signal.so needs to import it from libc.so. If we ever +// decide to merge libwasi-emulated-signal.so into libc.so, this will no longer +// be necessary. +const char *__lctrans_cur(const char *); +#endif hidden const char *__lctrans_impl(const char *, const struct __locale_map *); hidden int __loc_is_allocated(locale_t); hidden char *__gettextdomain(void); diff --git a/libc-top-half/musl/src/misc/dl.c b/libc-top-half/musl/src/misc/dl.c new file mode 100644 index 0000000..266594f --- /dev/null +++ b/libc-top-half/musl/src/misc/dl.c @@ -0,0 +1,45 @@ +/* This file is used to build libdl.so with stub versions of `dlopen`, `dlsym`, + * etc. The intention is that this stubbed libdl.so can be used to build + * libraries and applications which use `dlopen` without committing to a + * specific runtime implementation. Later, it can be replaced with a real, + * working libdl.so (e.g. at runtime or component composition time). + * + * For example, the `wasm-tools component link` subcommand can be used to create + * a component that bundles any `dlopen`-able libraries in such a way that their + * function exports can be resolved symbolically at runtime using an + * implementation of libdl.so designed for that purpose. In other cases, a + * runtime might provide Emscripten-style dynamic linking via URLs or else a + * more traditional, filesystem-based implementation. Finally, even this + * stubbed version of libdl.so can be used at runtime in cases where dynamic + * library resolution cannot or should not be supported (and the application can + * handle this situation gracefully). */ + +#include <stddef.h> +#include <dlfcn.h> + +static const char *error = NULL; + +weak int dlclose(void *library) +{ + error = "dlclose not implemented"; + return -1; +} + +weak char *dlerror(void) +{ + const char *var = error; + error = NULL; + return (char*) var; +} + +weak void *dlopen(const char *name, int flags) +{ + error = "dlopen not implemented"; + return NULL; +} + +weak void *dlsym(void *library, const char *name) +{ + error = "dlsym not implemented"; + return NULL; +} diff --git a/libc-top-half/musl/src/setjmp/wasm32/rt.c b/libc-top-half/musl/src/setjmp/wasm32/rt.c new file mode 100644 index 0000000..24e4e33 --- /dev/null +++ b/libc-top-half/musl/src/setjmp/wasm32/rt.c @@ -0,0 +1,83 @@ +/* + * a runtime implementation for + * https://github.com/llvm/llvm-project/pull/84137 + * https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit + */ + +#include <stddef.h> +#include <stdint.h> + +/* + * function prototypes + */ +void __wasm_setjmp(void *env, uint32_t label, void *func_invocation_id); +uint32_t __wasm_setjmp_test(void *env, void *func_invocation_id); +void __wasm_longjmp(void *env, int val); + +/* + * jmp_buf should have large enough size and alignment to contain + * this structure. + */ +struct jmp_buf_impl { + void *func_invocation_id; + uint32_t label; + + /* + * this is a temorary storage used by the communication between + * __wasm_sjlj_longjmp and WebAssemblyLowerEmscriptenEHSjL-generated + * logic. + * ideally, this can be replaced with multivalue. + */ + struct arg { + void *env; + int val; + } arg; +}; + +void +__wasm_setjmp(void *env, uint32_t label, void *func_invocation_id) +{ + struct jmp_buf_impl *jb = env; + if (label == 0) { /* ABI contract */ + __builtin_trap(); + } + if (func_invocation_id == NULL) { /* sanity check */ + __builtin_trap(); + } + jb->func_invocation_id = func_invocation_id; + jb->label = label; +} + +uint32_t +__wasm_setjmp_test(void *env, void *func_invocation_id) +{ + struct jmp_buf_impl *jb = env; + if (jb->label == 0) { /* ABI contract */ + __builtin_trap(); + } + if (func_invocation_id == NULL) { /* sanity check */ + __builtin_trap(); + } + if (jb->func_invocation_id == func_invocation_id) { + return jb->label; + } + return 0; +} + +void +__wasm_longjmp(void *env, int val) +{ + struct jmp_buf_impl *jb = env; + struct arg *arg = &jb->arg; + /* + * C standard says: + * The longjmp function cannot cause the setjmp macro to return + * the value 0; if val is 0, the setjmp macro returns the value 1. + */ + if (val == 0) { + val = 1; + } + arg->env = env; + arg->val = val; + __builtin_wasm_throw(1, arg); /* 1 == C_LONGJMP */ +} diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c index 5de9f5a..450fe15 100644 --- a/libc-top-half/musl/src/thread/pthread_create.c +++ b/libc-top-half/musl/src/thread/pthread_create.c @@ -13,6 +13,7 @@ #endif #include <stdalign.h> +#include <assert.h> static void dummy_0() { @@ -558,13 +559,17 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att __wait(&args->control, 0, 3, 0); } #else +#define WASI_THREADS_MAX_TID 0x1FFFFFFF /* `wasi_thread_spawn` will either return a host-provided thread ID (TID) - * (`>= 0`) or an error code (`< 0`). As in the unmodified version, all - * spawn failures translate to EAGAIN; unlike the modified version, there is - * no need to "start up" the child thread--the host does this. If the spawn - * did succeed, then we store the TID atomically, since this parent thread - * is racing with the child thread to set this field; this way, whichever - * thread reaches this point first can continue without waiting. */ + * (`<1, 0x1FFFFFFF>`) or an error code (`< 0`). Please note that `0` is + * reserved for compatibility reasons and must not be returned by the runtime. + * As in the unmodified version, all spawn failures translate to EAGAIN; + * unlike the modified version, there is no need to "start up" the child + * thread--the host does this. If the spawn did succeed, then we store the + * TID atomically, since this parent thread is racing with the child thread + * to set this field; this way, whichever thread reaches this point first + * can continue without waiting. */ + assert(ret != 0 && ret <= WASI_THREADS_MAX_TID); if (ret < 0) { ret = -EAGAIN; } else { diff --git a/libc-top-half/musl/src/thread/pthread_getattr_np.c b/libc-top-half/musl/src/thread/pthread_getattr_np.c index 2881831..c23e5d7 100644 --- a/libc-top-half/musl/src/thread/pthread_getattr_np.c +++ b/libc-top-half/musl/src/thread/pthread_getattr_np.c @@ -1,7 +1,9 @@ #define _GNU_SOURCE #include "pthread_impl.h" #include "libc.h" +#ifdef __wasilibc_unmodified_upstream #include <sys/mman.h> +#endif int pthread_getattr_np(pthread_t t, pthread_attr_t *a) { @@ -12,6 +14,7 @@ int pthread_getattr_np(pthread_t t, pthread_attr_t *a) a->_a_stackaddr = (uintptr_t)t->stack; a->_a_stacksize = t->stack_size; } else { +#ifdef __wasilibc_unmodified_upstream char *p = (void *)libc.auxv; size_t l = PAGE_SIZE; p += -(uintptr_t)p & PAGE_SIZE-1; @@ -19,6 +22,9 @@ int pthread_getattr_np(pthread_t t, pthread_attr_t *a) while (mremap(p-l-PAGE_SIZE, PAGE_SIZE, 2*PAGE_SIZE, 0)==MAP_FAILED && errno==ENOMEM) l += PAGE_SIZE; a->_a_stacksize = l; +#else + return ENOSYS; +#endif } return 0; } |