summaryrefslogtreecommitdiffstats
path: root/libc-top-half
diff options
context:
space:
mode:
Diffstat (limited to 'libc-top-half')
-rw-r--r--libc-top-half/musl/arch/wasm32/bits/setjmp.h1
-rw-r--r--libc-top-half/musl/include/dlfcn.h12
-rw-r--r--libc-top-half/musl/include/netdb.h5
-rw-r--r--libc-top-half/musl/include/pthread.h2
-rw-r--r--libc-top-half/musl/include/setjmp.h10
-rw-r--r--libc-top-half/musl/include/stdlib.h2
-rw-r--r--libc-top-half/musl/include/sys/socket.h18
-rw-r--r--libc-top-half/musl/include/sys/stat.h2
-rw-r--r--libc-top-half/musl/src/env/__init_tls.c36
-rw-r--r--libc-top-half/musl/src/internal/locale_impl.h8
-rw-r--r--libc-top-half/musl/src/misc/dl.c45
-rw-r--r--libc-top-half/musl/src/setjmp/wasm32/rt.c83
-rw-r--r--libc-top-half/musl/src/thread/pthread_create.c17
-rw-r--r--libc-top-half/musl/src/thread/pthread_getattr_np.c6
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;
}