linux-wasm/patches/musl/0001-NOMERGE-Hacks-to-get-Linux-Wasm-to-compile-minimal-a.patch
2025-10-31 18:38:01 +01:00

2354 lines
74 KiB
Diff

From 725521cc7eae536cc9542e832afba665d69545ea Mon Sep 17 00:00:00 2001
From: Joel Severin <joel.severin@icemanor.se>
Date: Wed, 27 Mar 2024 22:13:53 +0100
Subject: [PATCH] NOMERGE: Hacks to get Linux/Wasm to compile (minimal and
incorrect)
---
arch/wasm/arch.mak | 1 +
arch/wasm/atomic_arch.h | 15 +
arch/wasm/bits/alltypes.h.in | 17 ++
arch/wasm/bits/fenv.h | 10 +
arch/wasm/bits/float.h | 15 +
arch/wasm/bits/ipcstat.h | 1 +
arch/wasm/bits/msg.h | 18 ++
arch/wasm/bits/posix.h | 2 +
arch/wasm/bits/ptrace.h | 2 +
arch/wasm/bits/reg.h | 3 +
arch/wasm/bits/sem.h | 13 +
arch/wasm/bits/setjmp.h | 1 +
arch/wasm/bits/shm.h | 31 +++
arch/wasm/bits/signal.h | 85 ++++++
arch/wasm/bits/stat.h | 25 ++
arch/wasm/bits/stdint.h | 20 ++
arch/wasm/bits/syscall.h.in | 305 +++++++++++++++++++++
arch/wasm/bits/user.h | 8 +
arch/wasm/crt_arch.h | 40 +++
arch/wasm/kstat.h | 21 ++
arch/wasm/pthread_arch.h | 15 +
arch/wasm/reloc.h | 13 +
arch/wasm/syscall_arch.h | 12 +
configure | 13 +-
include/elf.h | 56 ++++
include/unistd.h | 5 +-
src/internal/pthread_impl.h | 9 +-
src/internal/syscall.h | 55 ++--
src/linux/clone.c | 21 +-
src/linux/reboot.c | 2 +-
src/misc/syscall.c | 56 +++-
src/misc/syscalls.c | 0
src/misc/wasm/syscalls.s | 123 +++++++++
src/network/accept.c | 2 +-
src/network/accept4.c | 2 +-
src/network/bind.c | 2 +-
src/network/connect.c | 2 +-
src/network/getpeername.c | 2 +-
src/network/getsockname.c | 2 +-
src/network/getsockopt.c | 6 +-
src/network/listen.c | 2 +-
src/network/recvmsg.c | 2 +-
src/network/sendmsg.c | 2 +-
src/network/setsockopt.c | 6 +-
src/network/shutdown.c | 2 +-
src/network/socket.c | 5 +-
src/network/socketpair.c | 5 +-
src/process/posix_spawn.c | 3 +-
src/process/vfork.c | 12 +-
src/setjmp/longjmp.c | 19 ++
src/setjmp/wasm/longjmp.S | 13 +
src/setjmp/wasm/setjmp.S | 5 +
src/signal/wasm/restore.s | 98 +++++++
src/signal/wasm/sigsetjmp.S | 5 +
src/thread/__syscall_cp.c | 18 --
src/thread/__timedwait.c | 6 +-
src/thread/__wait.c | 4 +-
src/thread/pthread_barrier_wait.c | 4 +-
src/thread/pthread_cancel.c | 108 ++++++--
src/thread/pthread_cond_timedwait.c | 4 +-
src/thread/pthread_mutex_timedlock.c | 6 +-
src/thread/pthread_mutex_trylock.c | 2 +-
src/thread/pthread_mutex_unlock.c | 2 +-
src/thread/pthread_mutexattr_setprotocol.c | 2 +-
src/thread/wasm/__set_thread_area.c | 9 +
src/thread/wasm/clone.s | 149 ++++++++++
src/unistd/access.c | 2 +-
src/unistd/faccessat.c | 2 +-
68 files changed, 1387 insertions(+), 141 deletions(-)
create mode 100644 arch/wasm/arch.mak
create mode 100644 arch/wasm/atomic_arch.h
create mode 100644 arch/wasm/bits/alltypes.h.in
create mode 100644 arch/wasm/bits/fenv.h
create mode 100644 arch/wasm/bits/float.h
create mode 100644 arch/wasm/bits/ipcstat.h
create mode 100644 arch/wasm/bits/msg.h
create mode 100644 arch/wasm/bits/posix.h
create mode 100644 arch/wasm/bits/ptrace.h
create mode 100644 arch/wasm/bits/reg.h
create mode 100644 arch/wasm/bits/sem.h
create mode 100644 arch/wasm/bits/setjmp.h
create mode 100644 arch/wasm/bits/shm.h
create mode 100644 arch/wasm/bits/signal.h
create mode 100644 arch/wasm/bits/stat.h
create mode 100644 arch/wasm/bits/stdint.h
create mode 100644 arch/wasm/bits/syscall.h.in
create mode 100644 arch/wasm/bits/user.h
create mode 100644 arch/wasm/crt_arch.h
create mode 100644 arch/wasm/kstat.h
create mode 100644 arch/wasm/pthread_arch.h
create mode 100644 arch/wasm/reloc.h
create mode 100644 arch/wasm/syscall_arch.h
create mode 100644 src/misc/syscalls.c
create mode 100644 src/misc/wasm/syscalls.s
create mode 100644 src/setjmp/wasm/longjmp.S
create mode 100644 src/setjmp/wasm/setjmp.S
create mode 100644 src/signal/wasm/restore.s
create mode 100644 src/signal/wasm/sigsetjmp.S
create mode 100644 src/thread/wasm/__set_thread_area.c
create mode 100644 src/thread/wasm/clone.s
diff --git a/arch/wasm/arch.mak b/arch/wasm/arch.mak
new file mode 100644
index 0000000..aa4d05c
--- /dev/null
+++ b/arch/wasm/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/wasm/atomic_arch.h b/arch/wasm/atomic_arch.h
new file mode 100644
index 0000000..95e840e
--- /dev/null
+++ b/arch/wasm/atomic_arch.h
@@ -0,0 +1,15 @@
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+ __atomic_compare_exchange_n(p, &t, s, (_Bool)0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ return t;
+}
+
+extern void __wasm_abort();
+
+#define a_crash a_crash
+static inline void a_crash()
+{
+ __wasm_abort();
+ __builtin_unreachable();
+}
diff --git a/arch/wasm/bits/alltypes.h.in b/arch/wasm/bits/alltypes.h.in
new file mode 100644
index 0000000..4b9c346
--- /dev/null
+++ b/arch/wasm/bits/alltypes.h.in
@@ -0,0 +1,17 @@
+#define _REDIR_TIME64 1
+#define _Addr long
+#define _Int64 long long
+#define _Reg int
+
+#define __BYTE_ORDER 1234
+
+#define __LONG_MAX 0x7fffffffL
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
diff --git a/arch/wasm/bits/fenv.h b/arch/wasm/bits/fenv.h
new file mode 100644
index 0000000..edbdea2
--- /dev/null
+++ b/arch/wasm/bits/fenv.h
@@ -0,0 +1,10 @@
+#define FE_ALL_EXCEPT 0
+#define FE_TONEAREST 0
+
+typedef unsigned long fexcept_t;
+
+typedef struct {
+ unsigned long __cw;
+} fenv_t;
+
+#define FE_DFL_ENV ((const fenv_t *) -1)
diff --git a/arch/wasm/bits/float.h b/arch/wasm/bits/float.h
new file mode 100644
index 0000000..97ba282
--- /dev/null
+++ b/arch/wasm/bits/float.h
@@ -0,0 +1,15 @@
+
+#define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
+#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
+#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
+#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
+
+#define LDBL_MANT_DIG 113
+#define LDBL_MIN_EXP (-16381)
+#define LDBL_MAX_EXP 16384
+
+#define LDBL_DIG 33
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
+
+#define DECIMAL_DIG 36
diff --git a/arch/wasm/bits/ipcstat.h b/arch/wasm/bits/ipcstat.h
new file mode 100644
index 0000000..4f4fcb0
--- /dev/null
+++ b/arch/wasm/bits/ipcstat.h
@@ -0,0 +1 @@
+#define IPC_STAT 0x102
diff --git a/arch/wasm/bits/msg.h b/arch/wasm/bits/msg.h
new file mode 100644
index 0000000..7bbbb2b
--- /dev/null
+++ b/arch/wasm/bits/msg.h
@@ -0,0 +1,18 @@
+struct msqid_ds {
+ struct ipc_perm msg_perm;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
+ unsigned long msg_cbytes;
+ msgqnum_t msg_qnum;
+ msglen_t msg_qbytes;
+ pid_t msg_lspid;
+ pid_t msg_lrpid;
+ unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
+};
diff --git a/arch/wasm/bits/posix.h b/arch/wasm/bits/posix.h
new file mode 100644
index 0000000..30a3871
--- /dev/null
+++ b/arch/wasm/bits/posix.h
@@ -0,0 +1,2 @@
+#define _POSIX_V6_ILP32_OFFBIG 1
+#define _POSIX_V7_ILP32_OFFBIG 1
diff --git a/arch/wasm/bits/ptrace.h b/arch/wasm/bits/ptrace.h
new file mode 100644
index 0000000..da93e7a
--- /dev/null
+++ b/arch/wasm/bits/ptrace.h
@@ -0,0 +1,2 @@
+#define PTRACE_GET_THREAD_AREA 25
+#define PTRACE_SINGLEBLOCK 33
diff --git a/arch/wasm/bits/reg.h b/arch/wasm/bits/reg.h
new file mode 100644
index 0000000..0c7bffc
--- /dev/null
+++ b/arch/wasm/bits/reg.h
@@ -0,0 +1,3 @@
+#undef __WORDSIZE
+#define __WORDSIZE 32
+/* FIXME */
diff --git a/arch/wasm/bits/sem.h b/arch/wasm/bits/sem.h
new file mode 100644
index 0000000..6566154
--- /dev/null
+++ b/arch/wasm/bits/sem.h
@@ -0,0 +1,13 @@
+struct semid_ds {
+ struct ipc_perm sem_perm;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_lo;
+ unsigned long __sem_ctime_hi;
+ unsigned short sem_nsems;
+ char __sem_nsems_pad[sizeof(long)-sizeof(short)];
+ long __unused3;
+ long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
+};
diff --git a/arch/wasm/bits/setjmp.h b/arch/wasm/bits/setjmp.h
new file mode 100644
index 0000000..55e3a95
--- /dev/null
+++ b/arch/wasm/bits/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long long __jmp_buf[32];
diff --git a/arch/wasm/bits/shm.h b/arch/wasm/bits/shm.h
new file mode 100644
index 0000000..725fb46
--- /dev/null
+++ b/arch/wasm/bits/shm.h
@@ -0,0 +1,31 @@
+#define SHMLBA 4096
+
+struct shmid_ds {
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_ctime_lo;
+ unsigned long __shm_ctime_hi;
+ pid_t shm_cpid;
+ pid_t shm_lpid;
+ unsigned long shm_nattch;
+ unsigned long __pad1;
+ unsigned long __pad2;
+ unsigned long __pad3;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+};
+
+struct shminfo {
+ unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+ int __used_ids;
+ unsigned long shm_tot, shm_rss, shm_swp;
+ unsigned long __swap_attempts, __swap_successes;
+};
diff --git a/arch/wasm/bits/signal.h b/arch/wasm/bits/signal.h
new file mode 100644
index 0000000..ab24d3d
--- /dev/null
+++ b/arch/wasm/bits/signal.h
@@ -0,0 +1,85 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+typedef unsigned long greg_t, gregset_t[2];
+typedef struct sigcontext {
+ unsigned long stack_pointer;
+ unsigned long tls;
+} mcontext_t;
+#else
+typedef struct {
+ unsigned long __regs[2];
+} mcontext_t;
+#endif
+
+#if defined(_GNU_SOURCE)
+#define REG_SP 0
+#define REG_TP 1
+#endif
+
+struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+};
+
+typedef struct __ucontext {
+ struct __ucontext *uc_link;
+ sigset_t uc_sigmask;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 1
+#define SA_NOCLDWAIT 2
+#define SA_SIGINFO 4
+#define SA_ONSTACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_NODEFER 0x40000000
+#define SA_RESETHAND 0x80000000
+#define SA_RESTORER 0x04000000
+
+#endif
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT SIGABRT
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL 29
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG 65
diff --git a/arch/wasm/bits/stat.h b/arch/wasm/bits/stat.h
new file mode 100644
index 0000000..8a4d509
--- /dev/null
+++ b/arch/wasm/bits/stat.h
@@ -0,0 +1,25 @@
+/* copied from kernel definition, but with padding replaced
+ * by the corresponding correctly-sized userspace types. */
+
+struct stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ long long __st_rdev_padding;
+ off_t st_size;
+ blksize_t st_blksize;
+ int __st_blksize_padding;
+ blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ unsigned __unused[2];
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+};
diff --git a/arch/wasm/bits/stdint.h b/arch/wasm/bits/stdint.h
new file mode 100644
index 0000000..d1b2712
--- /dev/null
+++ b/arch/wasm/bits/stdint.h
@@ -0,0 +1,20 @@
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST32_MIN INT32_MIN
+
+#define INT_FAST16_MAX INT32_MAX
+#define INT_FAST32_MAX INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#define UINTPTR_MAX UINT32_MAX
+#define PTRDIFF_MIN INT32_MIN
+#define PTRDIFF_MAX INT32_MAX
+#define SIZE_MAX UINT32_MAX
diff --git a/arch/wasm/bits/syscall.h.in b/arch/wasm/bits/syscall.h.in
new file mode 100644
index 0000000..5227a60
--- /dev/null
+++ b/arch/wasm/bits/syscall.h.in
@@ -0,0 +1,305 @@
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs64 43
+#define __NR_fstatfs64 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_getoverrun 109
+#define __NR_timer_delete 111
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap2 222
+#define __NR_fadvise64 223
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_arch_specific_syscall 244
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_statx 291
+#define __NR_rseq 293
+#define __NR_kexec_file_load 294
+#define __NR_clock_gettime64 403
+#define __NR_clock_settime64 404
+#define __NR_clock_adjtime64 405
+#define __NR_clock_getres_time64 406
+#define __NR_clock_nanosleep_time64 407
+#define __NR_timer_gettime64 408
+#define __NR_timer_settime64 409
+#define __NR_timerfd_gettime64 410
+#define __NR_timerfd_settime64 411
+#define __NR_utimensat_time64 412
+#define __NR_pselect6_time64 413
+#define __NR_ppoll_time64 414
+#define __NR_io_pgetevents_time64 416
+#define __NR_recvmmsg_time64 417
+#define __NR_mq_timedsend_time64 418
+#define __NR_mq_timedreceive_time64 419
+#define __NR_semtimedop_time64 420
+#define __NR_rt_sigtimedwait_time64 421
+#define __NR_futex_time64 422
+#define __NR_sched_rr_get_interval_time64 423
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
+#define __NR_process_madvise 440
+#define __NR_epoll_pwait2 441
+#define __NR_mount_setattr 442
+#define __NR_quotactl_fd 443
+#define __NR_landlock_create_ruleset 444
+#define __NR_landlock_add_rule 445
+#define __NR_landlock_restrict_self 446
+#define __NR_process_mrelease 448
+#define __NR_futex_waitv 449
+#define __NR_set_mempolicy_home_node 450
+#define __NR_cachestat 451
+#define __NR_fchmodat2 452
+
+/* These ones are NOT supported but required by musl - will return -ENOSYS. */
+#define __NR_nanosleep 101
+#define __NR_settimeofday 170
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+
+/* Required by musl to select the correct prototype. Notice the double __. */
+#define SYS__llseek __NR_lseek
diff --git a/arch/wasm/bits/user.h b/arch/wasm/bits/user.h
new file mode 100644
index 0000000..7954679
--- /dev/null
+++ b/arch/wasm/bits/user.h
@@ -0,0 +1,8 @@
+struct user_regs_struct {
+ unsigned long stack_pointer;
+ unsigned long tls;
+};
+
+typedef unsigned long elf_greg_t;
+typedef struct user_regs_struct elf_gregset_t;
+#define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t))
diff --git a/arch/wasm/crt_arch.h b/arch/wasm/crt_arch.h
new file mode 100644
index 0000000..fe3ce01
--- /dev/null
+++ b/arch/wasm/crt_arch.h
@@ -0,0 +1,40 @@
+/*
+ * We provide a prototype for main here (it's declared without prototype in crt1.c etc.). The reason
+ * we have to do this is to avoid an issue with LLVM wrapping and renaming it __original_main, which
+ * will fail when programs later on provide a real main with correct prototype and link it.
+ *
+ * Oh, and then it comes along and renames it __main_argc_argv because it has parameters, so we have
+ * to alias that as well and main will now be called __main_argc_argv. This cannot be a direct alias
+ * as it is not defined yet, so we just call it...
+ *
+ * To add salt to the injury, musl insists to call the 3-argument version with envp which is non-
+ * standard. What a wonderful mess... We need to clean this up someday, maybe auto-detect somehow.
+ */
+int __main_argc_argv(int argc, char *argv[]);
+int main(int argc, char *argv[], char *envp[])
+{
+ (void)envp;
+ return __main_argc_argv(argc, argv);
+}
+
+/*
+ * This must really be written in assembly (to capture the stack pointer properly), but we know that
+ * the initial stack pointer is page aligned, so we can cheat a bit and align it to the next page...
+ * The problem is that LLVM does not seem to work when functions are defined with inline asm (in C).
+ * TODO: fix this hack by refactoring musl and moving things into a .S file.
+ */
+#ifndef SHARED
+void _start(void)
+{
+ void _start_c(/* no prototype on purpose */);
+ int dummy;
+ _start_c(((unsigned long)(void*)&dummy + 4095UL) & ~4095UL);
+}
+#else
+void _dlstart(void)
+{
+ void _dlstart_c(/* no prototype on purpose */);
+ int dummy;
+ _dlstart_c(((unsigned long)(void*)&dummy + 4095UL) & ~4095UL);
+}
+#endif
diff --git a/arch/wasm/kstat.h b/arch/wasm/kstat.h
new file mode 100644
index 0000000..c144957
--- /dev/null
+++ b/arch/wasm/kstat.h
@@ -0,0 +1,21 @@
+struct kstat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ long long __st_rdev_padding;
+ off_t st_size;
+ blksize_t st_blksize;
+ int __st_blksize_padding;
+ blkcnt_t st_blocks;
+ long st_atime_sec;
+ long st_atime_nsec;
+ long st_mtime_sec;
+ long st_mtime_nsec;
+ long st_ctime_sec;
+ long st_ctime_nsec;
+ unsigned __unused[2];
+};
diff --git a/arch/wasm/pthread_arch.h b/arch/wasm/pthread_arch.h
new file mode 100644
index 0000000..0625bd1
--- /dev/null
+++ b/arch/wasm/pthread_arch.h
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+/*
+ * Wasm (as compiled with LLVM) handles TLS data directly, instead of the
+ * indirect approach used for ELF targets (where musl manages all TLS). There is
+ * still a pthread TLS area to keep track of, and musl manages that by these
+ * functions. In other words, __musl_tp will point to a struct pthread.
+ */
+
+extern _Thread_local uintptr_t __musl_tp;
+
+static inline uintptr_t __get_tp(void)
+{
+ return __musl_tp;
+}
diff --git a/arch/wasm/reloc.h b/arch/wasm/reloc.h
new file mode 100644
index 0000000..833a2f5
--- /dev/null
+++ b/arch/wasm/reloc.h
@@ -0,0 +1,13 @@
+#define LDSO_ARCH "wasm"
+
+#define TPOFF_K 0
+
+#define REL_SYMBOLIC R_WASM_64
+#define REL_PLT R_WASM_JUMP_SLOT
+#define REL_RELATIVE R_WASM_RELATIVE
+#define REL_COPY R_WASM_COPY
+#define REL_DTPMOD R_WASM_TLS_DTPMOD64
+#define REL_DTPOFF R_WASM_TLS_DTPREL64
+#define REL_TPOFF R_WASM_TLS_TPREL64
+
+#define CRTJMP(pc,sp) abort()
diff --git a/arch/wasm/syscall_arch.h b/arch/wasm/syscall_arch.h
new file mode 100644
index 0000000..1e06877
--- /dev/null
+++ b/arch/wasm/syscall_arch.h
@@ -0,0 +1,12 @@
+#define __SYSCALL_LL_E(x) \
+((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
+((union { long long ll; long l[2]; }){ .ll = x }).l[1]
+#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x))
+
+extern long __syscall0(long n);
+extern long __syscall1(long n, long a);
+extern long __syscall2(long n, long a, long b);
+extern long __syscall3(long n, long a, long b, long c);
+extern long __syscall4(long n, long a, long b, long c, long d);
+extern long __syscall5(long n, long a, long b, long c, long d, long e);
+extern long __syscall6(long n, long a, long b, long c, long d, long e, long f);
diff --git a/configure b/configure
index bc9fbe4..b44705b 100755
--- a/configure
+++ b/configure
@@ -340,6 +340,7 @@ riscv64*) ARCH=riscv64 ;;
riscv32*) ARCH=riscv32 ;;
sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
s390x*) ARCH=s390x ;;
+wasm*) ARCH=wasm ;;
unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
*) fail "$0: unknown or unsupported target \"$target\"" ;;
esac
@@ -586,33 +587,33 @@ fi
# Reduce space lost to padding for alignment purposes by sorting data
# objects according to their alignment reqirements. This approximates
# optimal packing.
-tryldflag LDFLAGS_AUTO -Wl,--sort-section,alignment
-tryldflag LDFLAGS_AUTO -Wl,--sort-common
+#tryldflag LDFLAGS_AUTO -Wl,--sort-section,alignment
+#tryldflag LDFLAGS_AUTO -Wl,--sort-common
# When linking shared library, drop dummy weak definitions that were
# replaced by strong definitions from other translation units.
tryldflag LDFLAGS_AUTO -Wl,--gc-sections
# Some patched GCC builds have these defaults messed up...
-tryldflag LDFLAGS_AUTO -Wl,--hash-style=both
+#tryldflag LDFLAGS_AUTO -Wl,--hash-style=both
# Prevent linking if there are undefined symbols; if any exist,
# libc.so will crash at runtime during relocation processing.
# The common way this can happen is failure to link the compiler
# runtime library; implementation error is also a possibility.
-tryldflag LDFLAGS_AUTO -Wl,--no-undefined
+#tryldflag LDFLAGS_AUTO -Wl,--no-undefined
# Avoid exporting symbols from compiler runtime libraries. They
# should be hidden anyway, but some toolchains including old gcc
# versions built without shared library support and pcc are broken.
-tryldflag LDFLAGS_AUTO -Wl,--exclude-libs=ALL
+#tryldflag LDFLAGS_AUTO -Wl,--exclude-libs=ALL
# Public data symbols must be interposable to allow for copy
# relocations, but otherwise we want to bind symbols at libc link
# time to eliminate startup relocations and PLT overhead. Use
# --dynamic-list rather than -Bsymbolic-functions for greater
# control over what symbols are left unbound.
-tryldflag LDFLAGS_AUTO -Wl,--dynamic-list="$srcdir/dynamic.list"
+#tryldflag LDFLAGS_AUTO -Wl,--dynamic-list="$srcdir/dynamic.list"
# Find compiler runtime library
test -z "$LIBCC" && tryldflag LIBCC -lgcc && tryldflag LIBCC -lgcc_eh
diff --git a/include/elf.h b/include/elf.h
index 3d5e13e..3620e8b 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -3310,6 +3310,62 @@ enum
#define R_RISCV_TLSDESC_ADD_LO12 64
#define R_RISCV_TLSDESC_CALL 65
+#define R_WASM_NONE 0
+#define R_WASM_32 1
+#define R_WASM_64 2
+#define R_WASM_RELATIVE 3
+#define R_WASM_COPY 4
+#define R_WASM_JUMP_SLOT 5
+#define R_WASM_TLS_DTPMOD32 6
+#define R_WASM_TLS_DTPMOD64 7
+#define R_WASM_TLS_DTPREL32 8
+#define R_WASM_TLS_DTPREL64 9
+#define R_WASM_TLS_TPREL32 10
+#define R_WASM_TLS_TPREL64 11
+
+#define R_WASM_BRANCH 16
+#define R_WASM_JAL 17
+#define R_WASM_CALL 18
+#define R_WASM_CALL_PLT 19
+#define R_WASM_GOT_HI20 20
+#define R_WASM_TLS_GOT_HI20 21
+#define R_WASM_TLS_GD_HI20 22
+#define R_WASM_PCREL_HI20 23
+#define R_WASM_PCREL_LO12_I 24
+#define R_WASM_PCREL_LO12_S 25
+#define R_WASM_HI20 26
+#define R_WASM_LO12_I 27
+#define R_WASM_LO12_S 28
+#define R_WASM_TPREL_HI20 29
+#define R_WASM_TPREL_LO12_I 30
+#define R_WASM_TPREL_LO12_S 31
+#define R_WASM_TPREL_ADD 32
+#define R_WASM_ADD8 33
+#define R_WASM_ADD16 34
+#define R_WASM_ADD32 35
+#define R_WASM_ADD64 36
+#define R_WASM_SUB8 37
+#define R_WASM_SUB16 38
+#define R_WASM_SUB32 39
+#define R_WASM_SUB64 40
+#define R_WASM_GNU_VTINHERIT 41
+#define R_WASM_GNU_VTENTRY 42
+#define R_WASM_ALIGN 43
+#define R_WASM_RVC_BRANCH 44
+#define R_WASM_RVC_JUMP 45
+#define R_WASM_LUI 46
+#define R_WASM_GPREL_I 47
+#define R_WASM_GPREL_S 48
+#define R_WASM_TPREL_I 49
+#define R_WASM_TPREL_S 50
+#define R_WASM_RELAX 51
+#define R_WASM_SUB6 52
+#define R_WASM_SET6 53
+#define R_WASM_SET8 54
+#define R_WASM_SET16 55
+#define R_WASM_SET32 56
+#define R_WASM_32_PCREL 57
+
#define EF_LARCH_ABI_MODIFIER_MASK 0x07
#define EF_LARCH_ABI_SOFT_FLOAT 0x01
#define EF_LARCH_ABI_SINGLE_FLOAT 0x02
diff --git a/include/unistd.h b/include/unistd.h
index 5bc7f79..ca939bd 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -177,7 +177,10 @@ void setusershell(void);
void endusershell(void);
char *getusershell(void);
int acct(const char *);
-long syscall(long, ...);
+#define __syscall_nargs_x(a,b,c,d,e,f,g,h,n,...) n
+#define __syscall_nargs(...) __syscall_nargs_x(__VA_ARGS__,7,6,5,4,3,2,1,0,)
+long syscall(long, long, ...);
+#define syscall(...) syscall(__syscall_nargs(__VA_ARGS__), __VA_ARGS__)
int execvpe(const char *, char *const [], char *const []);
int issetugid(void);
int getentropy(void *, size_t);
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index de2b9d8..e2ac283 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -158,6 +158,7 @@ extern hidden void *__pthread_tsd_main[];
extern hidden volatile int __eintr_valid_flag;
hidden int __clone(int (*)(void *), void *, int, void *, ...);
+hidden int _Clone(int (*)(void *), void *, int, void *, pid_t *, void *, pid_t *);
hidden int __set_thread_area(void *);
hidden int __libc_sigaction(int, const struct sigaction *, struct sigaction *);
hidden void __unmapself(void *, size_t);
@@ -169,14 +170,14 @@ static inline void __wake(volatile void *addr, int cnt, int priv)
{
if (priv) priv = FUTEX_PRIVATE;
if (cnt<0) cnt = INT_MAX;
- __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS ||
- __syscall(SYS_futex, addr, FUTEX_WAKE, cnt);
+ __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt, 0, 0, 0) != -ENOSYS ||
+ __syscall(SYS_futex, addr, FUTEX_WAKE, cnt, 0, 0, 0);
}
static inline void __futexwait(volatile void *addr, int val, int priv)
{
if (priv) priv = FUTEX_PRIVATE;
- __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS ||
- __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
+ __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0, 0, 0) != -ENOSYS ||
+ __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0, 0, 0);
}
hidden void __acquire_ptc(void);
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index 33d981f..590b6cb 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -23,9 +23,14 @@
typedef long syscall_arg_t;
#endif
-hidden long __syscall_ret(unsigned long),
- __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t,
- syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_ret(unsigned long);
+hidden long __syscall_cp_c0(syscall_arg_t);
+hidden long __syscall_cp_c1(syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c2(syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c3(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c4(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c5(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c6(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
#define __syscall1(n,a) __syscall1(n,__scc(a))
#define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b))
@@ -44,36 +49,22 @@ hidden long __syscall_ret(unsigned long),
#define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__)
#define syscall(...) __syscall_ret(__syscall(__VA_ARGS__))
-#define socketcall(nm,a,b,c,d,e,f) __syscall_ret(__socketcall(nm,a,b,c,d,e,f))
-#define socketcall_cp(nm,a,b,c,d,e,f) __syscall_ret(__socketcall_cp(nm,a,b,c,d,e,f))
+#define socketcall(...) __syscall_ret(__socketcall(__VA_ARGS__))
+#define socketcall_cp(...) __syscall_ret(__socketcall_cp(__VA_ARGS__))
-#define __syscall_cp0(n) (__syscall_cp)(n,0,0,0,0,0,0)
-#define __syscall_cp1(n,a) (__syscall_cp)(n,__scc(a),0,0,0,0,0)
-#define __syscall_cp2(n,a,b) (__syscall_cp)(n,__scc(a),__scc(b),0,0,0,0)
-#define __syscall_cp3(n,a,b,c) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),0,0,0)
-#define __syscall_cp4(n,a,b,c,d) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),0,0)
-#define __syscall_cp5(n,a,b,c,d,e) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),0)
-#define __syscall_cp6(n,a,b,c,d,e,f) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f))
+#define __syscall_cp0(n) __syscall_cp_c0(n)
+#define __syscall_cp1(n,a) __syscall_cp_c1(n,__scc(a))
+#define __syscall_cp2(n,a,b) __syscall_cp_c2(n,__scc(a),__scc(b))
+#define __syscall_cp3(n,a,b,c) __syscall_cp_c3(n,__scc(a),__scc(b),__scc(c))
+#define __syscall_cp4(n,a,b,c,d) __syscall_cp_c4(n,__scc(a),__scc(b),__scc(c),__scc(d))
+#define __syscall_cp5(n,a,b,c,d,e) __syscall_cp_c5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e))
+#define __syscall_cp6(n,a,b,c,d,e,f) __syscall_cp_c6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f))
#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__)
#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__))
-static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, syscall_arg_t b, syscall_arg_t c, syscall_arg_t d, syscall_arg_t e, syscall_arg_t f)
-{
- long r;
- if (cp) r = __syscall_cp(sys, a, b, c, d, e, f);
- else r = __syscall(sys, a, b, c, d, e, f);
- if (r != -ENOSYS) return r;
-#ifdef SYS_socketcall
- if (cp) r = __syscall_cp(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f}));
- else r = __syscall(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f}));
-#endif
- return r;
-}
-#define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \
- __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
-#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \
- __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
+#define __socketcall(nm, ...) __syscall(SYS_##nm, __VA_ARGS__)
+#define __socketcall_cp(nm, ...) __syscall_cp(SYS_##nm, __VA_ARGS__)
/* fixup legacy 16-bit junk */
@@ -374,14 +365,14 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a,
#endif
#ifdef SYS_open
-#define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE)
+#define __sys_open2(x,pn,fl) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, 0)
#define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo)
-#define __sys_open_cp2(x,pn,fl) __syscall_cp2(SYS_open, pn, (fl)|O_LARGEFILE)
+#define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_open, pn, (fl)|O_LARGEFILE, 0)
#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp3(SYS_open, pn, (fl)|O_LARGEFILE, mo)
#else
-#define __sys_open2(x,pn,fl) __syscall3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE)
+#define __sys_open2(x,pn,fl) __syscall4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, 0)
#define __sys_open3(x,pn,fl,mo) __syscall4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo)
-#define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE)
+#define __sys_open_cp2(x,pn,fl) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, 0)
#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo)
#endif
diff --git a/src/linux/clone.c b/src/linux/clone.c
index 257c1ce..e3e8aa0 100644
--- a/src/linux/clone.c
+++ b/src/linux/clone.c
@@ -31,7 +31,7 @@ int clone(int (*func)(void *), void *stack, int flags, void *arg, ...)
/* Flags that produce an invalid thread/TLS state are disallowed. */
int badflags = CLONE_THREAD | CLONE_SETTLS | CLONE_CHILD_CLEARTID;
- if ((flags & badflags) || !stack)
+ if ((flags & badflags) || (!stack && !(flags & CLONE_VFORK)))
return __syscall_ret(-EINVAL);
va_start(ap, arg);
@@ -63,3 +63,22 @@ int clone(int (*func)(void *), void *stack, int flags, void *arg, ...)
__restore_sigs(&csa.sigmask);
return __syscall_ret(ret);
}
+
+int __clone(int (*fn)(void *), void *stack, int flags, void *arg, ...)
+{
+ /* Avoid calling assembler functions with va_args (fails on Wasm). */
+ va_list ap;
+ pid_t *ptid = 0, *ctid = 0;
+ void *tls = 0;
+
+ va_start(ap, arg);
+ if (flags & (CLONE_PIDFD | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID))
+ ptid = va_arg(ap, pid_t *);
+ if (flags & CLONE_CHILD_SETTID) {
+ tls = va_arg(ap, void *);
+ ctid = va_arg(ap, pid_t *);
+ }
+ va_end(ap);
+
+ return _Clone(fn, stack, flags, arg, ptid, tls, ctid);
+}
diff --git a/src/linux/reboot.c b/src/linux/reboot.c
index 7f12af7..f131745 100644
--- a/src/linux/reboot.c
+++ b/src/linux/reboot.c
@@ -3,5 +3,5 @@
int reboot(int type)
{
- return syscall(SYS_reboot, 0xfee1dead, 672274793, type);
+ return syscall(SYS_reboot, 0xfee1dead, 672274793, type, 0);
}
diff --git a/src/misc/syscall.c b/src/misc/syscall.c
index 6f3ef65..471a9b2 100644
--- a/src/misc/syscall.c
+++ b/src/misc/syscall.c
@@ -5,17 +5,57 @@
#undef syscall
-long syscall(long n, ...)
+long syscall(long count, long n, ...)
{
va_list ap;
syscall_arg_t a,b,c,d,e,f;
va_start(ap, n);
- a=va_arg(ap, syscall_arg_t);
- b=va_arg(ap, syscall_arg_t);
- c=va_arg(ap, syscall_arg_t);
- d=va_arg(ap, syscall_arg_t);
- e=va_arg(ap, syscall_arg_t);
- f=va_arg(ap, syscall_arg_t);
+ switch (count) {
+ case 0:
+ va_end(ap);
+ return __syscall_ret(__syscall(n));
+ case 1:
+ a = va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n, a));
+ case 2:
+ a = va_arg(ap, syscall_arg_t);
+ b = va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n, a, b));
+ case 3:
+ a = va_arg(ap, syscall_arg_t);
+ b = va_arg(ap, syscall_arg_t);
+ c = va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n, a, b, c));
+ case 4:
+ a = va_arg(ap, syscall_arg_t);
+ b = va_arg(ap, syscall_arg_t);
+ c = va_arg(ap, syscall_arg_t);
+ d = va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n, a, b, c, d));
+ case 5:
+ a = va_arg(ap, syscall_arg_t);
+ b = va_arg(ap, syscall_arg_t);
+ c = va_arg(ap, syscall_arg_t);
+ d = va_arg(ap, syscall_arg_t);
+ e = va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n, a, b, c, d, e));
+ case 6:
+ a = va_arg(ap, syscall_arg_t);
+ b = va_arg(ap, syscall_arg_t);
+ c = va_arg(ap, syscall_arg_t);
+ d = va_arg(ap, syscall_arg_t);
+ e = va_arg(ap, syscall_arg_t);
+ f = va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n, a, b, c, d, e, f));
+ default:
+ break;
+ }
va_end(ap);
- return __syscall_ret(__syscall(n,a,b,c,d,e,f));
+ return -ENOSYS;
}
diff --git a/src/misc/syscalls.c b/src/misc/syscalls.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/misc/wasm/syscalls.s b/src/misc/wasm/syscalls.s
new file mode 100644
index 0000000..70e5069
--- /dev/null
+++ b/src/misc/wasm/syscalls.s
@@ -0,0 +1,123 @@
+.globaltype __stack_pointer, i32
+.globaltype __tls_base, i32
+.functype __wasm_syscall_0(i32, i32, i32) -> (i32)
+.functype __wasm_syscall_1(i32, i32, i32, i32) -> (i32)
+.functype __wasm_syscall_2(i32, i32, i32, i32, i32) -> (i32)
+.functype __wasm_syscall_3(i32, i32, i32, i32, i32, i32) -> (i32)
+.functype __wasm_syscall_4(i32, i32, i32, i32, i32, i32, i32) -> (i32)
+.functype __wasm_syscall_5(i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
+.functype __wasm_syscall_6(i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
+
+#define haxx
+
+.macro __SYSCALL_HEAD
+ global.get __stack_pointer
+ global.get __tls_base
+ local.get 0
+.endm
+
+.macro __SYSCALL_FOOT
+ /*
+ * The kernel never changes __stack_pointer or __tls_base during most
+ * syscalls. The ones where it does (clone, signals, exec) are handled
+ * separately and don't go via this function, making it safe to ignore.
+ */
+.endm
+
+.globl __syscall0
+.hidden __syscall0
+__syscall0:
+ .functype __syscall0(i32) -> (i32)
+
+ __SYSCALL_HEAD
+ call __wasm_syscall_0
+ __SYSCALL_FOOT
+
+ end_function
+
+.globl __syscall1
+.hidden __syscall1
+__syscall1:
+ .functype __syscall1(i32, i32) -> (i32)
+
+ __SYSCALL_HEAD
+ local.get 1
+ call __wasm_syscall_1
+ __SYSCALL_FOOT
+
+ end_function
+
+.globl __syscall2
+.hidden __syscall2
+__syscall2:
+ .functype __syscall2(i32, i32, i32) -> (i32)
+
+ __SYSCALL_HEAD
+ local.get 1
+ local.get 2
+ call __wasm_syscall_2
+ __SYSCALL_FOOT
+
+ end_function
+
+.globl __syscall3
+.hidden __syscall3
+__syscall3:
+ .functype __syscall3(i32, i32, i32, i32) -> (i32)
+
+ __SYSCALL_HEAD
+ local.get 1
+ local.get 2
+ local.get 3
+ call __wasm_syscall_3
+ __SYSCALL_FOOT
+
+ end_function
+
+.globl __syscall4
+.hidden __syscall4
+__syscall4:
+ .functype __syscall4(i32, i32, i32, i32, i32) -> (i32)
+
+ __SYSCALL_HEAD
+ local.get 1
+ local.get 2
+ local.get 3
+ local.get 4
+ call __wasm_syscall_4
+ __SYSCALL_FOOT
+
+ end_function
+
+.globl __syscall5
+.hidden __syscall5
+__syscall5:
+ .functype __syscall5(i32, i32, i32, i32, i32, i32) -> (i32)
+
+ __SYSCALL_HEAD
+ local.get 1
+ local.get 2
+ local.get 3
+ local.get 4
+ local.get 5
+ call __wasm_syscall_5
+ __SYSCALL_FOOT
+
+ end_function
+
+.globl __syscall6
+.hidden __syscall6
+__syscall6:
+ .functype __syscall6(i32, i32, i32, i32, i32, i32, i32) -> (i32)
+
+ __SYSCALL_HEAD
+ local.get 1
+ local.get 2
+ local.get 3
+ local.get 4
+ local.get 5
+ local.get 6
+ call __wasm_syscall_6
+ __SYSCALL_FOOT
+
+ end_function
diff --git a/src/network/accept.c b/src/network/accept.c
index a92406f..5fa901a 100644
--- a/src/network/accept.c
+++ b/src/network/accept.c
@@ -3,5 +3,5 @@
int accept(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
{
- return socketcall_cp(accept, fd, addr, len, 0, 0, 0);
+ return socketcall_cp(accept, fd, addr, len);
}
diff --git a/src/network/accept4.c b/src/network/accept4.c
index 765a38e..91575d1 100644
--- a/src/network/accept4.c
+++ b/src/network/accept4.c
@@ -7,7 +7,7 @@
int accept4(int fd, struct sockaddr *restrict addr, socklen_t *restrict len, int flg)
{
if (!flg) return accept(fd, addr, len);
- int ret = socketcall_cp(accept4, fd, addr, len, flg, 0, 0);
+ int ret = socketcall_cp(accept4, fd, addr, len, flg);
if (ret>=0 || (errno != ENOSYS && errno != EINVAL)) return ret;
if (flg & ~(SOCK_CLOEXEC|SOCK_NONBLOCK)) {
errno = EINVAL;
diff --git a/src/network/bind.c b/src/network/bind.c
index 07bb669..0ff11d9 100644
--- a/src/network/bind.c
+++ b/src/network/bind.c
@@ -3,5 +3,5 @@
int bind(int fd, const struct sockaddr *addr, socklen_t len)
{
- return socketcall(bind, fd, addr, len, 0, 0, 0);
+ return socketcall(bind, fd, addr, len);
}
diff --git a/src/network/connect.c b/src/network/connect.c
index 289127b..ace2add 100644
--- a/src/network/connect.c
+++ b/src/network/connect.c
@@ -3,5 +3,5 @@
int connect(int fd, const struct sockaddr *addr, socklen_t len)
{
- return socketcall_cp(connect, fd, addr, len, 0, 0, 0);
+ return socketcall_cp(connect, fd, addr, len);
}
diff --git a/src/network/getpeername.c b/src/network/getpeername.c
index 6567b45..fc366a3 100644
--- a/src/network/getpeername.c
+++ b/src/network/getpeername.c
@@ -3,5 +3,5 @@
int getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
{
- return socketcall(getpeername, fd, addr, len, 0, 0, 0);
+ return socketcall(getpeername, fd, addr, len);
}
diff --git a/src/network/getsockname.c b/src/network/getsockname.c
index 7885fc1..2a4d3eb 100644
--- a/src/network/getsockname.c
+++ b/src/network/getsockname.c
@@ -3,5 +3,5 @@
int getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
{
- return socketcall(getsockname, fd, addr, len, 0, 0, 0);
+ return socketcall(getsockname, fd, addr, len);
}
diff --git a/src/network/getsockopt.c b/src/network/getsockopt.c
index d3640d9..aaf0b7c 100644
--- a/src/network/getsockopt.c
+++ b/src/network/getsockopt.c
@@ -8,7 +8,7 @@ int getsockopt(int fd, int level, int optname, void *restrict optval, socklen_t
long tv32[2];
struct timeval *tv;
- int r = __socketcall(getsockopt, fd, level, optname, optval, optlen, 0);
+ int r = __socketcall(getsockopt, fd, level, optname, optval, optlen);
if (r==-ENOPROTOOPT) switch (level) {
case SOL_SOCKET:
@@ -20,7 +20,7 @@ int getsockopt(int fd, int level, int optname, void *restrict optval, socklen_t
if (optname==SO_RCVTIMEO) optname=SO_RCVTIMEO_OLD;
if (optname==SO_SNDTIMEO) optname=SO_SNDTIMEO_OLD;
r = __socketcall(getsockopt, fd, level, optname,
- tv32, (socklen_t[]){sizeof tv32}, 0);
+ tv32, (socklen_t[]){sizeof tv32});
if (r<0) break;
tv = optval;
tv->tv_sec = tv32[0];
@@ -33,7 +33,7 @@ int getsockopt(int fd, int level, int optname, void *restrict optval, socklen_t
if (optname==SO_TIMESTAMP) optname=SO_TIMESTAMP_OLD;
if (optname==SO_TIMESTAMPNS) optname=SO_TIMESTAMPNS_OLD;
r = __socketcall(getsockopt, fd, level,
- optname, optval, optlen, 0);
+ optname, optval, optlen);
break;
}
}
diff --git a/src/network/listen.c b/src/network/listen.c
index f84ad03..87eec05 100644
--- a/src/network/listen.c
+++ b/src/network/listen.c
@@ -3,5 +3,5 @@
int listen(int fd, int backlog)
{
- return socketcall(listen, fd, backlog, 0, 0, 0, 0);
+ return socketcall(listen, fd, backlog);
}
diff --git a/src/network/recvmsg.c b/src/network/recvmsg.c
index 0364162..8f9b81d 100644
--- a/src/network/recvmsg.c
+++ b/src/network/recvmsg.c
@@ -59,7 +59,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
msg = &h;
}
#endif
- r = socketcall_cp(recvmsg, fd, msg, flags, 0, 0, 0);
+ r = socketcall_cp(recvmsg, fd, msg, flags);
if (r >= 0) __convert_scm_timestamps(msg, orig_controllen);
#if LONG_MAX > INT_MAX
if (orig) *orig = h;
diff --git a/src/network/sendmsg.c b/src/network/sendmsg.c
index acdfdf2..611186d 100644
--- a/src/network/sendmsg.c
+++ b/src/network/sendmsg.c
@@ -28,5 +28,5 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
}
}
#endif
- return socketcall_cp(sendmsg, fd, msg, flags, 0, 0, 0);
+ return socketcall_cp(sendmsg, fd, msg, flags);
}
diff --git a/src/network/setsockopt.c b/src/network/setsockopt.c
index 612a194..d97ce57 100644
--- a/src/network/setsockopt.c
+++ b/src/network/setsockopt.c
@@ -12,7 +12,7 @@ int setsockopt(int fd, int level, int optname, const void *optval, socklen_t opt
time_t s;
suseconds_t us;
- int r = __socketcall(setsockopt, fd, level, optname, optval, optlen, 0);
+ int r = __socketcall(setsockopt, fd, level, optname, optval, optlen);
if (r==-ENOPROTOOPT) switch (level) {
case SOL_SOCKET:
@@ -30,7 +30,7 @@ int setsockopt(int fd, int level, int optname, const void *optval, socklen_t opt
if (optname==SO_SNDTIMEO) optname=SO_SNDTIMEO_OLD;
r = __socketcall(setsockopt, fd, level, optname,
- ((long[]){s, CLAMP(us)}), 2*sizeof(long), 0);
+ ((long[]){s, CLAMP(us)}), 2*sizeof(long));
break;
case SO_TIMESTAMP:
case SO_TIMESTAMPNS:
@@ -38,7 +38,7 @@ int setsockopt(int fd, int level, int optname, const void *optval, socklen_t opt
if (optname==SO_TIMESTAMP) optname=SO_TIMESTAMP_OLD;
if (optname==SO_TIMESTAMPNS) optname=SO_TIMESTAMPNS_OLD;
r = __socketcall(setsockopt, fd, level,
- optname, optval, optlen, 0);
+ optname, optval, optlen);
break;
}
}
diff --git a/src/network/shutdown.c b/src/network/shutdown.c
index 10ca21a..fa51bfc 100644
--- a/src/network/shutdown.c
+++ b/src/network/shutdown.c
@@ -3,5 +3,5 @@
int shutdown(int fd, int how)
{
- return socketcall(shutdown, fd, how, 0, 0, 0, 0);
+ return socketcall(shutdown, fd, how);
}
diff --git a/src/network/socket.c b/src/network/socket.c
index afa1a7f..d2beb31 100644
--- a/src/network/socket.c
+++ b/src/network/socket.c
@@ -5,12 +5,11 @@
int socket(int domain, int type, int protocol)
{
- int s = __socketcall(socket, domain, type, protocol, 0, 0, 0);
+ int s = __socketcall(socket, domain, type, protocol);
if ((s==-EINVAL || s==-EPROTONOSUPPORT)
&& (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
s = __socketcall(socket, domain,
- type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
- protocol, 0, 0, 0);
+ type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK), protocol);
if (s < 0) return __syscall_ret(s);
if (type & SOCK_CLOEXEC)
__syscall(SYS_fcntl, s, F_SETFD, FD_CLOEXEC);
diff --git a/src/network/socketpair.c b/src/network/socketpair.c
index f348962..28603ed 100644
--- a/src/network/socketpair.c
+++ b/src/network/socketpair.c
@@ -5,12 +5,11 @@
int socketpair(int domain, int type, int protocol, int fd[2])
{
- int r = socketcall(socketpair, domain, type, protocol, fd, 0, 0);
+ int r = socketcall(socketpair, domain, type, protocol, fd);
if (r<0 && (errno==EINVAL || errno==EPROTONOSUPPORT)
&& (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
r = socketcall(socketpair, domain,
- type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
- protocol, fd, 0, 0);
+ type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK), protocol, fd);
if (r < 0) return r;
if (type & SOCK_CLOEXEC) {
__syscall(SYS_fcntl, fd[0], F_SETFD, FD_CLOEXEC);
diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c
index 8294598..668694d 100644
--- a/src/process/posix_spawn.c
+++ b/src/process/posix_spawn.c
@@ -175,12 +175,13 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
char stack[1024+PATH_MAX];
int ec=0, cs;
struct args args;
+ const posix_spawnattr_t dummy = {0};
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
args.path = path;
args.fa = fa;
- args.attr = attr ? attr : &(const posix_spawnattr_t){0};
+ args.attr = attr ? attr : &dummy;
args.argv = argv;
args.envp = envp;
pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
diff --git a/src/process/vfork.c b/src/process/vfork.c
index d430c13..0b16b9d 100644
--- a/src/process/vfork.c
+++ b/src/process/vfork.c
@@ -1,14 +1,12 @@
#define _GNU_SOURCE
-#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
#include <signal.h>
#include "syscall.h"
pid_t vfork(void)
{
- /* vfork syscall cannot be made from C code */
-#ifdef SYS_fork
- return syscall(SYS_fork);
-#else
- return syscall(SYS_clone, SIGCHLD, 0);
-#endif
+ fprintf(stderr,
+ "vfork() is not implemented yet, use clone() instead!\n");
+ abort();
}
diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c
index e69de29..d03b171 100644
--- a/src/setjmp/longjmp.c
+++ b/src/setjmp/longjmp.c
@@ -0,0 +1,19 @@
+
+#include <stdlib.h>
+#include <setjmp.h>
+
+/*
+ * setjmp/sigsetjmp/longjmp is currently not supported (but it can be,
+ * LLVM has support for it with some fixup logic needed). Since some
+ * programs use setjmp but only longjmp when for example an error occurs,
+ * we can allow setjmp/sigsetjmp (by doing nothing). When it actually
+ * wants to longjmp we have to abort, let's just hope that never happens.
+ */
+_Noreturn void longjmp(jmp_buf env, int status);
+{
+ (void)env;
+ (void)status;
+
+ fprintf(stderr, "longjmp() is not implemented yet!\n");
+ abort();
+}
diff --git a/src/setjmp/wasm/longjmp.S b/src/setjmp/wasm/longjmp.S
new file mode 100644
index 0000000..192b0b3
--- /dev/null
+++ b/src/setjmp/wasm/longjmp.S
@@ -0,0 +1,13 @@
+.functype abort() -> ()
+
+.globl longjmp
+longjmp:
+ .functype longjmp(i32, i32) -> ()
+ # setjmp/sigsetjmp/longjmp is currently not supported (but it can be,
+ # LLVM has support for it with some fixup logic needed). Since some
+ # programs use setjmp but only longjmp when for example an error occurs,
+ # we can allow setjmp/sigsetjmp (by doing nothing). When it actually
+ # wants to longjmp we have to abort, let's just hope that never happens.
+ call abort
+
+ end_function
diff --git a/src/setjmp/wasm/setjmp.S b/src/setjmp/wasm/setjmp.S
new file mode 100644
index 0000000..50b8983
--- /dev/null
+++ b/src/setjmp/wasm/setjmp.S
@@ -0,0 +1,5 @@
+.globl setjmp
+setjmp:
+ .functype setjmp(i32) -> ()
+ # We allow this, but do nothing. longjmp() is forbidden though.
+ end_function
diff --git a/src/signal/wasm/restore.s b/src/signal/wasm/restore.s
new file mode 100644
index 0000000..f14b43c
--- /dev/null
+++ b/src/signal/wasm/restore.s
@@ -0,0 +1,98 @@
+.globaltype __stack_pointer, i32
+.globaltype __tls_base, i32
+.functype __wasm_syscall_0(i32, i32, i32) -> (i32)
+
+.globl __restore_rt
+.hidden __restore_rt
+__restore_rt:
+ .functype __restore_rt() -> ()
+
+ global.get __stack_pointer
+ global.get __tls_base
+ i32.const 139 # SYS_rt_sigreturn
+ call __wasm_syscall_0
+ unreachable
+
+ end_function
+
+.globl __restore
+.hidden __restore
+__restore:
+ .functype __restore() -> ()
+
+ call __restore_rt
+
+ end_function
+
+/* TODO: Move this to a better place... */
+.globl __libc_handle_signal
+__libc_handle_signal:
+ .functype __libc_handle_signal() -> ()
+ /* 0: sig_param */
+ /* 1: info_param */
+ /* 2: uc_param */
+ /* 3: sa_handler */
+ .local i32, i32, i32, i32
+
+ /* sig_param */
+ global.get __stack_pointer
+ i32.load 0
+ /*
+ * LLVM complains for some reason if we leave this on the Wasm stack. We
+ * put it in a local instead and then everything works, somehow...
+ */
+ local.set 0
+
+ /* info_param */
+ global.get __stack_pointer
+ i32.const 4
+ i32.add
+ i32.load 0
+ local.set 1
+
+ /* uc_param */
+ global.get __stack_pointer
+ i32.const 8
+ i32.add
+ i32.load 0
+ local.set 2
+
+ /* sa_handler */
+ global.get __stack_pointer
+ i32.const 12
+ i32.add
+ i32.load 0
+ local.set 3
+
+ /* (__stack_pointer is already 16-byte aligned by the kernel.) */
+
+ /* !SA_SIGINFO */
+ block
+ local.get 1
+ br_if 0
+
+ local.get 0 /* sig_param */
+ local.get 3 /* sa_handler cast to handler */
+ /* handler(sig) */
+ call_indirect (i32) -> ()
+ end_block
+
+ /* SA_SIGINFO */
+ block
+ local.get 1
+ i32.eqz
+ br_if 0
+
+ local.get 0 /* sig _param*/
+ local.get 1 /* info_param */
+ local.get 2 /* uc_param */
+ local.get 3 /* sa_handler cast to sigaction */
+ /* sigaction(sig_param, info_param, uc_param) */
+ call_indirect (i32, i32, i32) -> ()
+ end_block
+
+ /* Unless the handler itself calls SYS_rt_sigreturn we have to do it. */
+ call __restore_rt
+ unreachable
+
+ end_function
diff --git a/src/signal/wasm/sigsetjmp.S b/src/signal/wasm/sigsetjmp.S
new file mode 100644
index 0000000..83dd15d
--- /dev/null
+++ b/src/signal/wasm/sigsetjmp.S
@@ -0,0 +1,5 @@
+.globl sigsetjmp
+sigsetjmp:
+ .functype sigsetjmp(i32, i32) -> ()
+ # We allow this, but do nothing. longjmp() is forbidden though.
+ end_function
diff --git a/src/thread/__syscall_cp.c b/src/thread/__syscall_cp.c
index 42a0167..f33c5d0 100644
--- a/src/thread/__syscall_cp.c
+++ b/src/thread/__syscall_cp.c
@@ -1,20 +1,2 @@
#include "pthread_impl.h"
#include "syscall.h"
-
-hidden long __syscall_cp_c();
-
-static long sccp(syscall_arg_t nr,
- syscall_arg_t u, syscall_arg_t v, syscall_arg_t w,
- syscall_arg_t x, syscall_arg_t y, syscall_arg_t z)
-{
- return __syscall(nr, u, v, w, x, y, z);
-}
-
-weak_alias(sccp, __syscall_cp_c);
-
-long (__syscall_cp)(syscall_arg_t nr,
- syscall_arg_t u, syscall_arg_t v, syscall_arg_t w,
- syscall_arg_t x, syscall_arg_t y, syscall_arg_t z)
-{
- return __syscall_cp_c(nr, u, v, w, x, y, z);
-}
diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c
index 666093b..ffa12cc 100644
--- a/src/thread/__timedwait.c
+++ b/src/thread/__timedwait.c
@@ -17,13 +17,13 @@ static int __futex4_cp(volatile void *addr, int op, int val, const struct timesp
r = -ENOSYS;
if (SYS_futex == SYS_futex_time64 || !IS32BIT(s))
r = __syscall_cp(SYS_futex_time64, addr, op, val,
- to ? ((long long[]){s, ns}) : 0);
+ to ? ((long long[]){s, ns}) : 0, 0, 0);
if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r;
to = to ? (void *)(long[]){CLAMP(s), ns} : 0;
#endif
- r = __syscall_cp(SYS_futex, addr, op, val, to);
+ r = __syscall_cp(SYS_futex, addr, op, val, to, 0, 0);
if (r != -ENOSYS) return r;
- return __syscall_cp(SYS_futex, addr, op & ~FUTEX_PRIVATE, val, to);
+ return __syscall_cp(SYS_futex, addr, op & ~FUTEX_PRIVATE, val, to, 0, 0);
}
static volatile int dummy = 0;
diff --git a/src/thread/__wait.c b/src/thread/__wait.c
index dc33c1a..847de07 100644
--- a/src/thread/__wait.c
+++ b/src/thread/__wait.c
@@ -10,8 +10,8 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv)
}
if (waiters) a_inc(waiters);
while (*addr==val) {
- __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS
- || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
+ __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0, 0, 0) != -ENOSYS
+ || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0, 0, 0);
}
if (waiters) a_dec(waiters);
}
diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c
index cc2a8bb..e2fa679 100644
--- a/src/thread/pthread_barrier_wait.c
+++ b/src/thread/pthread_barrier_wait.c
@@ -84,8 +84,8 @@ int pthread_barrier_wait(pthread_barrier_t *b)
a_spin();
a_inc(&inst->finished);
while (inst->finished == 1)
- __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS
- || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0);
+ __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0,0,0) != -ENOSYS
+ || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0,0,0);
return PTHREAD_BARRIER_SERIAL_THREAD;
}
diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
index 139a6fc..4ba7b8e 100644
--- a/src/thread/pthread_cancel.c
+++ b/src/thread/pthread_cancel.c
@@ -3,9 +3,7 @@
#include "pthread_impl.h"
#include "syscall.h"
-hidden long __cancel(), __syscall_cp_asm(), __syscall_cp_c();
-
-long __cancel()
+hidden long __cancel()
{
pthread_t self = __pthread_self();
if (self->canceldisable == PTHREAD_CANCEL_ENABLE || self->cancelasync)
@@ -14,27 +12,85 @@ long __cancel()
return -ECANCELED;
}
-long __syscall_cp_asm(volatile void *, syscall_arg_t,
- syscall_arg_t, syscall_arg_t, syscall_arg_t,
- syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_asm0(volatile void *, syscall_arg_t);
+hidden long __syscall_cp_asm1(volatile void *, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_asm2(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_asm3(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_asm4(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_asm5(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_asm6(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+
+long __syscall_cp_asm0(volatile void *, syscall_arg_t) { abort(); /* TODO */ }
+long __syscall_cp_asm1(volatile void *, syscall_arg_t, syscall_arg_t) { abort(); /* TODO */ }
+long __syscall_cp_asm2(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t) { abort(); /* TODO */ }
+long __syscall_cp_asm3(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t) { abort(); /* TODO */ }
+long __syscall_cp_asm4(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t) { abort(); /* TODO */ }
+long __syscall_cp_asm5(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t) { abort(); /* TODO */ }
+long __syscall_cp_asm6(volatile void *, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t) { abort(); /* TODO */ }
+
+hidden long __syscall_cp_c0(syscall_arg_t);
+hidden long __syscall_cp_c1(syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c2(syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c3(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c4(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c5(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+hidden long __syscall_cp_c6(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t);
+
+/* It's a TODO to handle this... */
+/*
+#define SYSCALL_CP_C(num, ...) do {\
+ pthread_t self; \
+ long r; \
+ int st; \
+ \
+ if ((st=(self=__pthread_self())->canceldisable) \
+ && (st==PTHREAD_CANCEL_DISABLE || nr==SYS_close)) \
+ return __syscall(__VA_ARGS__); \
+ \
+ r = __syscall_cp_asm##num(&self->cancel, __VA_ARGS__); \
+ if (r==-EINTR && nr!=SYS_close && self->cancel && \
+ self->canceldisable != PTHREAD_CANCEL_DISABLE) \
+ r = __cancel(); \
+ return r; \
+ } while(0)
+*/
+#define SYSCALL_CP_C(num, ...) do {\
+ return __syscall(__VA_ARGS__); \
+ } while(0)
+
+long __syscall_cp_c0(syscall_arg_t nr)
+{
+ SYSCALL_CP_C(0, nr);
+}
+
+long __syscall_cp_c1(syscall_arg_t nr, syscall_arg_t u)
+{
+ SYSCALL_CP_C(1, nr, u);
+}
+
+long __syscall_cp_c2(syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v)
+{
+ SYSCALL_CP_C(2, nr, u, v);
+}
-long __syscall_cp_c(syscall_arg_t nr,
- syscall_arg_t u, syscall_arg_t v, syscall_arg_t w,
- syscall_arg_t x, syscall_arg_t y, syscall_arg_t z)
+long __syscall_cp_c3(syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w)
{
- pthread_t self;
- long r;
- int st;
-
- if ((st=(self=__pthread_self())->canceldisable)
- && (st==PTHREAD_CANCEL_DISABLE || nr==SYS_close))
- return __syscall(nr, u, v, w, x, y, z);
-
- r = __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z);
- if (r==-EINTR && nr!=SYS_close && self->cancel &&
- self->canceldisable != PTHREAD_CANCEL_DISABLE)
- r = __cancel();
- return r;
+ SYSCALL_CP_C(3, nr, u, v, w);
+}
+
+long __syscall_cp_c4(syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, syscall_arg_t x)
+{
+ SYSCALL_CP_C(4, nr, u, v, w, x);
+}
+
+long __syscall_cp_c5(syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, syscall_arg_t x, syscall_arg_t y)
+{
+ SYSCALL_CP_C(5, nr, u, v, w, x, y);
+}
+
+long __syscall_cp_c6(syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, syscall_arg_t x, syscall_arg_t y, syscall_arg_t z)
+{
+ SYSCALL_CP_C(6, nr, u, v, w, x, y, z);
}
static void _sigaddset(sigset_t *set, int sig)
@@ -49,7 +105,7 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
{
pthread_t self = __pthread_self();
ucontext_t *uc = ctx;
- uintptr_t pc = uc->uc_mcontext.MC_PC;
+ uintptr_t pc;
a_barrier();
if (!self->cancel || self->canceldisable == PTHREAD_CANCEL_DISABLE) return;
@@ -61,6 +117,8 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
__cancel();
}
+#ifdef MC_PC
+ pc = uc->uc_mcontext.MC_PC;
if (pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel;
#ifdef CANCEL_GOT
@@ -68,6 +126,10 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
#endif
return;
}
+#else
+ /* TODO: handle this. */
+ abort();
+#endif
__syscall(SYS_tkill, self->tid, SIGCANCEL);
}
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c
index 6b76145..fc6793e 100644
--- a/src/thread/pthread_cond_timedwait.c
+++ b/src/thread/pthread_cond_timedwait.c
@@ -49,8 +49,8 @@ static inline void unlock_requeue(volatile int *l, volatile int *r, int w)
{
a_store(l, 0);
if (w) __wake(l, 1, 1);
- else __syscall(SYS_futex, l, FUTEX_REQUEUE|FUTEX_PRIVATE, 0, 1, r) != -ENOSYS
- || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r);
+ else __syscall(SYS_futex, l, FUTEX_REQUEUE|FUTEX_PRIVATE, 0, 1, r, 0) != -ENOSYS
+ || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r, 0);
}
enum {
diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c
index 9279fc5..9615429 100644
--- a/src/thread/pthread_mutex_timedlock.c
+++ b/src/thread/pthread_mutex_timedlock.c
@@ -11,11 +11,11 @@ static int __futex4(volatile void *addr, int op, int val, const struct timespec
int r = -ENOSYS;
if (SYS_futex == SYS_futex_time64 || !IS32BIT(s))
r = __syscall(SYS_futex_time64, addr, op, val,
- to ? ((long long[]){s, ns}) : 0);
+ to ? ((long long[]){s, ns}) : 0, 0, 0);
if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r;
to = to ? (void *)(long[]){CLAMP(s), ns} : 0;
#endif
- return __syscall(SYS_futex, addr, op, val, to);
+ return __syscall(SYS_futex, addr, op, val, to, 0, 0);
}
static int pthread_mutex_timedlock_pi(pthread_mutex_t *restrict m, const struct timespec *restrict at)
@@ -36,7 +36,7 @@ static int pthread_mutex_timedlock_pi(pthread_mutex_t *restrict m, const struct
/* Catch spurious success for non-robust mutexes. */
if (!(type&4) && ((m->_m_lock & 0x40000000) || m->_m_waiters)) {
a_store(&m->_m_waiters, -1);
- __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
+ __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv, 0, 0, 0, 0);
self->robust_list.pending = 0;
break;
}
diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c
index a24e7c5..fc6dc8d 100644
--- a/src/thread/pthread_mutex_trylock.c
+++ b/src/thread/pthread_mutex_trylock.c
@@ -43,7 +43,7 @@ int __pthread_mutex_trylock_owner(pthread_mutex_t *m)
success:
if ((type&8) && m->_m_waiters) {
int priv = (type & 128) ^ 128;
- __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
+ __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv, 0, 0, 0, 0);
self->robust_list.pending = 0;
return (type&4) ? ENOTRECOVERABLE : EBUSY;
}
diff --git a/src/thread/pthread_mutex_unlock.c b/src/thread/pthread_mutex_unlock.c
index b66423e..69f1a9c 100644
--- a/src/thread/pthread_mutex_unlock.c
+++ b/src/thread/pthread_mutex_unlock.c
@@ -33,7 +33,7 @@ int __pthread_mutex_unlock(pthread_mutex_t *m)
if (type&8) {
if (old<0 || a_cas(&m->_m_lock, old, new)!=old) {
if (new) a_store(&m->_m_waiters, -1);
- __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
+ __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv, 0, 0, 0, 0);
}
cont = 0;
waiters = 0;
diff --git a/src/thread/pthread_mutexattr_setprotocol.c b/src/thread/pthread_mutexattr_setprotocol.c
index 8b80c1c..b98cbc2 100644
--- a/src/thread/pthread_mutexattr_setprotocol.c
+++ b/src/thread/pthread_mutexattr_setprotocol.c
@@ -14,7 +14,7 @@ int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol)
r = check_pi_result;
if (r < 0) {
volatile int lk = 0;
- r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
+ r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0, 0, 0);
a_store(&check_pi_result, r);
}
if (r) return r;
diff --git a/src/thread/wasm/__set_thread_area.c b/src/thread/wasm/__set_thread_area.c
new file mode 100644
index 0000000..f703c34
--- /dev/null
+++ b/src/thread/wasm/__set_thread_area.c
@@ -0,0 +1,9 @@
+#include "pthread_impl.h"
+
+_Thread_local uintptr_t __musl_tp = 0U;
+
+int __set_thread_area(void *p)
+{
+ __musl_tp = (uintptr_t)p;
+ return 0;
+}
diff --git a/src/thread/wasm/clone.s b/src/thread/wasm/clone.s
new file mode 100644
index 0000000..4aa3a7e
--- /dev/null
+++ b/src/thread/wasm/clone.s
@@ -0,0 +1,149 @@
+.globaltype __stack_pointer, i32
+.globaltype __tls_base, i32
+.functype __wasm_syscall_1(i32, i32, i32, i32) -> (i32)
+.functype __wasm_syscall_5(i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
+
+.globl __get_tls_base
+__get_tls_base:
+ .functype __get_tls_base() -> (i32)
+ global.get __tls_base
+ end_function
+
+# The runtime expects to be able to set __tls_base as part of it's clone setup.
+.globl __set_tls_base
+__set_tls_base:
+ .functype __set_tls_base(i32) -> ()
+ local.get 0
+ global.set __tls_base
+ end_function
+
+# This function gets called by the host once it detects a clone happening.
+.globl __libc_clone_callback
+__libc_clone_callback:
+ .functype __libc_clone_callback() -> (i32)
+
+ i32.const 0 # sp (no care)
+ i32.const 0 # tp (no care)
+ i32.const 93 # SYS_exit (will be used at the end of this function)
+
+ # Extract arg
+ global.get __stack_pointer
+ i32.const 4
+ i32.add
+ i32.load 0
+
+ # Extract fn
+ global.get __stack_pointer
+ i32.load 0
+
+ # Deallocate fn+arg+alignemnt
+ global.get __stack_pointer
+ i32.const 16
+ i32.add
+ global.set __stack_pointer
+
+ # Call fn(arg)
+ call_indirect (i32) -> (i32)
+
+ # syscall(SYS_exit, the return value from the callback)
+ call __wasm_syscall_1
+ end_function
+
+.globl _Clone
+_Clone:
+ # int _Clone(fn, stack, flags, arg, ptid, tls, ctid);
+ # 0 1 2 3 4 5 6
+ .functype _Clone(i32, i32, i32, i32, i32, i32, i32) -> (i32)
+ .local i32 /* 7: child_stack */
+
+ # We save fn+arg on the stack. There are two distincs cases for stack:
+ # * stack is NULL: the kernel will in this special case copy the value
+ # of __stack_pointer to the new task. This means we should fill in fn
+ # and arg on our stack. This also implies that the caller uses
+ # CLONE_VFORK which pauses the calling task (or it does not care about
+ # the stack being corrupted in the caller, which is a very odd case).
+ # * stack is not NULL: the kernel will in this case set the stack
+ # pointer of the new task to the value of the stack argument.
+ #
+ # In either case we don't really need to "allocate" space on these
+ # stacks, but we do it anyway, should the syscall wrappers change in the
+ # future to call C code. In that case we also need to align the stack.
+
+ # If stack was NULL, store into __stack_pointer instead. The kernel will
+ # in this special case copy the value of the stack pointer to the new
+ # task in the clone syscall. (Allocating space on these stacks is not
+ # strictly necessary but a nice thing if the syscall function changes
+ # to a C function in the future - in that case we should also align the
+ # stack to 16 bytes.) To be consistent, also allocate on non-NULL stack.
+ block
+ local.get 1
+ br_if 0 # if (stack != NULL): break to block 0;
+ # else if (stack == NULL):
+
+ global.get __stack_pointer
+ i32.const 16
+ i32.sub
+ local.tee 7
+ global.set __stack_pointer
+ end_block
+
+ block
+ local.get 1
+ i32.eqz
+ br_if 0 # if (stack == NULL): break to block 0;
+ # else if (stack != NULL):
+
+ local.get 1
+ i32.const 16
+ i32.sub
+ local.tee 7
+ local.set 1
+ end_block
+
+ /*
+ * At this point:
+ * local 1 contains the decremented stack address or NULL.
+ * local 7 contains the decremented stack address (never NULL).
+ * i.e. we don't pass the decremented __stack_pointer if stack == NULL.
+ */
+
+ # Store fn at the lowest address.
+ local.get 7
+ local.get 0
+ i32.store 0
+
+ # Store arg at the next-lowest address.
+ local.get 7
+ i32.const 4
+ i32.add
+ local.get 3
+ i32.store 0
+
+ # syscall(SYS_clone, clone_flags, newsp, parent_tidptr, child_tidptr, tls)
+ global.get __stack_pointer # our sp (used when newsp is NULL)
+ global.get __tls_base # our tp (used when CLONE_SETTLS is not set)
+ i32.const 220 # SYS_clone
+ local.get 2 # clone_flags
+ local.get 1 # newsp (maybe NULL)
+ local.get 4 # ptid
+ local.get 6 # ctid
+ local.get 5 # tls
+ call __wasm_syscall_5
+
+ # On Wasm, we don't end up returning twice - instead wasm_clone_callback
+ # is called and we can extract fn and arg from __stack_pointer. This
+ # means that we for sure currently are in the parent when returning.
+
+ block
+ local.get 1
+ br_if 0 # if (stack != NULL): break to block 0;
+ # else if(stack == NULL):
+
+ global.get __stack_pointer
+ i32.const 16
+ i32.add
+ global.set __stack_pointer
+ end_block
+
+ # (Pass on return value from the above syscall to the caller.)
+ end_function
diff --git a/src/unistd/access.c b/src/unistd/access.c
index d6eed68..449f9b4 100644
--- a/src/unistd/access.c
+++ b/src/unistd/access.c
@@ -7,6 +7,6 @@ int access(const char *filename, int amode)
#ifdef SYS_access
return syscall(SYS_access, filename, amode);
#else
- return syscall(SYS_faccessat, AT_FDCWD, filename, amode, 0);
+ return syscall(SYS_faccessat2, AT_FDCWD, filename, amode, 0);
#endif
}
diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c
index 43052dd..56d650c 100644
--- a/src/unistd/faccessat.c
+++ b/src/unistd/faccessat.c
@@ -18,7 +18,7 @@ static int checker(void *p)
if (__syscall(SYS_setregid, __syscall(SYS_getegid), -1)
|| __syscall(SYS_setreuid, __syscall(SYS_geteuid), -1))
__syscall(SYS_exit, 1);
- ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0);
+ ret = __syscall(SYS_faccessat2, c->fd, c->filename, c->amode, 0);
__syscall(SYS_write, c->p, &ret, sizeof ret);
return 0;
}
--
2.25.1